如果你要显示的是时钟、需要中间那个冒号,就买 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 |
材料清单 —— 两块数码管、一块 Uno,以及接得上它们的线
选配:排针由我们代焊
| Item | Price | Qty | |
|---|---|---|---|
Soldering Service for Circuit Boards & Electronics - 5 Pins Soldering ServiceSOLSE05 | RM0.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 能驱动八块,所以六十四位数字依然只花三支引脚。这个不对称,就是买它的理由。

你的 Arduino 项目该买哪一块?
TM1637 的那个冒号是一整类项目,不是装饰:时钟、倒计时、圈速表。我们的 DS3231 时钟制作把时间显示在 16×2 LCD 上;TM1637 只用两支引脚,占四分之一的地方就做到同一件事。MAX7219 拿手的则是带小数的读数和长数字。
| 如果你要显示的是…… | 就买 |
|---|---|
| HH:MM 或 MM:SS 的时钟、计时器 | TM1637 四位数码管模块 |
| 四位以内,而 Uno 的引脚已经很紧张 | TM1637 四位数码管模块 |
| 带一位小数的传感器读数 | MAX7219 八位数码管模块 |
| 五位以上,或者要两块并排 | MAX7219 八位数码管模块 |
| 文字、名字或菜单 | 两个都不行 —— 看我们的 OLED 监测指南 |

袋子里装了什么,以及 MAX7219 需要的那排排针
TM1637 模块出货就能接线:它那排四针直角排针是出厂焊在短边那一端的,顺序是 CLK、DIO、VCC、GND —— 丝印印在板子背面,所以先把它翻过来看一眼。
MAX7219 模块的出货方式不一样,而这正是下单之前值得先知道的事。它的五个输入焊盘 —— VCC、GND、DIN、CS、CLK,其中 VCC 落在标记第 1 脚的那个方形焊盘上 —— 是裸的镀通孔,没有焊排针,另一端那五个级联焊盘也一样。袋子里就是这块数码管,别的什么都没有。材料清单里那条 40-pin 公排针就是为它准备的:掰下五针,焊五个点,动烙铁之前先决定好针要从哪一面伸出去。或者直接加上五针代焊服务——那个页面是先咨询后下单的,请先用 WhatsApp 跟我们说一声。
一个安全提醒,这里唯一真正的危险。烙铁头的温度在 350 °C 上下,烫伤你的时候你还来不及感觉到;助焊剂的烟也是刺激性的:桌面要耐热,两个焊点之间烙铁一定放回架子上,开一扇窗或者用风扇把烟吹开。我们的焊接排针指南把这一排讲得更细。

八位数字全亮要吃多少电流?
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 联系我们。



TM1637 Based 4 Digit 7 Segment Display 4 Pin Only LED Display Module For Arduino IOT Application
MAX7219 8 Digit 7 Segment Display LED Digit Display Module For Arduino IOT Application
Arduino Uno Compatible SMD UNO R3 with Type B Cable - ATMEGA328P with CH340G-Microcontroller Project
Sensor Shield V5.0 Arduino Uno R3 Shield For Arduino Protoype Application
40pcs Dupont Wire 10cm 20cm 30cm for Breadboard DIY Experiment Jumper Wire Breadboard wire - DUPONT WIRE F-F 20CM
2.54mm Pin Header Female Male Single Row Header 40P Connector Black White Red Yellow Green Blue - 40P MALE HEADER
Soldering Service for Circuit Boards & Electronics - 5 Pins Soldering Service