stm32/display/tm1640-8digit-7seg.md

数码管(TM1640 LED 驱动芯片,8 位共阴 7 段)

知识库 · STM32

数码管(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 引脚模块引脚备注
SCLKPA11TM1640 SCLK时钟线,上升沿锁存数据
DINPA12TM1640 DIN数据线,LSB 先发
VCC5V 或 3.3VTM1640 VCC数码管模组通常需 5V 供电,看模块标注
GNDGNDTM1640 GND必须共地

注意:本板 TM1640 的 SCLK/DIN 走线在洋桃1号板上已连通,无需外部杜邦线。若自己接线按上表。

#三、踩坑清单

  1. 芯片型号确认:TM1640 不是 TM1637! 两者引脚/协议几乎一样但寄存器地址范围不同:TM1640 支持 16 个 GRID(8 个接数码管 GRID1-8,另 8 个 GRID9-16 可接 LED 灯珠,本板 GRID9-16 恒灭)。TM1637 仅 4 位。驱动前务必先确认型号再写寻址代码。
  2. 共阴段码:本板数码管为共阴(位选低电平导通),段码 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。段序不对时用诊断模式逐段点亮反推实际接线。
  3. 时序要慢:TM1640 时钟频率典型 1MHz 以下,软件 GPIO 时序要加延时(本工程 tm_delay 80 次空操作)。杜邦线过长或时序过快会花字/错位。
  4. 寻址方式:发送 0x44(固定地址写模式)后按地址命令 0xC0+i 逐位写数据最可靠(显式寻址),避免自动地址自增模式的行地址复位问题。
  5. 上电不亮先查供电:数码管较耗电,供电不足会闪烁/亮度不均;确认 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-教学视频示例程序\(数码管示例可参考)