UART接口

来源:互联网 发布:php软件用什么软件 编辑:程序博客网 时间:2024/05/16 07:41

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基本结构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两篇文章的重点内容而成,特此感谢!

0 0