串口通信(USART)

来源:互联网 发布:流程图软件visio 名称 编辑:程序博客网 时间:2024/06/05 06:45

一、USART介绍

     USART即通用同步异步收发器,它利用分数比特率发生器提供宽范围的比特率选择,还支持同步单向通信和半双工单线通信。STM32F10x系列芯片的USART串口功能十分强大。它的接口通过3个引脚与其他设备连接在一起。任何USART双向通信至少需要2个脚:RX(接收数据)和TX(发送数据)。我们通常使用的接口称之为RS232接口,RS232-C接口连接器一般使用型号为DB-99芯插头座,只需3条接口线,即"发送数据""接收数据""信号地"即可传输数据,其9个引脚的定义如图1所示。

                                          

图1  RS232接口连接器


      RS232的规范中,电压值在+3V~+15V(一般使用+6V)称为"0""ON"。电压在-3V~-15V(一般使用-6V)称为"1""OFF";计算机上的RS232"高电位"约为9V,而"低电位"则约为-9VRS232为全双工工作模式,其信号的电压是参考地线而得到的,可以同时进行数据的传送和接收。在实际应用中采用RS232接口,信号的传输距离可以达到15m。不过RS232只具有单站功能,即一对一通信。在串行通信中,数据通常是在两个站之间传送,按照数据在通信线路上的传送方向可分为3种基本的传送方式:单工、半双工和全双工,如图2所示。


图2 单工、半双工和全双工

      单工通信使用一根导线,信号的传送方和接收方有明确的方向性。也就是说,通信只在一个方向上进行。若使用同一根传输线既作为接收线路又作为发送线路,虽然数据可以在两个方向上传送,但通信双方不能同时收发数据,这样的传送方式称为半双工。采用半双工方式时,通信系统每一端的发送器和接收器,通过收发开关分时转接到通信线上,进行方向的切换。当数据的发送和接收,分别由两根不同的传输线传送时,通信双方都能在同一时刻进行发送和接收操作,这样的传送方式就是全双工。在全双工方式下,通信系统的每一端都设置了发送器和接收器,因此,能控制数据同时在两个方向上传输。全双工方式无须进行方向的切换。

     串行通信可分为两种类型,一种是同步通信,另一种是异步通信。采用同步通信时,将所有字符组成一个组,这样,字符可以一个接一个地传输,但是,在每组信息的开始要加上同步字符,在没有信息要传输时,填上空字符,因为同步传输不允许有空隙。采用异步通信时,两个字符之间的传输间隔是任意的,所以,每个字符的前后都要用一些数据位来作为分隔位。比较起来,在传输率相同时,同步通信方式下的信息有效率要比异步方式高,因为同步方式的非数据信息比例比较小。但是,从另一方面看,同步方式要求进行信息传输的双方必须用同一个时钟进行协调,正是这个时钟确定了同步串行传输过程中每一个信息位的位置。这样一来,如果采用同步方式,那么,在传输数据的同时,还必须传输时钟信号。而在异步方式下,接收方的时钟频率和发送方的时钟频率不必完全一样,而只要比较相近,即不超过一定的允许范围就行了。在数据传输中,较为广泛采用的是异步通信,异步通信的标准数据格式如图3所示。


图3 异步通信数据格式

      从图3所列格式可以看出,异步通信的特点是一个字符一个字符地传输,并且每个字符的传送总是以起始位开始,以停止位结束,字符之间没有固定的时间间隔要求。每一次有一个起始位,紧接着是5~8个的数据位,再后为校验位,可以是奇检验,也可以是偶校验,也可不设置,最后是1比特,或1比特半,或2比特的停止位,停止位后面是不定长度的空闲位。停止位和空闲位都规定为高电平,这样就保证起始位开始处一定有一个下降沿,以此标识开始传送数据。


二、USART之队列收发数据 

     在大量数据发送接收过程中,一般数据的处理都会放到中断里,但是这不符合中断处理尽量简短的原则。因此,在实际应用中我们使用一个数据缓冲队列,为先进先出(FIFO),在这个队列中,有接收指针与发送指针,当有新数据写入队列时,接收指针加1;当队列中数据发送出去时,发送指针加1。FIFO是一个循环队列,首尾相连,理论上接收指针总是在前,但并不是说在前接收指针就大。图4为这种队列的示意图。

   

图4 FIFO循环队列示意图

  接收数据进队列:

<span style="font-size:14px;">void USART1_IRQHandler(void){      if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //如果是接收中断    {           uart1_trx[uart1_rx] = USART_ReceiveData(USART1);    //把数据放入队列中      uart1_rx++ ;                                        //接收指针加1      uart1_rx &= 0x3f;                                   //判断发送指针是否到0    }}</span>

   从队列中发送数据:  

<span style="font-size:14px;"> if(uart1_tx != uart1_rx)                    //判断是否有数据发送    {      Uart1_PutChar(uart1_trx[uart1_tx]);    //发送数据      uart1_tx++;      uart1_tx &= 0x3f;                      //判断发送指针是否到0    }</span>

    

      在最开始,接收和发送指针都为0,当然这时是没有接收到数据的。如果接收到一个数据,把数据放到数组0中,然后接收指针加1,发送指针就与接收指针不同,到主循环中,由于检测到接收1和发送0的指针不等,认为接收到新数据。发送指针0所指向的数据,即数组0中的数据,数据发送后,发送指针加1,这样发送指针也指向1的位置,这时的发送指针和接收指针相等,没有新数据。依次类推,当接收到第17个数据时,队列数组只有16位,这时就会把这个数据放到0位置,接收指针也会变成0,这时接收指针小于发送指针,所以在判断中不能用大于或小于判断,只能用不等于判断,16位的缓冲队列最多只能缓冲16个数据,当有17个数据要缓冲时,前面16个数据会被丢掉。因此,在实际的开发过程中要根据实际情况开辟合理的buffer或者加上超过最大buffer范围程序,如果超出做相应的处理。

三、总结

      许多人认为串口太简单,但是越简单的事情我们约容易出错,因此在开发过程中要重视。在调试过程中,要设置串口调试助手或上位机的波特率、校验位、数据位、停止位等参数与串口程序初始化里的一致,否则得到的数据是乱码。串口通信是硬件板子与用户之间的桥梁,在开发应用中占据着不可或缺的地位。这篇博文是本人调试串口总结的,有些内容引用其他一些文章或者资源。为了写这篇博客,花费了一个晚上的时间,中间过程由于网络原因没保存又重写了一部分内容。。。。。。





1 0
原创粉丝点击