# PixelDriver **Repository Path**: Yuan-Prjs/pixel-driver ## Basic Information - **Project Name**: PixelDriver - **Description**: 一个适用于嵌入式单片机的屏幕打点库,可以实现任意x,y轴起点绘制,灵活的字库/位图抽象层,自由创建任意大小的字体和图片,支持负坐标边缘裁切、屏幕环绕(跑马灯效果)、横竖双向排列、自定义稀疏字库索引。全缓冲和半缓冲(可配置)适配不同小内存MCU。 - **Primary Language**: C - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-20 - **Last Updated**: 2026-08-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # PixelDriver 一个适用于嵌入式单片机的屏幕打点库,可以实现任意x,y轴起点绘制,灵活的字库/位图抽象层,自由创建任意大小的字体和图片,支持负坐标边缘裁切、屏幕环绕(跑马灯效果)、横竖双向排列、自定义稀疏字库索引。全缓冲和半缓冲(可配置)适配不同小内存MCU。 常见的屏幕绘制方式是设置column和page地址,然后写入数据。 这有一个缺陷就是64行即一次写入1个字节,屏幕上就是8个pixel. 显示内容行起始位置必须按页也就是8pixel的整数倍,如果要绘制一些复杂画面按页地址显然是不满足的. 那有没有别的方法呢?当然有,就是创建一个缓冲区也可以叫它显存. 一块128x64的单色屏幕我们需要创建一个128x64的缓冲区,由于是单色所以一个字节有8bit,除于8就是1KB, 按像素坐标体系将内容写进缓冲区后,刷新屏幕时全刷或者页刷就能实现任意column、row地址绘制了. 但这就结束了吗?显然没有,1KB的缓冲区对于学习者人手一块F103c8t6来说,8KB ram,64 KB rom确实没什么压力. 在实际开发需求中为了压缩成本恨不得SWD最后都复用成别的IO来使用,就拿目前国产芯片CH32V003 2KB ram,16KB rom. 显存已经用了其一半了,通常栈空间还要扣除512B,所以全屏缓冲不能采用. 我把全缓冲的代码喂给TRAE AI,让它写了个相当实用的半屏双缓冲,缺点是需要注册回调,在回调中绘制内容. 而全缓冲可以在任意代码地点绘制内容.半缓冲分两次绘制,一次上半屏一次下半屏,当然修改宏实现1/4、1/8缓冲,多次绘制耗时会加长. 不过使用时间换空间任然是非常赚的,刷新的帧率只要高于20帧就很流畅了,经测试半缓冲分两次绘制,在24Mhz的RISC-v处理器上 耗时约40-50ms,处在可以接收的范围. 移植非常简单,仅需实现Pixel_Refresh函数即可,将显存数据推送到屏幕上,头文件的屏幕大小以及缓冲区大小修改就可以了. 目前实现负坐标边缘裁切、屏幕环绕(跑马灯效果)、横竖双向排列、自定义稀疏字库索引。 # 使用 .h头文件 头部宏 按需修改 ```c PixelStrmap stF8x16map = { .libBuf = F8X16, .charWidth = 8, .charHeight = 16, .AsciiOffset = ' ', }; PixelBitmap stTempBitmap = { .data = TemperaturePic, .width = 10, .height = 16, }; PixelPicture stTempPic = { .Pic = &stTempBitmap, }; // 注册回调 Pixel_SetDrawCallback(OnPixelDraw); void OnPixelDraw(void) { Pixel_DrawNumber(0, 0, &stF8x16map, 123,1); Pixel_DrawString(0, 0, &stF8x16map, "hello",1); Pixel_DrawPic(0, 0, &stTempPic); } // 刷新 while(1) { Pixel_Refresh(); } ``` ![1](01_page_vs_framebuffer.png) ![2](02_memory_usage.png) ![3](03_double_buffer_flow.png) ![4](04_configurable_buffer.png) ![5](05_performance.png)