串口接收环形缓冲区
缓冲区大小:从100减至64,节省36字节。结构体优化:使用uint8_t和位域,减少变量占用。环形缓冲区:避免越界并提高内存利用率。溢出处理:通过标志位通知主程序,避免数据丢失。
·
最近写串口程序,了解到一种环形缓冲写法,故搜集资料记录下来
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)。
更多推荐



所有评论(0)