当前位置:网站首页>Realize serial port receiving data based on STM32 ring queue
Realize serial port receiving data based on STM32 ring queue
2022-07-31 19:44:00 【Li Xiaoyao】
关注、星标公众号,直达精彩内容
原文链接:https://blog.csdn.net/qq_36413982/article/details/103836946
说在前面
Those who code should learn data structures and have learned about queues.A circular queue is a special form of queue,It is widely used.Because there are so many articles about this,Theoretical knowledge can be seen by others,The following is well written:STM32进阶之串口环形缓冲区实现
代码实现
Ring queue data structure
typedef struct ringBuff{
unsigned int in; //写入的位置
unsigned int out; //读出的位置
unsigned char buffer[RING_BUFF_SIZE]; //数据域
}stRingBuff;
Write one byte of data to the queue
/**
- @brief: Write one byte of data to the circular queue
- @param[in]: None
- @retval[out]: None
- @note:
- @author: AresXu
- @version: v1.0.0
*/
char WriteOneByteToRingBuffer(stRingBuff *ringBuf,char data)
{
if (ringBuf == NULL)
{
printf("pointer is null\r\n");
return;
}
if(IsRingBufferFull(ringBuf)) //Before writing, check whether the queue is full
{
return FALSE;
}
ringBuf->buffer[ringBuf->in] = data;
ringBuf->in = (++ringBuf->in) % RING_BUFF_SIZE; //防止越界
return TRUE;
}
When writing data, it is necessary to judge whether the queue is full,When it is full, it cannot be written.
Determine if the queue is full
/**
- @brief: Check whether the ring queue is full
- @param[in]: None
- @retval[out]: None
- @note:
- @author: AresXu
- @version: v1.0.0
*/
bool IsRingBufferFull(stRingBuff *ringBuf)
{
if (ringBuf == NULL)
{
printf("pointer is null\r\n");
return;
}
if(((ringBuf->in+1) % RING_BUFF_SIZE) == ringBuf->out)
{
// printf("Ring buffer is Full\r\n");
return TRUE;
}
return FALSE;
}
当写满时,The read and write positions are also equal,Can't tell if it's full.There are two solutions to this situation:
The data structure adds a variable to count the number of data written
像这种((ringBuf->in+1) % RING_BUFF_SIZE) == ringBuf->out,Free up a byte to not write data

Read one byte of data
/**
- @brief: Read one byte of data from the circular queue
- @param[in]: None
- @retval[out]: None
- @note:
- @author: AresXu
- @version: v1.0.0
*/
char ReadOneByteFromRingBuffer(stRingBuff *ringBuf,char *data)
{
if (ringBuf == NULL)
{
printf("pointer is null\r\n");
return;
}
if(IsRingBufferEmpty(ringBuf)) //Check if the queue is empty before reading
{
return FALSE;
}
*data = ringBuf->buffer[ringBuf->out];
ringBuf->out = (++ringBuf->out) % RING_BUFF_SIZE; //防止越界
return TRUE;
}
判断队列是否为空 Empty when the write position and the read position are equal
/**
- @brief: Check if the ring queue is empty
- @param[in]: None
- @retval[out]: None
- @author: AresXu
- @version: v1.0.0
*/
bool IsRingBufferEmpty(stRingBuff *ringBuf)
{
if (ringBuf == NULL)
{
printf("pointer is null\r\n");
return;
}
if(ringBuf->in == ringBuf->out) //Empty when the write position and the read position are equal
{
// printf("Ring buffer is Empty\r\n");
return TRUE;
}
return FALSE;
}
Write multiple bytes to the queue
/**
* @brief: 寫lenbytes of data to the circular queue
* @param[in]: None
* @retval[out]: None
* @note:
* @author: AresXu
* @version: v1.0.0
*/
void WriteRingBuffer(stRingBuff *ringBuf,char *writeBuf,unsigned int len)
{
unsigned int i;
if (ringBuf == NULL)
{
printf("pointer is null\r\n");
return;
}
for(i = 0; i < len; i++)
{
WriteOneByteToRingBuffer(ringBuf,writeBuf[i]);
}
}
Read multiple bytes from the queue
/**
* @brief: Read from the circular queuelenbytes of data
* @param[in]: None
* @retval[out]: None
* @note:
* @author: AresXu
* @version: v1.0.0
*/
void ReadRingBuffer(stRingBuff *ringBuf,char *readBuf,unsigned int len)
{
unsigned int i;
if (ringBuf == NULL)
{
printf("pointer is null\r\n");
return;
}
for(i = 0; i < len; i++)
{
ReadOneByteFromRingBuffer(ringBuf,&readBuf[i]);
}
}
Get the length of data that has been written to the queue It is convenient to know how much data to read from the queue after receiving.
/**
* @brief: Get the length that has been written
* @param[in]: None
* @retval[out]: None
* @note:
* @author: AresXu
* @version: v1.0.0
*/
int GetRingBufferLength(stRingBuff *ringBuf)
{
if (ringBuf == NULL)
{
printf("pointer is null\r\n");
return;
}
return (ringBuf->in - ringBuf->out + RING_BUFF_SIZE) % RING_BUFF_SIZE;
}
画个图,You can know why by drawing and you can judge the length of the write.
到STM32上测试
Serial port receiving part:
static stRingBuff g_stRingBuffer = {0,0,0};
static u8 g_recvFinshFlag = 0;
stRingBuff *GetRingBufferStruct(void)
{
return &g_stRingBuffer;
}
u8 *IsUsart1RecvFinsh(void)
{
return &g_recvFinshFlag;
}
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 res;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
res = USART_ReceiveData(USART1); //读取接收到的数据
WriteOneByteToRingBuffer(GetRingBufferStruct(),res);
}
if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) //空闲中断
{
USART_ReceiveData(USART1); //清除空闲中断
g_recvFinshFlag = 1; //接收完成
}
}
主函数:
int main(void)
{
char readBuffer[100];
u16 t;
u16 len;
u16 times = 0;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
LED_Init(); //LED端口初始化
KEY_Init(); //初始化与按键连接的硬件接口
while(1)
{
times++;
if(*IsUsart1RecvFinsh())
{
ReadRingBuffer(GetRingBufferStruct(),readBuffer,GetRingBufferLength(GetRingBufferStruct()));
printf("%s",readBuffer);
memset(readBuffer,0,100);
*IsUsart1RecvFinsh() = 0;
}
if(times%500==0)
LED0=!LED0;
delay_ms(1);
}
}
串口收发测试

版权声明:本文来源网络,免费传达知识,版权归原作者所有.如涉及作品版权问题,请联系我进行删除.
‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧ END ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧
关注我的微信公众号,回复“加群”按规则加入技术交流群.
点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看.
边栏推荐
- Redis综述篇:与面试官彻夜长谈Redis缓存、持久化、淘汰机制、哨兵、集群底层原理!...
- Basic configuration of OSPFv3
- 求n以内的素数
- 深度学习中的batch(batch size,full batch,mini batch, online learning)、iterations与epoch
- The principle of ReentrantLock (to be continued)
- 学生管理系统第一天:完成登录退出操作逻辑 PyQt5 + MySQL5.8
- Cache and Database Consistency Solutions
- Batch (batch size, full batch, mini batch, online learning), iterations and epochs in deep learning
- 移动web开发02
- 基于STM32 环形队列来实现串口接收数据
猜你喜欢
Teach you how to deploy Nestjs projects
Redis综述篇:与面试官彻夜长谈Redis缓存、持久化、淘汰机制、哨兵、集群底层原理!...
MySQL---多表查询
Short-circuit characteristics and protection of SiC MOSFETs
关注!海泰方圆加入《个人信息保护自律公约》
【公开课预告】:超分辨率技术在视频画质增强领域的研究与应用
C# 之 扑克游戏 -- 21点规则介绍和代码实现
高通cDSP简单编程例子(实现查询高通cDSP使用率、签名),RK3588 npu使用率查询
手把手教你学会部署Nestjs项目
The whole network is on the verge of triggering, and the all-round assistant for content distribution from media people - Rongmeibao
随机推荐
STM32 full series development firmware installation guide under Arduino framework
全平台GPU通用AI视频补帧超分教程
Teach you how to deploy Nestjs projects
PCB叠层设计
微信小程序的路由拦截
Given an ip address, how does the subnet mask calculate the network number (how to get the ip address and subnet mask)
Bika LIMS open source LIMS set - use of SENAITE (detection process)
Redis综述篇:与面试官彻夜长谈Redis缓存、持久化、淘汰机制、哨兵、集群底层原理!...
How can we improve the real yourself, become an excellent architect?
Routing interception of WeChat applet
手把手教你学会部署Nestjs项目
性能优化:记一次树的搜索接口优化思路
架构实战营模块 8 作业
【核心概念】图像分类和目标检测中的正负样本划分以及架构理解
基于STM32 环形队列来实现串口接收数据
嵌入式开发没有激情了,正常吗?
求n以内的素数
MySQL---operator
35道MySQL面试必问题图解,这样也太好理解了吧
Basic Grammar Introduction of Carbon Tutorial (Tutorial)