前言

ESP32-S3的HUB75 通信,在应用层,点亮一个像素可能只需要一行代码:

display->drawPixel(x, y, color);

但 P2.5 HUB75 灯板并不认识坐标和 drawPixel()。这个函数只修改内存中的显示缓冲区,真正让灯珠发光的,是后台持续运行的 HUB75 刷新引擎。

本文以 ESP32-S3 和一块 64×64、1/32 扫描的 P2.5 灯板为例,详细拆解:

  • HUB75 每类信号的作用;
  • 一行数据如何移入和锁存;
  • 第一个发送的 bit 最后去了哪里;
  • RGB888 如何被拆成位平面;
  • 8 MHz、约 100 Hz 和 30 FPS 分别表示什么。

1. HUB75 和 WS2812B 有什么本质区别

WS2812B 通过一根数据线接收每颗灯珠的 GRB 数据,灯珠内部自己完成 PWM 调光。

普通 HUB75 灯板则更像一组需要外部不断扫描的移位寄存器和行驱动电路。它不接收“第 120 个像素亮度为 37”这种完整命令,只会观察:

  • RGB 数据线当前是 0 还是 1;
  • CLK 什么时候跳变;
  • LAT 什么时候锁存;
  • A~E 选中了哪一个行组;
  • OE 什么时候允许输出。

2. HUB75 信号线的作用

2.1 RGB1 和 RGB2

R1/G1/B1 负责上半屏,R2/G2/B2 负责下半屏。在一个 CLK 中,六根线可以同时送入上下两个像素的 RGB bit。

2.2 A、B、C、D、E

这五根线是行地址。对 1/32 扫描面板,它们可以表示 0~31 的行组地址。

例如地址 5 通常同时对应第 5 行和第 37 行,两行分别使用 RGB1 和 RGB2 数据。

2.3 CLK

CLK 是移位时钟。每个有效脉冲会把当前六根 RGB 线上的 bit 推入移位链。对于一行 64 列的面板,一个位平面、一组上下行需要 64 个 CLK。

2.4 LAT

LAT 是锁存信号。64 列数据填满移位寄存器后,给 LAT 一个脉冲,将整行数据一次性切换到输出端。

2.5 OE

OE 可以理解为输出总开关,通常低电平有效:

  • OE 拉高:暂时关闭所有输出;
  • OE 拉低:允许当前选中的行点亮。

更换数据和行地址时先关闭输出,可以避免中间状态变成鬼影。OE 的导通时间还参与亮度和灰度控制。

3. 一行像素如何被送进灯板

对某个位平面和某个行组,基本步骤如下:

  1. 设置当前列的 R1/G1/B1/R2/G2/B2。
  2. 产生一个 CLK,将六个 bit 同时推入。
  3. 重复 64 次,填满当前行的所有列。
  4. OE 拉高,暂时关闭显示输出。
  5. 触发 LAT,锁存整行数据。
  6. 设置 A~E,选择目标行组。
  7. OE 拉低并保持指定时长,显示当前行。

4. 第一个发送的 bit 最后去了哪里

假设移位链是:

DIN -> Q0 -> Q1 -> ... -> Q63

第一个 bit 最初进入 Q0,后续每来一个 CLK,它都会继续向后移一位。当 64 个 bit 全部送完时:

  • 最先发送的 bit 到达 Q63;
  • 最后发送的 bit 留在 Q0。

但 Q63 对应屏幕左侧还是右侧,取决于面板 PCB 走线。因此更准确的结论是:第一个数据最终会被推到移位链远端,左右映射由面板和驱动库决定。

5. 什么是位平面

颜色通道通常使用 0~255 表示亮度。例如红色亮度为 13:

13 = 00001101(B) = 8 + 4 + 1

驱动程序会把所有像素的 b0 抽出来组成第 0 个位平面,再把所有像素的 b1 抽出来组成第 1 个位平面,直到 b7。

可以把 RGB888 图像想象成 8 张只有 0 和 1 的透明片。每一层同时包含 R、G、B 对应位的数据,不是将三个通道分成 24 轮顺序发送。

位权从低到高为:

b0  b1  b2  b3  b4  b5  b6  b7
 1   2   4   8  16  32  64 128

高位平面需要更长的显示时间。驱动器快速轮播这些平面,人眼就会将它们融合成最终亮度。

6. 8 个位平面需要多少 CLK

一个位平面的一个行组需要 64 个 CLK,因此 8 个位平面需要:

64列 × 8个位平面 = 512个CLK/行组

1/32 扫描的整屏基础移位次数为:

64列 × 8个位平面 × 32个行组 = 16384个CLK

实际还存在 LAT、OE、位权时间、DMA 描述符和低位平面合并等开销,所以不能只用 CLK / 16384 粗暴当作最终刷新率。

7. 8 MHz、约 100 Hz 和 30 FPS 的区别

7.1 8 MHz:CLK 时钟

matrixConfig.i2sspeed = HUB75_I2S_CFG::HZ_8M;

8 MHz 表示移位时钟周期约为 125 ns,描述数据推入面板的速度。

7.2 约 100 Hz:HUB75 扫描刷新率

在本项目的 64×64、8 bit 色深、1/32 扫描和当前库配置下,计算刷新率约为 100 Hz。

该数值不是所有 P2.5 灯板的固定参数,它会受面板尺寸、扫描方式、色深、CLK 和驱动策略影响。

7.3 30 FPS:应用画面更新率

constexpr uint16_t TARGET_FPS = 30;

30 FPS 表示流体算法每秒生成 30 张新画面。在两张画面之间,HUB75 驱动仍然按约 100 Hz 重复扫描当前缓冲区。

8. 驱动库替应用程序做了什么

本项目使用 ESP32 HUB75 DMA 类驱动库。它主要完成:

  1. 将 RGB888 拆成位平面;
  2. 将 x/y 坐标映射到行、列和上下半屏;
  3. 组织 RGB、CLK、LAT、OE 和行地址时序;
  4. 利用 I2S 并行外设和 DMA 持续输出;
  5. 在刷新率、色深、内存和亮度之间折中。

总结

HUB75 的核心不是一条“发送完整像素数据”的串行协议,而是一套由完整时序配合起来的扫描机制:

拆分位平面
    -> 设置RGB数据
    -> CLK逐列移入
    -> LAT锁存
    -> A~E选行
    -> OE控制点亮时间
    -> 快速重复

应用程序可以继续使用成熟库,但理解这条底层链路后,面对错行、偏色、鬼影、闪烁和刷新率不足时,就能更快找到排查方向。

我是阿白,感谢您的观看。

更多推荐