文章目录
- 说明&感谢
- 环形缓冲区作用
- 编程步骤
- 代码&分析
- 实验现象
- 源代码
说明&感谢
- 互联网是个开放的世界, 感谢无数开源和分享者, 本次学习主要参考了杰杰的分享, 经了解杰杰现在大学尚未毕业, 而本人工作8年了, 闻道有先后术业有专攻,再次感谢!
- 参考链接: 杰杰CSDN
环形缓冲区作用
串口数据接收, 如果数据量过大, 很可能来不及处理这些数据, 因此需要把接收的数据存放到一个位置缓存, 待空闲时间处理, 防止接收的数据丢失; 环形缓冲区越大, 那么可以缓存的数据就越多, 这样就是以空间换时间的做法.
编程步骤
- UART初始化, 打开串口发送和接收;
- UART中断优先级配置NVIC;
- 环形缓冲区定义
- 环形缓冲区数据接收: 在串口中断中读取收到的数据到环形缓冲;
- 环形缓冲区数据发送: 在主程序中把环形缓冲区的数据发送给串口;
代码&分析
#define RINGBUFF_LEN 200 //定义最大接收字节数
#define FLASE 1
#define TRUE 0
- 结构体定义, 定义了头位置, 尾位置, 和头尾之间间隔数(lenght)
typedef struct
{
uint16_t heard;
uint16_t tail;
uint16_t lenght; //这个长度指头到尾的长度
uint8_t ring_buffer[RINGBUFF_LEN]; //环形缓冲区数组
}RingBufferStruct;
- 每写一个数据到缓冲区, 尾的位置+1, 即第一次写数据到数组ring_buffer[0], 那么下一次数据写到ring_buffer[1]; 且和头的间隔lenght增加1;
uint8_t write_ring_buffer(uint8_t data)
{
if(RingBuffer.lenght >= RINGBUFF_LEN)
{
return FLASE;
}
RingBuffer.ring_buffer[RingBuffer.tail] = data;
RingBuffer.tail = (RingBuffer.tail + 1) % RINGBUFF_LEN;
RingBuffer.lenght++;
return TRUE;
}
- 每读一个数据, 则头+1; 即第一次读ring_buffer[0], 下一次读数据就是ring_buffer[1]; 且和尾的间隔lenght减1;
uint8_t read_ring_buffer(uint8_t *rData)
{
if(RingBuffer.lenght == 0)
{
return FLASE;
}
*rData = RingBuffer.ring_buffer[RingBuffer.heard];
RingBuffer.heard = (RingBuffer.heard + 1) % RINGBUFF_LEN;
RingBuffer.lenght--;
return TRUE;
}
void USART1_IRQHandler(void)
{
if(USART_GetFlagStatus(DEBUG_UART, USART_FLAG_RXNE))
{
USART_ClearFlag(DEBUG_UART,USART_FLAG_RXNE);
write_ring_buffer(USART_ReceiveData(DEBUG_UART));
}
}
- 主程序中, 把环形缓冲区的数据读出来, 发送到串口, 打印出来
uint8_t data;
if(0==read_ring_buffer((uint8_t*) &data))
{
USART_SendData(DEBUG_UART,data);
}
实验现象
如果单次发送的数据大于环形缓冲区的大小, 还是会有丢数据的可能;
源代码
MCU型号: STM32F103VET6
开发板: 野火指南者
平台: keil V5.27.0.0
源代码
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)