2026-08-16 · STM32F405 + UC1617S(I2C1,128×96)
一句话结论
屏幕随机卡死的根因是:电荷泵飞跨电容用飞线连接,长引线的寄生电感把泵的开关噪声放大,经电源/地/辐射耦合进 I2C,随机打歪一个 bit,导致从机状态机错位卡死。 与波特率、上拉、代码、时序均无关。
现象与数据
- 症状:刷新若干帧后屏幕冻结,帧计数器停止。
- 卡死帧数与 I2C 波特率无相关性:
| 波特率 | 卡死帧数 |
|---|---|
| 400kHz | ~15 |
| 100kHz | ~60 |
| 50kHz | ~15 |
| 随机 | 有时能到 200 |
- 换小上拉电阻「好一点」,但未根治。
诊断过程
| 阶段 | 假设 | 结果 |
|---|---|---|
| 1 | 从机太慢 | ❌ 被「50kHz 反而 15 帧卡死」推翻 |
| 2 | 上拉电阻弱 | ⚠️ 改善但未根治 |
| 3 | I2C 超时太短 | ⚠️ 非根因 |
| 4 | 捏住泵电容复现 | ✅ 决定性证据 |
关键实验:用手捏住 VB0±/VB1± 之间的电荷泵电容,卡死立刻复现——手是 50Hz 天线 + 对地大电容,等于直接往高压泵节点灌噪声。这证明噪声源就在电荷泵。
根因机理
电荷泵开关 → 脉冲电流(di/dt 大)↓ 飞线寄生电感 L ≈ 1nH/mm
V = L·di/dt → 泵节点电压振铃(几伏)↓ 三条耦合路径① 传导:VDD 抖动 → I2C 逻辑供电漂移② 地弹:细地线电位差 → 电平被"平移"③ 辐射:飞线当天线 → SDA/SCL 感应毛刺↓
I2C 采样瞬间打歪一个 bit(I2C 无校验)↓
从机状态机错位 → 拉低 SCL 时钟拉伸等死↓
STM32 卡在 HAL_I2C_Master_Transmit → 屏幕冻结
为什么随机:泵开关与 I2C 位时序是两套完全异步的时钟,毛刺必须恰好命中「从机采样某个 bit 的瞬间」(每个 bit 只有极窄窗口)。命中与否纯靠运气,所以帧数 15~200 随机浮动。
硬件修复方案(按优先级)
必做(治本)
- 泵电容贴根焊:VB0±↔VB1± 的 1µF 换成 X7R 贴片陶瓷,直接焊在芯片引脚根,引线 ≤2mm,去掉飞线。
- VLCD 输出对地加电容:2.2~10µF 陶瓷,贴根焊。
强烈建议(挡噪声回流)
- 模块 VDD 就近加 100nF + 10µF。
- LCD 的 VDD 独立供电(别与 MCU 共用细线),入口串磁珠 + 对地电容做 π 滤波。
布局
- SDA/SCL 物理远离泵电容和 VLCD 走线;地线加粗、共地、短。
可选
- SDA/SCL 近 MCU 侧各串 100~330Ω 阻尼电阻;上拉保持 2.2k~4.7k。
电荷泵电容推荐
| 位置 | 容量 | 介质 | 耐压 | 封装 |
|---|---|---|---|---|
| VB0±↔VB1± 飞跨 ×2 | 1µF | X7R | ≥10V(16V 稳) | 0603 / 0805 |
| VLCD 输出对地 | 2.2~10µF | X7R | ≥16V(25V 稳) | 0805 / 1206 |
| VDD 去耦 | 100nF + 10µF | X7R | ≥6.3V | 0603 / 0805 |
要点:必须 X7R/X5R(低 ESR/ESL);禁用电解/钽;耐压要覆盖升压后的高压;手焊选 0805。
易错点澄清
- 泵不是被 I2C 触发的:上电后由
0x2F命令打开,之后内部 RC 振荡器一直自由运行,与 I2C 无关。 - 噪声一直都在,但只有 I2C 正在采样 bit 时才有破坏力:所以卡死总发生在
UpdateScreen写屏期间,而非空闲HAL_Delay。 - 飞跨电容别加大:问题在电感不在容量,加大(尤其电解/钽)反而更糟;只有 VLCD 输出电容加大才有效。
备注(未采用)
软件复位看门狗:UC1617S 有 System Reset 命令(约 0xE2,需确认 datasheet),失败后发复位 + 重新初始化可自愈。用户本次选择纯硬件路线,未实现。
