基于jz2440的串口使用
- 搬砖的文章
- 概述
- UART的发送和接收
- 串口之间的数据传输
- UART的用途
- 串口的数据帧参数说明
- 起始位
- 数据位
- 奇偶校验位
- 停止位
- 波特率
- 怎么发送一字节数据,比如‘A‘?
- UART的优缺点
- 优点
- 缺点
- UART相关配置寄存器
- ULCONn:线路控制寄存器
- UCONn:控制寄存器
- UFCONn:FIFO控制寄存器
- UMCONn:MODEM控制寄存器
- UTRSTATn:收发状态寄存器
- UERSTATn:错误状态寄存器
- UFSTATn:FIFO状态寄存器
- UMSTATn:Modem状态寄存器
- UTXHn/URXHn:传输缓冲寄存器
- UBRDIV:波特率除数寄存器
- 关于中断
- FIFO与非FIFO的区别
- 自动流控制(AFC)
- UART通讯编程
搬砖的文章
我只是代码的搬运工,为了学习而做的笔记。若是大家有补充的,希望留言,我会一一补充,下面的都是搬砖的文章,都非常优秀,建议查看
1、收藏!了解UART总线工作原理看这一篇就够了!
2、Part4:串口(UART)通信原理与硬件编程
3、韦东山——第011课 Jz2400串口(UART)的使用
4、UART原理
5、ARM硬件结构
6、UART串口异步通信驱动编程
7、s3c2440A开发板UART总结以及UART代码详解(寄存器方面)
概述
UART(Universal Asynchronous Receiver/Transmitter)是一种异步串口IO端口(Asynchronous Serial I/O PORT),每个SOC上可支持多个独立的UART,每个独立的UART的特性如下:
(1)每个UART PORT可基于中断或者DMA来工作,也就是UART可生成中断或者DMA请求,再内存和UART间进行数据的传输;
(2)可编程的波特率、红外传输(接收)、1~2个停止位、5-8个bit数据位宽、校验位(奇偶校验)
(3)主要组成部分是控制单元,接收器、发送器,发送器,波特率生成器
要发送数据时,CPU控制内存要发送的数据通过FIFO传给UART单位,UART里面的移位器,依次将数据发送出去,在发送完成后产生中断提醒CPU传输完成。
接收数据时,获取接收引脚的电平,逐位放进接收移位器,再放入FIFO,写入内存。在接收完成后产生中断提醒CPU传输完成。
UART的发送和接收
UART传输数据依靠的是UART总线,数据总线用于通过CPU,存储器或微控制器等其他设备将数据发送到UART。数据以并行形式从数据总线传输到发送UART。在发送UART从数据总线获得并行数据之后,它将添加起始位,奇偶校验位和停止位,从而创建数据包。接下来,数据包在Tx引脚上逐位串行输出。UART接收端则在其Rx引脚上逐位读取数据包。然后,接收UART将数据转换回并行形式,并删除起始位,奇偶校验位和停止位。最后,接收UART将数据包并行传输到接收端的数据总线。
串口之间的数据传输
- 通过TxD->RxD把ARM开发板要发送的信息发送给PC机。
- 通过RxD->TxD线把PC机要发送的信息发送给ARM开发板。
- 最下面的地线统一参考地。
UART的用途
- 打印调试信息;
- 外接各种模块:GPS、蓝牙;
串口的数据帧参数说明
UART传输的数据被组织成数据包。每个数据包包含1个起始位,5到9个数据位(取决于UART),可选的奇偶校验位以及1或2个停止位:
起始位
当UART数据传输线不传输数据时,它通常保持在高电压电平。为了开始数据传输,发送UART将传输线从高电平拉至低电平一个时钟周期。当接收UART检测到高电压到低电压转换时,它开始以波特率的频率读取数据帧中的位。
由1个逻辑 0 的数据位表示
先发出一个逻辑“0”的信号,表示传输字符开始。
数据位
数据框包含要传输的实际数据。如果使用奇偶校验位,则它可以是5位到8位长。如果不使用奇偶校验位,则数据帧可以是9位长。在大多数情况下,数据首先以最低有效位发送。
在起始位后紧接着的就是有效数据,有效数据的长度常被约定为 5、 6、 7 或 8 位长
奇偶校验位
奇偶校验描述数字的均匀性或奇数。奇偶校验位是接收UART在传输过程中判断是否有任何数据发生变化的一种方法。电磁辐射、不匹配的波特率或长距离传输时,数据都有可能发生变化。接收UART读取数据帧后,它会计算值为1的位数,并检查总数是偶数还是奇数。如果奇偶校验位为0(偶校验),则数据帧中的1位应总计为偶数。如果奇偶校验位是1(奇校验),则数据帧中的1位应总计为奇数。当奇偶校验位与数据匹配时,UART知道传输没有错误。但如果奇偶校验位为0,然而1位应总计为奇数;或者奇偶校验位是1,并且1位应总计是偶数,则数据帧中的位已经改变。
可选,为的是数据的抗干扰性。
校验方法分为:
- 1、奇校验(odd),有效数据和校验位中“ 1”的个数为奇数
- 2、偶校验(even) ,有效数据和校验位中“ 1”的个数为偶数
- 3、0 校验(space),不管有效数据中的内容是什么,校验位总为“ 0”
- 4、1校验(mark),不管有效数据中的内容是什么,校验位总为“ 1”
- 5、无校验(noparity)
- 空闲位,总是保持逻辑1
停止位
为了通知传输数据包的结束,UART发送端会将数据传输线从低电压驱动至高电压至少两位持续时间。它是一个字符数据的结束标志。
由 0.5、 1、 1.5 或 2 个逻辑 1 的数据位表示
波特率
波特率(Baud rate):一般选波特率都会有9600,19200,115200等选项。其实意思就是每秒传输这么多个比特位数(bit)。约定彼此收发数据的频率,即每1bit所占时间的约定
怎么发送一字节数据,比如‘A‘?
A 的ASCII值是0x41,二进制就是01000001,怎样把这8位数据发送给PC机呢?
- 双方约定好波特率(每一位占据的时间);
- 规定传输协议
当UART数据传输线不传输数据时,它通常保持在高电压电平。为了开始数据传输,发送UART将传输线从高电平拉至低电平一个时钟周期。
逻辑电平就是说代表信号1的引脚电平是人为规定的。
- 注:在xV至5V之间,就认为是逻辑1,在0V至yV之间就为逻辑0。 如图是TTL/CMOS逻辑电平下,传输‘A’时的波形:
UART的优缺点
优点
- 只使用两根电线
- 不需要时钟信号
- 有一个奇偶校验位
- 只要双方设置后,就可以改变数据包的结构
- 有完整的文档并且具有广泛的使用
缺点
- 数据帧的大小限制为最多9位
- 不支持多个从属或多个主系统
- 每个UART的波特率必须在10%之内
UART相关配置寄存器
uart各个寄存器各个位的含义
ULCONn:线路控制寄存器
ULCONn:线路控制寄存器,用于设定线路的字长度、停止位个数、奇偶校验方式、是否使用红外模式。(看的书中翻译成“线性控制寄存器”,我感觉是不正确的)
我在jz2440里配置为:
- ①取消红外线模式(Infrared Mode)
- ②无奇偶校验(Parity Mode)
- ③一个停止位(Number of Stop Bit)
- ④八个数据位(Word Length)
UCONn:控制寄存器
UCONn: 控制寄存器,用于设定操作模式(中断或轮询/DMA)、环回模式、中断方式、时钟选择。
我在jz2440里配置为:
- 时钟设置为PCLK(Clock Selection)
- 中断脉冲触发(Tx/Rx Interrupt Type)
- 接收超时中断不允许(Tx/Rx Error Status Interrupt Enable)
- 接收超时中断不允许(Rx Time Out Enable)
- 不产生接收错误中断(Rx Error Status Interrupt Enable)
- 设置正常模式,不使用环回模式(Loopback Mode)
- 设置正常模式,不启动间断发送(Send Break Signal)
- 发送/接收模式设置为中断请求或轮询模式(Transmit/Receive Mode)
UFCONn:FIFO控制寄存器
UFCONn:FIFO控制寄存器,用于控制FIFO操作方式,如是否使用FIFO以及触发级别。
这里我们不使用FIFO不用设置,默认即可。
由于我们需要大量数据的传输时,才使用FIFO,若是传输几个字节的数据时,不必启用FIFO。
UMCONn:MODEM控制寄存器
UMCONn:Modem控制寄存器,用于设置是否使用AFC(自动流控制)和RTS。TTL2是不支持流控制的,所以没有UMCON2寄存器。
我们不设置,所以就默认值就好。
UTRSTATn:收发状态寄存器
UTRSTATn:收发状态寄存器,可从中读取收发保持寄存器的状态,即是否有数据,仅在非FIFO模式下使用。
我们判断在[2]位是否存在数据
UERSTATn:错误状态寄存器
UERSTATn:错误状态寄存器,可从中读取接收错误状态。
我们不设置,所以就默认值就好。
UFSTATn:FIFO状态寄存器
UFSTATn:FIFO状态寄存器,可从中读取FIFO状态信息,用于FIFO模式。
我们不设置,所以就默认值就好。
UMSTATn:Modem状态寄存器
UMSTATn:Modem状态寄存器,可从中读取Modem状态,即CTS信号状态。TTL2不支持流控制,所以没有UMSTAT2寄存器。
我们不设置,所以就默认值就好。
UTXHn/URXHn:传输缓冲寄存器
UTXHn和URXHn:收发保持(对非FIFO模式)和缓冲(对FIFO模式)寄存器,用于收发数据。
在UART块中有三个UART传输缓冲区寄存器,包括UTXH0、UTXH1和UTXH2。UTXHn有一个用于传输数据的8位数据。
UBRDIV:波特率除数寄存器
UBRDIV:波特率除数寄存器,用于设定串口通信波特率。
我们根据波特率以及一些参数算出最终的值写入这个寄存器即可。
关于中断
-
边沿(脉冲?)触发:一旦(as soon as)Tx缓冲区变为(becomes)空(非FIFO模式)或者达到(reaches)Tx FIFO触发级别(FIFO模式),则请求中断。注意,这里的“一旦”不仅限定前半句(非FIFO模式),也限定后半句(FIFO模式)。“一旦”与“变为”和“达到”连接起来,表示的是一个时间点,一个变化过程,是变为空或者达到触发级别的时间点或者说变化过程中请求中断。这个时间点过后,或者变化完成后,就不再请求中断了。只要处理中断后,清除源未决寄存器(SRCPND)和中断寄存器(INTPND)的相关位,就不会再有中断发生了。
-
电平触发:当(while)Tx缓冲区为空(非FIFO模式)或者达到Tx FIFO触发级别,则请求中断。这里的“当”限定前半句和后半句。“当”表示的是一种状态,是处于缓冲区空或者达到Tx FIFO触发级别的状态的时候,就请求中断。处理中断后,即使清除了源未决寄存器(SRCPND)和中断寄存器(INTPND)的相关位,只要这种状态存在,就一直请求中断,即会再次发起中断请求。只有不存在这种状态了,才不会再发起中断请求。
FIFO与非FIFO的区别
- S3C2440A的UART内部对于接收和发送各有64字节的缓冲区,当使用FIFO模式时,UART将使用这个缓冲区进行数据暂存操作,这样可以增加数据吞吐量,提高传输速率。其实,非FIFO模式也可以看作是特殊的FIFO模式,即只有一个字节缓冲区的FIFO模式。二者的主要不同在于读取缓冲区状态的方式:非FIFO模式下,通过UTRSTAT寄存器得知收发缓冲区状态;FIFO模式下,则从UFSTAT寄存器获得缓冲区状态。要注意的是,在FIFO模式下,只有达到触发级别后才会发起Rx或Tx中断。比如说,如果设置接收触发级别为16字节,则只有在接收缓冲区中有16个字节以上数据时,才会发起Rx中断请求。如果需要进行输入回显,则可能导致不能立即回显用户在串口工具中输入的字符。
自动流控制(AFC)
-
AFC(Auto Flow Control):自动流控制。S3C44BoX中的UART用nRTS(发送请求信号)和nCTS(清除发送信号)来支持自动流控制,以此实现UART之间的互联。
-
自动流控制涉及到RTS和CTS,我查了下相关缩写的含义:
-
DTE:Data Terminal Equipment,数据终端设备,一般指计算机。
-
DCE:Data Communication Equipment,数据通信设备,一般是调制解调器(Modem)。
-
DTR:Data Terminal Ready,数据终端就绪,DTE向DCE发送这个信号表示已经准备就绪。
-
DSR:Data Set Ready,数据设备就绪,DCE向DTE发送这个信号表示已经准备就绪。
-
RTS:Request To Send,请求发送,DTE向DCE请求发送数据。
-
CTS:Clear To Send,清除发送,DCE向DTE表示准备就绪,可以接收数据了。
UART通讯编程
我们所使用的时RX0/TX0,所对应的引脚位GPH2、GPH3。
这里的GPHCON 之类的变量是自己定义的宏定义,比如把指针地址直接定义为一些宏定义,这样就方便以及隐藏地址,本质还是地址
代码如下:
#include "s3c2440.h"void uart0_init(){/* 设置引脚用于串口 *//* GPH2,3用于TxD0, RxD0 */GPHCON &= ~((3<<4)|(3<<6));GPHCON |= ((1<<4)|(1<<6));GPHUP &= ~((1<<2)|(1<<3)); //使能内部上拉/* * ULCONn:线路控制寄存器* 根据寄存器的[7:0]的数据位的配置可知为:000011也就是3*/ULCON0 = 0x03;/** UCONn:控制寄存器* 根据寄存器的[15:0]的数据位可知的配置位:0000 00 0 0 0 0 0 0 01 01也就是5*/UCON0 = 0x05;/* UFCONn:FIFO控制寄存器* * ->因为我们还没有使用FIFO,所以就暂时不设置<-*//* UMCONn:MODEM控制寄存器* * ->因为我们还没有使用MODEM,所以就暂时不设置<-*//* UERSTATn:错误状态寄存器* * ->因为我们还没有用到,所以就暂时不设置<-*//* UFSTATn:FIFO状态寄存器* * ->因为我们还没有用到,所以就暂时不设置<-*//* UMSTATn:Modem状态寄存器* * ->因为我们还没有用到,所以就暂时不设置<-*//* UBRDIV:波特率除数寄存器* * 设置波特率* UBRDIVn = (int)( UART clock / ( buad rate x 16) ) –1* UART clock = 50M* UBRDIVn = (int)( 50000000 / ( 115200 x 16) ) –1 = 26**/UBRDIV0 = 26;}/** UTXHn/URXHn:传输缓冲寄存器 ,用来发送接收数据的缓冲区。这里的UTXH0_B,以及UTXH0_L表示采用大尾端还是小尾端**判断UTRSTAT0里的[2]是否为1:若是为1,则表示里面的发送缓冲和发送移位寄存器时为空,则表示可以出发送数据,若是为0,表明有数据,死循环等待。* L是指尾端(endian)模式是小尾端模式* B是指尾端(endian)模式是大尾端模式* 大小尾端:大尾端是指数据的低位(就是权值较小的后面那几位)保存在内存的高地址中,而数据的高位,保存在内存的低地址中。小尾端反之*/
int putchar(char c){while(!(UTRSTAT0 & (1<<2));UTXH0_STR_B = (unsigned char)c;//这里的UTXH0_STR_B也就是传输缓冲寄存器}int getchar(void){while(!(UTRSTAT0 & (1<<0)));return URXH0_STR_B;//这里的URXH0_STR_B也就是传输缓冲寄存器}int putstring(const char *c){while (*s){putchar(*s);s++;}}