一、1位数码管的显示

1位数码管的引脚定义如下:-
在这里插入图片描述
将esp32引脚,按照下图的形式连接。直接驱动电流较大,中间注意串联电阻
在这里插入图片描述

在这里插入图片描述

其实数码管的本质就是一些按照规律排列组合的LED灯。数码管显示数字,实际上就是按照顺序让LED点亮。
结合第一节-点亮LED的内容,定义好管脚信息。

import machine
import time

# 按照连接方式定义管脚
a = machine.Pin(13, machine.Pin.OUT)
b = machine.Pin(12, machine.Pin.OUT)
c = machine.Pin(14, machine.Pin.OUT)
d = machine.Pin(27, machine.Pin.OUT)
e = machine.Pin(26, machine.Pin.OUT)
f = machine.Pin(25, machine.Pin.OUT)
g = machine.Pin(33, machine.Pin.OUT)
h = machine.Pin(32, machine.Pin.OUT)

# 以list的形式收录管脚信息
led_list = [a, b, c, d, e, f, g, h]
led_map = {
    0: "11111100", # 按照a-h的形式排列,1亮灯  0灭灯
    1: "01100000",
    2: "11011010",
    3: "11110010",
    4: "01100110",
    5: "10110110",
    6: "10111110",
    7: "11100000",
    8: "11111110",
    9: "11110110",
    }

def show_one_num(num):  # 定义显示数字方法,处理每一个管脚
    if num < 0 or num > 9:
        print("out of range") # 异常拦截
        return
    count = 0
    for bit in led_map.get(num):
        if bit == "1" :
            led_list[count].value(bit)
        else:
            led_list[count].value(0)
        count += 1

for i in range(0, 12):
    show_one_num(i)
    time.sleep_ms(500)

这里的管脚定义也可以使用PWM的形式,可以通过设置duty值来控制数码管的亮度

from machine import Pin, PWM
import time

a = PWM(Pin(13), freq = 10000)
# ......

led_list = [a, b, c, d, e, f, g, h]
led_map = {
# 与上一节中定义一致
    }


def show_one_num(num):
    if num < 0 or num > 9:
        print("out of range")
    count = 0
    for bit in led_map.get(num):
        if bit == "1" :
            led_list[count].duty(10) # 通过duty设置亮度
        else:
            led_list[count].duty(0)
        count += 1

for i in range(0, 100):
    # ......

二、四位数码管的显示

四位数码管的引脚定义,有一些变化,多出了led1-led4的控制引脚:
在这里插入图片描述
按照图示连接面包板电路:
在这里插入图片描述
在一位数码管的基础上,单独控制led1-led4引脚,可以直接让他们显示某一个数字

from machine import Pin, PWM
import time
import machine

a = PWM(Pin(13), freq = 10000)
# ...参考一位数码管实现

# 将四位数码管特有的控制引脚赋值
led1 = machine.Pin(5, machine.Pin.OUT)
led2 = machine.Pin(18, machine.Pin.OUT)
led3 = machine.Pin(19, machine.Pin.OUT)
led4 = machine.Pin(21, machine.Pin.OUT)

led_list = [a, b, c, d, e, f, g, h]
led_map = {# ...参考一位数码管实现
def show_one_num(num): # ...参考一位数码管实现

# 通过将ledx引脚激活/关闭,可以实现数码管按需同时亮灭
led1.value(0)
led2.value(0)
led3.value(1)
led4.value(0)

for i in range(0, 9):
    show_one_num(i)
    time.sleep_ms(500)

练习:依次让数码管显示0-9999的数字
参考前文一位数码管的逻辑,补充使能LED位数的代码
注意需要确保显示质量的话,注释中显示质量1 2中的实现比较重要

from machine import Pin, PWM
import time
import machine

a = PWM(Pin(13), freq = 10000)
# ...参考一位数码管实现

# 将四位数码管特有的控制引脚赋值
led1 = machine.Pin(5, machine.Pin.OUT)
led2 = machine.Pin(18, machine.Pin.OUT)
led3 = machine.Pin(19, machine.Pin.OUT)
led4 = machine.Pin(21, machine.Pin.OUT)

led_enable_list = [led1, led2, led3, led4]

led_list = [a, b, c, d, e, f, g, h]
led_map = {# ...参考一位数码管实现

def show_one_num(num): # ...参考一位数码管实现

def show_four_num(index, num): 
    for ledx in led_enable_list: # 先将所有的使能位置为不显示,防止快速刷新时留下残影
        ledx.value(1)  # <---显示质量1
    if num != -1: show_one_num(num) # 不为-1显示对应的一位数
    # 显示第几位数字
    for ledx in range(0, 4):
        if ledx == index and num != -1:
            led_enable_list[ledx].value(0) # 操作需要显示第几位数

for i in range(0, 10000):  # 显示0-9999的数字
    num_index = [-1, -1, -1, -1] # 个位 十位 百位 千位的列表,之后会对数字取余
    num_index[3] = i % 10
    if i >= 10: num_index[2] = int(i / 10 % 10) # 初值为-1 方便后续判断,未初始化的位数不亮灯
    if i >= 100: num_index[1] = int(i / 100 % 10)
    if i >= 1000: num_index[0] = int(i / 1000)
    print(num_index)
    for delay1 in range(150): # 确保显示质量,单个数字多次刷新 <---显示质量2
        for numx in range(0, 4): # 依次遍历数位
            show_four_num(numx, num_index[numx])

以上实现都在主线程里运行,不方便调节显示速率与显示内容的关系,
使用线程,可以很好的解决这个问题,显示数字与更新数字的线程分开,可以对不同的功能做针对性的操作

from machine import Pin, PWM
import time
import machine
import _thread

a = PWM(Pin(13), freq = 10000)
b = PWM(Pin(12), freq = 10000)
c = PWM(Pin(14), freq = 10000)
d = PWM(Pin(27), freq = 10000)
e = PWM(Pin(26), freq = 10000)
f = PWM(Pin(25), freq = 10000)
g = PWM(Pin(33), freq = 10000)
h = PWM(Pin(32), freq = 10000)

# 将四位数码管特有的控制引脚赋值
led1 = machine.Pin(5, machine.Pin.OUT)
led2 = machine.Pin(18, machine.Pin.OUT)
led3 = machine.Pin(19, machine.Pin.OUT)
led4 = machine.Pin(21, machine.Pin.OUT)

led_enable_list = [led1, led2, led3, led4]

led_list = [a, b, c, d, e, f, g, h]
led_map = {
    0: "11111100",
    1: "01100000",
    2: "11011010",
    3: "11110010",
    4: "01100110",
    5: "10110110",
    6: "10111110",
    7: "11100000",
    8: "11111110",
    9: "11110110",
}


def show_one_num(num):
    if num < 0 or num > 9:
        print("out of range")
    count = 0
    for bit in led_map.get(num):
        if bit == "1" :
            led_list[count].duty(1000)
        else:
            led_list[count].duty(0)
        count += 1
def clean():
    for ledx in led_enable_list: # 先将所有的使能位置为不显示,防止快速刷新时留下残影
        ledx.value(1)
    time.sleep_us(1)

def show_four_num(index, num):
    clean()
    if num != -1: show_one_num(num) # 不为-1显示对应的一位数 
    clean()
    # 显示第几位数字
    for ledx in range(0, 4):
        if ledx == index and num != -1:
            led_enable_list[ledx].value(0) # 操作需要显示第几位数

show_num_list = [-1, -1, -1, -1]

def show_num():
    while True:
        for numx in range(4): # 依次遍历数位
            show_four_num(numx, show_num_list[numx])
        time.sleep_us(10)
    
def split_num():
    for i in range(0, 10000):  # 显示0-9999的数字
        current_list = [-1, -1, -1, -1] # 个位 十位 百位 千位的列表,之后会对数字取余
        current_list[3] = i % 10
        if i >= 10: current_list[2] = int(i / 10 % 10) # 初值为-1 方便后续判断,未初始化的位数不亮灯
        if i >= 100: current_list[1] = int(i / 100 % 10)
        if i >= 1000: current_list[0] = int(i / 1000)
        # 更新显示数字
        global show_num_list
        show_num_list = current_list
        time.sleep_ms(500)
    

# 启动多个线程
_thread.start_new_thread(show_num, ())    # 显示线程,循环显示,不受迭代时间影响
_thread.start_new_thread(split_num, ())   # 数字拆分线程,拆分完成更新全局变量,保证显示的稳定

至此,数码管的显示就告一段落。

相关资料、代码

更多推荐