"); //-->
一个自己写的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
}
//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实验室
专栏文章内容及配图由作者撰写发布,仅供工程师学习之用,如有侵权或者其他违规问题,请联系本站处理。 联系我们
相关推荐
ARM9 2410开发板原理图(还有PCB)
CCl000 FSK 915/868/433/315 MHz低功率收发器
PIC®单片机与LED驱动及控制相关外设介绍(上)
外媒:DeepSeek技术突破,美AI芯片出口管制令被批太不现实
报道:苹果和阿里巴巴将为中国iPhone用户开发AI功能
在MC68HC908GP32上移植μC OS-II
远距离图文传输监控系统
特斯拉股价跌6%!外媒分析:比亚迪放大招,而马斯克在忙副业
推荐:RealARM 2410开发平台
利用PIC®单片机实现智能LED照明
基于PIC32的VGA.WVGA图形开发工具
“Albertgreen”的LED显示HEX视频
CYWUSB6934 CDMA GFSK 2.4 GHz收发器
恩智浦拟收购边缘NPU企业Kinara
.PHP数据库连接mysql说明实例~~ ~~
请教vxworks中usb驱动的问题?急!
CC2420 0-QPSK 2.4 GHz直接扩频收发器
预热式沐浴水箱水位自控器
Microchip WiFi模塊(MRF24WB0Mx系列) 的連線種類與方法—AdHoc Mode的三種連線方式
借助低功耗网状网络技术降低网关能耗
远距离图文传输监控系统2
阿里巴巴AI实力获苹果钟爱 年内股票累涨超30%
是德科技与KD携手合作,利用全新的信号分析能力推进多千兆位光纤车载以太网测试
CC2400 GFSK/FSK 2.4 GHz低功率收发器
在Linux下用Qt开发新一代DTS图形数据系统的分析
超薄型AC-DC电源,为BF等级的医疗和工业设备提供传导、对流和风扇冷却选项
MAX2820/MAX2821 I/Q 2.5~2.4 GHz收发器
无问芯穹打通七家国产芯片DeepSeek-R1适配优化,助力全国产化AI产业闭环构建
求一linux9.0系统复位函数
行业首家!海信电视正式接入DeepSeek!支持R1、V3自由切换