HUB08 接口的点阵显示屏

1. 参数

2. 接口

左侧引脚(1-8)
| 引脚 | 名称 | 作用分析 |
|---|---|---|
| 1 | GND | 电源地,为整个模块提供电流回路。 |
| 2 | GND | 电源地,与引脚1功能相同,用于增强接地能力。 |
| 3 | GND | 电源地,与引脚1、2功能相同。 |
| 4 | OE | 输出使能(Output Enable),通常为低电平有效。用于控制整屏的亮灭,可用于消隐和亮度调节。 |
| 5 | R1 | 红色数据输入1(Red Data 1),串行数据输入,用于传输上半屏(如1-16行)的红色LED数据。 |
| 6 | R2 | 红色数据输入2(Red Data 2),串行数据输入,用于传输下半屏(如17-31行)的红色LED数据。 |
| 7 | GND | 电源地。 |
| 8 | GND | 电源地。 |
| 9 | CLK | 时钟信号(Clock),用于同步串行数据的移位。在时钟的上升沿,数据被移入内部移位寄存器。 |
| 10 | LAT | 锁存信号(Latch / STB),当数据全部移入后,锁存信号的上升沿会将移位寄存器中的数据锁存到输出寄存器,更新显示内容。 |
| 11 | G2 | 绿色数据输入2(Green Data 2),用于传输下半屏的绿色LED数据。在单色屏中,此引脚通常未使用或悬空。 |
| 12 | G1 | 绿色数据输入1(Green Data 1),用于传输上半屏的绿色LED数据。在单色屏中,此引脚通常未使用或悬空。 |
| 13 | LD | 行地址选择D(Line D),与LA、LB、LC组成4位二进制编码,用于选择当前要显示的16行中的一行。 |
| 14 | LC | 行地址选择C(Line C),行地址选择信号之一。 |
| 15 | LB | 行地址选择B(Line B),行地址选择信号之一。 |
| 16 | LA | 行地址选择A(Line A),行地址选择信号之一。 |
工作原理总结
- 数据传输:主控通过
R1/R2(单色屏)或R1/R2/G1/G2(双色屏)发送串行数据,CLK同步移位。 - 行选择:
LA/LB/LC/LD组成4位地址,选中当前要刷新的行。 - 数据锁存:
LAT信号将移位寄存器中的数据锁存,更新该行的显示。 - 显示控制:
OE信号控制该行的LED是否点亮,通过快速切换行和控制OE,实现整屏的动态扫描显示。
3. 接线

4. 驱动代码
0. 定义显示缓冲区
c
// 像素数据缓冲区,分为上下两部分,每部分16行
uint8_t pixdata[LED_WIDTH_PIX * LED_HEIGHT_PIX / 8];1. 初始化
初始化基本不需要做什么,如果要做,那就把显示缓冲,清理一下.
c
void HUB8_Init(void) {
// 初始化时先关闭输出,防止闪烁
HAL_GPIO_WritePin(OE_GPIO_Port, OE_Pin, GPIO_PIN_SET);
HUB8_clear();
// 延迟一段时间后开启输出
vTaskDelay(pdMS_TO_TICKS(10));
HAL_GPIO_WritePin(OE_GPIO_Port, OE_Pin, GPIO_PIN_RESET);
}2. 将缓冲区的内容写入屏幕
由于屏幕是逐行刷新的,所以需要逐行写入.每一行写入完成后,都要停一下,让显示出来.
c
void HUB8_flush() {
uint8_t row = 0;
uint8_t col = 0;
for (row = 0; row < 16; row++) {
// 设置当前行
HUB8_SetRow(row);
// 逐列发送数据
for (col = 0; col < LED_WIDTH_PIX; col++) {
// 计算当前列在缓冲区中的位置
uint16_t idx = row * LED_WIDTH_PIX + col;
uint16_t idx_bottom = (row + 16) * LED_WIDTH_PIX + col;
// 获取上下部分的像素值
uint8_t pixelR1 = (pixdata[idx / 8] >> (idx % 8)) & 0x01;
uint8_t pixelR2 = (pixdata[idx_bottom / 8] >> (idx_bottom % 8)) & 0x01;
#if LED_REVERSE == 0
// 设置数据引脚
HAL_GPIO_WritePin(R1_GPIO_Port, R1_Pin, pixelR1 ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(R2_GPIO_Port, R2_Pin, pixelR2 ? GPIO_PIN_SET : GPIO_PIN_RESET);
#else
HAL_GPIO_WritePin(R1_GPIO_Port, R1_Pin, pixelR1 ? GPIO_PIN_RESET : GPIO_PIN_SET);
HAL_GPIO_WritePin(R2_GPIO_Port, R2_Pin, pixelR2 ? GPIO_PIN_RESET : GPIO_PIN_SET);
#endif
// 脉冲时钟,锁存数据
HAL_GPIO_WritePin(CLK_GPIO_Port, CLK_Pin, GPIO_PIN_RESET);
// delay_us(1); // 短暂延迟,确保时钟脉冲宽度足够
HAL_GPIO_WritePin(CLK_GPIO_Port, CLK_Pin, GPIO_PIN_SET);
// delay_us(1); // 短暂延迟,确保时钟脉冲宽度足够
}
// 锁存当前行的数据
HAL_GPIO_WritePin(LAT_GPIO_Port, LAT_Pin, GPIO_PIN_SET);
// delay_us(5); // 短暂延迟,确保锁存脉冲宽度足够
HAL_GPIO_WritePin(LAT_GPIO_Port, LAT_Pin, GPIO_PIN_RESET);
// delay_us(5);
// 开启输出显示当前行
HAL_GPIO_WritePin(OE_GPIO_Port, OE_Pin, GPIO_PIN_RESET);
vTaskDelay(1); // 行显示时间
HAL_GPIO_WritePin(OE_GPIO_Port, OE_Pin, GPIO_PIN_SET);
}
}以上就是整个驱动的核心代码,也是核逻辑.
3. 设置一行数据的逻辑图
将屏幕分为上下两个半部分,每部分有16行. 每一行有 64个像素. 每8个像素占用一个字节. 传输的逻辑是:
- 打开第1行的数据 (LA,LB,LC,LD来确定)
- 将第1行的数据通过
clk和R1来将数据输入进去. - 通过
OE引脚打开这一行的数据显示. - 开始下一行数据
可以参考下面的逻辑图: 
