stm32/display/tm1640-8digit-7seg.md
数码管(TM1640 LED 驱动芯片,8 位共阴 7 段)
数码管(TM1640 LED 驱动芯片,8 位共阴 7 段)
2026-08-19 实测验证:Demo00 工程(洋桃1号板载数码管)菜单第 5 项"数码管"显示温度(两位小数,1s 刷新)
#一、元信息
| 字段 | 值 |
|---|---|
| 芯片/平台 | STM32F103C8T6(HAL + FreeRTOS) |
| 接口类型 | 2 线串行(SCLK=PA11,DIN=PA12,软件时序) |
| 验证状态 | ✅ 已验证(2026-08-19) |
| 验证环境 | 洋桃1号开发板 / STM32CubeIDE 2.2.0 / OpenOCD / 2026-08-19 |
| 驱动方式 | 软件时序(GPIO 推挽输出模拟时钟/数据) |
#二、接线表
| 信号 | MCU 引脚 | 模块引脚 | 备注 |
|---|---|---|---|
| SCLK | PA11 | TM1640 SCLK | 时钟线,上升沿锁存数据 |
| DIN | PA12 | TM1640 DIN | 数据线,LSB 先发 |
| VCC | 5V 或 3.3V | TM1640 VCC | 数码管模组通常需 5V 供电,看模块标注 |
| GND | GND | TM1640 GND | 必须共地 |
注意:本板 TM1640 的 SCLK/DIN 走线在洋桃1号板上已连通,无需外部杜邦线。若自己接线按上表。
#三、踩坑清单
- 芯片型号确认:TM1640 不是 TM1637! 两者引脚/协议几乎一样但寄存器地址范围不同:TM1640 支持 16 个 GRID(8 个接数码管 GRID1-8,另 8 个 GRID9-16 可接 LED 灯珠,本板 GRID9-16 恒灭)。TM1637 仅 4 位。驱动前务必先确认型号再写寻址代码。
- 共阴段码:本板数码管为共阴(位选低电平导通),段码 bit0=a、bit1=b…bit6=g、bit7=dp。段码表:0=0x3F、1=0x06、2=0x5B、3=0x4F、4=0x66、5=0x6D、6=0x7D、7=0x07、8=0x7F、9=0x6F、A=0x77、b=0x7C、C=0x39、d=0x5E、E=0x79、F=0x71、负号=0x40、熄灭=0x00。段序不对时用诊断模式逐段点亮反推实际接线。
- 时序要慢:TM1640 时钟频率典型 1MHz 以下,软件 GPIO 时序要加延时(本工程
tm_delay80 次空操作)。杜邦线过长或时序过快会花字/错位。 - 寻址方式:发送 0x44(固定地址写模式)后按地址命令 0xC0+i 逐位写数据最可靠(显式寻址),避免自动地址自增模式的行地址复位问题。
- 上电不亮先查供电:数码管较耗电,供电不足会闪烁/亮度不均;确认 VCC 电压符合模块要求(3.3V 模块或 5V 模块勿混接)。
#四、驱动代码(Demo00 工程 tm1640.c 核心逻辑,已通过验证)
#4.1 tm1640.h
c#ifndef TM1640_H
#define TM1640_H
#include "main.h"
/* TM1640 软件时序(SCLK=PA11, DIN=PA12) */
void tm1640_init(void);
void tm1640_clear(void);
void tm1640_show_str(const char *str); /* 显示字符串(含小数点) */
void tm1640_show_temp(int16_t temp_cents); /* 显示温度:25.31 -> "25.31" */
void tm1640_diag(void); /* 诊断模式:逐段点亮反推段序 */
#endif
#4.2 tm1640.c 核心函数
c#include "tm1640.h"
#define TM_SCLK_PORT GPIOA
#define TM_SCLK_PIN GPIO_PIN_11
#define TM_DIN_PORT GPIOA
#define TM_DIN_PIN GPIO_PIN_12
#define TM_SCLK_H() HAL_GPIO_WritePin(TM_SCLK_PORT, TM_SCLK_PIN, GPIO_PIN_SET)
#define TM_SCLK_L() HAL_GPIO_WritePin(TM_SCLK_PORT, TM_SCLK_PIN, GPIO_PIN_RESET)
#define TM_DIN_H() HAL_GPIO_WritePin(TM_DIN_PORT, TM_DIN_PIN, GPIO_PIN_SET)
#define TM_DIN_L() HAL_GPIO_WritePin(TM_DIN_PORT, TM_DIN_PIN, GPIO_PIN_RESET)
#define TM_GRID_TOTAL 16 /* TM1640 共 16 个 GRID */
#define TM_GRID_DIGIT 8 /* 前 8 个 GRID 接数码管 */
static void tm_delay(void) { volatile uint16_t i; for (i = 0; i < 80; i++) { __NOP(); } }
/* 共阴数码管段码:bit0=a ... bit6=g, bit7=dp */
static const uint8_t seg_code[] = {
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,
0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71,
0x40, 0x00 /* '-' 负号 / 熄灭 */
};
static void tm_send_byte(uint8_t data)
{
for (uint8_t i = 0; i < 8; i++)
{
if (data & 0x01) TM_DIN_H(); else TM_DIN_L();
tm_delay(); TM_SCLK_H(); tm_delay(); TM_SCLK_L(); tm_delay();
data >>= 1;
}
}
static void tm_start(void) { TM_DIN_H(); TM_SCLK_H(); tm_delay(); TM_DIN_L(); tm_delay(); TM_SCLK_L(); tm_delay(); }
static void tm_stop(void) { TM_DIN_L(); tm_delay(); TM_SCLK_H(); tm_delay(); TM_DIN_H(); tm_delay(); }
void tm1640_init(void)
{
tm_start(); tm_send_byte(0x48); tm_stop(); /* 显示模式:8 位 × 16 段,亮度 3/8 */
tm_start(); tm_send_byte(0x8F); tm_stop(); /* 显示开,亮度等级 8(0x88~0x8F) */
tm1640_clear();
}
void tm1640_clear(void)
{
tm_start(); tm_send_byte(0x40); tm_stop(); /* 固定地址写模式 */
for (uint8_t i = 0; i < TM_GRID_TOTAL; i++)
{
tm_start(); tm_send_byte(0xC0 + i); tm_send_byte(0x00); tm_stop();
}
}
/* 显示字符串到前 8 位(不足 8 位右补空) */
void tm1640_show_str(const char *str)
{
uint8_t idx = 0;
tm_start(); tm_send_byte(0x40); tm_stop(); /* 固定地址写模式 */
for (uint8_t g = 0; g < TM_GRID_DIGIT; g++)
{
uint8_t code = 0x00;
if (str[idx] != '\0')
{
char ch = str[idx++];
if (ch >= '0' && ch <= '9') code = seg_code[ch - '0'];
else if (ch == '.') { if (idx > 0) code = 0x80; /* 小数点附加到前一位 */ }
/* 其余字符按需扩展 */
}
tm_start(); tm_send_byte(0xC0 + g); tm_send_byte(code); tm_stop();
}
}
void tm1640_show_temp(int16_t temp_cents)
{
char buf[10];
snprintf(buf, sizeof(buf), "%d.%02d", temp_cents / 100, (temp_cents < 0 ? -temp_cents : temp_cents) % 100);
tm1640_show_str(buf);
}
#五、调用示例
c/* main() 初始化顺序 */
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
tm1640_init(); /* 初始化并清屏 */
/* 菜单第 5 项进入后显示当前温度(25.31℃) */
tm1640_show_temp(2531); /* 2531 = 25.31℃ */
/* 返回菜单时熄灭 */
tm1640_clear();
#六、参考库/链接
- TM1640 数据手册:搜索 "TM1640 datasheet PDF"(天微电子 TM1640 中文手册,含时序图与寄存器表)
- TM1637 对比:TM1637 4 位、TM1640 8 位,协议类似但寄存器不同,别混用
- 洋桃1号官方例程:
D:\学习资料\【用户资料】洋桃1号开发板(2)\B5-教学视频示例程序\(数码管示例可参考)