QMK 中 IS31FL3741 驱动深入解析:I²C 39×9 LED 矩阵驱动器的配置、LED 映射与 API 实战
2026/9/14 2:22:43 网站建设 项目流程

QMK 中 IS31FL3741 驱动深入解析:I²C 39×9 LED 矩阵驱动器的配置、LED 映射与 API 实战

【免费下载链接】qmk_firmwareOpen-source keyboard firmware for Atmel AVR and Arm USB families项目地址: https://gitcode.com/GitHub_Trending/qm/qmk_firmware

本文聚焦 QMK Firmware 对 Lumissil IS31FL3741/IS31FL3741A 系列 I²C LED 矩阵驱动芯片的完整支持:从rules.mk/config.h的启用与全部配置项,到g_is31fl3741_ledsLED 映射表的编写,再到底层寄存器分页、缓冲刷新机制与完整 API 参考。读完本文,你将掌握在自家键盘固件中集成该驱动(单色背光或 RGB 灯效)、按硬件实际接线精确点亮每一颗 LED 的完整方法。

驱动概览:硬件能力与适用场景

IS31FL3741 是 Lumissil 推出的 I²C 接口 39×9 LED 矩阵驱动芯片。在 QMK 中,每个驱动最多可控制351 颗单色 LED,或组成117 颗 RGB LED(每颗 RGB LED 占用 3 个矩阵节点);一条 I²C 总线上最多挂载4 个驱动(驱动索引 0~3),因此单键盘最多可驱动 468 颗 RGB LED 或 1404 颗单色 LED 节点。官方数据手册可参考 Lumissil 的 IS31FL3741A Datasheet(该链接为芯片厂商资料,文中不再展开)。

驱动代码位于仓库 drivers/led/issi/ 目录,包含两套实现:

  • is31fl3741.c + is31fl3741.h:RGB 版本,提供is31fl3741_set_color()等三通道接口;
  • is31fl3741-mono.c + is31fl3741-mono.h:单色版本,提供is31fl3741_set_value()等单通道接口。

两套代码共享相同的寄存器映射、初始化序列和缓冲刷新策略,仅通道数不同。

快速启用:在 rules.mk 中引入驱动

如果使用 LED Matrix 或 RGB Matrix 功能,并在rules.mk中把驱动指定为is31fl3741(对应RGB_MATRIX_DRIVER = is31fl3741LED_MATRIX_DRIVER = is31fl3741),驱动代码会自动被构建系统引入,此时应直接使用 LED/RGB Matrix 的 API 而不是本驱动的底层接口。

若需要独立使用该驱动(不经过 LED/RGB Matrix 框架),在rules.mk中加入:

COMMON_VPATH += $(DRIVER_PATH)/led/issi SRC += is31fl3741-mono.c # For single-color SRC += is31fl3741.c # For RGB I2C_DRIVER_REQUIRED = yes

其中I2C_DRIVER_REQUIRED = yes会确保编译系统把底层 I²C 主机驱动链接进来(参见 docs/drivers/i2c.md 的启用说明)。

基础配置:config.h 配置项一览

将以下宏加入config.h(均为可选,带默认值):

DefineDefaultDescription
IS31FL3741_SDB_PINNot defined连接到驱动 SDB(shutdown)引脚的 GPIO 引脚
IS31FL3741_I2C_TIMEOUT100I²C 传输超时(毫秒)
IS31FL3741_I2C_PERSISTENCE0I²C 传输失败后的重试次数
IS31FL3741_I2C_ADDRESS_1Not defined驱动 0 的 I²C 地址
IS31FL3741_I2C_ADDRESS_2Not defined驱动 1 的 I²C 地址
IS31FL3741_I2C_ADDRESS_3Not defined驱动 2 的 I²C 地址
IS31FL3741_I2C_ADDRESS_4Not defined驱动 3 的 I²C 地址
IS31FL3741_CONFIGURATION1配置寄存器的写入值(1表示正常操作模式)
IS31FL3741_PWM_FREQUENCYIS31FL3741_PWM_FREQUENCY_29K_HZLED 的 PWM 频率(仅 IS31FL3741A 支持)
IS31FL3741_SW_PULLUPIS31FL3741_PUR_32K_OHMSWx引脚上拉电阻值
IS31FL3741_CS_PULLDOWNIS31FL3741_PDR_32K_OHMCSx引脚下拉电阻值
IS31FL3741_GLOBAL_CURRENT0xFF全局电流控制值(0~255)

这些默认值在源码中以#ifndef保护方式定义,见 is31fl3741.c(单色版本相同),因此未定义时也能安全编译。

I²C 地址分配

IS31FL3741 根据ADDR引脚连接方式共有 4 种 7 位 I²C 地址。在config.h中把IS31FL3741_I2C_ADDRESS_n(n 为驱动索引,从 1 开始)设为以下值之一:

DefineValue
IS31FL3741_I2C_ADDRESS_GND0x30
IS31FL3741_I2C_ADDRESS_SCL0x31
IS31FL3741_I2C_ADDRESS_SDA0x32
IS31FL3741_I2C_ADDRESS_VCC0x33

地址常量定义于 is31fl3741.h。驱动数量由“定义了哪个地址宏”自动推导:定义了IS31FL3741_I2C_ADDRESS_4IS31FL3741_DRIVER_COUNT为 4,定义了_3则为 3,依此类推(见 is31fl3741.h)。同时,驱动索引与地址的对应关系在 is31fl3741.c 中构建:i2c_addresses[0] = IS31FL3741_I2C_ADDRESS_1i2c_addresses[1] = IS31FL3741_I2C_ADDRESS_2,以此类推。

从真实键盘看典型写法,keyboards/kprepublic/bm80v2/config.h 与 keyboards/acheron/apollo/87h/gamma/config.h 均使用:

#define IS31FL3741_I2C_ADDRESS_1 IS31FL3741_I2C_ADDRESS_GND

即单驱动方案,ADDR引脚接地,地址0x30

PWM 频率调节

PWM 频率可调(仅 IS31FL3741A,IS31FL3741 基础版本不支持此寄存器配置)。在config.h中加入:

#define IS31FL3741_PWM_FREQUENCY IS31FL3741_PWM_FREQUENCY_29K_HZ

有效取值:

DefineFrequency
IS31FL3741_PWM_FREQUENCY_29K_HZ29 kHz(默认)
IS31FL3741_PWM_FREQUENCY_3K6_HZ3.6 kHz
IS31FL3741_PWM_FREQUENCY_1K8_HZ1.8 kHz
IS31FL3741_PWM_FREQUENCY_900_HZ900 Hz

对应的 4 位二进制编码定义在 is31fl3741.h,写入时驱动代码会做IS31FL3741_PWM_FREQUENCY & 0b1111掩码处理(见 is31fl3741.c)。降低 PWM 频率可以减少开关损耗、改善特定场景下的 EMI,但会带来更明显的刷新闪烁,一般保持默认 29 kHz 即可。

去鬼影(De-Ghosting)

IS31FL3741_SW_PULLUPIS31FL3741_CS_PULLDOWN分别控制SWxCSx引脚上的上拉/下拉电阻,用于消除矩阵扫描时的“鬼影”(ghosting,即未被选中的 LED 被旁路电流点亮的串扰现象)。其成因与消除原理详见数据手册第 18 页,本文不再复述。调整方式:

#define IS31FL3741_SW_PULLUP IS31FL3741_PUR_32K_OHM #define IS31FL3741_CS_PULLDOWN IS31FL3741_PDR_32K_OHM

IS31FL3741_SW_PULLUP的有效取值(二进制编码见 is31fl3741.h):

DefineResistance
IS31FL3741_PUR_0_OHM无上拉
IS31FL3741_PUR_0K5_OHM0.5 kΩ
IS31FL3741_PUR_1K_OHM1 kΩ
IS31FL3741_PUR_2K_OHM2 kΩ
IS31FL3741_PUR_4K_OHM4 kΩ
IS31FL3741_PUR_8K_OHM8 kΩ
IS31FL3741_PUR_16K_OHM16 kΩ
IS31FL3741_PUR_32K_OHM32 kΩ(默认)

IS31FL3741_CS_PULLDOWN的有效取值:

DefineResistance
IS31FL3741_PDR_0_OHM无下拉
IS31FL3741_PDR_0K5_OHM0.5 kΩ
IS31FL3741_PDR_1K_OHM1 kΩ
IS31FL3741_PDR_2K_OHM2 kΩ
IS31FL3741_PDR_4K_OHM4 kΩ
IS31FL3741_PDR_8K_OHM8 kΩ
IS31FL3741_PDR_16K_OHM16 kΩ
IS31FL3741_PDR_32K_OHM32 kΩ(默认)

在初始化时,驱动代码会把两者合并为一个字节写入FUNCTION_REG_PULLDOWNUP((IS31FL3741_CS_PULLDOWN << 4) | IS31FL3741_SW_PULLUP),即高 4 位为 CS 下拉、低 4 位为 SW 上拉(见 is31fl3741.c)。

全局电流控制

IS31FL3741_GLOBAL_CURRENT控制CSx引脚吸收的总电流,取值范围 0~255,默认 255(最大)。需要调低亮度上限或限制功耗时:

#define IS31FL3741_GLOBAL_CURRENT 0xFF

该值在初始化时写入全局电流寄存器(见 is31fl3741.c),作为所有 LED 的总体电流上限,其作用与逐通道 PWM 亮度是乘法关系。

ARM/ChibiOS 平台:I²C 总线的启用与配置

在 AVR 平台上 I²C(TWI)通常开箱即用;而在 ARM/ChibiOS 平台,I²C 外设需要在键盘级启用并配置引脚复用、时钟速率等参数,否则驱动初始化时的i2c_init()(见 is31fl3741.c)将无法正常工作。具体步骤请按所用 MCU 查阅 I²C 驱动的 ARM/ChibiOS 配置一节,其中包含I2C_DRIVER_REQUIRED、引脚选择与速率相关的完整说明。

LED 映射表:g_is31fl3741_leds 的编写

为了让驱动知道“哪个 LED 索引对应芯片的哪个输出”,必须在键盘源码(如<keyboard>.c)中定义映射数组。RGB 版本:

const is31fl3741_led_t PROGMEM g_is31fl3741_leds[IS31FL3741_LED_COUNT] = { /* Driver * | R G B */ {0, SW1_CS1, SW1_CS2, SW1_CS3}, // etc... };

上述示例中,驱动 0 上索引 0 这颗 RGB LED 的 R/G/B 三个通道,阳极全部接在SW1引脚上,阴极分别接CS1CS2CS3。单色版本原理相同,但只有单通道:

const is31fl3741_led_t PROGMEM g_is31fl3741_leds[IS31FL3741_LED_COUNT] = { /* Driver * | V */ {0, SW1_CS1}, // etc... };

SWx_CSy宏的值即芯片 PWM 输出寄存器的地址,与数据手册第 12 页 Figure 8 的寄存器索引一一对应。全套宏定义于 is31fl3741.h(单色头文件相同):SW1_CS10x00)到SW9_CS300x159)落在 PWM 页 0 的 180 个寄存器内,SW1_CS310x15A)到SW9_CS390x1AA)落在 PWM 页 1 的 171 个寄存器内——这正对应 39×9 = 351 个矩阵节点。

注意IS31FL3741_LED_COUNT在使用 RGB/RGB Matrix 时被自动定义为RGB_MATRIX_LED_COUNTLED_MATRIX_LED_COUNT(见 is31fl3741.h);独立使用时需自行保证数组长度正确。PROGMEM说明该表存放在 Flash 中,读取时驱动使用memcpy_P拷贝(见 is31fl3741.c),以节省宝贵的 RAM。

真实键盘映射示例

achenor 键盘(Acheron Apollo 87H Gamma)在gamma.c中给出了完整的 RGB 映射表,例如:

const is31fl3741_led_t PROGMEM g_is31fl3741_leds[IS31FL3741_LED_COUNT] = { /* driver * | R location * | | G location * | | | B location * | | | | */ {0, SW9_CS7 , SW9_CS9 , SW9_CS8 }, //ESC 0 {0, SW8_CS7 , SW8_CS9 , SW8_CS8 }, //F1 1 ... };

可以看到,同一颗 LED 的三个通道并不要求相邻,例如 ESC 键的 R 在SW9_CS7、G 在SW9_CS9、B 在SW9_CS8,这取决于 PCB 的走线。编写映射表时应逐一对照原理图,而不是机械地按顺序填。

驱动内部机制:从源码看初始化与刷新流程

寄存器分页与写锁

IS31FL3741 通过命令寄存器(0xFD)切换页面:0x00/0x01为 PWM 页 0/1,0x02/0x03为 Scaling(LED 开关/亮度调节)页 0/1,0x04为功能页。写命令寄存器前必须先向写锁寄存器0xFE写入解锁魔数0xC5(见 is31fl3741.c 的is31fl3741_select_page())。全部关键寄存器常量定义于 is31fl3741.h。

初始化序列

is31fl3741_init_drivers()(见 is31fl3741.c)按以下顺序工作:

  1. 调用i2c_init()初始化 I²C 主机;
  2. 若定义了IS31FL3741_SDB_PIN,将该引脚设为输出并拉高,使芯片退出硬件关断;
  3. 对每个驱动索引调用is31fl3741_init():切到功能页后依次写入配置寄存器(正常操作模式)、全局电流、上下拉电阻组合、PWM 频率,最后wait_ms(10)等待芯片完成唤醒(见 is31fl3741.c)。源码注释特别强调:为避免 PWM 寄存器中的垃圾数据驱动 LED,应在完成所有模式与寄存器设置后再解除软件关断;
  4. 将所有 LED 的控制寄存器置为使能(RGB 为三通道全开),并立即刷入芯片。

双缓冲与脏标记刷新

每个驱动的缓冲区在 is31fl3741.c 中定义为is31fl3741_driver_t:PWM 缓冲 0(180 字节)、PWM 缓冲 1(171 字节),以及对应的 Scaling 缓冲和两个dirty脏标记。所有set_*系列函数只修改 RAM 缓冲并置位脏标记,不会立即触发 I²C 传输;只有调用is31fl3741_update_pwm_buffers()/is31fl3741_update_led_control_registers()时,才在“缓冲区有变更”的前提下真正写芯片(见 is31fl3741.c)。这种设计把多次设置合并为一次 I²C 突发传输,显著降低总线占用。

传输本身也做了分段优化:PWM 页 0 的 180 个寄存器以6 次 × 30 字节的突发写入完成,PWM 页 1 的 171 个寄存器以9 次 × 19 字节完成(见 is31fl3741.c),以适配 I²C 协议的数据包长度限制。

与 LED/RGB Matrix 框架的对接

在 quantum/rgb_matrix/rgb_matrix_drivers.c 中,RGB_MATRIX_IS31FL3741驱动条目把.init.flush.set_color.set_color_all分别绑定到本驱动的is31fl3741_init_driversis31fl3741_flushis31fl3741_set_coloris31fl3741_set_color_all;quantum/led_matrix/led_matrix_drivers.c 则把单色版本绑定到is31fl3741_set_value系列。因此通过框架使用时,无需(也不应)直接调用底层 API。

API 参考

以下 API 声明于 is31fl3741.h(RGB)与 is31fl3741-mono.h(单色),独立使用驱动时可直接调用。

struct is31fl3741_led_t

保存单颗 RGB LED 的 PWM 寄存器地址。位域定义见 is31fl3741.h。

成员(RGB 版本):

  • uint32_t driver:LED 所属驱动索引,取值范围 0~3;
  • uint32_t r:红色通道的输出 PWM 寄存器地址(仅 RGB 驱动);
  • uint32_t g:绿色通道的输出 PWM 寄存器地址(仅 RGB 驱动);
  • uint32_t b:蓝色通道的输出 PWM 寄存器地址(仅 RGB 驱动);
  • uint32_t v:输出 PWM 寄存器地址(仅单色驱动)。

void is31fl3741_init(uint8_t index)

初始化指定索引的 LED 驱动,应当最先调用(框架模式下由is31fl3741_init_drivers()统一调用)。

  • uint8_t index:驱动索引。

void is31fl3741_write_register(uint8_t index, uint8_t reg, uint8_t data)

向指定寄存器写入值。底层实现为i2c_write_register(),并在IS31FL3741_I2C_PERSISTENCE > 0时按配置次数重试(见 is31fl3741.c)。

  • uint8_t index:驱动索引;
  • uint8_t reg:寄存器地址;
  • uint8_t data:要写入的值。

void is31fl3741_select_page(uint8_t index, uint8_t page)

切换当前配置页面。内部先写解锁魔数0xC5到写锁寄存器,再写页面号到命令寄存器。

  • uint8_t index:驱动索引;
  • uint8_t page:要选择的页面号(IS31FL3741_COMMAND_PWM_0等常量)。

void is31fl3741_set_color(int index, uint8_t red, uint8_t green, uint8_t blue)

设置单颗 LED 的颜色(仅 RGB 驱动)。不会立即更新硬件,修改完成后需调用is31fl3741_update_pwm_buffers()。若新值与缓冲中已有值相同,函数会提前返回,避免无谓的 I²C 流量(见 is31fl3741.c)。

  • int index:LED 索引(即g_is31fl3741_leds数组下标);
  • uint8_t red:红色分量(0~255);
  • uint8_t green:绿色分量(0~255);
  • uint8_t blue:蓝色分量(0~255)。

void is31fl3741_set_color_all(uint8_t red, uint8_t green, uint8_t blue)

将全部 LED 设为同一颜色(仅 RGB 驱动),等价于对所有索引循环调用is31fl3741_set_color()。同样需要随后刷新 PWM 缓冲。

void is31fl3741_set_value(int index, uint8_t value)

设置单颗 LED 的亮度(仅单色驱动)。不会立即更新硬件,需调用is31fl3741_update_pwm_buffers()

  • int index:LED 索引;
  • uint8_t value:亮度值(0~255)。

void is31fl3741_set_value_all(uint8_t value)

将全部 LED 设为同一亮度(仅单色驱动)。

void is31fl3741_set_led_control_register(uint8_t index, bool red, bool green, bool blue)

配置单颗 LED 的 LED 控制(Scaling)寄存器(仅 RGB 驱动),即决定各通道的使能状态(写入0xFF/0x00)。不会立即更新硬件,需调用is31fl3741_update_led_control_registers()

  • uint8_t index:LED 索引;
  • bool red:使能或禁用红色通道;
  • bool green:使能或禁用绿色通道;
  • bool blue:使能或禁用蓝色通道。

void is31fl3741_set_led_control_register(uint8_t index, bool value)

配置单颗 LED 的控制寄存器(仅单色驱动)。不会立即更新硬件,需调用is31fl3741_update_led_control_registers()

  • uint8_t index:LED 索引;
  • bool value:使能或禁用该 LED。

void is31fl3741_update_pwm_buffers(uint8_t index)

将本驱动索引的 PWM 缓冲刷新到芯片(脏标记置位时执行)。源码注释提示:不应在中断(如定时器中断)中调用,应在矩阵扫描间隙的空闲期调用;is31fl3741_flush()会一次性刷新全部驱动索引。

  • uint8_t index:驱动索引。

void is31fl3741_update_led_control_registers(uint8_t index)

将本驱动索引的 LED 控制寄存器缓冲刷新到芯片(脏标记置位时执行),分两页逐寄存器写入(见 is31fl3741.c)。

  • uint8_t index:驱动索引。

综上,使用 IS31FL3741 驱动的完整链路为:rules.mk引入源码与 I²C 依赖 →config.h设定地址、去鬼影电阻、PWM 频率与全局电流 → 在键盘.c中按原理图编写g_is31fl3741_leds映射表 → 由 LED/RGB Matrix 框架自动初始化并驱动,或在独立模式下依次调用初始化、设置颜色与刷新函数。仓库中的 drivers/led/issi/ 源码与 Acheron Apollo 87H Gamma、KPrepublic BM80v2 等真实键盘实现可作为移植与排查问题的参考。

【免费下载链接】qmk_firmwareOpen-source keyboard firmware for Atmel AVR and Arm USB families项目地址: https://gitcode.com/GitHub_Trending/qm/qmk_firmware

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

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

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

立即咨询