七、UART
16.1 介绍
UART(Universal Asynchronous Receiver Transmitter),通用异步收发器,用来传输穿行数据时
UART 之间以全双工方式传输数据,连线方法只有 3 根电线:TXD 用于发送数据,RXD 用于接收数据,GND用于给双方提供参考地。
串口数据线以 “位”为最小单位传输数据。帧(frame)由具有完整意义的、不可分割的若干位组成,它包含开始位、数据位、校验位和停止位。
UART 使用标准的 TTL/CMOS 逻辑电平(0~5V、0~3.3V、0~2.5V 或 0~1.8V)来表示数据,高电平表示1,低电平表示0。为了增强数据的抗干扰能力、提高传输长度,通常将 TLL/CMOS 逻辑电平转换位 RS-232 逻辑电平,3~12V 表示0,-3~-12V 表示1。
数据的传输流程如下:
- 平时数据处于 空闲 状态
- 当要发送数据时,UART 改变 TXD 数据线的状态(变为 0 状态)并维持 1 位的时间,这样接收方检测到开始位后,再等待 1.5 位的时间就开始一位一位地检测数据线的状态得到所传输的数据
- UART 一帧中可以由5、6、7或8位的数据,发送方一位一位的改变数据线的状态将它们发送出去,首先发送最低位
- 如果使用校验功能,UART 在发送完数据位后,还要发送一个校验位。有两种校验方法:奇校验、偶校验——数据位连同校验位中,“1”的数目等于奇数或偶数
- 最后,发送停止位,数据线恢复到“空闲”状态(1状态)。停止位的长度有3种:1位、1.5位、2位
16.2 S3C2440 UART 特性
S3C2440 UART 中有3个独立的通道,每个通道都可以工作于中断模式或DMA模式,即UART可以发出中断或DMA请求以便在UART、CPU 间传输数据。UART 由波特率发生器、发送器、接收器和控制逻辑组成
使用系统时钟时,UART的波特率可以达到 115.2Kbit/s,若使用 UEXTCLK 引脚提供的外部时钟,则可以达到更高的波特率。波特率可以通过编程进行控制。
S3C2440 UART 的 FIFO 深度位64.。发送数据时,CPU 先将数据写入发送 FIFO 中,然后 UART 会自动将 FIFO 中的数据复制到“发送移位器”(Transmit Shifter)中,发送移位器将数据一位一位的发送到 TXDn 数据线上(根据设定的格式,插入开始位、校验位和停止位)。接收数据时,“接收移位器”(Receive Shifter)将RXDn 数据线上的数据一位一位接收进来,然后复制到接收 FIFO 中,CPU 即可以从中读取数据。
S3C2440 UART 的每个通道支持的停止位有 1 位、2位,数据位有5、6、7、8位,支持校验功能,另外还有红外发送/接收功能。
UART 结构图如下:
其他说明见芯片手册第11章节
16.3 程序
uart.lds
- SECTIONS {
- . = 0x30000000;
- .text : { *(.text) }
- .rodata ALIGN() : {*(.rodata)}
- .data ALIGN() : { *(.data) }
- .bss ALIGN() : { *(.bss) *(COMMON) }
- }
s3c24xx.h
- /* WOTCH DOG register */
- #define WTCON (*(volatile unsigned long *)0x53000000)
- /* SDRAM regisers */
- #define MEM_CTL_BASE 0x48000000
- #define SDRAM_BASE 0x30000000
- /* NAND Flash registers */
- #define NFCONF (*(volatile unsigned int *)0x4e000000)
- #define NFCMD (*(volatile unsigned char *)0x4e000004)
- #define NFADDR (*(volatile unsigned char *)0x4e000008)
- #define NFDATA (*(volatile unsigned char *)0x4e00000c)
- #define NFSTAT (*(volatile unsigned char *)0x4e000010)
- /*GPIO registers*/
- #define GPBCON (*(volatile unsigned long *)0x56000010)
- #define GPBDAT (*(volatile unsigned long *)0x56000014)
- #define GPFCON (*(volatile unsigned long *)0x56000050)
- #define GPFDAT (*(volatile unsigned long *)0x56000054)
- #define GPFUP (*(volatile unsigned long *)0x56000058)
- #define GPGCON (*(volatile unsigned long *)0x56000060)
- #define GPGDAT (*(volatile unsigned long *)0x56000064)
- #define GPGUP (*(volatile unsigned long *)0x56000068)
- #define GPHCON (*(volatile unsigned long *)0x56000070)
- #define GPHDAT (*(volatile unsigned long *)0x56000074)
- #define GPHUP (*(volatile unsigned long *)0x56000078)
- /*UART registers*/
- #define ULCON0 (*(volatile unsigned long *)0x50000000)
- #define UCON0 (*(volatile unsigned long *)0x50000004)
- #define UFCON0 (*(volatile unsigned long *)0x50000008)
- #define UMCON0 (*(volatile unsigned long *)0x5000000c)
- #define UTRSTAT0 (*(volatile unsigned long *)0x50000010)
- #define UTXH0 (*(volatile unsigned char *)0x50000020)
- #define URXH0 (*(volatile unsigned char *)0x50000024)
- #define UBRDIV0 (*(volatile unsigned long *)0x50000028)
- /*interrupt registes*/
- #define SRCPND (*(volatile unsigned long *)0x4A000000)
- #define INTMOD (*(volatile unsigned long *)0x4A000004)
- #define INTMSK (*(volatile unsigned long *)0x4A000008)
- #define PRIORITY (*(volatile unsigned long *)0x4A00000c)
- #define INTPND (*(volatile unsigned long *)0x4A000010)
- #define INTOFFSET (*(volatile unsigned long *)0x4A000014)
- #define SUBSRCPND (*(volatile unsigned long *)0x4A000018)
- #define INTSUBMSK (*(volatile unsigned long *)0x4A00001c)
- /*external interrupt registers*/
- #define EINTMASK (*(volatile unsigned long *)0x560000a4)
- #define EINTPEND (*(volatile unsigned long *)0x560000a8)
- /*clock registers*/
- #define LOCKTIME (*(volatile unsigned long *)0x4c000000)
- #define MPLLCON (*(volatile unsigned long *)0x4c000004)
- #define UPLLCON (*(volatile unsigned long *)0x4c000008)
- #define CLKCON (*(volatile unsigned long *)0x4c00000c)
- #define CLKSLOW (*(volatile unsigned long *)0x4c000010)
- #define CLKDIVN (*(volatile unsigned long *)0x4c000014)
- /*PWM & Timer registers*/
- #define TCFG0 (*(volatile unsigned long *)0x51000000)
- #define TCFG1 (*(volatile unsigned long *)0x51000004)
- #define TCON (*(volatile unsigned long *)0x51000008)
- #define TCNTB0 (*(volatile unsigned long *)0x5100000c)
- #define TCMPB0 (*(volatile unsigned long *)0x51000010)
- #define TCNTO0 (*(volatile unsigned long *)0x51000014)
- #define GSTATUS1 (*(volatile unsigned long *)0x560000B0)
serial.h
- void uart0_init(void);
- void putc(unsigned char c);
- unsigned char getc(void);
- int isDigit(unsigned char c);
- int isLetter(unsigned char c);
head.S
- @******************************************************************************
- @ File:head.S
- @ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
- @******************************************************************************
- .extern main
- .text
- .global _start
- _start:
- Reset:
- ldr sp, = @ 设置栈指针,以下都是C函数,调用前需要设好栈
- bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启
- bl clock_init @ 设置MPLL,改变FCLK、HCLK、PCLK
- bl memsetup @ 设置存储控制器以使用SDRAM
- bl copy_steppingstone_to_sdram @ 复制代码到SDRAM中
- ldr pc, =on_sdram @ 跳到SDRAM中继续执行
- on_sdram:
- ldr sp, =0x34000000 @ 设置栈指针
- ldr lr, =halt_loop @ 设置返回地址
- ldr pc, =main @ 调用main函数
- halt_loop:
- b halt_loop
init.c
- /*
- * init.c: 进行一些初始化
- */
- #include "s3c24xx.h"
- void disable_watch_dog(void);
- void clock_init(void);
- void memsetup(void);
- void copy_steppingstone_to_sdram(void);
- /*
- * 关闭WATCHDOG,否则CPU会不断重启
- */
- void disable_watch_dog(void)
- {
- WTCON = ; // 关闭WATCHDOG很简单,往这个寄存器写0即可
- }
- #define S3C2410_MPLL_200MHZ ((0x5c<<12)|(0x04<<4)|(0x00))
- #define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))
- /*
- * 对于MPLLCON寄存器,[19:12]为MDIV,[9:4]为PDIV,[1:0]为SDIV
- * 有如下计算公式:
- * S3C2410: MPLL(FCLK) = (m * Fin)/(p * 2^s)
- * S3C2440: MPLL(FCLK) = (2 * m * Fin)/(p * 2^s)
- * 其中: m = MDIV + 8, p = PDIV + 2, s = SDIV
- * 对于本开发板,Fin = 12MHz
- * 设置CLKDIVN,令分频比为:FCLK:HCLK:PCLK=1:2:4,
- * FCLK=200MHz,HCLK=100MHz,PCLK=50MHz
- */
- void clock_init(void)
- {
- // LOCKTIME = 0x00ffffff; // 使用默认值即可
- CLKDIVN = 0x03; // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
- /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
- __asm__(
- "mrc p15, 0, r1, c1, c0, 0\n" /* 读出控制寄存器 */
- "orr r1, r1, #0xc0000000\n" /* 设置为“asynchronous bus mode” */
- "mcr p15, 0, r1, c1, c0, 0\n" /* 写入控制寄存器 */
- );
- /* 判断是S3C2410还是S3C2440 */
- if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
- {
- MPLLCON = S3C2410_MPLL_200MHZ; /* 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */
- }
- else
- {
- MPLLCON = S3C2440_MPLL_200MHZ; /* 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */
- }
- }
- /*
- * 设置存储控制器以使用SDRAM
- */
- void memsetup(void)
- {
- volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;
- /* 这个函数之所以这样赋值,而不是像前面的实验(比如mmu实验)那样将配置值
- * 写在数组中,是因为要生成”位置无关的代码”,使得这个函数可以在被复制到
- * SDRAM之前就可以在steppingstone中运行
- */
- /* 存储控制器13个寄存器的值 */
- p[] = 0x22011110; //BWSCON
- p[] = 0x00000700; //BANKCON0
- p[] = 0x00000700; //BANKCON1
- p[] = 0x00000700; //BANKCON2
- p[] = 0x00000700; //BANKCON3
- p[] = 0x00000700; //BANKCON4
- p[] = 0x00000700; //BANKCON5
- p[] = 0x00018005; //BANKCON6
- p[] = 0x00018005; //BANKCON7
- /* REFRESH,
- * HCLK=12MHz: 0x008C07A3,
- * HCLK=100MHz: 0x008C04F4
- */
- p[] = 0x008C04F4;
- p[] = 0x000000B1; //BANKSIZE
- p[] = 0x00000030; //MRSRB6
- p[] = 0x00000030; //MRSRB7
- }
- void copy_steppingstone_to_sdram(void)
- {
- unsigned int *pdwSrc = (unsigned int *);
- unsigned int *pdwDest = (unsigned int *)0x30000000;
- while (pdwSrc < (unsigned int *))
- {
- *pdwDest = *pdwSrc;
- pdwDest++;
- pdwSrc++;
- }
- }
serial.c
- #include "s3c24xx.h"
- #include "serial.h"
- #define TXD0READY (1<<2)
- #define RXD0READY (1)
- #define PCLK 50000000 // init.c中的clock_init函数设置PCLK为50MHz
- #define UART_CLK PCLK // UART0的时钟源设为PCLK
- #define UART_BAUD_RATE 115200 // 波特率
- #define UART_BRD ((UART_CLK / (UART_BAUD_RATE * 16)) - 1)
- /*
- * 初始化UART0
- * 115200,8N1,无流控
- */
- void uart0_init(void)
- {
- GPHCON |= 0xa0; // GPH2,GPH3用作TXD0,RXD0
- GPHUP = 0x0c; // GPH2,GPH3内部上拉
- ULCON0 = 0x03; // 8N1(8个数据位,无较验,1个停止位)
- UCON0 = 0x05; // 查询方式,UART时钟源为PCLK
- UFCON0 = 0x00; // 不使用FIFO
- UMCON0 = 0x00; // 不使用流控
- UBRDIV0 = UART_BRD; // 波特率为115200
- }
- /*
- * 发送一个字符
- */
- void putc(unsigned char c)
- {
- /* 等待,直到发送缓冲区中的数据已经全部发送出去 */
- while (!(UTRSTAT0 & TXD0READY));
- /* 向UTXH0寄存器中写入数据,UART即自动将它发送出去 */
- UTXH0 = c;
- }
- /*
- * 接收字符
- */
- unsigned char getc(void)
- {
- /* 等待,直到接收缓冲区中的有数据 */
- while (!(UTRSTAT0 & RXD0READY));
- /* 直接读取URXH0寄存器,即可获得接收到的数据 */
- return URXH0;
- }
- /*
- * 判断一个字符是否数字
- */
- int isDigit(unsigned char c)
- {
- if (c >= '' && c <= '')
- return ;
- else
- return ;
- }
- /*
- * 判断一个字符是否英文字母
- */
- int isLetter(unsigned char c)
- {
- if (c >= 'a' && c <= 'z')
- return ;
- else if (c >= 'A' && c <= 'Z')
- return ;
- else
- return ;
- }
main.c
- #include "serial.h"
- int main()
- {
- unsigned char c;
- uart0_init(); // 波特率115200,8N1(8个数据位,无校验位,1个停止位)
- while()
- {
- // 从串口接收数据后,判断其是否数字或子母,若是则加1后输出
- c = getc();
- if (isDigit(c) || isLetter(c))
- putc(c+);
- }
- return ;
- }
七、UART的更多相关文章
- am335x system upgrade kernel uart(七)
1 Scope of Document This document describes UART hardware design, uart driver porting 2 Re ...
- UART
一.协议部分: 协议部分转自:http://www.s8052.com/index.htm 串行通信的传送方向通常有三种: 1.为单工,只允许数据向一个方向传送: 2.半双工,允许数据向两个方向中的任 ...
- [ZigBee] 13、ZigBee基础阶段性回顾与加深理解——用定时器1产生PWM来控制LED亮度(七色灯)
引言:PWM对于很多软件工程师可能又熟悉又陌生,以PWM调节LED亮度为例,其本质是在每个周期都偷工减料一些,整体表现出LED欠压亮度不同的效果.像大家看到的七色彩灯其原理也类似,只是用3路PWM分别 ...
- 【转】Android bluetooth介绍(二): android blueZ蓝牙代码架构及其uart 到rfcomm流程
原文网址:http://blog.sina.com.cn/s/blog_602c72c50102uzoj.html 关键词:蓝牙blueZ UART HCI_UART H4 HCI L2CAP ...
- v3学院带你一次性认清UART、RS-232、RS-422、RS-485的区别
通讯问题,和交通问题一样,也有高速.低速.拥堵.中断等等各种情况.如果把串口通讯比做交通,UART比作车站,那么一帧的数据就好比汽车.汽车跑在路上,要遵守交通规则.如果是市内,一般限速30.40,而高 ...
- 八、mini2440裸机程序之UART(1)简单介绍【转】
转自:http://blog.csdn.net/shengnan_wu/article/details/8298869 一.概述 S3C2440通用异步接收和发送(UART)提供了三 ...
- SAM4E单片机之旅——8、UART初步
通信还是比让LED灯闪烁实用得多的. 这次试试使用UART,实现开发版和PC间的通信.功能比较简单,就是把PC发向开发版的内容发送回去.这次主要介绍一下UART的配置,至于通信,则使用较为简单的不断查 ...
- Android bluetooth介绍(两): android 蓝牙源架构和uart 至rfcomm过程
关键词:蓝牙blueZ UART HCI_UART H4 HCI L2CAP RFCOMM 版本号:基于android4.2先前版本 bluez内核:linux/linux3.08系统:an ...
- C与ARM汇编结合实现mini2440串口uart简单程序
最近学完了ARM的一些基础知识,开始在mini2440上开发一些简单的程序,串口发送程序是一开始涉及多个寄存器的例子,稍有繁多的步骤应该是开发过程中要慢慢适应的境况 下面的程序的目的是实现mini24 ...
随机推荐
- centos 7 修改系统屏幕分辨率
centos 7 修改系统屏幕分辨率,命令方式和图形方式的修改方法. 命令:xrandr 通过命令 xrandr 修改系统的分辨率,输入xrandr: bash [admin@localhost ~] ...
- linux学习之centos(三):mysql数据库的安装和配置
前言:mysql简介 说到数据库,我们大多想到的是关系型数据库,比如mysql.oracle.sqlserver等等,这些数据库软件在windows上安装都非常的方便,在Linux上如果要安装数据库, ...
- 我终于激活Windows Server2008 R2了!!
经过我不懈的努力,在重装两次系统后,我终于实现了win2008的KMS激活.这个方法可以避免虚拟机架设KMS服务器的麻烦.现将激活方法发布如下. 首先要选择安装的操作系统.Windows Server ...
- 网页性能优化之异步加载js文件
一个网页的有很多地方可以进行性能优化,比较常见的一种方式就是异步加载js脚本文件.在谈异步加载之前,先来看看浏览器加载js文件的原理. 浏览器加载 JavaScript 脚本,主要通过<scri ...
- html5 视频和音频
视频:html5支持视屏文件或者视屏流. html5使用video元素来播放视屏,支持的类型有OGG,MEPG 4,webM,但是不同的浏览器支持类型不同. src可以放置视屏文件的路径,可以使用元素 ...
- 封装caffe版的deeplab为库供第三方使用
1.解决deeplab编译问题 http://m.2cto.com/kf/201612/579545.html
- docker--Dockerfile--java
# AlpineLinux with a glibc-2.26-r0 and Oracle Java 7FROM alpine:3.6 MAINTAINER Anastas Dancha <an ...
- Codeforces Round #381 (Div. 2)C Alyona and mex
Alyona's mother wants to present an array of n non-negative integers to Alyona. The array should be ...
- MT【207】|ax^2+bx+c|中判别式$\Delta$的含义
已知$a,b\in R^+,a+b=2$且对任意的$x\in R$,均有$|2x^2+ax-b|\ge|x^2+cx+d|$则$\dfrac{d-4c}{cd}$的最小值______ 提示:注意到$\ ...
- Shell基础知识(二)
对于一个shell脚本来说,第一行是 "#!/bin/bash",这条命令中的 "#!" 告诉系统该用哪一款解释器来对该脚本进行解释,后面的"/bin ...