跳转至

exs_tm1638 扩展库

作者:江访 | 最后修改:2026-07-08

一、概述

exs_tm1638 是天微电子 TM1638 驱动芯片的 LuatOS 扩展库。TM1638 是一款带键盘扫描接口的 LED 驱动控制专用 IC,内部集成 MCU 数字接口、数据锁存器、LED 驱动、键盘扫描等电路。

TM1638 一个芯片可以同时完成 数码管显示 + 按键检测 + LED 指示灯 三项功能,用三个 GPIO 实现最丰富的交互面板,非常适合家电控制面板、工业仪表、嵌入式调试面板等场景。

1.1 主要特性

  • 芯片最大支持 10 段 ×8 位 数码管显示(比普通 8 段多两个段,可显示更多特殊符号)
  • 芯片最大支持 8×3bit 共 24 个按键 扫描检测
  • 芯片最大支持 8 颗独立 LED 指示灯 控制
  • 8 级亮度辉度调节(脉冲宽度 1/16 ~ 14/16)
  • 3 线串行接口(CLK + DIO + STB),最高时钟 1MHz
  • 内置 LED 反偏漏电优化电路,解决 LED 微弱暗亮问题
  • 内置上电复位电路和数据锁存电路
  • 工作电压范围 3V~6V,宽于 TM1637 的 4.5V~5.5V
  • 工作温度 -40℃~+85℃,工业级

1.2 加载方式

-- 扩展库需要 require 加载后才能调用
local exs_tm1638 = require "exs_tm1638"

1.3 注意事项

  • TM1638 使用 STB、CLK、DIO 三线通信,其中 STB 是片选信号,拉低开始传输,拉高结束
  • TM1638 支持两种显存写入模式:自动地址递增模式(批量写入效率高,但最多传 14 字节)和固定地址模式(单字节写入,不受数量限制,用于定点更新)
  • CLK 和 DIO 需外接 4.7kΩ~10kΩ 上拉电阻到 VCC
  • GRID 物理位置映射:若所购买的产品显示位置不一致(例如设置 "12345678" 实际显示 "87654321"),则通过 init()grid_map 参数适配。配置方式:从左到右观察 8 位数码管,记录每个物理位置当前显示的 GRID 编号(1~8),填入数组。LED 指示灯自动同步此映射。默认 nil 使用芯片默认 GRID 顺序

示例:设置 "12345678" 后实际显示 "87654321",说明第 1 位显示的是 GRID8 的内容,第 8 位显示的是 GRID1 的内容。则 grid_map = {8, 7, 6, 5, 4, 3, 2, 1}

  • 显存写入模式选择exs_tm1638.init(config)write_mode 参数可选两种模式:
**模式**
**参数**
**写入方式**
**STB 通信次数**
**速度**
**可靠性**
**适用场景**
固定地址
"fixed"

固定地址,每字节独立 STB 帧
32 次(16 字节 × 2 次/字节)


高(逐帧独立,抗干扰)
调试排查硬件接线
自动递增
"auto"

自动递增批量 14 字节 + 固定地址补写 2 字节
4 次(1 次批量 + 2 次补写)
快(约 fixed的8 倍)
较高

量产稳定运行
  • 如需驱动共阳数码管,在 exs_tm1638.init(config) 时传入 common_anode = true
  • 低功耗休眠前必须关闭按键回调:如果使用了 exs_tm1638.set_key_callback(),设备进入休眠前需调用 exs_tm1638.set_key_callback(nil) 停止内部轮询定时器,否则定时器会阻止系统进入低功耗模式

1.4 硬件连接

  ┌──────────────┐                    ┌──────────────────┐
  │    主控      │                    │     TM1638       │
  │  (AirXXX)    │                    │  驱动芯片         │
  │              │                    │                  │
  │ GPIO_CLK ────┼────────────────────┼──→ CLK           │
  │              │                    │                  │
  │ GPIO_DIO ←───┼────────────────────┼──→ DIO           │
  │              │                    │  (需外接上拉电阻)│
  │ GPIO_STB ────┼────────────────────┼──→ STB           │
  │              │                    │                  │
  │ VCC 3V   ────┼────────────────────┼──→ VDD           │
  │              │                    │                  │
  │ GND      ────┼────────────────────┼──→ GND           │
  │              │                    │                  │
  │              │                    │ SEG1~SEG10 ──────┼──→ 数码管段信号
  │              │                    │ GRID1~GRID8 ─────┼──→ 数码管位选信号
  │              │                    │                  │
  │              │                    │ SEG9 ~ GRIDn ────┼──→ 8 颗 LED 指示灯
  │              │                    │  (段位组合选通) │      (正极/负极接法)
  │              │                    │                  │
  │              │                    │ K1~K3 ──────────┼──→ 按键矩阵行输入
  │              │                    │ KS1~KS8 ────────┼──→ 按键矩阵列扫描
  └──────────────┘                    └──────────────────┘


二、核心示例

1、核心示例是指:使用本库文件提供的核心 API,开发的基础业务逻辑的演示代码;

2、核心示例的作用是:帮助开发者快速理解如何使用本库,所以核心示例的逻辑都比较简单;

3、更加完整和详细的 demo,请参考 LuatOS 仓库 中各个产品目录下的 demo/sensor/tm1638

2.1 数码管显示示例

-- 加载扩展库
local exs_tm1638 = require "exs_tm1638"

-- 应用主函数
local function tm1638_demo()
    -- 初始化 TM1638
    -- clk=27, dio=26, stb=28, 初始亮度 3 级
    local result = exs_tm1638.init({
        clk    = 27,
        dio    = 26,
        stb    = 28,
        bright = 3,
    })

    if not result then
        log.error("exs_tm1638", "TM1638 初始化失败")
        return
    end
    log.info("exs_tm1638", "TM1638 初始化成功")

    -- 显示字符串
    exs_tm1638.set_display("12345678")

    -- 延时 2 秒
    sys.wait(2000)

    -- 清空显示
    exs_tm1638.clear()

    -- 设置亮度为最亮(7 级)
    exs_tm1638.set_brightness(7)

    -- 从第 3 位开始显示
    exs_tm1638.set_display("8888", 3)
end

-- 启动任务(sys.wait 只能在协程内使用,需要用 sys.taskInit 启动)
sys.taskInit(tm1638_demo)

2.2 按键检测示例

-- 加载扩展库
local exs_tm1638 = require "exs_tm1638"

-- 按键回调函数
local function on_key(key_code)
    log.info("exs_tm1638", "按键回调,编码:", key_code)
    exs_tm1638.set_display(string.format("KEY%02d", key_code))
end

-- 初始化
local result = exs_tm1638.init({
    clk     = 27,
    dio     = 26,
    stb     = 28,
    bright  = 3,
})

-- 方式一:轮询读取按键
local function key_scan_task()
    while true do
        local key = exs_tm1638.get_key()
        if key then
            log.info("exs_tm1638", "按键按下,编码:", key)
        end
        sys.wait(50)
    end
end
sys.taskInit(key_scan_task)

-- 方式二:回调方式(推荐)
exs_tm1638.set_key_callback(on_key)

2.3 LED 指示灯示例

local exs_tm1638 = require "exs_tm1638"

exs_tm1638.init({
    clk    = 27,
    dio    = 26,
    stb    = 28,
    bright = 3,
})

-- 控制单个 LED(位置从 1 开始)
exs_tm1638.set_led(true, 1)
exs_tm1638.set_led(true, 2)
exs_tm1638.set_led(false, 1)

-- 批量设置 8 个 LED
exs_tm1638.set_led({
    true, true, true, true,
    false, false, false, false,
})

-- LED 跑马灯
local function led_task()
    local led_pos = 1
    while true do
        exs_tm1638.clear()
        exs_tm1638.set_led(true, led_pos)
        led_pos = (led_pos % 8) + 1
        sys.wait(300)
    end
end
sys.taskInit(led_task)

三、常量解释

扩展库常量,顾名思义是由合宙 LuatOS 扩展库中定义的、不可重新赋值或修改的固定值,在脚本代码中不需要声明,可直接调用,本扩展库没有常量。


四、函数详解

4.1 初始化与控制

4.1.1 exs_tm1638.init(config)

功能

初始化 TM1638 驱动芯片,配置通信引脚和初始参数

参数

config

参数含义:初始化配置表
数据类型:table
取值范围:包含以下子参数:
{
    参数含义:CLK 时钟引脚 GPIO 编号
    数据类型:number
    取值范围:有效的 GPIO 编号
    是否必选:是
    注意事项:该引脚连接 TM1638 的 CLK 管脚
    参数示例:27
    config.clk ,

    参数含义:DIO 数据引脚 GPIO 编号
    数据类型:number
    取值范围:有效的 GPIO 编号
    是否必选:是
    注意事项:该引脚连接 TM1638 的 DIO 管脚,需外接 4.7kΩ~10kΩ 上拉电阻
    参数示例:26
    config.dio ,

    参数含义:STB 片选引脚 GPIO 编号
    数据类型:number
    取值范围:有效的 GPIO 编号
    是否必选:是
    注意事项:该引脚连接 TM1638 的 STB 管脚
    参数示例:28
    config.stb ,

    参数含义:初始显示亮度等级
    数据类型:number
    取值范围:0~7(0最暗,7最亮)
    是否必选:否
    注意事项:默认值为 3。设置 0 不会关闭显示
    参数示例:3
    config.bright ,

    参数含义:是否开启显示
    数据类型:boolean
    取值范围:true(开启), false(关闭)
    是否必选:否
    注意事项:默认值为 true。设为 false 时初始化后不点亮,之后可通过 set_brightness() 开启
    参数示例:true
    config.display_on ,

    参数含义:是否使用共阳数码管
    数据类型:boolean
    取值范围:true(共阳), false(共阴)
    是否必选:否
    注意事项:默认 false(共阴极)。设为 true 时库内部自动对段码取反
    参数示例:false
    config.common_anode ,

    参数含义:GRID 物理位置映射表
    数据类型:table
    取值范围:包含 8 个元素的数组,每个元素为 1~8 的 GRID 编号
    是否必选:否
    注意事项:默认 nil(不映射)。显示位置与默认位置不一致时使用。
             例如设置 "12345678" 后实际显示 "87654321",则填入 {8,7,6,5,4,3,2,1}。
              LED 指示灯自动同步此映射
    参数示例:{3, 4, 5, 6, 7, 8, 1, 2}
    config.grid_map ,

    参数含义:显存写入模式
    数据类型:string
    取值范围:"fixed"(固定地址,默认)、"auto"(自动递增)
    是否必选:否
    注意事项:"fixed"逐个写入 16 字节,兼容性好;"auto"批量写 14 字节 + 固定地址补写 2 字节,效率更高
    参数示例:"auto"
    config.write_mode ,
}
是否必选:是
注意事项:必须包含 clk、dio、stb 三个引脚配置,否则初始化失败。库内部在初始化时自动清空全部 16 字节显存(含 GRID8 高/低地址),无需手动调用
参数示例:{clk = 27, dio = 26, stb = 28, bright = 3}

返回值

local init_result = exs_tm1638.init(config)

init_result

含义说明:初始化是否成功
数据类型:boolean
取值范围:true(成功), false(失败)
注意事项:失败时请检查接线和供电
返回示例:true

示例

-- 基础初始化
local result = exs_tm1638.init({clk = 27, dio = 26, stb = 28, bright = 3})

-- 共阳数码管
local result = exs_tm1638.init({clk = 27, dio = 26, stb = 28, bright = 3, common_anode = true})

4.1.2 exs_tm1638.set_brightness(level)

功能

设置显示亮度,8 级亮度调节

参数

level

参数含义:亮度等级
数据类型:number
取值范围:0~7(0最暗,7最亮)
是否必选:是
注意事项:调用此接口会自动开启显示
参数示例:7

返回值

示例

exs_tm1638.set_brightness(7)  -- 最亮
exs_tm1638.set_brightness(3)  -- 中等
exs_tm1638.set_brightness(0)  -- 最暗

4.1.3 exs_tm1638.clear()

功能

清空所有显示寄存器和 LED 指示灯,熄灭所有数码管和 LED

参数

返回值

示例

exs_tm1638.set_display("87654321")
sys.wait(1000)
exs_tm1638.clear()

4.2 数码管显示

4.2.1 exs_tm1638.set_display(str, offset)

功能

从指定起始位开始显示字符串

参数

str

参数含义:要显示的字符串
数据类型:string
取值范围:支持显示以下类型:
         1、数字(0–9)
            0, 1, 2, 3, 4, 5, 6, 7, 8, 9
         2、大写字母(A–Z)
            A, B, C, D, E, F, G, H, I, J, K(同H), L, M, N(同M), O(同0), 
            P, Q, R, S(同5), T(同R), U, V(同U), W, X(同H), Y, Z(同2)
         3、小写字母(a–z)
            a(同A), b(同B), c, d(同D), e(同E), f(同F), g(同9), h, i(同I), 
            j, k, l(同I), m, n(同m), o, p(同P), q(同Q), r, s(同S), t, u, 
            v(同u), w(同U), x(同H), y(同Y), z(同2)
         4、其他符号
            - , _ , = , °, .
是否必选:是
注意事项:点号"."作为小数点附加在前一个字符上,不占独立位置。温度显示可用 "25°C"、"77°F"表示 。° 支持 UTF-8、GBK、Latin-1 三种编码自动识别。
参数示例:"12345678"

offset

参数含义:起始位置
数据类型:number
取值范围:1~8(1 对应第 1 位数码管,8 对应第 8 位数码管)
是否必选:否
注意事项:默认 1。超出范围时超出部分不显示
参数示例:3

返回值

示例

exs_tm1638.set_display("12345678")
exs_tm1638.set_display("88.88")
exs_tm1638.set_display("1234", 3)  -- 从第 3 位开始显示

4.3 LED 指示灯

4.3.1 exs_tm1638.set_led(state, pos)

功能

控制 LED 指示灯的亮灭。支持单个控制和批量设置两种模式:

  • 单个控制:传入状态(boolean)和位置(number)
  • 批量设置:传入 8 颗 LED 状态的数组(table)

参数

state

参数含义:LED 状态(单个控制模式),或 8 颗 LED 的状态数组(批量设置模式)
数据类型:boolean | table
取值范围:
  单个控制模式:true(亮), false(灭)
  批量设置模式:包含 8 个 boolean 值的数组,true=亮,false=灭,nil 值表示该位保持不变
是否必选:是
注意事项:单个控制时 state 为 boolean,批量设置时 state 为数组
参数示例(单个):true
参数示例(批量):{true, false, true, false, true, false, true, false}

pos

参数含义:LED 指示灯位置(仅单个控制模式使用)
数据类型:number
取值范围:1~8(1 对应第 1 颗 LED 指示灯,8 对应第 8 颗 LED 指示灯)
是否必选:单个控制模式为是,批量设置模式无此参数
注意事项:nil
参数示例:3

返回值

示例

-- 单个控制
exs_tm1638.set_led(true, 1)   -- 点亮第 1 颗 LED 指示灯
exs_tm1638.set_led(false, 5)  -- 熄灭第 5 颗 LED 指示灯

-- 批量设置(全部 8 颗 LED)
exs_tm1638.set_led({true, false, true, false, true, false, true, false})

4.4 按键扫描

TM1638 内置 8×3 按键扫描矩阵,最多支持 24 个按键。按键扫描由芯片自动完成(内部每 4.7ms 扫描一轮),结果存储在芯片内部的按键寄存器中,主控只需要通过通信总线读取即可。

为什么不能配 GPIO 中断? TM1638 的 K1~K3 引脚是芯片输入脚(带 7.3kΩ 下拉),芯片扫描时轮流拉高 KS1~ KS8 来检测这些脚的电平变化。K 脚上的电平是脉冲式的(只有 KS 轮到的那一瞬间才有信号),不是稳定的电平,所以不能直接接主控 GPIO 中断,否则会因为扫描脉冲不断误触发。 因此 TM1638 的按键读取只能用轮询方式。支持中断的型号是 TM1650(有专用 KP 引脚)。

按键编码 1~24 的排列:

      KS1  KS2  KS3  KS4  KS5  KS6  KS7  KS8
K1 ──  1    2    3    4    5    6    7    8
K2 ──  9   10   11   12   13   14   15   16
K3 ── 17   18   19   20   21   22   23   24

4.4.1 exs_tm1638.get_key()

功能

轮询读取当前按下的按键编码,无按键按下时返回 nil

参数

返回值

local key = exs_tm1638.get_key()

key

含义说明:按键编码
数据类型:number 或 nil
取值范围:1~24(有按键按下),nil(无按键按下)
注意事项:多个键同时按下时返回编码最小的那个
返回示例:5

示例

local function check_key_task()
    while true do
        local key = exs_tm1638.get_key()
        if key then
            log.info("exs_tm1638", "检测到按键:", key)
        end
        sys.wait(30)
    end
end
sys.taskInit(check_key_task)

4.4.2 exs_tm1638.set_key_callback(cbfunc)

功能

设置按键回调函数。注册后库内部每隔 50ms 自动轮询,按键按下时调用回调。

设备进入低功耗休眠前,必须先调用 exs_tm1638.set_key_callback(nil) 停止内部轮询定时器,否则定时器会阻止休眠。唤醒后重新注册回调即可。

参数

cbfunc

参数含义:按键回调函数
数据类型:function
取值范围:有效的 Lua 函数
是否必选:是
注意事项:回调接收一个参数 key_code(number 类型 1~24)。传入 nil 取消回调。回调中避免长时间阻塞
参数示例:local function on_key(key_code) log.info("key", key_code) end

返回值

示例

-- 按键回调函数
local function on_key(key_code)
    log.info("exs_tm1638", "按键:", key_code)
end

-- 注册
exs_tm1638.set_key_callback(on_key)

-- 取消
exs_tm1638.set_key_callback(nil)

4.5 版本管理

4.5.1 exs_tm1638.version()

功能

获取 exs_tm1638 库的版本号

参数

返回值

local ver = exs_tm1638.version()

ver

含义说明:版本号字符串
数据类型:string
取值范围:格式 "yyyymmddhhmm",表示 yyyy年mm月dd日hh时mm分发布的版本
注意事项:无
返回示例:"202607071200"

示例

local ver = exs_tm1638.version()
log.info("exs_tm1638", "版本号:", ver)

五、版本更新说明

版本号:202607071200

  1. 更新时间:2026-07-07
  2. 更新内容:

  3. 首次发布,实现 TM1638 基础驱动功能

  4. 支持数码管显示(10 段 ×8 位)
  5. 支持 LED 指示灯独立控制
  6. 支持按键扫描(轮询 + 回调两种方式)
  7. 支持 8 级亮度调节
  8. 支持共阴/共阳数码管切换

六、产品支持说明

所有支持 luatos 二次开发的模块,具体可以查看选型手册

问一下 AI