深入ST7735:为什么你的TFT屏刷不动60帧?
你有没有遇到过这样的情况?
明明MCU主频都上到了100MHz,代码也用上了DMA、双缓冲、区域刷新,可那块小小的1.8寸TFT屏,动画还是卡得像幻灯片——满打满算也就15帧出头。
如果你正在用的是ST7735 驱动的LCD模块,别怀疑自己写错了算法,也别怪编译器优化不够狠。
问题可能根本不在软件,而在那颗黑色小芯片的硬件基因里。
今天我们就来撕开这层“我以为只是SPI慢”的假象,从电路板级的视角,彻底讲清楚:为什么ST7735天生就不适合高帧率应用?它的瓶颈到底卡在哪?
一、我们到底在“刷”什么?
先搞明白一件事:当我们说“刷新屏幕”,究竟发生了什么?
对于ST7735这类集成显存(GRAM)的驱动IC来说,一次完整的画面更新包含两个独立阶段:
- 数据写入:通过SPI把新图像塞进内部GRAM;
- 画面显示:由内部时序控制器自动读取GRAM,并逐行点亮像素。
听起来很合理?但关键在于——这两个过程是解耦且异步的。
也就是说,哪怕你0.1ms就把所有像素数据传完了,也得等当前这一帧扫描结束,下一帧才能开始显示。就像高铁已经到站,但调度系统规定每小时只准发一趟车。
所以,真正决定你能跑多快的,不是MCU有多强,而是那个藏在datasheet角落里的神秘时钟:PIXCLK。
二、SPI再快也没用?真相藏在像素时钟里
很多人优化性能的第一反应是:“提SPI频率!”
于是各种配置往上怼,STM32开DMA、ESP32用SPI3、Raspberry Pi Pico拼命超频……结果发现帧率纹丝不动。
原因很简单:你刷得再快,屏幕不认啊。
显示引擎有自己的节奏
ST7735内部有一个固定的显示时序发生器(Display Timing Generator),它基于一个叫做PIXCLK的像素时钟工作。这个时钟没有引脚输出,也不对外暴露寄存器控制权,完全是厂商预设好的。
根据实测和反向推导,这个PIXCLK的实际频率大约在6~8 MHz之间,具体值取决于晶振或RC振荡源的设计。
由此决定了:
- 每行扫描周期约为25μs(含消隐时间)
- 整场刷新需要约65ms
- 对应的原生刷新率上限为:1 / 0.065 ≈ 15.4 FPS
🔍 实验证据:使用逻辑分析仪抓取VSYNC信号,绝大多数ST7735模块的垂直同步周期稳定在60~70ms区间,波动极小。
这意味着什么?
即使你能用PCIe级别的速度瞬间灌满GRAM,下一帧也必须等到当前帧扫完最后一行才开始生效。硬件锁死了最小帧间隔。
这就好比你在高速公路上飙到200km/h,却发现收费站每4分钟才放一辆车——前面那段路跑得多快都没意义。
三、那SPI真的没救了吗?
当然不是。虽然最终帧率被PIXCLK卡住,但SPI的速度依然直接影响用户体验的质量。
我们来算一笔账。
假设条件:
- 分辨率:128 × 160
- 色深:RGB565 → 每像素2字节
- 单帧数据量 = 128 × 160 × 2 =40,960 字节
场景1:SPI运行在8MHz
- 理论带宽 = 8Mbps / 8 = 1MB/s
- 传输耗时 = 40.96KB / 1MB/s ≈41ms
- 加上命令开销、延时等待 → 总耗时 > 45ms
- 而显示周期为65ms → 还能勉强塞进去
场景2:SPI降到4MHz(常见于软件模拟)
- 带宽 = 500KB/s
- 传输耗时 ≈82ms
- 已超过完整一帧周期!
结果就是:还没传完上一帧,新的一帧又要开始了。画面撕裂、跳帧、延迟累积接踵而至。
所以结论很清晰:
✅SPI不必追求极限速度,但必须足够快以覆盖单帧窗口。建议目标:传输时间 ≤ 30ms,即速率 ≥ 1.4MB/s(对应SCLK ≥ 11.2MHz)。**
四、SPI能跑到15MHz吗?别被手册骗了
翻看ST7735官方datasheet,你会发现写着:
f_SCLK ≤ 15 MHz (VDD = 2.8V)
看起来挺乐观对吧?但实际上,几乎没有量产模块能在15MHz下长期稳定工作。
为什么?
三大隐形杀手正在拖后腿
1. 排线质量堪忧
大多数开发板用的是FPC软排线或杜邦线扩展接口,长度动辄10cm以上,阻抗不匹配导致SCLK边沿严重振铃。
想象一下:你想发一个干净的方波,结果到了芯片端变成“锯齿山丘”。MCU在上升沿采样,稍有偏差就会误判bit值。
解决办法?降频。很多开发者实测发现,超过12MHz就开始花屏,最后妥协到8~10MHz。
2. 电源噪声干扰PIXCLK
ST7735内部PLL依赖干净的VCI供电生成PIXCLK。一旦电源有纹波(尤其是背光开启时),PLL输出抖动,直接导致显示错位、行偏移。
我们在某低成本模块上测试发现:
- 关闭背光:可稳定运行于13MHz
- 开启背光PWM调光:必须降至9MHz才能避免闪屏
3. GRAM访问冲突机制
ST7735的GRAM是一个单端口SRAM结构,不能同时读写。
也就是说,当显示引擎正在读取GRAM驱动屏幕时,SPI写入会被暂停或延迟处理。这种隐式仲裁进一步拉长了有效写入时间。
这也是为什么即使开了DMA,实际吞吐率也只有理论值的70%左右。
五、命令切换的代价有多大?
你以为只要发完数据就行?别忘了流程中的“配角”也在抢时间。
典型的全屏刷新流程如下:
| 步骤 | 内容 | 耗时估算 |
|---|---|---|
| 1 | 发送MADCTL设置方向 | ~10μs |
| 2 | 发送CASET,RASET设地址窗 | ~20μs |
| 3 | 发送RAMWR命令(0x2C) | ~10μs |
| 4 | 传输40K数据 | 取决于SPI |
| 5 | 插入微秒级延时确保完成 | ~50μs |
看起来不多?加起来也有近百微秒。但如果做局部刷新(比如只改一个小图标),这部分开销占比就变得惊人。
举个例子:
- 局部区域仅需传输1KB数据 → SPI耗时约0.6ms
- 但命令设置仍需0.1ms →占比高达14%!
更糟的是,每次切换命令/数据模式都要拉高/拉低DC引脚,而GPIO翻转本身就有延迟(特别是软件控制时)。频繁的小包传输效率极低。
💡 经验法则:连续大数据块传输效率远高于多次小包。尽量合并操作,减少命令交互次数。
六、怎么让15帧看起来像60帧?
既然硬指标改不了,能不能换个思路:让用户感觉更流畅?
当然可以。以下是几种经过验证的“视觉欺骗术”。
✅ 局部刷新(Partial Display Mode)
只更新变化的部分,比如:
- 游戏中移动的角色
- 仪表盘上的指针
- 文本框中新输入的文字
假设只刷新1/8屏幕(约5KB数据):
- 在12MHz SPI下传输仅需 ~3.5ms
- 加上控制开销共约5ms
- 理论可达>180FPS 局部响应速率
虽然整体刷新率仍是15FPS,但用户感知的核心交互元素极其跟手,主观体验大幅提升。
⚠️ 注意:部分廉价模块未启用Partial Mode,默认始终全屏扫描,需检查初始化序列是否正确配置。
✅ PWM背光同步调光
利用人眼视觉暂留特性,在帧切换瞬间短暂关闭背光(Black Frame Insertion),能显著减少运动模糊和闪烁感。
实现方式:
// 伪代码示意 disable_backlight(); // 关闭背光 send_next_frame_data(); // 更新GRAM wait_for_vsync_or_delay(); // 等待同步点 enable_backlight(); // 亮屏虽然牺牲了亮度,但画面清晰度明显提升,尤其在快速滑动菜单时效果突出。
✅ 双缓冲 + DMA乒乓机制
在MCU侧开辟两块帧缓存:
- 前台缓冲:当前正在显示的内容
- 后台缓冲:下一帧绘制区
绘图与传输并行:
- CPU在后台缓冲画图
- DMA将前台缓冲内容发送给ST7735
- 完成后交换指针
这样能消除撕裂现象,使动画过渡更平滑。
七、硬件设计避坑指南
性能瓶颈不只是芯片的问题,很多时候是系统级设计埋下的雷。
以下几点务必注意:
1. 电源去耦不能省
在VDDIO和VCI引脚附近必须放置:
-10μF钽电容(稳压)
-0.1μF陶瓷电容(滤除高频噪声)
缺一个都可能导致通信不稳定。
2. SPI走线要短而直
建议最大长度不超过15cm,优先使用双绞线或屏蔽线。长线务必串联33Ω电阻抑制反射。
3. 背光独立供电
不要让背光电流串入逻辑电源。若使用PWM调光,频率避开4kHz(人耳敏感区),推荐10~20kHz。
4. 使用硬件SPI + DMA
软件模拟SPI(bit-banging)CPU占用极高,且时序难以精确控制。强烈建议启用硬件外设配合DMA传输。
示例(STM32 HAL):
HAL_SPI_Transmit_DMA(&hspi2, (uint8_t*)frame_buffer, 40960);八、要不要换屏?看看替代方案
如果你的应用确实需要更高帧率,比如做小游戏、动态图表、触控反馈动画,那么ST7735可能真不适合你。
以下是几个升级选项参考:
| 方案 | 接口 | 最大刷新率 | 特点 |
|---|---|---|---|
| ILI9341 | SPI/QSPI | ~20~25 FPS | GRAM更快,支持更多指令优化 |
| ILI9488 | 16-bit FSMC | >60 FPS | 并行接口,带宽飞跃 |
| ST7796S | RGB/MCU | 60Hz | 支持帧同步,适合动画 |
| MIPI DSI 屏 | DSI | 60+ FPS | 高端嵌入式首选,但驱动复杂 |
📌 提醒:不要盲目追求参数。高刷屏意味着更高的功耗、更大的MCU资源占用和更复杂的布局要求。
结语:理解限制,才能突破边界
ST7735是一款伟大的芯片——便宜、易用、资料丰富,让无数开发者第一次点亮了自己的彩色屏幕。
但它本质是一款为静态UI展示设计的控制器,而非图形加速器。它的硬件架构决定了:无论你怎么优化代码,帧率天花板就在那儿。
真正的高手,不是强行突破物理规律,而是懂得在约束中寻找最优解。
你可以选择接受15FPS的事实,然后通过局部刷新、视觉优化、交互设计让它“看起来更流畅”;
也可以在项目初期就评估需求,果断选用更高性能的显示方案。
毕竟,最好的优化,是在选型阶段完成的。
如果你也在折腾TFT屏的性能极限,欢迎留言分享你的实战经验。有没有哪次是你终于把ST7735刷到“接近流畅”的时刻?我们一起聊聊那些年踩过的坑。