【ESP32+MicroPython】单位数码管使用

在本教程中,我们将使用ESP32和MicroPython来驱动一个带小数点的单位数码管(7段显示器)。将详细讲解数码管的工作原理,并分步骤完成从基本的段位控制到完整的数字显示,最后封装成可重用的控制类。同时,本文将提供如何判断数码管是共阳极还是共阴极的方法,并为不同类型的数码管提供兼容代码。

数码管基础知识

数码管结构及显示原理

数码管通常包含7个段位(A-G)和一个小数点(DP)。不同的段位可以组合显示0-9的数字,或显示部分字母。数码管的两个主要分类是共阳极和共阴极:

  • 共阳极数码管:数码管的阳极引脚连接到电源,单个段位点亮时接地。
  • 共阴极数码管:数码管的阴极引脚接地,单个段位点亮时接电源。

判断数码管的类型

我们可以通过简单测试来判断数码管的类型。以下步骤有助于辨别:

  1. 准备电源:取一个3.3V或5V的电源。
  2. 连接任意段位引脚:将数码管的任一段位引脚连接到电源的正极。
  3. 测试公共引脚:依次将公共引脚(标记为COM或“+”“-”)接到电源的负极,观察数码管是否亮起。
    • 数码管亮起,则该数码管为共阳极
    • 若数码管未亮,再将公共引脚接到电源的正极,若此时数码管亮起,则该数码管为共阴极

硬件连接

在测试完成后,我们将数码管连接到ESP32上。以下是连接方案示例:

公共引脚的接法取决于数码管的类型:

  1. 共阳极数码管:公共引脚连接到电源(VCC,3.3V或5V)。这种类型的数码管需要通过给各段位的引脚提供低电平(即接地)来点亮段位。

  2. 共阴极数码管:公共引脚连接到地(GND)。这种类型的数码管需要通过给各段位的引脚提供高电平(即接电源)来点亮段位。

假设以下引脚分配:

  • A - GPIO 15
  • B - GPIO 2
  • C - GPIO 4
  • D - GPIO 16
  • E - GPIO 17
  • F - GPIO 5
  • G - GPIO 18
  • DP(小数点) - GPIO 19

数码管显示逻辑

数码管每个数字所需的段位亮灭状态如下表:

数字ABCDEFGDP
011111100
101100000
211011010
311110010
401100110
510110110
610111110
711100000
811111110
911110110

在代码中将使用该段位状态表来控制数码管显示。

MicroPython代码实现

初始化GPIO引脚

首先,为ESP32上连接的每个段位定义一个GPIO引脚,并初始化为输出模式。

from machine import Pin
import time

# 定义数码管段位引脚(A-G 和 DP分别连接GPIO引脚)
pins = {
    'A': Pin(15, Pin.OUT),
    'B': Pin(2, Pin.OUT),
    'C': Pin(4, Pin.OUT),
    'D': Pin(16, Pin.OUT),
    'E': Pin(17, Pin.OUT),
    'F': Pin(5, Pin.OUT),
    'G': Pin(18, Pin.OUT),
    'DP': Pin(19, Pin.OUT)  # 小数点引脚
}

# 判断数码管类型
is_common_anode = True  # 设置为 True 表示共阳极,False 表示共阴极

数字显示字典

根据数码管类型,调整段位的高低电平。例如,共阳极数码管需要低电平点亮,而共阴极数码管需要高电平点亮。

# 数字的段位组合,1 表示点亮,0 表示熄灭
segments = {
    '0': [1, 1, 1, 1, 1, 1, 0, 0],
    '1': [0, 1, 1, 0, 0, 0, 0, 0],
    '2': [1, 1, 0, 1, 1, 0, 1, 0],
    '3': [1, 1, 1, 1, 0, 0, 1, 0],
    '4': [0, 1, 1, 0, 0, 1, 1, 0],
    '5': [1, 0, 1, 1, 0, 1, 1, 0],
    '6': [1, 0, 1, 1, 1, 1, 1, 0],
    '7': [1, 1, 1, 0, 0, 0, 0, 0],
    '8': [1, 1, 1, 1, 1, 1, 1, 0],
    '9': [1, 1, 1, 1, 0, 1, 1, 0]
}

# 根据数码管类型调整段位的电平状态
def get_segment_state(state):
    return not state if is_common_anode else state

定义显示函数

编写一个函数,接受一个数字字符,根据数码管类型设置各段位的电平状态。

def display_digit(digit, dp=False):
    """显示一个数字,并控制小数点"""
    if digit not in segments:
        print("无效数字")
        return

    segment_states = segments[digit]

    # 设置每个段位的状态
    for i, (seg, pin) in enumerate(pins.items()):
        state = segment_states[i] if i < 7 else dp  # dp 为小数点控制
        pin.value(get_segment_state(state))

测试显示功能

依次循环显示0-9,并带小数点。

while True:
    for digit in '0123456789':
        display_digit(digit, dp=True)  # 小数点显示
        time.sleep(1)
        display_digit(digit, dp=False) # 小数点熄灭
        time.sleep(0.5)

面向对象封装

将数码管显示功能封装为一个类,使其更具可复用性。

class SevenSegmentDisplay:
    def __init__(self, pin_map, is_common_anode=True):
        self.segments = {key: Pin(pin, Pin.OUT) for key, pin in pin_map.items()}
        self.is_common_anode = is_common_anode
        self.numbers = {
            '0': [1, 1, 1, 1, 1, 1, 0, 0],
            '1': [0, 1, 1, 0, 0, 0, 0, 0],
            '2': [1, 1, 0, 1, 1, 0, 1, 0],
            '3': [1, 1, 1, 1, 0, 0, 1, 0],
            '4': [0, 1, 1, 0, 0, 1, 1, 0],
            '5': [1, 0, 1, 1, 0, 1, 1, 0],
            '6': [1, 0, 1, 1, 1, 1, 1, 0],
            '7': [1, 1, 1, 0, 0, 0, 0, 0],
            '8': [1, 1, 1, 1, 1, 1, 1, 0],
            '9': [1, 1, 1, 1, 0, 1, 1, 0]
        }

    def display(self, digit, dp=False):
        if digit not in self.numbers:
            print("Invalid digit")
            return
        for i, (seg, pin) in enumerate(self.segments.items()):
            state = self.numbers[digit][i] if i < 7 else dp
            pin.value(not state if self.is_common_anode else state)

使用方式:

display = SevenSegmentDisplay(pins, is_common_anode=True)
while True:
    for digit in '0123456789':
        display.display(digit, dp=True)
        time.sleep(1)

总结

通过本教程,我们深入学习了单位数码管的控制原理,掌握了使用ESP32和MicroPython驱动数码管的完整流程。从判断数码管类型到封装类实现数码管显示,这一系列操作将为你提供坚实的硬件控制基础。

### 使用ESP32驱动数码管的实现方法 #### 方法一:直接连接数码管ESP32 GPIO引脚 当使用共阴极数码管时,可以将其各段(a, b, c, d, e, f, g 和 dp)分别连接到 ESP32 的 GPIO 引脚上。为了保护数码管并防止电流过大,通常会在每条数据线上串联一个约 220 欧姆的电阻[^2]。 以下是基于 MicroPython 实现的代码示例: ```python from machine import Pin import time # 定义数码管各段对应的GPIO引脚 segments = { 'a': Pin(18, Pin.OUT), 'b': Pin(19, Pin.OUT), 'c': Pin(21, Pin.OUT), 'd': Pin(5, Pin.OUT), 'e': Pin=Pin(17, Pin.OUT), 'f': Pin(16, Pin.OUT), 'g': Pin(4, Pin.OUT) } digit_pins = [ Pin(2, Pin.OUT), # 数码管第1位选通 Pin(15, Pin.OUT) # 数码管第2位选通 ] def display_digit(digit_index, number): """ 显示指定位置上的数字 """ segment_map = { 0: ['a', 'b', 'c', 'd', 'e', 'f'], 1: ['b', 'c'], 2: ['a', 'b', 'd', 'e', 'g'], 3: ['a', 'b', 'c', 'd', 'g'], 4: ['b', 'c', 'f', 'g'], 5: ['a', 'c', 'd', 'f', 'g'], 6: ['a', 'c', 'd', 'e', 'f', 'g'], 7: ['a', 'b', 'c'], 8: ['a', 'b', 'c', 'd', 'e', 'f', 'g'], 9: ['a', 'b', 'c', 'd', 'f', 'g'] } digit_pins[digit_index].on() # 启用当前数码管的位置 for seg in segments.keys(): if seg in segment_map[number]: segments[seg].on() else: segments[seg].off() while True: for i in range(len(digit_pins)): display_digit(i, (i + 1)) # 循环显示不同数字 time.sleep_ms(500) for pin in digit_pins: pin.off() # 关闭所有数码管 ``` 此代码实现了在两个数码管之间切换显示不同的数字,并通过 `time.sleep` 控制刷新频率[^1]。 --- #### 方法二:利用移位寄存器 HC595 驱动多位数码管 对于多于两位以上的数码管或者更复杂的场景下,推荐采用移位寄存器(如 HC595)。这种方法能够显著减少所需的 GPIO 引脚数量[^3]。 下面是具体的 Python 示例代码片段用于配置和控制 HC595 芯片来点亮多个七段数码管: ```python from machine import Pin import time class ShiftRegisterSevenSegment: def __init__(self, data_pin, clock_pin, latch_pin): self.data_pin = Pin(data_pin, Pin.OUT) self.clock_pin = Pin(clock_pin, Pin.OUT) self.latch_pin = Pin(latch_pin, Pin.OUT) def shift_out(self, value): self.latch_pin.low() bit_mask = 1 << 7 while(bit_mask != 0): self.clock_pin.low() if(value & bit_mask): self.data_pin.high() else: self.data_pin.low() self.clock_pin.high() bit_mask >>= 1 self.latch_pin.high() sr_seven_seg = ShiftRegisterSevenSegment(data_pin=13, clock_pin=14, latch_pin=12) try: while True: sr_seven_seg.shift_out(int('0x3F', base=16)) # Displaying the character '0' time.sleep(1) except KeyboardInterrupt: pass finally: sr_seven_seg.shift_out(0x00) # Clear all outputs when done. ``` 上述程序展示了如何设置一个类对象以简化向 HC595 发送命令的过程,从而轻松更新所连结之数码管的内容。 --- #### 方法三:封装函数提高可读性和复用率 如果希望进一步优化代码结构,则可以通过创建自定义库文件或将逻辑抽象成独立模块的形式完成。这种方式不仅便于维护还利于移植到其他项目当中去[^4]。 例如,在单独的一个 `.py` 文件里编写如下内容作为工具集的一部分供调用者导入即可: ```python # seven_segment_utils.py def get_segments_for_number(number): mapping = { ... } # Similar to previous examples' mappings but expanded here as needed. result = [] for char in str(number).zfill(4): try: result.append(mapping[int(char)]) except KeyError: raise ValueError(f"Unsupported character '{char}' encountered.") return tuple(result[::-1]) # Reverse order so LSB is first sent out by SPI/shift register logic later on... ``` 随后主应用程序只需简单地引入该实用程序包中的辅助功能即可快速构建起完整的解决方案框架体系。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值