通用异步收发器UART
《嵌入式Linux应用完全开发手册》第2篇第11章总结归纳
本章目标
- 了解UART的原理
- 掌握S3C2410/S3C2440中UART的使用
UART原理以及UART部件使用方法
UART原理说明
通用异步收发器简称UART(Universal Asynchronous Reciver Transmitter),它用来传输串行数据。发送数据时,CPU将并行数据写入UART,UART按照一定的格式在一根电线上发出;接收数据时,UART检测另一根电线上的信号,将串行收集放在缓冲区中,CPU即可读取UART获得这些数据。UART之间以全双工方式传输数据,最精简的连线方法只有三根电线,TxD用于发送数据,RxD用于接收数据,GnD用于给双方提供参考电平。
UART使用标准的TTL/CMOS逻辑电平(0-5V、0-3.3V、0-2.5V、0-1.8V)来表示数据,高电平表示1,低电平表示0。为了增强数据的抗干扰能力、提高传输长度,通常将TTL/CMOS逻辑电平转换为RS-232逻辑电平,312V表示0,-3-12V表示1。
TxD、RxD数据线以“位”为最小单位传输数据。帧(Frame)由具有完整意义、不可分割的若干位组成,它包含开始位、数据位、校验位(需要的话)和停止位。发送数据之前,UART之间要约定好数据的传输速率(即每位所占据的时间,其倒数称为波特率)、数据的传输格式(即有多少个数据位、是否使用校验位、奇校验还是偶校验、有多少个停止位)。
数据传输流程如下:
- 平时数据线处于空闭状态(1状态)。
- 当要发送数据时,UART改变TxD数据线的状态(变为0状态),并维持1位的时间,这样接收方检测到开始位之后,再等待1.5位的时间就开始一位一位检测数据线的状态得到所传输的数据。
- UART一帧中可以有5、6、7或8位得数据,发送方一位一位地改变数据线的状态将它们发送出去,首先发送最低位。
- 如果使用校验功能,UART在发送完数据位之后,还要发送一个校验位。有两种校验方法:奇校验、偶校验—数据位连同校验位中“1”的数目等于奇数还是偶数。
- 最后,发送停止位,数据线恢复到空闭状态(1状态)。停止位的长度有3种:1位、1.5位、2位。
下图演示了UART使用7个数据位、偶校验、2个停止位的格式传输字符’A‘(二进制格式为0b1000001)时,TTL/CMOS逻辑电平、RS232逻辑电平对应的波形。
S3C2410/S3C2440 UART的特性
S3C2410/S3C2440 中UART的特性相似,有3个独立的通道,每个通道都可以工作于中断模式或DMA模式,即UART可以发出中断或DMA请求以便在CPU、UART之间传输数据。S3C2410/S3C2440 UART由波特率发生器、发送器、接收器和控制逻辑组成。
使用系统时钟时,S3C2410的UART波特率可以达到230.4Kbit/s,S3C2440则可以达到115.2Kbit/s;如果使用UEXTCLK引脚提供的外部时钟,则可以达到更高的波特率。波特率可以通过编程控制。
S3C2410 UART的每个控制通道都有16字节的发送FIFO和16字节的接收FIFO,S3C2440 UART的FIFO深度为64。发送数据时,CPU先将数据写入发送FIFO中,然后UART控制器会自动将FIFO中的数据复制到“发送移位器(Transmit Shifter)”中,发送移位器将数据一位一位的发送到TxD数据线上。接收数据时,“接收移位器(Receive Shifter)”,将RxD数据线上的数据一位一位的接收进来,然后复制到接收FIFO中,CPU即可从中读取数据。
S3C2410/S3C2440 UART的每个通道支持的停止位有1位、2位,数据位有5、6、7或8位,支持校验功能,另外还有红外发送/接收功能。
S3C2410/S3C2440 UART结构如下图所示:
S3C2410/S3C2440 UART的使用
在使用UART之前需要设置波特率、传输格式;对于S3C2410/S3C2440,还要选择所涉及管脚为UART功能,选择UART通道的工作模式为中断模式还是DMA模式。设置好之后,往某个寄存器写入数据即可发送。可以通过查询状态寄存器或设置中断来获知数据是否已经发送完毕、是否已经接收到数据。
将所涉及的UART通道管脚设为UART功能
比如UART通道0中,GPH2、GPH3分别用作TXD0、RXD0,要使用UART通道0时,先设置GPHCON寄存器将GPH2、GPH3引脚的功能设为TXD0、RXD0。
UBRDIVn寄存器(UART BAUD RATE DIVISOR):设置波特率
S3C2410 UART的时钟源有两种选择:PCLK、UEXTCLK;S3C2440的时钟源有三种选择:PCLK、UEXTCLK、FCLK/n,其中n通过UCON0UCON2联合设置。2,对应3个UART通道)。
根据给定的波特率、所选择的时钟源的频率,可以通过以下公式计算UBRDIVn寄存器(n为0
1 | UBRDIVn = (int)(UART clock/(baud rate x 16)) - 1 |
上述公式计算出来的UBRDIVn寄存器值不一定是整数,只要误差在1.87%之内即可。误差计算公式如下:
1 | tUPCLK = (UBRDIVn + 1) x 16 x 1Frame / (UART clock) //tUPCLK 实际的UART时钟 |
ULCONn寄存器(UART LINE CONTROL):设置传输格式
ULCONn寄存器(n为0~2)格式如下表所示:
功能 | 位 | 说明 |
---|---|---|
数据位宽度 | [1:0] | 0b00:5位 0b01:6位 0b10:7位 0b11:8位 |
停止位宽度 | [2] | 0:一帧中有一个停止位 1:一帧中有两个停止位 |
校验模式 | [5:3] | 设置校验位的产生方法、检验方法: 0b0xx:无校验 0b100:奇校验 0b101:偶校验 0b110:发送数据时强制设为1,接收数据时检查是否为1 0b111:发送数据时强制设为0,接收数据时检查是否为0 |
红外模式 | [6] | 0:正常模式 1:红外模式 |
UART通道被设为红外模式时,其串行数据的波形与正常模式稍有不同。
ULCONn寄存器(UART CONTROL)
ULCONn寄存器用于选择UART时钟源、设置UART中断方式等。S3C2410 UART的时钟源有两种选择:PCLK、UEXTCLK;S3C2440的时钟源有三种选择:PCLK、UEXTCLK、FCLK/n。所以在时钟源的选择与设置方面稍有不同。
S3C2410的ULCONn寄存器格式如下表所示:
功能 | 位 | 说明 |
---|---|---|
接收模式 | [1:0] | 选择如何从UART接收缓冲区中读取数据。 0b00:禁止接收数据 0b01:中断方式或者查询方式 0b10:DMA0请求(UART0) DMA3请求(UART2) 0b11:DMA1请求(UART1) |
发送模式 | [3:2] | 选择如何将数据发送到UART发送缓存区。 0b00:禁止发送数据 0b01:中断方式或者查询方式 0b10:DMA0请求(UART0) DMA3请求(UART2) 0b11:DMA1请求(UART1) |
自环模式 | [5] | 自环模式就是将TxDn和RxDn在内部相连,用于自发自收。 0:正常模式 1:自环模式 |
接收错误状态中断使能 | [6] | 用于使能当发生错误时(帧错误、溢出)时,产生中断。 0:出错时不产生中断 1:出错时产生中断 |
接收超时使能 | [7] | 当使用UART FIFO时,用于使能/禁止接收超时的中断。 0=禁止 1=使能 |
接收中断方式 | [8] | 如下情况发生时,将产生接收中断。 不使用FIFO时,接收到一个数据; 使用FIFO时,FIFO中的数据达到RxFIFO的触发阈值。 中断方式如下设置。 0:脉冲 1:电平 |
发送中断方式 | [9] | 如下情况发生时,将产生发送中断。 不使用FIFO时,发送缓冲区变空; 使用FIFO时,FIFO中的数据达到TxFIFO的触发阈值。 中断方式如下设置。 0:脉冲 1:电平 |
时钟选择 | [10] | 选择UART时钟源。 0:PCLK UEXTCLK |
S3C2440的UCONn寄存器在UART时钟的选择方面与S3C2410有所不同,从位[10]往上的位含义不一样,并且原来的位[4]用于选择是否发出“break”信号,这些位的含义如下表所示:
功能 | 位 | 说明 |
---|---|---|
“break”信号 | [4] | 设置此位时,UART会在一帧的时间内发出一个“break”信号。 0:正常发送 1:发出“break”信号 |
时钟选择 | [11:10] | 选择UART时钟源。 0b00/0b10:PCLK 0b01:UEXTVLK 0b11:FCLK/n |
FCLK分频率系数 | [15:12] | 用来设置“FCLK/n”中的n值 |
ULCON0、ULCON1、ULCON2这3个寄存器的位[15:12]一起用来确定n值,它们的意义如下。
- ULCON2[15]:“FCLK/n”使能位。
它等于0时,禁止使用“FCLK/n”作为UART时钟源;等于1时,可以用作UART时钟源。 - n值的设置。
ULCON0[15:12]、ULCON1[15:12]、ULCON2[14:12]三者用于设置n值,当其中一个被设置为非0值时,其他两个必须为0。- n值处于7~12时,UART时钟=FCLK/(divider + 6),divider为ULCON0[15:12]的值,大于0。
- n值处于22~36时,UART时钟=FCLK/(divider + 21),divider为ULCON1[15:12]的值,大于0。
- n值处于37~43时,UART时钟=FCLK/(divider + 36),divider为ULCON2[14:12]的值,大于0。
- ULCON0[15:12]、ULCON1[15:12]、ULCON2[14:12]都等于0时,UART时钟:FCLK/44。
UFCONn寄存器(UART FIFO CONTROL)、UFSTATn寄存器(UART FIFO STATUS)
UFCONn寄存器用于设置是否使用FIFO,设置各FIFO的触发阈值,即发送FIFO中有多少个数据产生中断、接收FIFO中有多少个数据产生中断。并可以通过设置UFCONn寄存器来复位各个FIFO。
读取UFSTATn寄存器可以知道各个FIFO是否已经满、其中有多少个数据。
不适用FIFO时,可以认为FIFO的深度是1,使用FIFO时,S3C2410的FIFO深度是16,S3C2440的深度是64。
UMCONn寄存器(UART MODEM CONTROL)、UMSTATn寄存器(UART MODEM STATUS)
这两类寄存器用于流量控制。
UTRSTATn寄存器(UART TX/RX STATUS)
UTRSTATn寄存器用来表明数据是否已经发送完毕、是否已经接收到数据。格式如下表所示。缓冲区其实就是FIFO,只不过不适用FIFO时,FIFO的深度为1。
功能 | 位 | 说明 |
---|---|---|
接收缓冲区数据就绪 | [0] | 当接收到数据时,此位被自动设为1 |
发送缓冲区空 | [1] | 当发送缓冲区没有数据时,此位被自动设为1 |
发送器空 | [2] | 当发送缓冲区中没有数据,并且最后一个数据也已经发送出去,此位被自动设为1 |
UERSTATn寄存器(UART ERROR STATUS)
用来表示各种错误是否发生,位[0]~位[3]为1时分别表示溢出错误、校验错误、帧错误、检测到“break”信号。读取这个寄存器时,它会自动清0。
需要注意的是,接收数据时如果使用FIFO,则UART内部会使用一个“错误FIFO”来表明接收FIFO中哪个数据在接收过程中发生了错误。CPU只有在读出这个错误的数据时,才会察觉到发生了错误。要想清除“错误FIFO”,则必须读出错误的数据,并读出UERSTATn寄存器。
UTXHn寄存器(UART TRANSMIT BUFFER REGISTER)
CPU将数据写入这个寄存器,UART即会将它保存到缓冲区,并自动发送出去。
URXHn寄存器(UART RECEIVER BUFFER REGISTER)
当UART接收到数据,CPU读取这个寄存器,即可获得数据。
UART操作实例
代码详解
本示例代码的目的是在串口上输出一串字符,单板接收到后将它的ASCII码加1后从串口输出。
首先设置MPLL提高系统时钟,令PCLK为50MHz,UART将选择PCLK为时钟源。将代码复制到SDRAM中之后,调用main函数。重点在于UART0的初始化、收发数据,这由3个函数来实现:uart0_init、getc和putc。
UART初始化
uart0_init函数代码如下:
1 |
|
发送字符的函数
本实例不使用FIFO,发送字符前,首先判断上一个字符是否已经被发送出去。如果没有,则不断查询UTRSTAT0寄存器的位[2],当它为1时表示已经发送完毕。于是,即可向UTXH0寄存器中写入当前要发送的字符。代码如下(宏TXD0READY被定义为(1 << 2)):
1 | /* |
接收字符的函数
试图读取数据前,先查询UTRSTAT0寄存器的位[1],当它为1时表示接收缓冲区有数据,于是,即可读取URXH0得到数据。
1 | /* |
主函数
在main函数中,初始化UART0之后,即不断读取串口数据,并判断它是否为数字或字母。如果是的话,就将它加1后从串口输出。
1 |
|
测试方式
首先使用串口将开发板的COM0和PC的串口相连,打开PC上的串口工具(推荐使用SecureCRT),设置其波特率为115200、8N1(8个数据位,无校验位,1个停止位)。然后将编译生成的uart.bin文件烧入NAND Flash后上电运行。最后在PC上的串口工具中输入数字或者字母,可以看到输出另一个字符(加1);如果输入其他字符,则无输出。