# EPD_GFX **Repository Path**: chiyoooo/epd_gfx ## Basic Information - **Project Name**: EPD_GFX - **Description**: 一个面向 ESP32 的通用墨水屏驱动库,当前统一封装了 4 色和 6 色屏幕。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-03-28 - **Last Updated**: 2026-04-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # EPD_GFX 一个面向 ESP32 的通用墨水屏驱动库,当前统一封装了 4 色和 6 色屏幕。 这个仓库的目标是: - 对外保持一套统一接口 - 对内按颜色类型、屏幕尺寸拆分驱动,避免把不同屏幕时序强行揉在一起 - 当前代码里真正实现的是 4 色和 6 色;2 色、3 色目前只保留了枚举入口,尚未提供驱动实现 底层绘图基于 `Adafruit_GFX`,当前支持: - 基础图形绘制 - 文本绘制 - 2/4/8bit 索引 BMP 读取 - 24bit BMP 六色/四色抖动显示 - SD 卡图片轮播示例 - ESP32 上的 FreeRTOS 换图队列与 BUSY 中止 - ESP32 上的“即时打断刷新”换图 ## 当前支持 已实现的面板组合如下: | 系列 | 尺寸 | 分辨率 | 驱动芯片 | 状态 | | --- | ----- | ------- | --------- | --- | | E4 | 1.54" | 200×200 | 200×200 | 已测试 | | E4 | 2.13" | 122×250 | JD79676CB | 已测试 | | E4 | 2.66" | 152×296 | JD79661CA | 已测试 | | E4 | 3.97" | 800×480 | SSD2677 | 已测试 | | E4 | 4.2" | 400×300 | SSD2683 | 已测试 | | E6 | 2.66" | 152×296 | | 已测试 | | E6 | 4.2" | 400×300 | | 已测试 | | E6 | 7.3" | 800×480 | | 已适配 | | E6 | 10.0" | 1600×1200 | EL100UF1 / GDEP100E01 类 | 已接通(请以资料与实机校准) | 说明: - `已测试` 表示当前仓库里已有实机验证记录 - `已适配` 表示驱动、显存格式和示例路径已接通,建议以上板结果为准继续回归 - 4 色面板使用 `2bpp` - 6 色面板通常使用 `4bpp`;**尺寸码 `1000`(GDEP100E01 / EL100UF1)为 `8bpp`**,像素值为 T2001 色码(与《程序注意事项》一致:黑 `0x00`、白 `0xF8`、黄 `0x20`、红 `0x40`、蓝 `0x10`、绿 `0x30`) - 各 E6 面板(除 1000 外)共用 `EPD_GFX::colorToPackedValue()` 的 **4bpp nibble**:逻辑色为黑、白、黄、红、蓝、绿;写入帧缓冲为 `0..3` 与蓝 `0x5`、绿 `0x6`(不使用 `0x4`) - **尺寸码 `1000`**:经 **IT8957 + T2001**,帧缓冲约 **1.92MB**;`EPD_driver_setPanel` 在堆上分配(ESP32 先内部 RAM、不足再 PSRAM),失败则返回 `false`。调用顺序须 **`EPD_driver_begin()`(会初始化 IT8957 SPI,与普通 SPI 面板互斥)→ `init`**;引脚:`busy` = HRDY,`dc` = TCON 上电(与普通屏的 DC 含义不同) - 10" 刷新流程见 `src/drivers/color6/panel_el100uf1.cpp` 与 `src/drivers/gdep100/` 官方移植层 ## 功能边界 当前代码里的接口能力如下: - `EPD_driver_setPanel(colorMode, panelSize)` 只对已实现的组合返回 `true` - `EPD_driver_getBitsPerPixel()` 可区分 4 色 `2bpp`、6 色 `4bpp` 与 10" 六色 `8bpp` - `EPD_GFX::drawBMP()` 当前支持 `2/4/8/24 bpp` - `EPD_GFX::display()` 返回 `bool`;若 BUSY 等待阶段被中止会返回 `false`,并自动重新 `init` - `readID()` 目前只对部分型号实现,未覆盖的面板会直接打印提示 - `sleep()` 对 7.3" 六色使用单独休眠路径;10" 六色会关 TCON;其它六色屏走默认深睡 - ESP32 下可用 `begin(imageCount, instantInterrupt, handler, user, stack)` 启动库内 worker 队列 - `requestShow(index)` 用于向 worker 提交“请显示哪一张” - `showJobObsolete()` 可在解码完成后判断本帧是否已经过期,避免旧图闪上屏 `readID()` 当前实现情况: - 4 色 1.54" - 4 色 2.13" - 6 色 2.66" 以下内容目前还没有真正实现驱动: - 黑白 2 色面板 - 三色面板 - `readID()` 的全型号覆盖 ## 即时打断刷新 这个库支持“用户又发了新请求时,尽量不要傻等上一帧完整刷完”的模式,主要用于 SD 轮播、按键翻页、串口快速跳图这类场景。 工作方式: - 仅在 `ESP32 + FreeRTOS worker` 路径下启用 - 入口是 `EPD_GFX::begin(imageCount, true, handler, user, workerStackBytes)` - 这里第二个参数 `instantInterrupt=true` 时,如果屏幕当前正在 `display()` 的 BUSY 等待阶段,又有新的 `requestShow()` 到来,库会触发 `EPD_driver_requestBusyWaitAbort()` - 当前这次 `display()` 会尽快返回 `false`,驱动自动重新 `init`,然后跟随后续最新请求继续处理 这套机制不是简单“强杀当前任务”,而是分成两层: - 刷屏中止:如果已经进入 `display()` 并在等 BUSY,新请求会触发 BUSY 中止,让当前刷新尽快退出 - 过期帧跳过:如果 worker 还在解码 BMP、写帧缓冲,但这时目标图片已经变了,可以用 `showJobObsolete()` 跳过本次 `display()`,避免旧图上屏 队列本身还做了“合并连按”: - 多次 `requestShow()` 不会机械地把每一帧都刷出来 - worker 会以“最新意图”为准追平请求 - 适合快速连按上一张/下一张、串口连续 `GOTO`、或者自动轮播时中途抢占 相关接口见: - [EPD_GFX.h](D:/FuckArduino/EPD_GFX/src/EPD_GFX.h#L83) - [EPD_SubmittedShow.h](D:/FuckArduino/EPD_GFX/src/EPD_SubmittedShow.h#L25) - [EPD_CoalescedShowRequest.h](D:/FuckArduino/EPD_GFX/src/EPD_CoalescedShowRequest.h#L32) ## 目录结构 ```text src/ EPD_GFX.h EPD_GFX.cpp EPD_driver.h EPD_driver.cpp drivers/ common/ epd_bus.cpp epd_driver_internal.h color4/ panel_154.cpp panel_213.cpp panel_266.cpp panel_397.cpp panel_420.cpp color6/ panel_266.cpp panel_420.cpp panel_730.cpp panel_el100uf1.cpp examples/ common/ EPD_Example_Config.h ExampleRunner.cpp TextAndGraphics_Combo/ TextAndGraphics_Combo.cpp SD_Slideshow_Simple/ SD_Slideshow_Simple.cpp SD_Slideshow_FreeRTOS/ SD_Slideshow_FreeRTOS.cpp ``` 说明: - `EPD_driver.cpp` 只负责统一入口和分发 - `drivers/common` 放 SPI / GPIO / busy / reset 等公共部分 - `drivers/color4` 和 `drivers/color6` 各自保存不同屏幕的独立时序 - 示例统一从 `ExampleRunner.cpp` 进入 - 六色 packed 色码在 `EPD_GFX.cpp` 中与面板尺寸无关,2.66"/4.2"/7.3" 共用 ## 快速开始 ### 1. 打开公共配置文件 所有示例切换都统一放在: [EPD_Example_Config.h](D:/FuckArduino/EPD_GFX/examples/common/EPD_Example_Config.h) 你只需要改这一份文件。 ### 2. 选择示例 ```cpp #define EPD_EXAMPLE_KIND EPD_EXAMPLE_TEXT_AND_GRAPHICS ``` 可选值: - `EPD_EXAMPLE_TEXT_AND_GRAPHICS` - `EPD_EXAMPLE_SD_SLIDESHOW_SIMPLE`(或旧名 `EPD_EXAMPLE_SD_SLIDESHOW`,值 2) - `EPD_EXAMPLE_SD_SLIDESHOW_FREERTOS`(或旧名 `EPD_EXAMPLE_SD_INSTANT_SLIDESHOW`,值 4) - `EPD_EXAMPLE_PANEL_SERIAL_TEST`(值 6) ### 3. 选择颜色和尺寸 ```cpp #define EPD_EXAMPLE_COLOR_COUNT 4 #define EPD_EXAMPLE_SIZE_CODE 266 ``` 可选尺寸代码: - `154` - `213` - `266` - `397` - `420` - `730` - `1000`(10" 六色 EL100UF1 类,需足够 RAM/PSRAM) ### 4. 编译 ```bash pio run ``` ### 5. 烧录 ```bash pio run -t upload ``` ## 旋转方向 示例默认旋转角度跟随屏幕尺寸自动选择,不需要每个示例单独改。 当前默认映射在 [EPD_Example_Config.h](D:/FuckArduino/EPD_GFX/examples/common/EPD_Example_Config.h) 中: - `154 -> EPD_GFX_ROTATION_0` - `213 -> EPD_GFX_ROTATION_0` - `266 -> EPD_GFX_ROTATION_2` - `397 -> EPD_GFX_ROTATION_0` - `420 -> EPD_GFX_ROTATION_0` - `730 -> EPD_GFX_ROTATION_3` - `1000 -> EPD_GFX_ROTATION_0` 如果某块屏要临时覆盖方向,可以在配置文件里直接改默认映射,或者手动定义: ```cpp #define EPD_ROTATION EPD_GFX_ROTATION_1 ``` ## 示例说明 ### 1. TextAndGraphics_Combo 文件: [TextAndGraphics_Combo.cpp](D:/FuckArduino/EPD_GFX/examples/TextAndGraphics_Combo/TextAndGraphics_Combo.cpp) 特点: - 串口「全能台」:色条、文字+图形组合、SD BMP + FreeRTOS 换图队列(`MODE IMG`)可在一条固件里切换 - 不插 SD 时仍可做面板与 GFX 测试;具体命令见该文件头注释 - 支持 `APPLY <颜色数> <尺寸码>` 热切换逻辑面板、`ROT` 改旋转、`MODE BARS/COMBO/IMG` 切模式 - `MODE IMG` 下支持 `NEXT`、`PREV`、`GOTO 3`、`#3`、`G3`,适合专门观察“连发请求 + 过期帧跳过 + 即时打断刷新” - `STACK ` 可调整下一次 `MODE IMG` 使用的 worker 栈,适合调大图/BMP 解码栈空间 - 如果你只想带一条固件做大部分联调,这个示例最合适 适合验证: - 面板选择、旋转、颜色条、基础 GFX 绘图 - `drawBMP()` 和 SD 目录规则 - FreeRTOS worker 队列 - 即时打断刷新 - 串口命令联调流程 ### 2. SD_Slideshow_Simple 文件: [SD_Slideshow_Simple.cpp](D:/FuckArduino/EPD_GFX/examples/SD_Slideshow_Simple/SD_Slideshow_Simple.cpp) 特点: - 主循环里同步 `drawBMP` + `display()`,无换图队列,逻辑最简单 - 默认 SPI 读卡;配置里可切 SDIO - 适合先排除“BMP 文件 / SD 读卡 / 面板时序 / 颜色映射”这些基础问题 - 这条路径没有即时打断刷新,用户发新请求时会等当前这次同步刷新跑完 适合验证: - BMP 解码是否正常 - 某块屏最基础的刷图路径 - 不想引入 worker/并发因素时的最小问题面 ### 3. SD_Slideshow_FreeRTOS 文件: [SD_Slideshow_FreeRTOS.cpp](D:/FuckArduino/EPD_GFX/examples/SD_Slideshow_FreeRTOS/SD_Slideshow_FreeRTOS.cpp) 特点: - `begin(n, worker)` + `requestShow`,刷新可在 BUSY 阶段被新请求打断 - 适合与 Simple 示例对照理解 worker 路径 - 按键和串口都可以发换图请求,示例里已经把“即时打断刷新”接通了 - worker 里在 `drawBMP()` 后会检查 `showJobObsolete()`,所以连按时旧图会被跳过而不是都刷一遍 - 刷新失败或被中止时,`display()` 返回 `false`,示例会提示“已自动 re-init,将跟随后续请求” 适合验证: - 即时打断刷新是否生效 - 按键快速连按是否只落实最新目标 - worker 栈大小是否足够 - 解码期间/刷屏期间被新请求抢占时的行为 ### 4. Panel_Serial_Test 文件: [Panel_Serial_Test.cpp](D:/FuckArduino/EPD_GFX/examples/Panel_Serial_Test/Panel_Serial_Test.cpp) 特点: - 单固件 bench 工具,可通过串口 `APPLY 4 266`、`APPLY 6 730`、`ROT 2`、`DRAW` 快速切换逻辑配置 - 每次切换后会重建 `EPD_GFX` 对象并重画测试图,适合做“这块屏当前到底按哪个型号驱动才对”的排查 - `READID` 也集成进去了,虽然当前仍只覆盖部分面板 适合验证: - 当前固件内哪些面板组合已经实现 - 颜色数 / 尺寸码 / 旋转的基本切换 - 不依赖 SD 的基础回归 ### 5. ExampleRunner 文件: [ExampleRunner.cpp](D:/FuckArduino/EPD_GFX/examples/common/ExampleRunner.cpp) 特点: - 这是统一入口,不是单独演示某个功能的示例 - `platformIO.ini` 只编译它,再由 [EPD_Example_Config.h](D:/FuckArduino/EPD_GFX/examples/common/EPD_Example_Config.h) 选择真正要包含的示例源码 - 这样切换示例时通常不需要改 `platformIO.ini` ## SD 卡配置 SD 卡相关配置也统一放在 [EPD_Example_Config.h](D:/FuckArduino/EPD_GFX/examples/common/EPD_Example_Config.h)。 ### 读取模式 ```cpp #define EPD_SD_USE_SDIO 0 ``` - `0` = SPI - `1` = SDIO (`SD_MMC`) ### SPI 模式配置 ```cpp #define EPD_SD_SPI_BUS HSPI #define EPD_SD_SPI_FREQ 8000000u ``` ### SPI 默认引脚 - `SCK = GPIO40` - `MOSI = GPIO39` - `MISO = GPIO41` - `CS = GPIO38` ### SDIO 默认引脚 - `CLK = GPIO40` - `CMD = GPIO39` - `D0 = GPIO41` - `D1 = GPIO42` - `D2 = GPIO48` - `D3 = GPIO38` 说明: - SPI 模式下仍然保留了 `SDO/D0` 的说明 - 后续如果启用 SDIO,只需要把 `EPD_SD_USE_SDIO` 改成 `1` ## SD 图片目录规则 当前示例默认按“颜色 / 尺寸”分目录: - 4 色 2.13 -> `/E4/213` - 4 色 4.2 -> `/E4/420` - 6 色 2.66 -> `/E6/266` - 6 色 7.3 -> `/E6/730` - 6 色 10" -> `/E6/1000` 如果你想自定义目录,可以在 `SD_Slideshow_Simple.cpp`(或 FreeRTOS 版)中重定义: ```cpp #define EPD_SD_IMAGE_DIR "/你的目录" ``` ## 当前开发方式 这个仓库已经改成: - `platformIO.ini` 固定编译 `ExampleRunner.cpp` - 示例切换由 `EPD_Example_Config.h` 控制 - 屏幕颜色、尺寸、旋转、引脚、SD 模式、SD 引脚都集中在配置头中管理 所以以后通常不需要再改 `platformIO.ini`。 ## 注意事项 ### 1. 不同屏幕不要过度复用 虽然对外接口统一了,但不同屏幕的初始化、刷新、休眠顺序并不完全一样。 这个仓库内部已经按颜色和尺寸拆开,后续新增面板时也建议继续保持这个原则: - 新增自己的独立驱动文件 - 在入口处分发 - 不要为了“看起来通用”去改坏已验证的时序 ### 2. 第一次调试建议先不用 SD 建议顺序: 1. 先跑 `TextAndGraphics_Combo` 2. 确认屏幕方向、颜色、刷新正常 3. 再切到 `SD_Slideshow_Simple` 或 `SD_Slideshow_FreeRTOS` ### 3. E6 颜色码(含 7.3") 图形、文字与 BMP(索引/抖动)最终都经 `colorToPackedValue()` 写入帧缓冲,**不区分** 2.66"/4.2"/7.3"。逻辑顺序为黑、白、黄、红、蓝、绿;硬件 nibble 为 `0x0..0x3`、`0x5`(蓝)、`0x6`(绿)。 ### 4. 本地库依赖 仓库里已经放了本地 `lib/` 依赖,避免在线拉库失败导致无法编译。 ## 相关文件 - 公共配置:[EPD_Example_Config.h](D:/FuckArduino/EPD_GFX/examples/common/EPD_Example_Config.h) - 统一示例入口:[ExampleRunner.cpp](D:/FuckArduino/EPD_GFX/examples/common/ExampleRunner.cpp) - 文字图形示例:[TextAndGraphics_Combo.cpp](D:/FuckArduino/EPD_GFX/examples/TextAndGraphics_Combo/TextAndGraphics_Combo.cpp) - SD 简单轮播:[SD_Slideshow_Simple.cpp](D:/FuckArduino/EPD_GFX/examples/SD_Slideshow_Simple/SD_Slideshow_Simple.cpp) - SD FreeRTOS 轮播:[SD_Slideshow_FreeRTOS.cpp](D:/FuckArduino/EPD_GFX/examples/SD_Slideshow_FreeRTOS/SD_Slideshow_FreeRTOS.cpp) - 驱动入口:[EPD_driver.cpp](D:/FuckArduino/EPD_GFX/src/EPD_driver.cpp)