如何做OLED 屏幕绘图函数中节约存储空间
核心优化策略1. 分页缓冲机制 (Page Buffering)
传统方法:全帧缓冲 (1024字节 for 128x64)
优化方法:按页处理 (8页 × 128字节 = 1024字节 → 单页 128字节)
// 分页绘图函数
void draw_horizontal_line_page(uint8_t page, uint8_t start_x, uint8_t end_x) {
uint8_t buf;
read_page(page, buf); // 读取当前页
for(uint8_t x = start_x; x <= end_x; x++) {
buf |= 0x01; // 设置最低位 (y0)
}
write_page(page, buf); // 写回修改
}节省:RAM 从 1024字节 → 128字节 (减少 87.5%)
2. 直接显存操作 (Zero-Buffer)
适用场景:简单图形(直线、矩形)
原理:不读回显存,直接写入修改
void draw_vertical_line(uint8_t x, uint8_t start_page, uint8_t end_page) {
for(uint8_t page = start_page; page <= end_page; page++) {
set_cursor(x, page);
write_data(0xFF); // 整列点亮
}
}优势:零缓冲区需求,Flash 占用减少 30%
3. 位运算图形绘制
高效绘制基础图形:
// 绘制矩形框 (无填充)
void draw_rect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) {
draw_h_line(y1/8, x1, x2, 1 << (y1%8)); // 上边
draw_h_line(y2/8, x1, x2, 1 << (y2%8)); // 下边
draw_v_line(x1, y1/8, y2/8, 1 << (y1%8)); // 左边
draw_v_line(x2, y1/8, y2/8, 1 << (y1%8)); // 右边
}4. 精简算法实现
Bresenham 直线算法优化:
void draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) {
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
int dy = -abs(y1-y0), sy = y0<y1 ? 1 : -1;
int err = dx+dy, e2; /* error value e_xy */
while(1) {
draw_pixel(x0, y0);
if (x0==x1 && y0==y1) break;
e2 = 2*err;
if (e2 >= dy) { err += dy; x0 += sx; } /* e_xy+e_x > 0 */
if (e2 <= dx) { err += dx; y0 += sy; } /* e_xy+e_y < 0 */
}
}特点:纯整数运算,无浮点,代码精简 (约 200 字节)
数据存储优化
1. 字体压缩技术
位图垂直存储:
// 传统: 5x8字体 = 5字节/字符 (ASCII 95字符 = 475字节)
// 优化:
const uint8_t font_5x8[] PROGMEM = {
0x00,0x00,0x00,0x00,0x00, // 空格 (32)
0x00,0x00,0x5F,0x00,0x00, // ! (33)
// ...
};RLE 压缩字体:
// 行程编码压缩
const uint8_t font_compressed[] = {
0x03, 0x00, // 3字节0x00 (空格)
0x01, 0x5F, 0x02, 0x00, // !: + 2字节0x00
// ...
};2. 位图处理优化
分块存储位图:
// 128x64 位图 → 分8页存储
const uint8_t bitmap_page0[] = { ... }; // 第0页数据
const uint8_t bitmap_page1[] = { ... }; // 第1页数据
// ...XBM 格式直接使用:
// XBM 是C数组格式,可直接编译
const uint8_t **_bits[] = {
0x00, 0x18, 0x3C, 0x7E, // ...
};
架构级优化
1. 选择性功能编译
// 在头文件中定义功能开关
#define ENABLE_CIRCLE 0
#define ENABLE_TRIANGLE 0
#define ENABLE_FILL 1
#if ENABLE_CIRCLE
void draw_circle(...) { ... }
#endif2. 模块化链接
分离核心与扩展功能:
ssd1306_core.c (必备功能: 文本/点/线)
ssd1306_gfx.c (扩展图形: 圆/多边形)
链接时排除未使用模块
资源节省对比表
优化技术RAM 节省Flash 节省适用场景
分页缓冲机制896字节 (87.5%)无变化所有图形操作
直接显存操作100% (零缓冲)减少 20-40%简单几何图形
Bresenham 算法无变化减少 50-70%直线/圆绘制
字体垂直存储无变化减少 30-50%文本显示
RLE 字体压缩增加 10-20字节减少 40-60%中大型字体集
功能选择性编译无变化减少 20-80%功能定制化项目
实战建议组合
基础显示需求 (传感器数据):
直接显存操作 + 精简字体
预计占用:< 1.5KB Flash + 50字节 RAM
图形界面需求 (简单菜单):
分页缓冲 + Bresenham算法 + 垂直字体
预计占用:~3KB Flash + 128字节 RAM
复杂图形应用 (波形显示):
分页缓冲 + 所有优化算法 + 选择性编译
预计占用:4-6KB Flash + 256字节 RAM 终极优化技巧
// 使用位域极致压缩图形状态
struct {
uint8_t color : 1; // 1位存储颜色
uint8_t reserved : 7;
} pixel_state;
// PROGMEM 存储大型资源
const uint8_t large_bitmap PROGMEM = { ... };
// 内联关键函数
static inline void __attribute__((always_inline))
set_pixel(uint8_t x, uint8_t y) {
// 内联汇编优化
asm volatile(
"lds r24, 0x%0" :: "i" (display_buffer)
);
}黄金法则:优先优化算法而非数据,80%的性能提升来自20%的关键算法优化。实际项目中,分页缓冲+直接显存操作的组合通常能提供最佳性价比。
页:
[1]