打印
[学习资料]

如何做OLED 屏幕绘图函数中节约存储空间

[复制链接]
90|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
小明的同学|  楼主 | 2025-6-20 19:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
核心优化策略

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[128];
    read_page(page, buf); // 读取当前页
   
    for(uint8_t x = start_x; x <= end_x; x++) {
        buf[x] |= 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 字节)

使用特权

评论回复
沙发
小明的同学|  楼主 | 2025-6-20 19:57 | 只看该作者
数据存储优化

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, // !: [0x5F] + 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, // ...
};





使用特权

评论回复
板凳
小明的同学|  楼主 | 2025-6-20 19:58 | 只看该作者
架构级优化

1. 选择性功能编译

// 在头文件中定义功能开关
#define ENABLE_CIRCLE   0
#define ENABLE_TRIANGLE 0
#define ENABLE_FILL     1

#if ENABLE_CIRCLE
void draw_circle(...) { ... }
#endif
2. 模块化链接
分离核心与扩展功能:

ssd1306_core.c (必备功能: 文本/点/线)

ssd1306_gfx.c (扩展图形: 圆/多边形)

链接时排除未使用模块



使用特权

评论回复
地板
小明的同学|  楼主 | 2025-6-20 19:59 | 只看该作者
资源节省对比表

优化技术
RAM 节省
Flash 节省
适用场景
分页缓冲机制896字节 (87.5%)无变化所有图形操作
直接显存操作100% (零缓冲)减少 20-40%简单几何图形
Bresenham 算法无变化减少 50-70%直线/圆绘制
字体垂直存储无变化减少 30-50%文本显示
RLE 字体压缩增加 10-20字节减少 40-60%中大型字体集
功能选择性编译无变化减少 20-80%功能定制化项目


使用特权

评论回复
5
小明的同学|  楼主 | 2025-6-20 19:59 | 只看该作者
实战建议组合
基础显示需求 (传感器数据):

直接显存操作 + 精简字体

预计占用:< 1.5KB Flash + 50字节 RAM

图形界面需求 (简单菜单):

分页缓冲 + Bresenham算法 + 垂直字体

预计占用:~3KB Flash + 128字节 RAM

复杂图形应用 (波形显示):

分页缓冲 + 所有优化算法 + 选择性编译

预计占用:4-6KB Flash + 256字节 RAM

使用特权

评论回复
6
小明的同学|  楼主 | 2025-6-20 20:00 | 只看该作者
终极优化技巧

// 使用位域极致压缩图形状态
struct {
    uint8_t color : 1;   // 1位存储颜色
    uint8_t reserved : 7;
} pixel_state;

// PROGMEM 存储大型资源
const uint8_t large_bitmap[1024] 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%的关键算法优化。实际项目中,分页缓冲+直接显存操作的组合通常能提供最佳性价比。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

155

主题

1606

帖子

2

粉丝