历史上的今天
返回首页

历史上的今天

今天是:2024年08月26日(星期一)

正在发生

2019年08月26日 | 基于STM32的串口数据环形缓冲队列

2019-08-26 来源:eefocus

最近进行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);

}


参考博客:基于stm32串口环形缓冲队列处理机制—入门级(单字节)


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);

}

}

}

}

推荐阅读

史海拾趣

Geyer Electronic E K公司的发展小趣事

Geyer Electronic E.K.公司的发展故事

故事一:创立与初步发展

Geyer Electronic E.K.公司由Rudolf Geyer于1964年创立,最初是一家位于慕尼黑莱姆区的电子产品零售店。在那个年代,电子产品行业正处于快速发展阶段,Geyer凭借其敏锐的市场洞察力和对技术的热情,逐渐在市场中站稳了脚跟。起初,店铺销售各类电子产品,从简单的收音机到复杂的电子设备,一应俱全。随着时间的推移,Geyer Electronic凭借其优质的服务和丰富的产品线,逐渐赢得了当地消费者的信任和支持。

故事二:转型与专业化

1992年,Geyer Electronic经历了一次重要的转折点。在Jürgen Reichmann的领导下,公司被收购并进行了战略调整,正式转型为一家专门从事频率产品和特殊电池的公司。这一转型标志着Geyer Electronic开始专注于某一特定领域,并致力于在该领域成为行业的领导者。公司投入大量资源进行技术研发和产品创新,不断推出符合市场需求的高质量频率产品和特殊电池,逐渐在行业内树立了良好的口碑。

故事三:全球化布局

随着业务的不断扩展,Geyer Electronic开始将目光投向全球市场。公司不仅在欧洲建立了稳固的市场地位,还逐渐将业务拓展到亚洲和美国等其他地区。为了实现全球化战略,Geyer Electronic加强了与全球合作伙伴的合作与交流,共同推动频率产品和特殊电池技术的创新与发展。同时,公司还建立了完善的全球销售网络,确保产品能够在短时间内送达全球各地的客户手中。

故事四:认证与品质保证

为了进一步提升产品质量和客户满意度,Geyer Electronic积极寻求国际认证。公司通过了DIN ISO 9001:2015等国际质量管理体系认证,这标志着Geyer Electronic在质量管理方面已经达到了国际先进水平。通过严格的质量控制和持续的技术创新,Geyer Electronic不断推出高品质的频率产品和特殊电池,赢得了全球客户的广泛认可和信赖。

故事五:搬迁与未来发展

为了满足未来发展的需要,Geyer Electronic于2022年搬到了位于Planegg的新公司所在地。这次搬迁不仅为公司提供了更加宽敞和现代化的办公和生产环境,还为公司未来的发展奠定了坚实的基础。在新的起点上,Geyer Electronic将继续秉承“质量第一、客户至上”的经营理念,不断推动技术创新和产品升级,为全球客户提供更加优质、高效的服务和解决方案。同时,公司还将积极探索新的市场领域和发展机遇,努力成为全球电子行业中的佼佼者。

Diodes公司的发展小趣事

随着科技的快速发展和市场的不断变化,客户需求也在不断更新。为了满足客户不断变化的需求,Diodes公司始终保持敏锐的市场洞察力和创新力。公司不断推出新产品、新技术和新应用方案,以满足客户在性能、可靠性、成本等方面的需求。同时,Diodes还积极与客户沟通交流,了解客户的实际需求和反馈意见,不断优化产品和服务。这些努力使得Diodes能够紧跟市场步伐、满足客户需求,在激烈的市场竞争中保持领先地位。

Antenova公司的发展小趣事

除了优秀的产品外,Antenova公司还提供一系列专业的服务,包括产品结构确认和指导、主板Gerber文件和PCB堆叠预审和检查等。这些服务帮助客户更好地使用Antenova的产品,并提高了客户的满意度和忠诚度。通过提供卓越的服务,Antenova赢得了众多客户的信赖和支持,为公司的长期发展奠定了坚实基础。

Future Designs, Inc. (FDI)公司的发展小趣事

为了进一步提升公司的竞争力和市场份额,FDI实施了国际化战略。他们积极拓展海外市场,与多个国家和地区的客户建立了合作关系。通过参加国际展会、设立海外分支机构等方式,FDI不断提升品牌知名度和影响力。同时,他们还加强与当地供应商和合作伙伴的合作,共同开拓市场,实现互利共赢。这些努力使得FDI在全球电子行业中的地位日益稳固。

Grayhill公司的发展小趣事
选择高质量的元件,如功率晶体管、电容、电阻等,以保证电路的稳定性和可靠性。
ALD [Advanced Linear Devices]公司的发展小趣事
由于扩展输出电流会增加功率损耗,因此必须充分考虑散热问题,避免元件过热损坏。

问答坊 | AI 解惑

《Keil –C51 编译器用户手册 中文完整版》403页

《Keil –C51 编译器用户手册 中文完整版》403页 非常有用!!…

查看全部问答>

GSM相关的词汇中英对照

数字、英文 1/4比特数 quarter bit number AGC恢复时间 AGC recovery time AGC启动时间 AGC attack time ATM技术 asynchronous transfer technics, 异步转移模式,为多种速率信 息的情况下研究的一种合适的传输与交换方式。 GSM 泛欧数字蜂窝 ...…

查看全部问答>

如何在ATMAGE16L上写些测试程序

        第一次接触到单片机这块,前几天老师给了我一块带ATMAGE16L的开发板,上面只有一个JTAG接口,一个flash存储块,还有一个8兆的晶振元件(上面标有8.000,我对硬件不熟悉,不知道是不是这么称呼),要求我用8兆的晶振 ...…

查看全部问答>

构造函数,构造函数,构造函数,构造函数,构造函数,构造函数

evc4开发环境 我自己写了一个类。 CRulers::CRulers() {         CRect rect;         GetClientRect(rect);         m_X = 20;         m_DownY =(m_rec ...…

查看全部问答>

菜鸟求救,evc4.0编译后连接模拟器时遇到的问题!

从网上下载了一个mp3播放器的代码应该是wince5.0自带的媒体播放器,在EVC4.0下能够编译,但连接后启动模拟器时就弹出一个对话框,出现下面的错误提示!(SDK是自己导出的,不是标准的SDK,CPU没选是在模拟器下运行的) The   specified& ...…

查看全部问答>

CCS编译错误error:symbol referencing errors-`f14.out` not built

如题目。我编译的时候只有这一个错误,请问谁能帮我指点一下到底错在哪里了??…

查看全部问答>

S3C6410 IIC驱动问题

s3c6410_iic.dll 文件可以被加载,也生成了IIC0设备,但是IIC_Init()函数里的打印信息没有输出来: DEBUGMSG(1,(TEXT(\"+IIC_Init\\r\\n\"))); 打开IIC0设备进行操作也没有信号丛SCL与SDA输出。 为什么驱动被加载了,但没有跑IIC_Init()函数 ...…

查看全部问答>

如何做一名优秀职员

你想力争上游吗?你想成为一名优秀职员吗?你想在企业中实现自己的人生价值吗?请欣赏下面的演讲稿。 今天,对于当选为优秀职员的人来说,是一个难忘的日子!   今天,对于当选为优秀职员的人来说,是一个收获的日子!   今天,更是一位 ...…

查看全部问答>

Linear成立三十年 NS被TI收购及其他

Linear公司于1981年9月26日建立,今天刚好是其30岁生日,公司由Bob Widlar、Bob Swanson以及Bob Dobkin创办。作为从美国国家半导体分拆出的业务部门,Linear一直扎根于模拟IC业,而其“导师”NS(美国国家半导体)最近十余年一直在迷失着方向。从收 ...…

查看全部问答>

msp430 AD转换

我用的是msp430f149型,想要用A5通道测外部电压,并在1602上显示出来,但程序烧进去后A5通道还未连接任何待测器件时1602上就显示了1.87V的电压。当我依次测十二个电阻串联时的电压时 前两个还是准的可约到后面测的越不准了,电压变化越来越小。这是 ...…

查看全部问答>