2018-08-06补充(百度百科):
异步通信是一种很常用的通信方式。相对于同步通信,异步通信在发送字符时,
所发送的字符之间的时隙可以是任意的,当然,接收端必须时刻做好接收的准备(如果接收端主机的电源都没有加上,那么发送端发送字符就没有意义,因为接收端根本无法接收)。发送端可以在任意时刻开始发送字符,因此必须在每一个字符的开始和结束的地方加上标志,即加上开始位和停止位,以便使接收端能够正确地将每一个字符接收下来。
异步通信的好处是通信设备简单、便宜,
缺点信道利用率较低(因为开始位和停止位的开销所占比例较大),但随着光网络的发展,这些已不是根本问题。
一、异步串行方式的数据格式
由于UART是串行异步通信方式,因此在UART通信过程中每次只能传输1位(bit),若干位组成一个数据帧(frame),帧是UART通信中最基本单元,它主要包含:开始位,数据位,校验位(如果开启了数据校验,要包含校验位),和停止位,帧结构如下图所示。
开发者要通过寄存器的设置,来指定帧的格式,帧的封装最终还是由硬件自动完成。
UART在通信之前要在发送端和接收端约定好帧结构,也就是约定好传输数据帧格式。
l 开始位:必须包含在数据帧中,表示一个帧的开始。
l 数据位:可选5,6,7,8位,该位长度可由编程人员指定。
l 校验位:如果在开启了数据校验时,该位必须指定。
l 停止位:可选1,2位,该位长度可由编程人员指定。
通信双方约定好帧格式后,指定同一波特率,以保证双方数据传输的同步。波特率是指单位时间传输二进制数据的位数,其单位为比特每秒(bps或bit/s),表示美秒传多少位。
二、Exynos4412异步串行通信
1. 控制器框架如下图所示:
(1)数据发送
发送的数据帧可编程的,它的一个帧长度是用户指定的,它包括一个开始位,5~8个数据位,一个可选的奇偶校验位和1~2个停止位,数据帧格式可以通过设置ULCONn寄存器来设置。发送器也可以产生一个终止信号,它是由一个全部为0的数据帧组成。在当前发送数据被完全传输完以后,该模块发送一个终止信号。在终止信号发送后,它可以继续通过FIFO(FIFO)或发送保持寄存器(NON-FIFO)发送数据。
(2)数据接收
同样接收端的数据也是可编程的,接收器可以侦测到溢出错误奇偶校验错误,帧错误和终止条件,每个错误都可以设置一个错误标志。
l 溢出错误是指在旧数据被读取到之前,新数据覆盖了旧数据
l 奇偶校验错误是指接收器侦测到了接收数据校验结果失败,接收数据无效
l 帧错误是指接收到的数据没有一个有效的停止位,无法判定数据帧结束
l 终止条件是指RxDn接收到保持逻辑0状态持续长于一个数据帧的传输时间
2. 寄存器配置
1)配置管脚
2)通过ULCONn寄存器设置帧格式,比如0x3代表8位数据位,1位奇偶校验位,1位停止位。
3)UCONn 设置串口为中断或轮询方式发送或接收数据
4)UFCONn设置FIFO的长度,我们这里不使用FIFO,认定深度为1
5)UMCONn 流量控制寄存器
6)UTRSTATn 数据是否发送完毕或者是否接收到数据
7)串口发送寄存器UTXHn
将数据写入到这个寄存器,UART就会把他保存到缓冲区中,并自动发送
8)串口接收寄存器URXHn
uart收到数据的时候,会把数据保存到这个寄存器,直接读取就可以获得数据
9)波特率设置寄存器UBRDIVn和UFRACVALn,这两个寄存器如何初始化,按照如下规则:
三、示例代码
/**********************************************************************
* @brief uart_init, Normal mode, No parity,One stopbit,8 data bits
* Buad-reate : 115200, clock srouce100Mhz
* @param[in] int (ms)
* @return None
**********************************************************************/
void uart_init(void)
{
/*UART2initialize*/
GPA1.GPA1CON= (GPA1.GPA1CON & ~0xFF ) | (0x22); //GPA1_0:RX;GPA1_1:TX
UART2.ULCON2= 0x3; //Normal mode, No parity,One stop bit,8 data bits
UART2.UCON2 =0x5; //Interrupt request or polling mode
/*
* Baud-rate 115200: src_clock:100Mhz
* DIV_VAL = (100*10^6 / (115200*16) -1) =(54.3 - 1) = 53.3
* UBRDIV2 = (Integer part of 53.3) = 53 = 0x35
* UFRACVAL2 = 0.3*16 = 0x5
* */
UART2.UBRDIV2= 0x35;
UART2.UFRACVAL2= 0x5;
}
void putc(const char data)
{
/*判断发送缓冲区是否为空*/
while(!(UART2.UTRSTAT2& 0X2));
UART2.UTXH2 =data;
/*在linux中
换行符为
,在windows中换行符为
,此句意思是将
换成
*/
if (data =='
')
putc('
');
}
void puts(const char *pstr)
{
while(*pstr!= '