您的位置:首页 > 其它

UART接口

2015-11-09 11:14 197 查看
UART传输时序如图所示:



1、UART作为异步串口通信协议的一种,工作原理是将传输数据的每个字符一位接一位地传输。其中各位的意义如下:

起始位:先发出一个逻辑”0”的信号,表示传输字符的开始。

数据位:紧接着起始位之后。数据位的个数可以是4、5、6、7、8等,构成一个字符。通常采用ASCII码。从最低位开始传送,靠时钟定位。

奇偶校验位:数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验资料传送的正确性。

停止位:它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。 由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。

空闲位:处于逻辑“1”状态,表示当前线路上没有数据传送。

2、收发过程

发送数据过程:

空闲状态,线路处于高电位;当收到发送数据指令后,拉低线路一个数据位的时间T,接着数据按低位到高位依次发送,数据发送完毕后,接着发送奇偶校验位和停止位(停止位为高电位),一帧数据发送结束。

接收数据过程:

空闲状态,线路处于高电位;当检测到线路的下降沿(线路电位由高电位变为低电位)时说明线路有数据传输,按照约定的波特率从低位到高位接收数据,数据接收完毕后,接着接收并比较奇偶校验位是否正确,如果正确则通知后续设备准备接收数据或存入缓存。

UART的接收数据时序为:

当检测到数据的下降沿时,表明线路上有数据进行传输,这时计数器CNT开始计数,当计数器为24=16+8时,采样的值为第0位数据;当计数器的值为40时,采样的值为第1位数据,依此类推,进行后面6个数据的采样。如果需要进行奇偶校验,则当计数器的值为152时,采样的值即为奇偶位;当计数器的值为168时,采样的值为"1"表示停止位,一帧数据接收完成。


3、基本结构:

⑴输出缓冲寄存器,它接收CPU从数据总线上送来的并行数据,并加以保存。



uart基本结构

⑵ 输出移位寄存器,它接收从输出缓冲器送来的并行数据,以发送时钟的速率把数据逐位移出,即将并行数据转换为串行数据输出

⑶ 输入移位寄存器,它以接收时钟的速率把出现在串行数据输入线上的数据逐位移入,当数据装满后,并行送往输入缓冲寄存器,即将串行数据转换成并行数据。

⑷ 输入缓冲寄存器,它从输入移位寄存器中接收并行数据,然后由CPU取走。

控制寄存器,它接收CPU送来的控制字,由控制字的内容,决定通信时的传输方式以及数据格式等。例如采用异步方式还是同步方式,数据字符的位数,有无奇偶校验,是奇校验还是偶校验,停止位的位数等参数。

状态寄存器。状态寄存器中存放着接口的各种状态信息,例如输出缓冲区是否空,输入字符是否准备好等。在通信过程中,当符合某种状态时,接口中的状态检测逻辑将状态寄存器的相应位置“1”,以便让CPU查询。

波特率:是衡量资料传送速率的指标。表示每秒钟传送的符号数(symbol)。一个符号代表的信息量(比特数)与符号的阶数有关。例如资料传送速率为120字符/秒,传输使用256阶符号,每个符号代表8bit,则波特率就是120baud,比特率是120*8=960bit/s。这两者的概念很容易搞错。

4、设计思想

数据发送的思想是,当启动字节发送时,通过TxD先发起始位,然后发数据位和奇偶数校验位,最后再发停止位,发送过程由发送状态机控制,每次中断只发送1个位,经过若干个定时中断完成1个字节帧的发送。

数据接收的思想是,当不在字节帧接收过程时,每次定时中断以3倍的波特率监视RxD的状态,当其连续3次采样电平依次为1、0、0时,就认为检测到了起始位,则开始启动一次字节帧接收,字节帧接收过程由接收状态机控制,每次中断只接收1个位,经过若干个定时中断完成1个字节帧的接收。

为了提高串口的性能,在发送和接收上都实现了FIFO功能,提高通信的实时性。FIFO的长度可以进行自由定义,适应用户的不同需要。

波特率的计算按照计算公式进行,在设置最高波特率时一定要考虑模拟串口程序代码的执行时间,该定时时间必须大于模拟串口的程序的规定时间。单片机的执行速度越快,则可以实现更高的串口通讯速度。


5、代码:

/*
工作流程:
通过“串口助手”发送数据,经串口送至51单片机,51单片机收到数据后,发送数据给电脑,显示在“串口助手”!
实际效果:当给单片机发送整数(0~255),单片机返回ch,ch的值每次自增1,当ch为99时,ch重新置0

*/
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char

uchar re = 0;

bit read_flag = 0 ;//取数标志位

void init_serialcom( void ) //串口通信初始设定
{
SCON = 0x50 ;   //UART为模式1,8位数据,允许接收  0101 0000
TMOD |= 0x20 ; //定时器1为模式2,8位自动重装          0010 0000
PCON |= 0x80 ; //SMOD=1;                          1000 0000
TH1 = 0xFD ;   //Baud:19200 fosc="11".0592MHz     1111 1100
IE |= 0x90 ;     //Enable Serial Interrupt        1001 0000
TR1 = 1 ;       // timer 1 run
}

//向串口发送一个字符
uchar send_char_com(uchar ch)
{
SBUF = ch;
ch++;
if (ch == 99)
{
ch = 0;
}

while (TI == 0);//数据发送后,TI由硬件置1
TI = 0 ;        //必须由软件清零
return ch;
}

//串口接收中断函数
void serial () interrupt 4 using 3
{
if (RI) //当接收到数据后,由硬件自动置位
{
RI = 0 ;
re = SBUF;  //收到的数据
read_flag = 1;
}
}

int main()
{
uchar ch;
init_serialcom(); //初始化串口
//关闭不用的数码

while ( 1 )
{
if (read_flag == 1) //如果取数标志已置位,就将读到的数从串口发出
{
read_flag = 0 ; //取数标志清0
ch = send_char_com(ch); //发送可以被接收的中断所中断
}
}
}


注:此文章经过整合:http://blog.csdn.net/to_dreams/article/details/7716678,http://blog.sina.com.cn/s/blog_3e6ed8f90100mkv0.html两篇文章的重点内容而成,特此感谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: