本文将以Exynos4412的UART掌握器为根本,讲解UART的事理以及驱动程序如何编写。
UART是什么UART是通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),常日称作UART,是一种异步收发传输器,是设备间进行异步通信的关键模块。UART卖力处理数据总线和串行口之间的串/并、并/串转换,并规定了帧格式;通信双方只要采取相同的帧格式和波特率,就能在未共享时钟旗子暗记的情形下,仅用两根旗子暗记线(Rx 和Tx)就可以完成通信过程,因此也称为异步串行通信。UART总线双向通信,可以实现全双工传输和吸收。在嵌入式设计中,UART用于主机与赞助设备通信,如汽车音响与外接AP之间的通信,与PC机通信包括与监控调试器和其它器件,如EEPROM通信。
常日须要加入一个得当的电平转换器,如SP3232E、SP3485,UART还能用于RS-232、RS-485 通信,或与打算机的端口连接。UART 运用非常广泛,手机、工业掌握、PC 等运用中都要用到UART。
UART通信办法
UART利用的是 异步,串行通信办法。
串行通信
串行通信是指利用一条传输线将资料一位位地顺序传送。好比是一列纵队,每个数据元素依次纵向排列。如下图所示,传输时一个比特一个比特的串行传输,每个时钟周期传输一个比特,这种传输办法相比拟较大略,速率较慢,但是利用总线数较少,常日一根吸收线,一根发送线即可实现串行通信。
它的缺陷是要增加额外的数据来掌握一个数据帧的开始和结束。特点是通信线路大略,利用大略的线缆就可实现通信,降落本钱,适用于远间隔通信,但传输速率慢的运用处所。
并行通信
并行通信好比一排横队,齐头并进同时传输。这种通信办法每个时钟周期传输的数据量和其总线宽度成正比,但是实现较为繁芜。
异步通信
异步通信以一个字符为传输单位,通信中两个字符间的韶光间隔多少是不固定的,然而在同一个字符中的两个相邻位间的韶光间隔是固定的。
在异步通信技能中,数据发送方和数据吸收方没有同步时钟,只有数据旗子暗记线,只不过发送端和吸收端会按照协商好的协议(固定频率)来进行数据采样。数据发送方以每秒钟57600bits的速率发送数据,吸收方也以57600bits的速率去吸收数据,这样就可以担保数据的有效和精确。常日异步通信中利用波特率(Baud-Rate)来规定双方传输速率,其单位为bps(bits per second每秒传输位数)。
同步通信
在发送数据旗子暗记的时候,会同时送出一根同步时钟旗子暗记, 用来同步发送方和吸收方的数据采样频率。如下图所示,同步通信时,旗子暗记线1是一根同步时钟旗子暗记线,以固定的频率进行电平的切换,其频率周期为t,在每个电平的上升沿之后进行对同步送出的数据旗子暗记线2进行采样(高电平代表1,低电平代表0),根据采样数据电平高低取得输出数据信息。如果双方没有同步时钟的话,那么吸收方就不知道采样周期,也就不能正常的取得数据信息。
帧格式
数据传送速率用波特率来表示,即每秒钟传送的二进制位数。例如数据传送速率为120字符/秒,而每一个字符为10位(1个起始位,7个数据位,1个校验位,1个结束位),则其传送的波特率为10×120=1200字符/秒=1200波特。数据通信格式如下图:
个中各位的意义如下:
起始位:先发出一个逻辑”0”旗子暗记,表示传输字符的开始。数据位:可以是5~8位逻辑”0”或”1”。如ASCII码(7位),扩展BCD码(8位)。小端传输校验位:数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验)停滞位:它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。空闲位:处于逻辑“1”状态,表示当前哨路上没有资料传送。
注:异步通信是按字符传输的,吸收设备在收到起始旗子暗记之后只要在一个字符的传输韶光内能和发送设备保持同步就能精确吸收。下一个字符起始位的到来又使同步重新校准(依赖检测起始位来实现发送与吸收方的时钟自同步的)
关于RS-232、RS-422、RS-485等标准,大家可以参考文章《一篇文章理解什么是串口,UART、RS-232、RS-422、RS-485 》
Exynos4412 Uart
本文谈论UART 是基于Cortex-A9架构的Exynos4412 为例。
特性
Exynos4412 中UART,有4 个独立的通道,每个通道都可以事情于中断模式或DMA 模式,即UART 可以发出中断或 DMA 要求以便在UART 、CPU 间传输数据。利用系统时钟时,Exynos4412 的 UART 波特率可以达到 4Mbps 。每个UART通道包含两个FIFO用来吸收和发送:
通道 0有 256 字节的发送 FIFO 和 256 字节的吸收FIFO
通道 1、4有 64 字节的发送 FIFO 和 64 字节的吸收FIFO
通道 2、3有 16 字节的发送FIFO 和 16 字节 的吸收 FIFO 。
UART include:
波特率可以通过编程进行 。
红外吸收/发送
每个通道支持停滞位有 1位、 2位
数据位有 5、6、7或 8位
每个UART还包括
波特率发生器、发送器、吸收器、掌握逻辑组成。
Uart掌握器功能模块
每个UART包含一个波特率产生器,发送器,吸收器和一个掌握单元,如上图所示:
发送数据CPU 先将数据写入发送FIFO 中,然后 UART 会自动将FIFO 中的数据复制到“发送移位器” (Transmit Shifter )中,发送移位器将数据一位一位地发送到 TxDn 数据线上 (根据设定的格式,插入开始位 、较验和停滞)。
吸收数据“移位器” (Receive Shifter )将 RxDn 数据线上的数据一位一位的吸收进来,然后复制到FIFO 中, CPU即可从中读取数据。
UART因此异步办法实现通信的,其采样速率由波特率决定,波特率产生器的事情频率可以由PCLK(外围设备频率),FCLK/n(CPU事情频率的分频),UEXTCLK(外部输入时钟)三个时钟作为输入频率,波特率设置寄存器是可编程的,用户可以设置其波特率决定发送和吸收的频率。发送器和吸收器包含了64Byte的FIFO和数据移位器。UART通信是面向字节流的,待发送数据写到FIFO之后,被拷贝到数据移位器(1字节大小)里,数据通过发送数据管脚TXDn发出。同样道理,吸收数据通过RXDn管脚来吸收数据(1字节大小)到吸收移位器,然后将其拷贝到FIFO吸收缓冲区里。(1)数据发送发送的数据帧可编程的,它的一个帧长度是用户指定的,它包括一个开始位,5~8个数据位,一个可选的奇偶校验位和1~2个停滞位,数据帧格式可以通过设置ULCONn寄存器来设置。发送器也可以产生一个终止旗子暗记,它是由一个全部为0的数据帧组成。在当前发送数据被完备传输完往后,该模块发送一个终止旗子暗记。在终止旗子暗记发送后,它可以连续通过FIFO(FIFO)或发送保持寄存器(NON-FIFO)发送数据。(2)数据吸收同样吸收真个数据也是可编程的,吸收器可以侦测到溢出错误奇偶校验缺点,帧缺点和终止条件,每个缺点都可以设置一个缺点标志。• 溢出错误 :在旧数据被读取到之前,新数据覆盖了旧数据• 奇偶校验缺点:吸收器侦测到了吸收数据校验结果失落败,吸收数据无效• 帧缺点 :吸收到的数据没有一个有效的停滞位,无法剖断数据帧结束• 终止条件 :RxDn吸收到保持逻辑0状态持续长于一个数据帧的传输韶光
(3)自动流控AFC(Auto Float Control)UART0和UART1支持有nRTS和nCTS的自动流控。在AFC情形下,通信双方nRTS和nCTS管脚分别连接对方的nCTS和nRTS管脚。通过软件掌握数据帧的发送和吸收。在开启AFC时,发送端吸收发送前要判断nCTS旗子暗记状态,当吸收到nCTS激活旗子暗记时,发送数据帧。该nCTS管脚连接对方nRTS管脚。吸收端在准备吸收数据帧前,其吸收器FIFO有大于32个字节的空闲空间,nRTS管脚会发送激活旗子暗记,当其吸收FIFO小于32个字节的空闲空间,nRTS必须置非激活状态。
选择时钟源
Exynos4412 UART的时钟源有八种选择:XXTI 、XusbXTI 、SCLK_HDMI24M 、SCLK_USBPHY0 、 SCLK_HDMIPHY 、SCLKMPLL_USER_T 、SCLKEPLL 、SCLKVPLL ,由 CLK_SRC_PERIL0 寄存器掌握。选择好时钟源后,还可以通过 DIVUART0 ~4设置分频系数,由 CLK_DIV_PERIL0 寄存器掌握。从分频器得到的时钟被称为SCLK UART 。SCLK UART 经由上图中的“ UCLK Generator”后,得到UCLK ,它的频率便是UART 的波特率。“ Generator UCLK Generator ”通过这 2个寄存器来设置:UBRDIVn(UART BAUD RATE DIVISOR) 、UFRACVALn 。
UART配置寄存器
ULCONn
bite [6] 红外模式选择串口0是否利用红外模式:0 = 正常通信模式1 = 红外通信模式
bite [5:3] 校验模式设置串口0在数据吸收和发送时采取的校验办法:0xx = 无校验100 = 奇校验101 = 偶校验110 = 逼迫校验/检测是否为1111 = 逼迫校验/检测是否为0
[2] 停滞位设置串口0停滞位数:0 = 每个数据帧一个停滞位1 = 每个数据帧二个停滞位
[1:0] 数据位设置串口0数据位数:00 = 5个数据位 01 = 6个数据位10 = 7个数据位 11 = 8个数据位
该寄存器我们通用的配置是:
ULCON2=0x3;//Normalmode,Noparity,Onestopbit,8databits
UCONn
[15:12] FCLK分频因子当UART0选择FCLK作为时钟源时,设置其FCLK的分频因子UART0 事情时钟频率 = FCLK/ FCLK分频因子 + 6
[11:10] UART时钟源选择选择UART0的事情时钟PCLK,UEXTCLK,FCLK/n:00,10 = PCLK01 = UEXTCLK11 = FCLK/n当选择FCLK/n作为UART0事情时钟时还要做其它设置,详细请读者自行查看硬件手册
[9] 发送数据中断产生类型设置UART0中断要求类型,在非FIFO传输模式下,一旦发送数据缓冲区为空,立即产生中断旗子暗记,在FIFO传输模式下达到发送数据触发条件时立即产生中断旗子暗记:0 = 脉冲触发1 = 电平触发
[8] 吸收数据中断产生类型设置UART0中断要求类型,在非FIFO传输模式下,一旦吸收到数据,立即产生中断旗子暗记,在FIFO传输模式下达到吸收数据触发条件时立即产生中断旗子暗记:0 = 脉冲触发1 = 电平触发
[7] 吸收数据超时设置当吸收数据时,如果数据超时,是否产生吸收中断:0 = 不开启超时中断 1 = 开启超时中断10 = 7个数据位 11 = 8个数据位
[6] 吸收数据缺点中断设置当吸收数据时,如果产生非常,如传输中止,帧缺点,校验缺点时,是否产生吸收状态中断旗子暗记:0 = 不产生缺点状态中断 1 = 产生缺点状态中断
[5] 回送模式设置该位时UART会进入回送模式,该模式仅用于测试0 = 正常模式 1 = 回送模式
[4] 发送终止旗子暗记设置该位时,UART会发送一个帧长度的终止旗子暗记,发送完毕后,该位自动规复为00 = 正常传输 1 = 发送终止旗子暗记
[3:2] 发送模式设置采取哪个办法实行数据写入发送缓冲区00 = 无效01 = 中断要求或查询模式10 = DMA0要求
[1:0] 吸收模式设置采取哪个办法实行数据写入吸收缓冲区00 = 无效01 = 中断要求或查询模式10 = DMA0要求
该寄存器通用配置为:
UCON2=0x5;//Interruptrequestorpollingmode
一样平常裸机情形下,采取轮询模式。
UTRSTATn
UTRSTAT n寄存器用来表明数据是否已经发送完毕、是否已经吸收到数据,格式如下图所示,上面说的“缓冲区”,实在便是下图中的 FIFO ,不该用 FIFO 功能时可以认为其深度为 1。当我们读取数据时,就轮询检讨bit[0]置1之后,然后再从URXHn寄存器读取数据;当我们读取数据时,就轮询检讨bit[1]置1之后,然后再向UTXHn寄存器写入数据来发送数据;
UTXHn寄存器(UART TRANSMIT BUFFER REGISTER)
CPU将数据写入这个寄存器,UART即会将它保存到缓冲区中,并自动发送出去。
URXHn寄存器(UART RECEIVE BUFFER REGISTER)
当UART吸收到数据时,读取这个寄存器,即可得到数据。
UFRACVALn 打算波特率
根据给定的波特率、所选择时钟源频率,可以通过以下公式打算 UBRDIVn 寄存器 (n 为 0~4,对应 5个 UART 通道 )的值。
UBRDIVn=(int)(UARTclock/(buadratex16))–1
上式打算出来的 UBRDIVn 寄存器值不一定是整数, UBRDIVn 寄存器取其整数部分,小部分由 UFRACVALn 寄存器设置, UFRACVALn 寄存器的引入,使产生波特率更加精确。【举例】当UART clock为100MHz时,哀求波特率为115200 bps,则:
100000000/(115200x16)–1=54.25–1=53.25UBRDIVn=整数部分=53UFRACVALn/16=小数部分=0.25UFRACVALn=4
电路图
外设电路图:
SP3232EEA 用来将TTL电平转换成RS232电平。我们利用的是COM2。
外设与核心板连接电路图可见UART的收发引脚连接到了GPA上,打开exynos4412芯片手册:我们只须要将GPA1 的低8位设置为0x22。
实例代码裸机代码,紧张实现uart_init()、putc()、getc()这三个函数。
uart_init()
该函数紧张配置UART的,波特率115200,数据位:8,奇偶校验位:0,终止位:1,不设置流控。如下图:是运行在windows下常用的串口工具配置信息,配置信息必须完备同等。
putc()
该函数是向串口发送一个数据data,他的实现逻辑便是轮询检讨寄存器UART2.UTRSTAT2 ,判断其bite【1】是否置1,如果置1,则向UART2.UTXH2存入要发送的数据即可。
getc()
该函数是从串口吸收一个数据data,他的实现逻辑便是轮询检讨寄存器UART2.UTRSTAT2 ,判断其bite【0】是否置1,如果置1,解释数据准备好,则可以从寄存器UART2.URXH2取出数据。
/UART2/typedefstruct{unsignedintULCON2;unsignedintUCON2;unsignedintUFCON2;unsignedintUMCON2;unsignedintUTRSTAT2;unsignedintUERSTAT2;unsignedintUFSTAT2;unsignedintUMSTAT2;unsignedintUTXH2;unsignedintURXH2;unsignedintUBRDIV2;unsignedintUFRACVAL2;unsignedintUINTP2;unsignedintUINTSP2;unsignedintUINTM2;}uart2;#defineUART2((volatileuart2)0x13820000)/GPA1/typedefstruct{unsignedintCON;unsignedintDAT;unsignedintPUD;unsignedintDRV;unsignedintCONPDN;unsignedintPUDPDN;}gpa1;#defineGPA1((volatilegpa1)0x11400020)voiduart_init(){/UART2initialize/GPA1.CON=(GPA1.CON&~0xFF)|(0x22);//GPA1_0:RX;GPA1_1:TXUART2.ULCON2=0x3;//Normalmode,Noparity,Onestopbit,8databitsUART2.UCON2=0x5;//Interruptrequestorpollingmode//Baud-rate:src_clock:100MhzUART2.UBRDIV2=0x35;UART2.UFRACVAL2=0x4;}voidputc(constchardata){while(!(UART2.UTRSTAT2&0X2));UART2.UTXH2=data;if(data=='\n')putc('\r');}chargetc(void){chardata;while(!(UART2.UTRSTAT2&0x1));data=UART2.URXH2;if((data=='\n')||(data=='\r')){putc('\n');putc('\r');}elseputc(data);returndata;}voidputs(constcharpstr){while(pstr!='\0')putc(pstr++);}voidgets(charp){chardata;while((data=getc())!='\r'){if(data=='\b'){p--;}p++=data;}if(data=='\r')p++='\n';p='\0';}