TM1637 与 MAX7219 数码管:Arduino 该用哪一块?

Cartoon of a blue TM1637 four-digit display with a red colon wired by four jumper leads to a blue Arduino Uno with a sensor shield, beside a long blue MAX7219 eight-digit display whose five input pads are still bare

如果你要显示的是时钟、需要中间那个冒号,就买 TM1637 四位数码管模块;如果你需要五位以上、需要小数点,或者要接好几块,就买 MAX7219 八位数码管模块。决定的另一半是袋子里到底装了什么:我们的 TM1637 出货时排针已经焊好,MAX7219 则是五个裸焊盘。

一句话回答:TM1637 还是 MAX7219?

TM1637 和 MAX7219 这两块模块,对同一个问题给出的是相反的答案:你要显示几位数,对上你还能腾出几支 Arduino 引脚

  TM1637 模块(4DI1637) MAX7219 模块(8DI7291)
位数 4 8(两块四位拼起来)
分隔符 固定的中央冒号,没有小数点 每一位下面都有小数点,没有冒号
接口 两线(CLK + DIO),私有协议 —— 不是 I2C 三线串行,SPI 形式(DIN、CS、CLK)
接一块要几支 Uno 引脚 2 支信号引脚 3 支信号引脚
接 N 块要几支 Uno 引脚 1 + N(共用 CLK,每块各自一条 DIO) 3,级联多少块都一样
板子尺寸 约 42 x 25 mm,四角各一个 M2 孔 约 82 x 15 mm 长条,四个 3 mm 孔
亮度调节 8 级,写在显示命令里 16 级占空比,写在亮度寄存器里
我们出货时的状态 4-pin 直角排针已经焊好 五个裸焊盘 —— 排针没有焊
Arduino 库 TM1637,作者 Avishay Orpaz LedControl,作者 Eberhard Fahle

选配:排针由我们代焊

ItemPriceQty
Soldering Service for Circuit Boards & Electronics - 5 Pins Soldering ServiceSoldering Service for Circuit Boards & Electronics - 5 Pins Soldering ServiceSOLSE05RM0.80

MAX7219 上的五支引脚,出货前先帮你焊好。这项服务是先咨询后下单的,所以加进购物车之前请先用 WhatsApp 跟我们说一声。

TM1637 那两根线为什么不是 I2C?

TM1637 的这条链路,拿示波器看跟 I2C 一模一样:CLK 为高时 DIO 落下就是起始,抬起来就是结束,芯片则在第八个时钟的下降沿把 DIO 拉低表示应答。Titan Micro 的 TM1637 数据手册写下了那句决定性的话:这个协议「is not equal to I2C bus protocol totally because there is no slave address」——它并不完全等同于 I2C 总线协议,因为它没有从机地址。

把地址拿掉,三件事随之而来。没有 Wire 这条路,也没有任何理由去用 A4 和 A5:库是用软件位模拟(bit-bang)出这条链路的,所以任意两支普通数字引脚都可以;而 DIO 是开漏的——库只会把它拉低,或者松手让模块自己的上拉电阻把它抬回去。字节是低位在前发出去的,I2C 则是高位在前。还有,两块模块共用同一对 CLK 和 DIO,会一起锁存同样的字节,因为没有任何东西说明这是在对谁讲话。所以它是按引脚数扩展的:CLK 共用,DIO 各自一条。

MAX7219 怎么把 64 位数字塞进三支引脚?

MAX7219 讲的是固定长度的 16 位数据包。Analog Devices 的 MAX7219/MAX7221 数据手册把这一帧写得很清楚:每一个 CLK 上升沿把一位移进芯片内部的 16 位寄存器,最先进去的是 D15,D8–D11 是寄存器地址,D0–D7 是数据,整个字则在 LOAD/CS 的上升沿被锁存。这除了名字之外就是 SPI —— 只不过数据手册把「fully SPI compatible」这句话留给了它的孪生型号 MAX7221,因为在 MAX7219 上,不管 CS 在做什么,每一个 CLK 上升沿数据都照移不误;CS 只负责锁存。

级联才是聪明的地方。进到 DIN 的东西,会在 16.5 个时钟周期之后从 DOUT 出来,所以第二个数据包会把第一个从模块 1 顶进模块 2。把 DOUT 接到下一块的 DIN,所有 CS 并在一起,要写到第四块就发四个数据包——一个是真的,三个是空操作——再由一个 CS 上升沿一起锁存。LedControl 能驱动八块,所以六十四位数字依然只花三支引脚。这个不对称,就是买它的理由。

卡通概念图:五条线从主板扇出,分别接到四块小小的红字数码管;对照下方三条线喂进四块长条八位数码管串成的级联链
四块 TM1637 要花五支 Arduino 引脚,因为每一块都要自己的数据线。四块 MAX7219 只花三支——四十块也一样是三支。

你的 Arduino 项目该买哪一块?

TM1637 的那个冒号是一整类项目,不是装饰:时钟、倒计时、圈速表。我们的 DS3231 时钟制作把时间显示在 16×2 LCD 上;TM1637 只用两支引脚,占四分之一的地方就做到同一件事。MAX7219 拿手的则是带小数的读数和长数字。

如果你要显示的是…… 就买
HH:MM 或 MM:SS 的时钟、计时器 TM1637 四位数码管模块
四位以内,而 Uno 的引脚已经很紧张 TM1637 四位数码管模块
带一位小数的传感器读数 MAX7219 八位数码管模块
五位以上,或者要两块并排 MAX7219 八位数码管模块
文字、名字或菜单 两个都不行 —— 看我们的 OLED 监测指南
卡通特写:小块蓝色四位数码管上亮着一个红色冒号,对照长条蓝色八位数码管上亮着一个红色小数点
TM1637 有冒号,没有小数点。MAX7219 每一位下面都有小数点,却没有冒号。两者都借不到对方的那一个。

袋子里装了什么,以及 MAX7219 需要的那排排针

TM1637 模块出货就能接线:它那排四针直角排针是出厂焊在短边那一端的,顺序是 CLK、DIO、VCC、GND —— 丝印印在板子背面,所以先把它翻过来看一眼。

MAX7219 模块的出货方式不一样,而这正是下单之前值得先知道的事。它的五个输入焊盘 —— VCC、GND、DIN、CS、CLK,其中 VCC 落在标记第 1 脚的那个方形焊盘上 —— 是裸的镀通孔,没有焊排针,另一端那五个级联焊盘也一样。袋子里就是这块数码管,别的什么都没有。材料清单里那条 40-pin 公排针就是为它准备的:掰下五针,焊五个点,动烙铁之前先决定好针要从哪一面伸出去。或者直接加上五针代焊服务——那个页面是先咨询后下单的,请先用 WhatsApp 跟我们说一声。

一个安全提醒,这里唯一真正的危险。烙铁头的温度在 350 °C 上下,烫伤你的时候你还来不及感觉到;助焊剂的烟也是刺激性的:桌面要耐热,两个焊点之间烙铁一定放回架子上,开一扇窗或者用风扇把烟吹开。我们的焊接排针指南把这一排讲得更细。

卡通特写:长条蓝色 MAX7219 板上五个裸露的镀锡焊盘,旁边是掰下来的黑色五针排针和正在焊一个焊点的烙铁
MAX7219 的五个输入焊盘是裸的。从排针条上掰下五针焊上去,这块模块就能接杜邦线了。

八位数字全亮要吃多少电流?

MAX7219 从来不会同时点亮八位。芯片内的硬件振荡器以 500–1300 Hz 轮流扫描八个位驱动,所以任何一个瞬间只有一位是亮的,最多它的八段——七根笔画加一个小数点——在吃电流。每一段的峰值电流由硬件决定,不是代码:V+ 和芯片 ISET 脚之间的一颗电阻,段驱动输出的电流大约是流进这只脚的 100 倍。数据手册给这颗电阻的下限是 9.53 kΩ,对应一段接近 40 mA,八段就是 320 mA。当八位同时显示 8. 的时候,总有一位正处在这个峰值上,所以峰值同时也就是平均值——这就是数据手册那个「所有段加小数点全亮」的典型值 330 mA 的来处。空着的位在自己的时隙里不吃电,所以只显示两位的读数平均下来大约只有四分之一,尽管它的峰值一点没变。

USB 2.0 端口的预算是 500 mA,Uno 自己还要分掉一部分,所以一块全亮的数码管挂在同一条线上就已经贴着边缘了,症状是数字越填越满、板子突然重启。把亮度调下来——那个寄存器本来就是占空比控制,从 1/32 到 31/32 分十六级,平均电流跟着一起降——或者给数码管另外接一路 5 V 电源,接到模块的 VCC 和 GND,两边的地要接在一起。别接到扩展板那个螺丝端子上:端子旁边那个小跳线帽把它跟 Uno 自己的 5 V 轨连在一起,第二路电源落在那里,最后会跟 USB 那一路互相顶。跟我们 WS2812 指南里同一课电流预算。

这颗设定电流的电阻,在我们这块模块上是已经装好的,所以这里的亮度只能靠软件调。TM1637 没有对应的东西:它把段电流设定在芯片内部,给你八级脉宽调节,不用焊也没得修。两颗芯片都在硬件里扫描,所以都不会闪,也都不需要你的 loop() 去刷新它们。

两块各自要怎么接线、怎么写代码?

把 MAX7219 那五支针焊上以后,两块模块伸出来的都是公针——TM1637 的是出厂就焊好的——而 Arduino Uno 板上是母座。Sensor Shield V5.0 扩展板一压就解决:它把每一支数字引脚重新做成 G/V/S 三针一组里的那支公 S 针,于是普通的母对母杜邦线就能把两边接起来。

TM1637 引脚 接到
CLK 扩展板第 2 列的 S 针 → D2
DIO 扩展板第 3 列的 S 针 → D3
VCC 扩展板上任意一支 V 针 → Uno 5V
GND 扩展板上任意一支 G 针 → Uno GND
// TM1637 四位数码管 - 显示 分:秒,中间冒号常亮。
// 库:"TM1637" by Avishay Orpaz(库管理器)- 头文件 TM1637Display.h
#include <TM1637Display.h>

const uint8_t PIN_CLK = 2;   // 任意两支普通数字引脚都可以
const uint8_t PIN_DIO = 3;

TM1637Display display(PIN_CLK, PIN_DIO);

void setup() {
  display.setBrightness(3);  // 0 = 最暗,7 = 最亮
  display.clear();
}

void loop() {
  static unsigned long shown = 0;
  unsigned long secs = millis() / 1000UL;      // 上电以来的秒数
  if (secs == shown) return;                   // 数字变了才重画
  shown = secs;

  unsigned int mm = (secs / 60UL) % 100UL;     // 0..99 分钟
  unsigned int ss = secs % 60UL;

  // 0b01000000 点亮冒号(bit 6 = 第二位的小数点位)
  display.showNumberDecEx(mm * 100 + ss, 0b01000000, true);
}
MAX7219 引脚 接到
VCC 扩展板上任意一支 V 针 → Uno 5V
GND 扩展板上任意一支 G 针 → Uno GND
DIN 扩展板第 11 列的 S 针 → D11
CS 扩展板第 10 列的 S 针 → D10
CLK 扩展板第 13 列的 S 针 → D13
// MAX7219 八位数码管 - 一个读到一位小数的秒表。
// 库:"LedControl" by Eberhard Fahle(库管理器)
#include <LedControl.h>

const uint8_t PIN_DIN = 11;
const uint8_t PIN_CLK = 13;
const uint8_t PIN_CS  = 10;

LedControl lc(PIN_DIN, PIN_CLK, PIN_CS, 1);  // 1 = 链上只有一块模块

void setup() {
  lc.shutdown(0, false);     // 芯片上电是熄灭的 - 这一行把它唤醒
  lc.setIntensity(0, 2);     // 0..15 级占空比;调低让电流保持理智
  lc.clearDisplay(0);
}

// 这块板上,第 0 位是最右边那一位。
void showTenths(unsigned long tenths) {
  uint8_t pos = 0;
  do {
    lc.setDigit(0, pos, (byte)(tenths % 10), pos == 1);  // 小数点点在个位上
    tenths /= 10;
    pos++;
  } while ((tenths > 0 || pos < 2) && pos < 8);
}

void loop() {
  static unsigned long shown = 0;
  unsigned long tenths = millis() / 100UL;
  if (tenths == shown) return;
  shown = tenths;
  showTenths(tenths % 100000000UL);   // 八位数最多到 99999999
}

LedControl 是用 shiftOut() 软件模拟这三条线的,没有用 Uno 的硬件 SPI,所以 D11、D13 和 D10 只是习惯,不是要求——任意三支数字引脚都行。不过 setScanLimit() 请别动:数据手册警告说,扫描位数少到三位或更少时,各个位驱动会耗散过大的功率,除非把那颗设定电流的电阻也跟着调大——而在这块模块上它是固定的。要让多余的位不显示,改用 lc.setRow(0, pos, 0x00)。想看看这套硬件和这个库在实机上跑起来的样子:

我们从真实客户身上看到的常见错误

MAX7219 接得完全正确,却还是黑的。这是设计如此,而且是两层。数据手册写着:「On initial power-up, all control registers are reset, the display is blanked, and the MAX7219/MAX7221 enter shutdown mode.」——上电时所有控制寄存器复位、显示熄灭,芯片进入关断模式。接着 LedControl 的构造函数又把它送回关断状态,好让你的 sketch 在做初始化的时候屏幕不会乱闪。在 lc.shutdown(0, false) 跑起来之前,什么都不会亮——这就是 setup() 第一行的意义。

亮是亮了,显示的却是一堆乱笔画。那是地址 0x09 的译码模式寄存器:MAX7219 要么替你把一个普通数字译成七段(BCD Code B),要么直接收下原始的段位图,而这个寄存器决定的就是走哪一条。LedControl 送的是原始位图,并且在启动时把译码模式清成零,所以自己手写的代码要是又把 Code B 打开,后面每一个字节都会被当成另一种东西来读。

数字是反过来的。在这块板上,第 0 位是最右边那一位,所以最低位放在位置 0,然后往左走——上面那段 sketch 就是这么做的,它的小数点也因此落在位置 1。想确认的话,单独点亮位置 0,看哪一头有反应。

Sketch 编译不过。这两个名字在库管理器里都很挤:上面那段 TM1637 代码要的是 Avishay Orpaz 那个库,头文件是 TM1637Display.h,其他叫 TM1637 的条目用的是不一样的类名和方法名。MAX7219 这边要选 LedControl —— MD_MAX72xx 是 8×8 点阵用的库,API 跟它一点都不共通。

数码管填满 8 的时候 Uno 会重启。那不是代码的 bug——是上面那笔电流账撞上了 500 mA 的 USB 端口。另外也还是有人买八位板来做冒号时钟:它有小数点、没有冒号,那个活是 TM1637 的。

关于 TM1637 与 MAX7219 的常见问题

TM1637 可以接到 Arduino 的 I2C 引脚 A4 和 A5 吗?

接得上,但没有任何好处,也没有 Wire 这条路:这个协议不带设备地址,所以它没办法跟 I2C 器件共用一条总线。用任意两支空着的数字引脚就好。

MAX7219 模块出货时排针焊好了吗?

没有——它两端各是五个裸的镀通孔,袋子里只有数码管本身。从 40-pin 排针条上掰五针自己焊,或者加购我们的五针代焊服务。

一块 Arduino Uno 能带几块数码管?

级联的 MAX7219 不管你加多少块都只花三支引脚,而 LedControl 支持八块——六十四位数字。TM1637 则是每块一支引脚,因为它们可以共用 CLK,但各自需要自己的 DIO。

七段数码管能显示字母或单词吗?

只有七根笔画拼得出来的那些字母——A、b、C、d、E、F、H、L、P 和另外几个。要拼出单词的,得用字符 LCD 或者一块小 OLED。

这两块模块能配 ESP32 或 NodeMCU 吗?

两块都用 5 V 供电。MAX7219 的供电范围是 4.0–5.5 V,而它的数据输入规定要 3.5 V 才保证读成逻辑高,所以 3.3 V 的板子驱动它刚好压在保证门槛之下;在 DIN、CS 和 CLK 上加一片电平转换,它就靠得住了。TM1637 的开漏 DIO 空闲时停在模块自己的供电电压上,所以它也想要 5 V —— 我们的开发板对比里有完整的 3.3 V 与 5 V 故事。

最后更新:2026年8月。有问题?WhatsApp 联系我们

Leave a Reply

Your email address will not be published. Required fields are marked *