最近写串口程序,了解到一种环形缓冲写法,故搜集资料记录下来

1、调整缓冲区大小

根据实际需求减小缓冲区大小,例如从100字节减至64字节,显著减少RAM使用。

#define USART_BUF_SIZE 64  // 根据实际需求调整

2. 使用环形缓冲区

改用头尾指针管理数据,避免线性索引越界,并提高内存利用率。

struct usart_struct {
    volatile uint8_t head;         // 写入位置
    volatile uint8_t tail;         // 读取位置
    uint8_t buf[USART_BUF_SIZE];
    volatile uint8_t overflow : 1; // 缓冲区溢出标志
};
struct usart_struct usart0;

3. 优化数据类型和结构体布局

使用uint8_t代替整型,利用位域节省空间。

// 示例结构体优化后:
#include <stdint.h>
struct usart_struct {
    volatile uint8_t head;
    volatile uint8_t tail;
    uint8_t buf[USART_BUF_SIZE];
    volatile uint8_t overflow : 1; // 溢出标志
    // 其他标志位可合并至此
};

4. 修正中断服务例程

修复数组越界问题,并实现环形写入。

ISR(USART_RXC_vect) {
    uint8_t data = UDR; // 读取数据
    uint8_t next_head = (usart0.head + 1) % USART_BUF_SIZE;

    if (next_head != usart0.tail) { // 缓冲区未满
        usart0.buf[usart0.head] = data;
        usart0.head = next_head;
    } else {
        usart0.overflow = 1; // 设置溢出标志
    }
}

5. 主程序中处理数据

在主循环中读取数据,避免在中断中处理耗时操作。

// 示例:主程序读取缓冲区
while (usart0.tail != usart0.head) {
    uint8_t data = usart0.buf[usart0.tail];
    usart0.tail = (usart0.tail + 1) % USART_BUF_SIZE;
    // 处理data...
}

优化点总结:

  • 缓冲区大小:从100减至64,节省36字节。
  • 结构体优化:使用uint8_t和位域,减少变量占用。
  • 环形缓冲区:避免越界并提高内存利用率。
  • 溢出处理:通过标志位通知主程序,避免数据丢失。

注意事项:

  • 原子操作:确保主程序读写缓冲区时禁用中断,防止数据竞争。
  • 编译器优化:启用-Os选项减少代码体积。
  • 数据类型:确保所有变量使用最小适用类型(如uint8_t)。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐