当前位置:网站首页>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 ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧
关注我的微信公众号,回复“加群”按规则加入技术交流群.点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看.边栏推荐
- Apache EventMesh distributed event-driven multi-runtime
- cas与自旋锁(轻量级锁就是自旋锁吗)
- MySQL---单行函数
- What is Thymeleaf?How to use.
- The server encountered an internal error that prevented it from fulfilling this request的一种解决办法[通俗易懂]
- What's wrong with the sql syntax in my sql
- matplotlib ax bar color 设置ax bar的颜色、 透明度、label legend
- Returns a zero-length array or empty collection, do not return null
- 程序员如何学习开源项目,这篇文章告诉你
- MySQL---创建和管理数据库和数据表
猜你喜欢

【公开课预告】:超分辨率技术在视频画质增强领域的研究与应用

leetcode:6135. 图中的最长环【内向基环树 + 最长环板子 + 时间戳】

如何才能真正的提高自己,成为一名出色的架构师?

Financial profitability and solvency indicators

老牌音乐播放器 WinAmp 发布 5.9 RC1 版:迁移到 VS 2019 完全重建,兼容 Win11

Chinese encoding Settings and action methods return values

利用反射实现一个管理对象信息的简单框架

统计UTF-8字符串中的字符函数

Apache EventMesh 分布式事件驱动多运行时
Cache and Database Consistency Solutions
随机推荐
Tkinter 入门之旅
-xms -xmx(information value)
Redis Overview: Talk to the interviewer all night long about Redis caching, persistence, elimination mechanism, sentinel, and the underlying principles of clusters!...
NVIDIA has begun testing graphics products with AD106 and AD107 GPU cores
广汽本田安全体验营:“危险”是最好的老师
Bika LIMS open source LIMS set - use of SENAITE (detection process)
MySQL---子查询
35 MySQL interview questions and diagrams, this is also easy to understand
【Yugong Series】July 2022 Go Teaching Course 025-Recursive Function
几款永久免费内网穿透,好用且简单(内网穿透教程)
Taobao/Tmall get Taobao password real url API
Getting Started with Tkinter
BOW/DOM(上)
利用反射实现一个管理对象信息的简单框架
rj45对接头千兆(百兆以太网接口定义)
Three.js入门
OSPFv3的基本配置
UVM RAL模型和内置seq
Memblaze发布首款基于长存颗粒的企业级SSD,背后有何新价值?
PCB叠层设计