Skip to content

HUB08 接口的点阵显示屏

1. 参数

2. 接口

左侧引脚(1-8)

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

工作原理总结

  1. 数据传输:主控通过 R1/R2(单色屏)或 R1/R2/G1/G2(双色屏)发送串行数据,CLK 同步移位。
  2. 行选择LA/LB/LC/LD 组成4位地址,选中当前要刷新的行。
  3. 数据锁存LAT 信号将移位寄存器中的数据锁存,更新该行的显示。
  4. 显示控制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. 打开第1行的数据 (LA,LB,LC,LD来确定)
  2. 将第1行的数据通过 clkR1来将数据输入进去.
  3. 通过 OE引脚打开这一行的数据显示.
  4. 开始下一行数据

可以参考下面的逻辑图: