党新苗 发表于 2025-6-11 15:26:08

STM32串口缓冲区

在嵌入式开发中,外设通信(如UART、SPI、I2C)的数据接收常面临两大挑战:不定时、不定量数据的实时处理和高频率数据流下的稳定性保障。传统的轮询方式效率低下,而中断驱动的接收逻辑又容易因处理延迟导致数据丢失。
本文提出了一种基于STM32 HAL库的轻量级环形缓冲区解决方案!
已解决
非阻塞数据接收:避免因数据处理延迟导致外设中断阻塞
动态数据缓存:支持UART、SPI、I2C等多种外设的异步数据流
内存高效利用:通过环形缓冲区设计减少内存碎片
跨平台兼容:提供GCC与Keil双版本静态库,无缝适配不同开发环境
实现原理

[*]HAL库的RxXferCount机制
STM32 HAL库为每个外设句柄(如UART_HandleTypeDef)维护了RxXferCount成员。该计数器在每次接收一个字节后递增,当传输完成时触发回调并重置。项目通过监控RxXferCount的值变化,动态追踪接收数据的边界。
[*]环形缓冲区设计
写入策略:通过比较当前RxXferCount与上次记录值的差值,计算新数据长度
覆盖保护:当缓冲区满时自动覆盖旧数据(可配置为阻塞模式)
使用示例
#include "peripheral_buff.h"

PeripheralBufHandle PeripheralUart1Buf;
UART_HandleTypeDef uart1_handle;

char uart1_buffer;
int uart1_buffer_len;

int main()
{
    HAL_Init();
    SystemClock_Config(); // 此处未实现
    USART1_Init(921600);// 此处未实现

    // 缓冲区初始化
    PeripheralUart1Buf = PeripheralBuffer_Init((const uint16_t *)&uart1_handle.RxXferCount, 1024);
    if (!PeripheralUart1Buf)
    {
      printf("peripheral_buffer 初始化失败!(calloc();返回 NULL,检查 startup_stm32fxx_hd.s Heap_Size 值)\n");
      printf("相关网址: https://blog.csdn.net/weixin_42518229/article/details/108574311 \n");
    }
    // 开启中断接收
    HAL_UART_Receive_IT(&uart1_handle, (uint8_t *)PeripheralUart1Buf->Buf, PeripheralUart1Buf->Size);

    while (1)
    {

      if (PeripheralBuffer_ReadInterval(PeripheralUart1Buf)) // 判断当前传输是否已停止,非必要
      {
            uart1_buffer_len = PeripheralBuffer_ReadAvailable(PeripheralUart1Buf); // 读取缓冲区内内容长度
            if (uart1_buffer_len > 0)
            {
                if (uart1_buffer_len > sizeof(uart1_buffer))
                  uart1_buffer_len = sizeof(uart1_buffer);
                PeripheralBuffer_ReadBytes(PeripheralUart1Buf, uart1_buffer, uart1_buffer_len); // 读取缓冲区内内容
                uart1_buffer = 0;
                printf("缓冲区数据 %s\n", uart1_buffer);
            }
      }
      HAL_Delay(10);
    }
    return 0;
}注意
1.单次接收超长文件而又未及时处理,会导致数据覆盖。
2.用户缓冲区数据边界
仓库地址


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: STM32串口缓冲区