完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
最近进行STM32开发,在处理大规模串口数据的时候,由于数据处理速度不够及时而出现掉包的问题,为此通过以下方案成功解决。
BTW:在串口循环发送一组数据的时候,应该在发送第一个字节之前也加上判断缓冲区是否为空。 正确形式如下: //这个函数会循环执行 void stop(void){ //发送10给上位机,使其进入数据解调 float_data.d = 10 * 10000; while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); USART_SendData(USART1,0xff);//发送开始帧标志位 while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); USART_SendData(USART1,float_data.s[3]); while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); USART_SendData(USART1,float_data.s[2]); while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); USART_SendData(USART1,float_data.s[1]); while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); USART_SendData(USART1,float_data.s[0]); while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); USART_SendData(USART1,0x0e);//发送结束标志位 while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); } 1. 环形缓冲队列 STM32串口在接收数据的时候,数据的处理速度小于数据接收的速度,造成数据丢包现象。 为此,引进串口环形缓冲区对未来得及处理的数据进行缓存,待系统空闲的时候进行处理。 环形缓冲区就是一个带“头指针”和“尾指针”的数组。头指针指向环形缓冲区中可读的数据,尾指针指向环形缓冲区中可写的缓冲空间。 缓冲区建立过程: 当串口接收到新的数组,则将数组保存到环形缓冲区中,同时将“尾指针”加1,以保存下一个数据;应用程序在读取数据时,“头指针”加1,以读取下一个数据。当“尾指针”超过数组大小,则“尾指针”重新指向数组的首元素,从而形成“环形缓冲区”!,有效数据区域在“头指针”和“尾指针”之间。 缓冲区构造: #define MAX_SIZE 12//缓冲区大小 typedef struct { unsigned char head; //缓冲区头部位置 unsigned char tail; //缓冲区尾部位置 unsigned int ringBuf[MAX_SIZE]; //缓冲区数组 } ringBuffer_t; ringBuffer_t buffer = {0,0,{0}}; //定义一个结构体,并初始化 ① 空队列:头指针head和尾指针tail都是指向数组的元素0 ② 缓冲区满 当如果l加入队列,则缓冲队列处于满载状态,如图所示。 如果此时,接收到新的数据并需要保存,则tail需要归零,将接收到的数据存到数组的第一个元素空间,如果尚未读取缓冲数组的一个元素空间的数据,则此数据会被新接收的数据覆盖。同时head需要增加1,修改头节点偏移位置丢弃早期数据。 ③ 缓冲区为空: tail和head相等 2. 环形缓冲队列的实现 ringbuffer.h #ifndef _RINGBUFFER_H #define _RINGBUFFER_H #define BUFFER_MAX 6000//定义缓冲区大小 typedef struct{ unsigned int headPosition;//缓冲区头部位置 unsigned int tailPosition; float ringBuf[BUFFER_MAX];//缓冲区数组 }ringBuffer_t; void RingBuf_Write(float data);//向缓冲区写入一个字节 unsigned char RingBuf_Read(float* pData);//读取缓冲区一个字节的数据 unsigned char VoltageSend(void); void stop(void); #endif ringbuffer.c: #include "ringbuffer.h" ringBuffer_t buffer = {0,0,{0}}; void RingBuf_Write(float data){//向缓冲区写入一个字节 buffer.ringBuf[buffer.tailPosition] = data;//从尾部追加 // printf("writeokrn"); if(++buffer.tailPosition >= BUFFER_MAX)//尾节点偏移 buffer.tailPosition = 0;//大于数组,最大长度归零,形成环形数组 //如果尾部节点追到头部节点,则修改头节点偏移位置丢弃早期数据 if(buffer.tailPosition == buffer.headPosition) if(++buffer.headPosition >= BUFFER_MAX) buffer.headPosition=0; } unsigned char RingBuf_Read(float* pData){//读取缓冲区一个字节的数据 if(buffer.headPosition == buffer.tailPosition){//头尾相接表示缓冲区数据为空 return 0;//读取失败返回0 } else{ *pData = buffer.ringBuf[buffer.headPosition];//如果缓冲区非空则取头结点值并偏移头结点 if(++buffer.headPosition>=BUFFER_MAX) buffer.headPosition = 0; return 1;//读取成功返回1 } } main.c:关注核心代码即可 int main() { unsigned int totalSend = 0; unsigned int datacount = 0; SysTick_Init(); LED_Config(); USART1_Config(); NVIC_Config(); ADC1_Config(); DMA1Config(); PWM_Config(); // printf("hello,stoprn"); // printf("%drn",totalSend); // printf("hello,stoprn"); while(1){ //从缓冲区取数据进行发送 if(datacount < 120){ if(!VoltageSend())//数据发送成功 { totalSend++; // printf("rn"); // printf("%drn",totalSend); if(totalSend == 600){ delay_ms(100); stop(); totalSend = 0; datacount++; //延时,等待上位机开启数据解调线程10ms delay_s(6); } delay_ms(50); } } } } |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1767 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1619 浏览 1 评论
1069 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
724 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1673 浏览 2 评论
1935浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
726浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
567浏览 3评论
592浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
551浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-21 18:24 , Processed in 0.728558 second(s), Total 76, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号