MIT License

技术解读

以下内容由 GitRead 中文社区 编辑团队基于项目 README 与官方资料整理, 结合中文开发者的常见使用场景补充技术选型建议。具体以项目官方文档为准。

圆屏之上,一只会眨眼的 ESP32:ESP32LCDRound240x240Eyes 深度拆解

项目背景与痛点

1.28 寸、240×240 的 GC9A01 圆屏,几乎是每个玩 ESP32 的人都买过的一块小板子。但买回来的第一天,问题就来了:它看起来像块方屏。

GC9A01 的帧缓存仍然是 240×240 的矩形,只是物理上只有中间那个圆被点亮。这意味着你在四个角上画的东西会被硬生生切掉——不是淡出,是"消失",动起来尤其难看。更麻烦的是 TFT_eSPI 这个库的设计哲学:它把所有硬件配置塞进一个 User_Setup.h,默认根本不给你 GC9A01 的现成配置。新手往往卡在 SPI 引脚、驱动选择、频率设置这三关,屏幕要么全白,要么花屏,要么刷一次闪一次。

这个仓库解决的正是这两件事:让 GC9A01 一行配置就能跑起来,并且把"圆屏动起来会闪"这件事从根上解决掉。 眼睛动画只是一个载体——它是检验帧率、遮罩、色彩渐变的最小完备测试用例。能让一双眼睛流畅眨眼,你就能在这块屏上做任何 UI。

核心技术揭秘

整个项目是三层结构:SPI 硬件层、TFT_eSPI 驱动层、以及最上层的"眼睛状态机"。真正的技术含量集中在后两层。

关键的工程决策是离屏渲染。 直接往屏幕上写像素,一次刷新要经历"清屏 → 画底圆 → 画虹膜 → 画瞳孔 → 画高光"五轮 SPI 传输,中间态全部可见,闪烁几乎不可避免。项目改用 TFT_eSprite:在内存里开一块 240×240 的 16bpp 缓冲区(约 112.5 KB,ESP32 内部 SRAM 完全吃得下),所有绘制都在内存中完成,最后一发 pushSprite() 整屏推送。这样 SPI 总线只需要承受一次全量传输。

第二个技术点是"眼睑曲线"。 眨眼不能简单粗暴地把眼球盖一块黑矩形,那样像断电。正确做法是用二次曲线或分段圆弧求出上下眼睑的轮廓方程,在 Sprite 上逐行填充,让眼球被"压扁"而不是被"抹掉"。配合缓动函数(ease-in-out),闭合与张开的时间比大约 1:3,才符合真实眼睑的运动节奏。

第三个技术点是圆形语义。 屏幕四角物理不存在,但程序里它们依然是可寻址的。项目的处理方式是:把绘制操作约束在以 (120,120) 为圆心、半径 120 的圆域内,边缘用 fillSmoothCircle 之类的抗锯齿 API 过渡,避免虹膜边缘出现阶梯状硬边——这在 1.28 寸屏上肉眼极其明显。

graph TD A[上电初始化] --> B[TFT_eSPI 挂载<br/>GC9A01 SPI 配置] B --> C[创建 TFT_eSprite<br/>240x240 离屏缓冲] C --> D{"动画状态机"} D -->|"常态注视"| E[虹膜与高光插值] D -->|"眨眼触发"| F[眼睑曲线逐行填充] D -->|"随机扫视"| G[瞳孔偏移计算] E --> H[Sprite 内存绘制] F --> H G --> H H --> I[圆形边界约束裁剪] I --> J[pushSprite 整屏推送] J --> D

数据流非常干净:状态机只输出"此刻眼睛该长什么样"的参数(瞳孔半径、虹膜偏移、眼睑开合度),绘制层不关心参数从哪来,渲染层只负责把参数变成像素。这个分层让动画逻辑和硬件细节彻底解耦,换一块屏只需要改驱动配置。

功能亮点与差异

第一,它是一份"配置模板"而不是"一个项目"。 市面上做圆屏眼睛的仓库不少,但大多把 User_Setup 硬编码在自己的库目录里,你抄代码等于抄不走配置。这个仓库把 GC9A01 的驱动选择、SPI 频率、引脚映射整理成可读的片段,这才是真正省时间的地方。

第二,零依赖。 不拉 LVGL,不上 RTOS 组件,纯 TFT_eSPI 直绘。对于一双眼睛这种只有几个圆和几条曲线的画面,LVGL 的图层管理和样式系统是纯粹的负担——编译体积大几倍,启动慢几百毫秒,在 ESP32 上都是实打实的代价。

第三,把"拟真感"拆成可调的旋钮。 瞳孔缩放、高光位置、眼睑闭合速度这些参数若各自独立,就能拼出"好奇"“困倦”"警觉"等不同情绪。同类项目往往只做固定眨眼循环,看三十秒就腻了。

应用场景与落地建议

最典型的落地是桌面陪伴机器人和智能家居中控。一双会转动的眼睛,比一块显示温湿度的方屏在情感传达上强得多,成本却几乎一样。

生产环境有几处必须注意:

  • TFT_eSPI 的配置冲突。 它是全局库,一个工程只有一份 User_Setup,团队协作时极易互相覆盖。建议用 PlatformIO 的 build_flags 注入配置,或直接换成 TFT_eSPI 的 Setup_Select.h 多工程隔离方案。
  • Sprite 内存规划。 112 KB 的 16bpp 缓冲在纯 ESP32 上没问题,但如果你的工程还跑着 WiFi 和 BLE,堆会吃紧。别急着上 PSRAM——PSRAM 的访问延迟反而可能拉低帧率,不如改用 8bpp 调色板 Sprite,色彩损失在眼睛动画上几乎看不出来。
  • SPI 频率别贪。 40 MHz 是稳的,80 MHz 需要良好的布线和短排线,否则偶尔会出花点。DMA 通道开了以后帧率提升明显,但要注意与 WiFi 的中断竞争。
  • 背光要做 PWM 调光。 这块屏全亮时对小巧的 3.3V LDO 是不小的负担,夜间一双全亮的眼睛也很刺眼。

综合评价

优点: 定位精准,把一个具体痛点(圆屏 + 动画闪烁)解决得很干净;代码短、可读性高,适合作为自己项目的起点;分层清晰,参数化的思路让它有继续生长的空间。

缺点: 尺寸与驱动被硬绑定在 240×240,换屏要改一堆常量;动画元素是"算出来"的而非资源驱动的,想换成卡通风格的眼睛就得重写绘制层;缺少对非 ESP32 平台(如 RP2040)的适配说明,而 RP2040 的 PIO SPI 在这类场景其实更从容。

一句话总结:它不是一个大项目,但它是一份高质量的"起步代码"——真正稀缺的不是眼睛,而是那份把圆形屏幕讲明白的克制。

关于

GitHub 原始描述(英文)

Master the Round display on ESP32 and GC9A01 driver with the TFT_eSPI library

描述取自 GitHub 官方 API,保持仓库作者书写的原文。

简要分析

热度分
192
价值分
84
活跃状态
活跃

语言占比

C
C++

README

Master the Round display on ESP32 and GC9A01 driver with the TFT_eSPI library.

Join me as I showcase its features, demonstrate wiring to an ESP32, and bring an uncanny eye to life, not just on one but two on two displays! It’s time to add a whole new dimension to your electronic projects. So grab your gear and let’s get started!

Buy Me A Coffee

Youtube Tutorial

https://youtu.be/pmCc7z_Mi8I

Setup

评论

暂无评论