游乐游手机版
首页/AI热点日报/热点详情

树莓派Pico驱动TM1637数码管模块教程

类型:热点整理2026-07-21
树莓派 Pico 与 TM1637 数码管模块:从零开始的实战教程 这篇教程将带你一步步掌握如何在树莓派 Pico(或 Pico W)上驱动 TM1637 4 位数码管模块,最终实现数字、文字、甚至滚动消息的显示。别担心接线和代码,我们从头说起。 所需组件 树莓派 Pico 或 Pico W TM1

树莓派 Pico 与 TM1637 数码管模块:从零开始的实战教程

这篇教程将带你一步步掌握如何在树莓派 Pico(或 Pico W)上驱动 TM1637 4 位数码管模块,最终实现数字、文字、甚至滚动消息的显示。别担心接线和代码,我们从头说起。

所需组件

  • 树莓派 Pico 或 Pico W
  • TM1637 4 位数码管模块
  • 面包板和跳线
  • microUSB 数据线

认识 TM1637 模块

TM1637 是一颗非常实用的 LED 驱动控制芯片,内部集成了 MCU 数字接口、数据锁存器、高压驱动和键盘扫描电路。这类数码管模块之所以受欢迎,是因为它只用了 4 个引脚(两个电源、两个控制)就能搞定 4 位 7 段显示,接线简单到令人感动。

  • CLK:时钟引脚,负责与微控制器保持同步脉冲。
  • DIO:数据引脚,用于发送和接收数据。
  • GND:接地。
  • VCC:电源输入,支持 3.3V~5V。

树莓派 Pico 的 I2C 引脚分配

RP2040 芯片提供了两个 I2C 控制器,每个控制器都可以通过多个 GPIO 引脚灵活配置。下面这张表就是它们的映射关系——你完全可以按自己手头的接线来选。

I2C 控制器功能可选 GPIO 引脚
I2C0SDAGP0/GP4/GP8/GP12/GP16/GP20
I2C0SCLGP1/GP5/GP9/GP13/GP17/GP21
I2C1SDAGP2/GP6/GP10/GP14/GP18/GP26
I2C1SCLGP3/GP7/GP11/GP15/GP19/GP27

实际连接非常简单:我们直接把 CLK 接到 GP26,DIO 接到 GP27 就行。当然你也可以用表里其他 SDA/SCL 组合,只要软件里配置一致即可。

安装 TM1637 库

要驱动这个模块,我们需要一个干净的 MicroPython 库。下面的代码就是完整的 tm1637.py,直接复制到 Thonny 中,保存到 Pico 的根目录或 lib 文件夹即可。

from micropython import const
from machine import Pin
from time import sleep_us, sleep_ms

TM1637_CMD1 = const(64)  # 0x40 data command
TM1637_CMD2 = const(192) # 0xC0 address command
TM1637_CMD3 = const(128) # 0x80 display control command
TM1637_DSP_ON = const(8) # 0x08 display on
TM1637_DELAY = const(10) # 10us delay between clk/dio pulses
TM1637_MSB = const(128)  # msb is the decimal point or the colon depending on your display

# 0-9, a-z, blank, dash, star
_SEGMENTS = bytearray(b'x3Fx06x5Bx4Fx66x6Dx7Dx07x7Fx6Fx77x7Cx39x5Ex79x71x3Dx76x06x1Ex76x38x55x54x3Fx73x67x50x6Dx78x3Ex1Cx2Ax76x6Ex5Bx00x40x63')

class TM1637(object):
    """Library for quad 7-segment LED modules based on the TM1637 LED driver."""
    def __init__(self, clk, dio, brightness=7):
        self.clk = clk
        self.dio = dio
        if not 0 <= brightness <= 7:
            raise ValueError("Brightness out of range")
        self._brightness = brightness
        self.clk.init(Pin.OUT, value=0)
        self.dio.init(Pin.OUT, value=0)
        sleep_us(TM1637_DELAY)
        self._write_data_cmd()
        self._write_dsp_ctrl()

    def _start(self):
        self.dio(0)
        sleep_us(TM1637_DELAY)
        self.clk(0)
        sleep_us(TM1637_DELAY)

    def _stop(self):
        self.dio(0)
        sleep_us(TM1637_DELAY)
        self.clk(1)
        sleep_us(TM1637_DELAY)
        self.dio(1)

    def _write_data_cmd(self):
        # automatic address increment, normal mode
        self._start()
        self._write_byte(TM1637_CMD1)
        self._stop()

    def _write_dsp_ctrl(self):
        # display on, set brightness
        self._start()
        self._write_byte(TM1637_CMD3 | TM1637_DSP_ON | self._brightness)
        self._stop()

    def _write_byte(self, b):
        for i in range(8):
            self.dio((b >> i) & 1)
            sleep_us(TM1637_DELAY)
            self.clk(1)
            sleep_us(TM1637_DELAY)
            self.clk(0)
            sleep_us(TM1637_DELAY)
        self.clk(0)
        sleep_us(TM1637_DELAY)
        self.clk(1)
        sleep_us(TM1637_DELAY)
        self.clk(0)
        sleep_us(TM1637_DELAY)

    def brightness(self, val=None):
        """Set the display brightness 0-7."""
        if val is None:
            return self._brightness
        if not 0 <= val <= 7:
            raise ValueError("Brightness out of range")
        self._brightness = val
        self._write_data_cmd()
        self._write_dsp_ctrl()

    def write(self, segments, pos=0):
        """Display up to 6 segments moving right from a given position."""
        if not 0 <= pos <= 5:
            raise ValueError("Position out of range")
        self._write_data_cmd()
        self._start()
        self._write_byte(TM1637_CMD2 | pos)
        for seg in segments:
            self._write_byte(seg)
        self._stop()
        self._write_dsp_ctrl()

    def encode_digit(self, digit):
        return _SEGMENTS[digit & 0x0f]

    def encode_string(self, string):
        segments = bytearray(len(string))
        for i in range(len(string)):
            segments[i] = self.encode_char(string[i])
        return segments

    def encode_char(self, char):
        o = ord(char)
        if o == 32:
            return _SEGMENTS[36] # space
        if o == 42:
            return _SEGMENTS[38] # star/degrees
        if o == 45:
            return _SEGMENTS[37] # dash
        if o >= 65 and o <= 90:
            return _SEGMENTS[o-55] # uppercase A-Z
        if o >= 97 and o <= 122:
            return _SEGMENTS[o-87] # lowercase a-z
        if o >= 48 and o <= 57:
            return _SEGMENTS[o-48] # 0-9
        raise ValueError("Character out of range: {:d} '{:s}'".format(o, chr(o)))

    def hex(self, val):
        string = '{:04x}'.format(val & 0xffff)
        self.write(self.encode_string(string))

    def number(self, num):
        num = max(-999, min(num, 9999))
        string = '{0: >4d}'.format(num)
        self.write(self.encode_string(string))

    def numbers(self, num1, num2, colon=True):
        num1 = max(-9, min(num1, 99))
        num2 = max(-9, min(num2, 99))
        segments = self.encode_string('{0:0>2d}{1:0>2d}'.format(num1, num2))
        if colon:
            segments[1] |= 0x80  # colon on
        self.write(segments)

    def temperature(self, num):
        if num < -9:
            self.show('lo')
        elif num > 99:
            self.show('hi')
        else:
            string = '{0: >2d}'.format(num)
            self.write(self.encode_string(string))
        self.write([_SEGMENTS[38], _SEGMENTS[12]], 2)  # degrees C

    def show(self, string, colon=False):
        segments = self.encode_string(string)
        if len(segments) > 1 and colon:
            segments[1] |= 128
        self.write(segments[:4])

    def scroll(self, string, delay=250):
        segments = string if isinstance(string, list) else self.encode_string(string)
        data = [0] * 8
        data[4:0] = list(segments)
        for i in range(len(segments) + 5):
            self.write(data[0+i:4+i])
            sleep_ms(delay)

class TM1637Decimal(TM1637):
    """For modules with decimal points after each digit."""
    def encode_string(self, string):
        segments = bytearray(len(string.replace('.','')))
        j = 0
        for i in range(len(string)):
            if string[i] == '.' and j > 0:
                segments[j-1] |= TM1637_MSB
                continue
            segments[j] = self.encode_char(string[i])
            j += 1
        return segments

库文件就绪后,就可以进入真正的实战阶段了。

树莓派 Pico MicroPython:TM1637 示例代码

首先确保你的 Pico 已经刷入了 MicroPython(如果不清楚,可以参考之前的入门教程)。按上图完成硬件连接,然后用 USB 线连上电脑。打开 Thonny,新建一个文件,粘贴下面的代码:

import tm1637
from machine import Pin
import time

tm = tm1637.TM1637(clk=Pin(0), dio=Pin(1))

# 设置亮度(0-7)
tm.brightness(5)

# 显示 "10:24"
tm.numbers(10, 24, colon=True)
time.sleep(2)

# 显示单词
tm.show("AbCd", colon=False)
time.sleep(2)

# 直接通过位段显示 "COOL"
tm.write([0b00111001, 0b00111111, 0b00111111, 0b00111000])
time.sleep(2)

# 清屏
tm.show("    ")
time.sleep(2)

# 显示十六进制 "bEEF"
tm.hex(0xbeef)
time.sleep(2)

# 显示负数 "-123"
tm.number(-123)
time.sleep(2)

# 显示温度 "24*C"
tm.temperature(24)
time.sleep(2)

# 滚动显示长文本
tm.scroll('RPI-ICU', delay=250)

点击 Thonny 的“运行”按钮(或按 F5),然后将脚本保存到 Pico 中(比如命名为 main.py 或任意 .py 文件)。上传成功后,你会看到数码管依次切换显示各种内容,每次显示停留约 2 秒。

代码逐段解析

先看导入部分:import tm1637 是我们的核心驱动,Pin 用于控制 GPIO,time 负责延时。

import tm1637
from machine import Pin
import time

tm = tm1637.TM1637(clk=Pin(0), dio=Pin(1))

这里实例化了一个 TM1637 对象,指定 CLK 接 GP0,DIO 接 GP1。

tm.brightness(5)

亮度范围 1~7,数字越大越亮。

tm.numbers(10, 24, colon=True)

numbers() 函数在冒号两侧各显示两个数字,前导会自动补零。如果不想显示冒号,把 colon 设为 False 即可。

tm.write([0b00111001, 0b00111111, 0b00111111, 0b00111000])

这是最底层的控制方式——直接指定每个段的状态。每个 8 位二进制数对应一个数码管的 a~g 和 DP 段。比如 0b00111001 点亮了 a、d、e、f 段,正好显示字母 'c'。熟悉 7 段显示原理的话,这个写法会格外顺手。

   __2__
  |     |
1 |     | 3
  |__7__|
  |     |
6 |     | 4
  |__5__|  DP

对照上面的段位图,0b00111001 = 二进制位的 0~7 分别对应 a、b、c、d、e、f、g、DP。最低位是 a,最高位是 DP。所以 0b00111001 点亮 a、d、e、f,拼出 'c'。同理,0b00111111 点亮 a、b、c、d、e、f,拼出 'o';0b00111000 点亮 a、d、e 和 g,拼出 'l'。

tm.show('heya', colon=False)
tm.hex(0xbeef)
tm.number(-123)

这些是更高级的封装函数:show() 直接显示字符串,hex() 显示 4 位十六进制数,number() 显示 -999 到 9999 范围内的整数,数字自动右对齐。

tm.scroll('scrolling', delay=250)

当内容超过 4 位时,scroll() 可以滚动显示。参数 delay 是每个字符在屏幕上停留的毫秒数。

最后

上传代码后,TM1637 数码管模块就会依次展示数字、文字、十六进制值、温度符号和滚动消息。整个过程直观且易于调试,非常适合作为树莓派 Pico 的入门显示项目。有问题的话,不妨先核对接线和库的版本,再检查一下代码中的引脚号是否与实物一致。

来源:https://m.elecfans.com/article/2327844.html

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。