本文关于UART的介绍,首先借助百度百科,进行基础部分阐述
一、UART基础知识
定义:通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),通常称作UART,是一种异步收发传输器。主要功能实现串并行数据的转换,具体实物表现为模块化芯片,常常被用来作为嵌入式芯片的外设模块,与外部设备进行通信。
UART常常也被理解为一种通信协议,用来实现异步串行通信,规定了数据传输格式和波特率,多是数据链路层的概念。常常被用来和UART做对比的RS-232和RS-485则规定了数据通信的电气接口,更多的是物理层的概念。
二、UART基本结构
数据发送的思想是,当启动字节发送时,通过TxD先发起始位,然后发数据位和奇偶数校验位,最后再发停止位,发送过程由发送状态机控制,每次中断只发送1个位,经过若干个定时中断完成1个字节帧的发送。
数据接收的思想是,当不在字节帧接收过程时,每次定时中断以3倍的波特率监视RxD的状态,当其连续3次采样电平依次为1、0、0时,就认为检测到了起始位,则开始启动一次字节帧接收,字节帧接收过程由接收状态机控制,每次中断只接收1个位,经过若干个定时中断完成1个字节帧的接收。
四、UART工作原理
(1)发送与接收
发送逻辑对从发送FIFO 读取的数据执行“并→串”转换。控制逻辑输出起始位在先的串行位流,并且根据控制寄存器中已编程的配置,后面紧跟着数据位(注意:最低位 LSB 先输出)、奇偶校验位和停止位。
在检测到一个有效的起始脉冲后,接收逻辑对接收到的位流执行“串→并”转换。此外还会对溢出错误、奇偶校验错误、帧错误和线中止(line-break)错误进行检测,并将检测到的状态附加到被写入接收FIFO 的数据中。
(2)波特率产生
波特率除法器(baud-rate divisor)是一个22 位数,它由16 位整数和6 位小数组成。波特率发生器使用这两个值组成的数字来决定位周期。通过带有小数波特率的除法器,在足够高的系统时钟速率下,UART 可以产生所有标准的波特率,而误差很小。
(3)基于FIFO的数据收发
发送时,数据被写入发送FIFO。如果UART 被使能,则会按照预先设置好的参数(波特率、数据位、停止位、校验位等)开始发送数据,一直到发送FIFO 中没有数据。一旦向发送FIFO 写数据(如果FIFO 未空),UART 的忙标志位BUSY 就有效,并且在发送数据期间一直保持有效。BUSY 位仅在发送FIFO 为空,且已从移位寄存器发送最后一个字符,包括停止位时才变无效。即 UART 不再使能,它也可以指示忙状态。
在UART 接收器空闲时,如果数据输入变成“低电平”,即接收到了起始位,则接收计数器开始运行,并且数据在Baud16 的第8 个周期被采样。如果Rx 在Baud16 的第8 周期仍然为低电平,则起始位有效,否则会被认为是错误的起始位并将其忽略。
如果起始位有效,则根据数据字符被编程的长度,在 Baud16 的每第 16 个周期对连续的数据位(即一个位周期之后)进行采样。如果奇偶校验模式使能,则还会检测奇偶校验位。
最后,如果Rx 为高电平,则有效的停止位被确认,否则发生帧错误。当接收到一个完整的字符时,将数据存放在接收FIFO 中。
(4)中断控制
出现以下情况时,可使UART 产生中断:
1.FIFO 溢出错误
2.线中止错误(line-break,即Rx 信号一直为0 的状态,包括校验位和停止位在内)
3.奇偶校验错误
4.帧错误(停止位不为1)
5.接收超时(接收FIFO 已有数据但未满,而后续数据长时间不来)
6.发送
7.接收
由于所有中断事件在发送到中断控制器之前会一起进行“或运算”操作,所以任意时刻 UART 只能向中断产生一个中断请求。通过查询中断状态函数,软件可以在同一个中断服务函数里处理多个中断事件(多个并列的if 语句)。
五、UART的FIFO操作
FIFO 是“First-In First-Out”的缩写,意为“先进先出”,是一种常见的队列操作。 Stellaris 系列ARM 的UART 模块包含有2 个16 字节的FIFO:一个用于发送,另一个用于接收。可以将两个FIFO 分别配置为以不同深度触发中断。可供选择的配置包括:1/8、 1/4、1/2、3/4 和7/8 深度。例如,如果接收FIFO 选择1/4,则在UART 接收到4 个数据时产生接收中断。
发送FIFO的基本工作过程: 只要有数据填充到发送FIFO 里,就会立即启动发送过程。由于发送本身是个相对缓慢的过程,因此在发送的同时其它需要发送的数据还可以继续填充到发送 FIFO 里。当发送 FIFO 被填满时就不能再继续填充了,否则会造成数据丢失,此时只能等待。这个等待并不会很久,以9600 的波特率为例,等待出现一个空位的时间在1ms 上下。发送 FIFO 会按照填入数据的先后顺序把数据一个个发送出去,直到发送 FIFO 全空时为止。已发送完毕的数据会被自动清除,在发送FIFO 里同时会多出一个空位。
接收FIFO的基本工作过程: 当硬件逻辑接收到数据时,就会往接收FIFO 里填充接收到的数据。程序应当及时取走这些数据,数据被取走也是在接收FIFO 里被自动删除的过程,因此在接收 FIFO 里同时会多出一个空位。如果在接收 FIFO 里的数据未被及时取走而造成接收FIFO 已满,则以后再接收到数据时因无空位可以填充而造成数据丢失。
收发FIFO 主要是为了解决UART 收发中断过于频繁而导致CPU 效率不高的问题而引入的。在进行 UART 通信时,中断方式比轮询方式要简便且效率高。但是,如果没有收发 FIFO,则每收发一个数据都要中断处理一次,效率仍然不够高。如果有了收发FIFO,则可以在连续收发若干个数据(可多至14 个)后才产生一次中断然后一并处理,这就大大提高了收发效率。
完全不必要担心FIFO 机制可能带来的数据丢失或得不到及时处理的问题,因为它已经帮你想到了收发过程中存在的任何问题,只要在初始化配置UART 后,就可以放心收发了, FIFO 和中断例程会自动搞定一切。
六、UART的回环模式
UART 可以进入一个内部回环(Loopback)模式,用于诊断或调试。在回环模式下,从Tx 上发送的数据将被Rx 输入端接收。
七、UART与串行红外协议
在某些 Stellaris 系列 ARM 芯片里,UART 还包含一个 IrDA 串行红外(SIR)编码器/ 解码器模块。IrDA SIR 模块的作用是在异步UART数据流和半双工串行SIR 接口之间进行转换。片上不会执行任何模拟处理操作。SIR 模块的任务就是要给UART 提供一个数字编码输出和一个解码输入。UART 信号管脚可以和一个红外收发器连接以实现IrDA SIR物理层连接。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
完成基础部分的介绍之后,我们以Telink的TLSR8255F512为例(又称为5562),具体介绍该模块的组成原理及使用方法
5562的UART模块是通过UART Tx和UART Rx接口实现全双工模式的数据传输和接收;硬件流控是通过RTS和CTS接口实现的。
如图所示,数据是先通过MCU或者DMA写入到发送buffer,再通过发送引脚将数据传输给其他设备;接收数据时,数据先是通过接收引脚将数据存放到接收buffer中,再被MCU或者DMA读取。
当5562的UART模块的接收buffer接近饱和的时候,UART模块就会通过RTS发送level signal(configurable)给发送端,阻止数据发送;反之,当UART模块通过CTS引脚接收到来自接收端的level signal(configurable),也会停止数据的发送
在没有使用DMA模式的情况下,数据的发送或者接收会通过循环访问4个字节的寄存器来实现。
寄存器uart_clk_div[14:0]用来配置时钟分频因子,计算公式为:
uart_sclk=sclk/(uart_clk_div[14:0]+1)
寄存器uart_clk_div[15]用来使能时钟分频器,只有使能了时钟分频器之后,才能通过时钟分频因子对系统时钟进行分频,从而获得UART模块的时钟。
寄存器uart ctrl0[3:0]用来配置位宽(bwpc>2),设置波特率,计算公式为:
Baudrate = uart_sclk/(uart ctrl0[3:0]+1)
根据sclk=(uart_clk_div[14:0]+1)*(uart ctrl0[3:0]+1)*Baudrate可知:在编写软件代码时,为获得标准的波特率,必须适当配置uart_clk_div[14:0]和uart ctrl0[3:0]
寄存器Uart ctrl0[5:4]用来使能UART的Tx和Rx的DMA模式。关于DMA模式做如下介绍:
常规工作情况下,UART的数据收发可由MCU控制UART的内部FIFO来完成,但具体不论是以中断还是以查询的形式,过程中总是会占用MCU的时间,即便FIFO的有效利用率达到最高时也是如此。这样,在实际应用中,当串口数据包量较大时,UART的发送过程会占用MCU很长时间,其中大多数时间是在等待一次数据传输的完成。为了节省这段时间,提高MCU的使用效率,以完成更多的数据处理,将会用到DMA控制器。
DMA(英文全称:Direct Memory Access)直接内存访问,是指不经由MCU而直接从内存中存取数据的数据交换模式。当UART使用DMA控制器控制发送过程时,MCU会将发送的控制权交给DMA控制器,从而在数据发送的时期间去处理其它过程。
UART_DmaInit();
5562的UART模块在使用DMA模式时,需要先通过配置Uart ctrl0[5:4]使能Tx和Rx的DMA模式;再者,通过配置寄存器DMA0MODE[0]和DMA1MODE[0]为UART的发送和接收选择相应的DMA 通道channel;
UART_RecBuffInit(recBuff,16);
完成上述配置之后,需要进行DMA模式下的接收buffer的配置,通过配置DMA0AL[7:0],DMA0AM[7:0],DMA0AH[2:0]来实现DMA模式下接收buffer起始地址的配置;接下来配置寄存器DMA0SIZE[7:0]设置DMA模式下的buffer大小:DMA0SIZEx16,因此在设置时,需要先除以16字节!
IRQ_UartDmaIrqEnable(FLD_UART_IRQ_RX|FLD_UART_IRQ_TX);
配置UART中断屏蔽寄存器DMAMASK[1:0],根据需要分别进行接收中断屏蔽寄存器DMAMASK[0]和发送中断屏蔽寄存器DMAMASK[1]的配置([0]和[1]分别对应通道0和通道1,这是之前已经选择好的);最后,通过配置MASK_0[4]=1使能DMA中断。
至此,完成了对UART的DMA模式的基本配置,现在我们来看一下,UART的发送函数UART_Send(unsigned char* Addr)
如上图所示,DMA模式下,数据的发送原理:存储在SRAM中的数据,在DMA控制器作用下开始执行数据搬运工作:
1.将数据从SRAM中搬运到UART,搬运完成后产生0x526:DMA1 packetx transferred flag=1;
2.再由UART将数据发送出去,发送完成后产生0x9e:Txdone:irq_sts[0]=1;
在操作第一步时,首先设置SRAM buffer size,该设置是通过所发送数据的前4个字节实现的,硬件默认将所发送数据的前4个字节作为SRAM buffer size ,比如发送的数据字节存放在trans_buf[16]数组中,那么trans_buf[0]~trans_buf[3]依次存放SRAM buffer size 的低字节到高字节,trans_buf[0]=0x6,trans_buf[1]=0x00,trans_buf[2]=0x00,trans_buf[3]=0x00,即SRAM buffer size=6,数据发送从trans_buf[4]开始,总共6个字节;
完成SRAM buffer size的设置之后,需要通过配置0xc24:DMAREADY0[1]=1启动DMA数据包搬运工作;
第二步操作由UART模块自动完成,我们只需要在再次发送前检查发送完成标识位0x9e:Txdone:irq_sts[0]即可。
------------------------------------------------------------------------------------------------------------------------------------
总结一下,DMA模式下所用到的配置寄存器如下:
1.与波特率相关的寄存器:uart_clk_div[14:0],uart ctrl0[3:0]
(关键公式:sclk=(uart_clk_div[14:0]+1)*(uart ctrl0[3:0]+1)*Baudrate)
2.与FIFO相关的寄存器:uart_data_buf0~uart_data_buf3
(4层FIFO,常规模式下循环访问它来进行数据收发;DMA模式下,由DMA控制,自动访问实现数据收发,不需设置)
3.与DMA模式相关的寄存器:
1) Uart ctrl0[5:4],DMA0MODE[0]和DMA1MODE[0]
(前者使能Rx和Tx的DMA模式;后者为Rx和Tx配置DMA通道,这里分别配置的是通道0和通道1)
2) DMA0AL[7:0],DMA0AM[7:0],DMA0AH[2:0],DMA0SIZE[7:0]
(前三个是进行DMA模式下的接收buffer的首地址配置;后者是进行接收buffer大小配置)
3) DMAMASK[1:0],MASK_0[4]
(前者是开启通道0和通道1的中断屏蔽寄存器;后者是开启DMA中断)
4.与发送相关的寄存器:
1) DMA1AL[7:0],DMA1AM[7:0],DMA1AH[2:0]
(设置待发送缓存区的首地址;硬件默认将所发送数据的前4个字节作为SRAM buffer size,自动偏移4个地址作为待发
送数据的首地址)
2) 设置DMAREADY0[1]=1,来启动DMA数据的搬运工作,此时,UART就会在DMA的控制下完成数据的发送工作
3) 两个重要的标识位(再次发送时只需要判断发送完成标识位即可):
(1)将数据从SRAM中搬运到UART,搬运完成后产生0x526:DMA1 packetx transferred flag=1;
(2)再由UART将数据发送出去,发送完成后产生0x9e:Txdone:irq_sts[0]=1(只读);
注意:标识位在被读取完成之后是被自动清除的------------------------------------------------------------------------------------------------------------------------------------
以上详细描述了整个UART的DMA模式下寄存器配置使用和基本工作原理,