ESP-IoT-Solution 数码管与 LED 点阵驱动指南:CH450 / HT16C21 / IS31FL3XXX 实战
2026/9/19 13:26:25 网站建设 项目流程

ESP-IoT-Solution 数码管与 LED 点阵驱动指南:CH450 / HT16C21 / IS31FL3XXX 实战

【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution

本文基于乐鑫 ESP-IoT-Solution 仓库的数码管/LED 点阵驱动组件,系统讲解三款通过 I2C 接口驱动的显示芯片:数码管驱动芯片 CH450、RAM 映射 LCD 控制器 HT16C21、LED 点阵控制器 IS31FL3XXX(含 IS31FL3218 与 IS31FL3736)。读完本文,你将掌握这些驱动在 ESP32 上的初始化流程、核心 API 用法、寄存器与参数配置含义,以及如何结合仓库内的源码与测试用例快速完成计时、计数、状态显示和点阵动画等场景的开发。

数码管 / LED 点阵方案概览

在嵌入式系统中,数码管和 LED 点阵是比 LCD 显示屏更轻量的显示方案:它们占用更少的引脚与内存资源,实现逻辑也更简单,非常适合计时、计数、状态显示这类单一显示需求。ESP-IoT-Solution 已为三类常见驱动芯片封装了可复用的驱动组件,全部挂在components/display/digital_tube/目录下,接口统一基于仓库的 i2c_bus 组件。

名称功能接口驱动组件
CH450数码管显示驱动芯片,支持 6 位数码管(或 48 点 LED 矩阵)I2Cch450
HT16C2120×4 / 16×8 LCD 控制器,支持 RAM 映射I2Cht16c21
IS31FL3XXXLED 点阵控制器(18 通道恒流 / 12×8 矩阵)I2Cis31fl3xxx

三个组件均遵循一致的使用范式:先创建i2c_bus实例,再调用对应的xxx_create创建设备句柄,随后调用写接口输出显示数据,最后通过xxx_delete释放资源。下面分别展开。

CH450 驱动:6 位数码管显示

CH450 是 WCH(沁恒)推出的一款数码管显示驱动芯片,可驱动6 位数码管或 48 点 LED 矩阵,与 ESP32 之间通过 I2C 接口通信,仅需两根信号线即可完成显示控制。

CH450 典型应用电路图(来自 ESP-IoT-Solution 文档静态资源)

核心 API

该驱动对 CH450 的基本操作进行了封装,核心接口定义在 components/display/digital_tube/ch450/include/ch450.h:

  • ch450_create(i2c_bus_handle_t bus):创建并初始化设备对象,返回句柄;失败返回NULL
  • ch450_write(handle, ch450_cmd, val):向芯片写入命令寄存器。ch450_cmdch450_cmd_t枚举,val为寄存器值。
  • ch450_write_num(handle, seg_idx, val):向 7 段数码管的指定位置(seg_idx取值 0~5)写入数字val
  • ch450_delete(handle):删除并释放设备对象。

其中命令码定义如下:CH450_SEG_2(0x64)~CH450_SEG_7(0x6E)对应 6 个段位寄存器的写命令,CH450_SYS(0x48)为系统参数寄存器,CH450_READ(0x4F)为键扫读取命令。

源码实现要点

从 ch450.c 可以看到几个值得注意的实现细节:

  1. 无从机地址ch450_create中调用i2c_bus_device_create(bus, 0, 0)时传入地址为 0,源码注释明确说明 "The ch450 device does not have slave address",即 CH450 在 I2C 总线上通过命令字节本身寻址,这与常规带地址的从机不同。
  2. 创建即配置:创建时驱动会执行ch450_write(seg, CH450_SYS, CH450_SYS_DISP_MASK),将系统寄存器置为"开启显示、禁用键盘"状态,保证上电即可使用。
  3. 数字字模表:源码内置了ch450_digit[10]字模数组(0~9 对应 0xee、0x28、0xcd、0x6d、0x2b、0x67、0xe7、0x2c、0xef、0x6f),ch450_write_num通过ch450_cmd_t seg_cmd = CH450_SEG_2 + seg_idx * 2;计算目标段位命令码,再查表写入字模。需要说明的是,字模与具体硬件段位连线强相关,若你的硬件接线不同,需按实际电路调整该数组。

示例:循环显示 0~9

i2c_bus_handle_t i2c_bus = NULL; ch450_handle_t seg = NULL; i2c_config_t conf = { .mode = I2C_MODE_MASTER, .sda_io_num = I2C_MASTER_SDA_IO, .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_io_num = I2C_MASTER_SCL_IO, .scl_pullup_en = GPIO_PULLUP_ENABLE, .master.clk_speed = I2C_MASTER_FREQ_HZ, }; i2c_bus = i2c_bus_create(I2C_MASTER_NUM, &conf); seg = ch450_create(i2c_bus); for (size_t i = 0; i < 10; i++) { for (size_t index = 0; index < 6; index++) { ch450_write_num(seg, index, i); } vTaskDelay(1000 / portTICK_PERIOD_MS); } ch450_delete(seg); i2c_bus_delete(&i2c_bus);

其中I2C_MASTER_NUMI2C_MASTER_SDA_IOI2C_MASTER_SCL_IOI2C_MASTER_FREQ_HZ需根据你的板卡自行定义。仓库在 components/display/digital_tube/ch450/test/ch450_test.c 中提供了基于 Unity 的测试用例,可直接参考其引脚与时钟配置(例如 SCL/SDA 引脚选择与 400 kHz 主频)。

HT16C21 驱动:RAM 映射段码式 LCD 控制

HT16C21 是合泰(Holtek)出品、支持 RAM 映射的 LCD 控制/驱动芯片,可用于驱动20×4 或 16×8段码式液晶屏,通过 I2C 与 ESP32 通信。它与数码管方案的最大区别在于:显示内容通过写芯片内部 Display Data RAM 实现,因此 RAM 的地址布局与 LCD 段位一一对应。

HT16C21 驱动模式与波形示意(来自 ESP-IoT-Solution 文档静态资源)

配置结构体与命令

驱动在 ht16c21.h 中定义了ht16c21_config_t配置结构体,字段如下:

字段可选值(节选)含义
duty_biasHT16C21_4DUTY_3BIAS/HT16C21_4DUTY_4BIAS/HT16C21_8DUTY_3BIAS/HT16C21_8DUTY_4BIAS1/4 或 1/8 占空比与 1/3 或 1/4 偏压的驱动模式
oscillator_displayHT16C21_OSCILLATOR_OFF_DISPLAY_OFF/HT16C21_OSCILLATOR_ON_DISPLAY_OFF/HT16C21_OSCILLATOR_ON_DISPLAY_ON系统振荡器与显示的开关组合
frame_frequencyHT16C21_FRAME_80HZ/HT16C21_FRAME_160HZ帧频 80 Hz 或 160 Hz
blinking_frequencyHT16C21_BLINKING_OFF/HT16C21_BLINKING_2HZ/HT16C21_BLINKING_1HZ/HT16C21_BLINKING_5HZ闪烁功能开关与频率(0.5/1/2 Hz)
pin_and_voltageHT16C21_VLCD_PIN_VOL_ADJ_OFF/ONHT16C21_SEGMENT_PIN_VOL_ADJ_OFF/ONSegment/VLCD 引脚功能与内部电压调整的使能组合
adjustment_voltage0x00~0x0F内部电压调整量(DA3~DA0 位),配合 VLCD 电压跟随器使用

这些配置最终会写入芯片的命令寄存器:HT16C21_CMD_DRIMO(0x82,器件模式)、HT16C21_CMD_SYSMO(0x84,系统模式)、HT16C21_CMD_FRAME(0x86,帧频)、HT16C21_CMD_BLINK(0x88,闪烁频率)、HT16C21_CMD_IVA(0x8a,内部电压调整)。从 ht16c21.c 的ht16c21_param_config实现可见,驱动会依次调用ht16c21_write_cmd将上述五个命令逐一写入,其中 IVA 命令由pin_and_voltage | adjustment_voltage组合而成。

核心 API 与 RAM 读写

  • ht16c21_create(bus, dev_addr):创建设备实例,默认从机地址为宏HT16C21_I2C_ADDRESS_DEFAULT(0x70)。
  • ht16c21_param_config(dev, conf):按上述结构体批量下发驱动参数。
  • ht16c21_ram_write(dev, address, buf, len)/ht16c21_ram_write_byte(...):向 Display Data RAM 写入数据。
  • ht16c21_ram_read(dev, address, buf, len)/ht16c21_ram_read_byte(...):从 RAM 回读数据(可用于校验)。
  • ht16c21_write_cmd(dev, cmd, val):单条命令写入。

源码中 RAM 写操作会先发送HT16C21_CMD_IOOUT(0x80,配置 Display Data RAM),再发送起始地址与数据,读操作则在写地址后以I2C_MASTER_LAST_NACK结束读取,实现细节可对照 ht16c21.c 查看。

示例:配置并写入 RAM

i2c_bus_handle_t i2c_bus = NULL; ht16c21_handle_t seg = NULL; uint8_t lcd_data[8] = { 0x10, 0x20, 0x30, 0x50, 0x60, 0x70, 0x80 }; i2c_config_t conf = { .mode = I2C_MODE_MASTER, .sda_io_num = I2C_MASTER_SDA_IO, .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_io_num = I2C_MASTER_SCL_IO, .scl_pullup_en = GPIO_PULLUP_ENABLE, .master.clk_speed = I2C_MASTER_FREQ_HZ, }; i2c_bus = i2c_bus_create(I2C_MASTER_NUM, &conf); seg = ht16c21_create(i2c_bus, HT16C21_I2C_ADDRESS_DEFAULT); ht16c21_config_t ht16c21_conf = { .duty_bias = HT16C21_4DUTY_3BIAS, .oscillator_display = HT16C21_OSCILLATOR_ON_DISPLAY_ON, .frame_frequency = HT16C21_FRAME_160HZ, .blinking_frequency = HT16C21_BLINKING_OFF, .pin_and_voltage = HT16C21_VLCD_PIN_VOL_ADJ_ON, .adjustment_voltage = 0, }; ht16c21_param_config(seg, &ht16c21_conf); ht16c21_ram_write(seg, 0x00, lcd_data, 8); ht16c21_delete(seg); i2c_bus_delete(&i2c_bus);

注意:原文档示例代码中配置结构体字段间误用了分号;,本文已按 C 语法修正为逗号,,实际编写时请以逗号分隔结构体成员初始化项。

IS31FL3XXX 驱动:LED 点阵显示

IS31FL3XXX 系列是 Lumissil(ISSI)的 LED 点阵控制器家族,可用于驱动不同规模的 LED 点阵屏幕。ESP-IoT-Solution 在 is31fl3xxx 组件中同时提供了IS31FL3218IS31FL3736两款芯片的驱动。

IS31FL3218 典型应用电路图(来自 ESP-IoT-Solution 文档静态资源)

IS31FL3218:18 通道恒流 PWM 输出

IS31FL3218 支持18 个恒流通道,每个通道由独立 PWM 控制,最大输出电流38 mA,可直接驱动 LED 显示。驱动头文件为 is31fl3218.h,关键点:

  • I2C 地址:IS31FL3218_I2C_ID为 0xA8(8 位写地址,等效 7 位地址 0x54),is31fl3218_create(bus)会据此自动创建设备。
  • 寄存器布局:0x00 为关闭模式寄存器(IS31FL3218_REG_SHUTDOWN),0x01~0x12 为 PWM1~PWM18 占空比寄存器,其后依次为 LED 控制寄存器(CONL_1~3)、UPDATE 更新寄存器与 RESET 复位寄存器。
  • 核心接口:is31fl3218_set_mode(软件关闭/正常运行)、is31fl3218_channel_set(handle, ch_bit, duty)(按位选通道并设置占空比,duty 范围 0~255)、is31fl3218_write_pwm_regs(批量写入 PWM 寄存器)、is31fl3218_reset_register(复位所有寄存器)。

从 is31fl3218.c 的实现看,is31fl3218_create会依次完成:复位寄存器 → 进入正常模式 → 使能全部 18 个通道(IS31FL3218_CH_NUM_MAX_MASK,即 0x3ffff)→ 更新寄存器。而is31fl3218_channel_set先逐位遍历ch_bit写入对应 PWM 寄存器,再写 UPDATE 寄存器使新占空比生效——写 PWM 寄存器后必须触发一次 UPDATE,LED 亮度才会真正刷新,这是该芯片的关键操作时序。

示例:将 PWM1~PWM8 通道占空比统一设置为 50%(128/255):

i2c_bus_handle_t i2c_bus = NULL; is31fl3218_handle_t fxled = NULL; i2c_config_t conf = { .mode = I2C_MODE_MASTER, .sda_io_num = I2C_MASTER_SDA_IO, .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_io_num = I2C_MASTER_SCL_IO, .scl_pullup_en = GPIO_PULLUP_ENABLE, .master.clk_speed = I2C_MASTER_FREQ_HZ, }; i2c_bus = i2c_bus_create(I2C_MASTER_NUM, &conf); fxled = is31fl3218_create(i2c_bus); is31fl3218_channel_set(fxled, 0x00ff, 128); // set PWM 1 ~ PWM 8 duty cycle 50% is31fl3218_delete(fxled); i2c_bus_delete(&i2c_bus);

IS31FL3736:12×8 LED 矩阵与 256 级渐变

IS31FL3736 支持更多的通道,最大可组成12×8 LED 矩阵,每个通道由一个 8 位 PWM 驱动,支持256 级(0~255)渐变。相比 IS31FL3218,它的功能更丰富:支持分页寄存器(P0~P3)、全局电流控制、SWy/CSx 上下拉电阻配置、自动呼吸模式(ABM1~ABM3)以及开路/短路检测中断。驱动头文件为 is31fl3736.h,寄存器位定义见 is31fl3736_reg.h。

创建接口(参数较复杂,需结合硬件接线):

is31fl3736_handle_t is31fl3736_create(i2c_bus_handle_t bus, gpio_num_t rst_io, is31fl3736_addr_pin_t addr1, is31fl3736_addr_pin_t addr2, uint8_t cur_val);
  • rst_io:SDB 复位引脚编号。源码中若该引脚有效(rst_io < GPIO_NUM_MAX且非负),会将其配置为带上拉的输出 GPIO,用于硬件复位;is31fl3736_hw_reset通过拉低 10 ms 再拉高完成复位。
  • addr1/addr2:地址配置引脚(ADDR_PIN_GND/SCL/SDA/VCC),决定从机 I2C 地址。is31fl3736_get_i2c_addr0xA0 | (addr1 << 1) | (addr2 << 3)计算地址,因此同一 I2C 总线上最多可挂载多片 IS31FL3736。
  • cur_val:全局电流值(0~255)。输出电流满足I_out = 840 / R_ext × curr_value / 256,需结合外部电阻 R_ext 设定。

核心功能接口

  • is31fl3736_set_mode:配置软件关闭/正常运行、自动呼吸使能、开路/短路检测使能、同步模式(高阻/主/从)。
  • is31fl3736_set_global_current:设置全局电流(寄存器在 P3 页)。
  • is31fl3736_set_resistor(type, res_val):选择 SWy 上拉 / CSx 下拉电阻(0Ω、0.5K、1K、2K、3K、4K、8K、16K、32K)。
  • is31fl3736_set_led_matrix(cs_x_bit, sw_y_bit, status):点亮/熄灭矩阵中指定交点(CSx 为 8 路恒流源,SWy 为 12 路开关通道,共 96 个 LED 点)。
  • is31fl3736_set_pwm_duty_matrix(cs_x_bit, sw_y_bit, duty):为指定交点设置 PWM 占空比,实现灰度显示。
  • is31fl3736_set_channel_duty/is31fl3736_set_breath_mode:PWM 模式下单通道调亮度,或为通道绑定 ABM 自动呼吸模式。
  • is31fl3736_fill_buf(duty, buf):按 12 行位图缓冲区批量填充矩阵,非常适合整屏刷新。

从 is31fl3736.c 的初始化流程(is31fl3736_init)可以看出完整的上电序列:硬件复位 → 设置初始模式 → 打开全部 LED → PWM 数据清零 → 解除软件关闭进入正常运行 → 设置全局电流 → 逐点写 PWM 寄存器。所有写操作前都会先通过命令锁寄存器(写入魔数IS31FL3736_CMD_WRITE_EN,0xC5)解锁并切换到目标页(is31fl3736_write_page),这是 IS31FL3736 分页寄存器架构下的固定访问前置步骤。

IS31FL3736 点阵实测:滚动显示 "ESP"

仓库在 is31fl3736_test.c 中提供了完整的 Unity 测试用例,演示了在 12×8 矩阵上滚动显示字符 "E"、"S"、"P" 的完整过程:

  1. 初始化 I2C 总线(测试中 SCL=GPIO21、SDA=GPIO15、频率 400 kHz),创建is31fl3736_create(i2c_bus, GPIO_NUM_32, 0, 0, 0XCF)
  2. 用字模数组(如image_e[12])按 12 行位图编码字符,通过is31fl3736_display_buf进行位移拼帧;
  3. 调用is31fl3736_fill_buf(led3736, duty, buf)整屏刷新;
  4. 通过改变字符纵坐标实现上下滚动动画。

测试中还提供了fill_pixel(x, y, duty)示例函数,直接按reg = x * 2 + y * 0x10计算 PWM 寄存器地址并写入,展示了矩阵坐标与 P1 页寄存器地址的换算规律(CSx 索引 x 步进 2 字节、SWy 索引 y 步进 0x10),对实现自定义逐点绘制很有参考价值。

测试与验证

三个驱动组件均在test/子目录下提供了基于 Unity 的 I2C 测试用例(ch450_test.c、ht16c21_test.c、is31fl3218_test.c 与 is31fl3736_test.c),使用方式为:将对应组件加入你的 ESP-IDF 工程(组件本身声明于 components/display/digital_tube/ch450/CMakeLists.txt 等构建文件),启用测试构建后烧录运行,通过串口观察断言结果即可确认 I2C 通信与芯片操作是否正常。

选型建议

  • 仅需显示数字/简单符号、追求接线最少:选CH450,两线 I2C 驱动 6 位数码管,无需从机地址;
  • 需要驱动段码式 LCD 屏(20×4 / 16×8)并支持闪烁、内部电压调节等特性:选HT16C21
  • 需要点阵动画、灰度渐变、或大电流恒流直驱 LED:选IS31FL3218(18 通道独立 PWM)或IS31FL3736(12×8 矩阵 + 256 级渐变 + 自动呼吸模式)。

以上驱动的完整头文件、实现与测试代码均可直接在components/display/digital_tube/目录下查阅,是理解 I2C 显示外设驱动编写范式的良好参考。

【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询