当前位置:网站首页>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 ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧
关注我的微信公众号,回复“加群”按规则加入技术交流群.点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看.边栏推荐
- 程序员如何学习开源项目,这篇文章告诉你
- Jiuqi ny3p series voice chip replaces the domestic solution KT148A, which is more cost-effective and has a length of 420 seconds
- 【PIMF】OpenHarmony 啃论文俱乐部—盘点开源鸿蒙三方库【3】
- 淘宝/天猫获得淘口令真实url API
- find prime numbers up to n
- leetcode 665. Non-decreasing Array 非递减数列(中等)
- 关注!海泰方圆加入《个人信息保护自律公约》
- MySQL---operator
- ThreadLocal
- 架构实战营模块八作业
猜你喜欢

中文编码的设置与action方法的返回值

Redis综述篇:与面试官彻夜长谈Redis缓存、持久化、淘汰机制、哨兵、集群底层原理!...

NVIDIA has begun testing graphics products with AD106 and AD107 GPU cores

Apache EventMesh distributed event-driven multi-runtime

How can we improve the real yourself, become an excellent architect?

The principle of ReentrantLock (to be continued)

基于STM32 环形队列来实现串口接收数据
Cache and Database Consistency Solutions

MySQL - multi-table query

NVIDIA已经开始测试AD106和AD107 GPU核心的显卡产品
随机推荐
MySQL---Create and manage databases and data tables
How can we improve the real yourself, become an excellent architect?
ReentrantLock原理(未完待续)
OSPFv3的基本配置
获取抖音视频详情 API
Apache EventMesh distributed event-driven multi-runtime
性能优化:记一次树的搜索接口优化思路
Get Douyin Video Details API
请问我的这段sql中sql语法哪里出了错
npm 更改为淘宝镜像的方法[通俗易懂]
高效并发:Synchornized的锁优化详解
老牌音乐播放器 WinAmp 发布 5.9 RC1 版:迁移到 VS 2019 完全重建,兼容 Win11
sqlite3简单操作
深度学习中的batch(batch size,full batch,mini batch, online learning)、iterations与epoch
API for JD.com to obtain historical price information of commodities
中文编码的设置与action方法的返回值
STM32 full series development firmware installation guide under Arduino framework
Three. Introduction to js
MySQL---aggregate function
MySQL---创建和管理数据库和数据表