新闻  |   论坛  |   博客  |   在线研讨会
一个自己写的UART双数据缓冲(buffer)乒乓中断读取程序(原创)
HXW718059156 | 2012-02-23 10:17:48    阅读:14188   发布文章

本文参与参与“相伴ADI,相随UDC——博客征文比赛”获投票:40
 

一个自己写的UART双数据缓冲(buffer)乒乓中断读取程序(原创)

首先介绍一下,背景:在本次UDC大赛中,我们队的作品需要将现场采样的实时环境数据和智能小车运行状态通过无线方式传输至PC上位机软件(C++编写)显示和绘图,另一方面,我们还要实现上位机对现场智能蔽障小车的控制。由于数据量大,并且要保证实时可靠的接收数据和发送控制命令,对PC机一端UART通信及无线通信的可靠性和实时性提出了严格的要求,无线由于采用的是nRF24L01模块,其具有自动应答,片上完整的CRC校验功能,再加上我们精心设计的(数据和命令)通信帧,以及两端的中断接收,保证了无线数传的可靠性和实时性。

这里主要谈一下UART与PC之间的通信,之前采用惯用的一个数据缓存,加中断标志控制的方式实现,在数据量不大的情况下,可以正常无误的通信,但是当增大收发的数据量是,出现错误数据和数据丢失现象。

我们配置的UART设置为:

    波特率:9600bitps;8比特数据;1位停止位,无奇偶校验位,接收端RX buffer为32 Bytes;接收RX中断使能;

当然,提高通信波特率可以增大安全数据通信速率,但是总是治标不治本。经过一番思考,我们编写了如下的UART双数据缓冲(buffer)乒乓中断读取程序,保证任何波特率下的可靠实时通信。实测结果令人满意(在单片机循环发送大量数据至PC机的情况下,上位机软件每间隔1ms向下发送100字节数据,测试五数据丢失和错误)。

最后,附上源代码并简单解释一下原理:

所谓双数据缓存即:rx_buffer1[RX_BUFFER_SIZE]和rx_buffer2[RX_BUFFER_SIZE],BufferUsed,作为全局变量,用于记录并传递两个buffer操作顺序;所谓乒乓中断读取,即在UART中断服务程序中轮流交替使用上述两个数据缓存接收PC发来的数据。

其中main.C的语句if(BufferUsed!=LastBuffer){….LastBuffer = BufferUsed;….}用于完成两个buffer乒乓操作的检测与切换,具体代码如下:

  • 中断服务程序代码:

#define RX_BUFFER_SIZE128

uint8BufferUsed = 0;//

uint8rx_buffer1[RX_BUFFER_SIZE]={0};

uint8rx_buffer2[RX_BUFFER_SIZE]={0};

CY_ISR(isr_UartRX_Interrupt)

{

    /*  Place your Interrupt code here. */

    /* `#START isr_UartRX_Interrupt` */

    uint8rec_status = 0u;

    staticuint8pointerRX = 0u;

    staticuint8buffer = 0;

    uint8ReceiveChar = 0;

   

    rec_status = UART_ReadRxStatus();//read the RX state

    while(rec_status & UART_RX_STS_FIFO_NOTEMPTY)//there are data in the FIFO

    {

       if(pointerRX<RX_BUFFER_SIZE)

           if(buffer%2==0)

              rx_buffer1[pointerRX++] = UART_RXDATA_REG;

           else

              rx_buffer2[pointerRX++] = UART_RXDATA_REG;

       else

       {

           pointerRX = 0;   

           buffer++;

           BufferUsed = buffer;

       }

       rec_status = UART_ReadRxStatus();

    }

    /* `#END` */

 

    /* PSoC3 ES1, ES2 RTC ISR PATCH  */

    #if(CYDEV_CHIP_FAMILY_USED == CYDEV_CHIP_FAMILY_PSOC3)

        #if((CYDEV_CHIP_REVISION_USED <= CYDEV_CHIP_REVISION_3A_ES2) && (isr_UartRX__ES2_PATCH ))     

            isr_UartRX_ISR_PATCH();

        #endif

    #endif

}

  • Main函数处理代码:

//UART to PC communication

externuint8BufferUsed;

externuint8rx_buffer1[RX_BUFFER_SIZE];

externuint8rx_buffer2[RX_BUFFER_SIZE];

voidmain()

{

uint8LastBuffer = 0;

While(1)

{

UART_PutArray(MutiInfo,32);//send large information to PC

       if(BufferUsed!=LastBuffer)//if there is one buffer data ready

       {

           if(BufferUsed%2)

           {

//just send the buffer back to PC for verify

              UART_PutArray(rx_buffer1,RX_BUFFER_SIZE);

              //clean the buffer for next data receive

               for(i=0;i<RX_BUFFER_SIZE;i++) rx_buffer1[i] = 0;

           }

           else

           {

//just send the buffer back to PC for verify

              UART_PutArray(rx_buffer2,RX_BUFFER_SIZE);

              //clean the buffer for next data receive

              for(i=0;i<RX_BUFFER_SIZE;i++) rx_buffer2[i] = 0;

           }

           LastBuffer = BufferUsed;//record current operate state

          

           LCD_Char_1602_Position(1,0);

           LCD_Char_1602_PrintString("UART Get data!");

       }

}

}

 

                                            胡恩伟

                                      2011年9月7日星期三

                                    于重大A区主教2601实验室

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
jidan  2013-04-08 13:14:52 

用循环缓冲应该也可以

ytfdhb  2012-03-10 16:08:54 

路过,来学习学习^_^

欢迎大家关注我的微信公众号--汽车电子expert成长之路,阅读更多原创性精彩文章。如果你觉得我的文章对你的学习/工作有所帮助,也请你帮忙转发到你的朋友圈,让更多的人能够看到我的文章,大家一起学习,一起进步!
推荐文章
最近访客