当前位置:网站首页>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 ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧
关注我的微信公众号,回复“加群”按规则加入技术交流群.点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看.边栏推荐
- iNeuOS工业互联网操作系统,设备运维业务和“低代码”表单开发工具
- BM5 合并k个已排序的链表
- leetcode 665. Non-decreasing Array 非递减数列(中等)
- How programmers learn open source projects, this article tells you
- Short-circuit characteristics and protection of SiC MOSFETs
- 第六章
- Get Douyin Video Details API
- 基于STM32 环形队列来实现串口接收数据
- GAC Honda Safety Experience Camp: "Danger" is the best teacher
- MySQL---Basic select statement
猜你喜欢

手把手教你学会部署Nestjs项目

Architecture Battalion Module 8 Homework

OSPFv3的基本配置

All-platform GPU general AI video supplementary frame super-score tutorial

Architect 04 - Application Service Encryption Design and Practice

ReentrantLock原理(未完待续)

Jiuqi ny3p series voice chip replaces the domestic solution KT148A, which is more cost-effective and has a length of 420 seconds

使用 Flutter 和 Firebase 制作!计数器应用程序

MySQL---operator
![[PIMF] OpenHarmony Thesis Club - Inventory of the open source Hongmeng tripartite library [3]](/img/8c/22e083d2a9a4a6f983b985fe454893.png)
[PIMF] OpenHarmony Thesis Club - Inventory of the open source Hongmeng tripartite library [3]
随机推荐
Unity 之 音频类型和编码格式介绍
返回一个零长度的数组或者空的集合,不要返回null
matplotlib ax bar color Set the color, transparency, label legend of the ax bar
Chinese encoding Settings and action methods return values
老牌音乐播放器 WinAmp 发布 5.9 RC1 版:迁移到 VS 2019 完全重建,兼容 Win11
Shell script quick start to actual combat -02
Thymeleaf是什么?该如何使用。
ReentrantLock原理(未完待续)
角色妆容的实现
【论文精读】iNeRF
【公开课预告】:超分辨率技术在视频画质增强领域的研究与应用
架构实战营模块八作业
Introduction to Audio Types and Encoding Formats in Unity
Given an ip address, how does the subnet mask calculate the network number (how to get the ip address and subnet mask)
iNeuOS工业互联网操作系统,设备运维业务和“低代码”表单开发工具
ResNet的基础:残差块的原理
【Yugong Series】July 2022 Go Teaching Course 023-List of Go Containers
SiC MOSFET的短路特性及保护
京东获取商品历史价格信息 API
C# 之 扑克游戏 -- 21点规则介绍和代码实现
