本文将介绍一个在Raspberry Pi Pico上运行的MicroPython程序,该程序控制一个8x8 LED矩阵(MAX7219),并通过I2C与EEPROM进行数据交互。程序会随机生成一个数字,将其存储到EEPROM中,并在LED矩阵上显示相应的数字。如果从EEPROM读取的值与存储的值匹配,则显示数字;如果不匹配,则显示叉号。
效果
完整源码
使用的组件:
- Raspberry Pi Pico:一款基于RP2040芯片的小型微控制器开发板。
- MAX7219 8x8 LED矩阵:一种常见的显示模块,用于显示数字或字符。
- 24LC64 EEPROM:一种通过I2C通信的串行EEPROM,用于数据存储。
关键功能:
- 使用SPI协议与MAX7219通信:MAX7219 LED矩阵通过SPI协议进行控制。
- 通过I2C与EEPROM交互:程序使用I2C协议与24LC64 EEPROM进行读写操作。
- 随机生成数字并存储:程序会生成一个随机数字并将其写入EEPROM。
- 显示效果:根据读取的EEPROM值来决定LED矩阵显示数字或叉号。
程序分析
from machine import Pin, SPI, I2C
from max7219 import max7219
import time
import random
# SPI接口设置
spi = SPI(1, baudrate=10000000, polarity=0, phase=0)
cs = Pin(0, Pin.OUT)
# I2C接口设置 (修改为I2C1,SDA=GPIO2, SCL=GPIO3)
i2c = I2C(1, scl=Pin(3), sda=Pin(2), freq=400000)
首先,程序初始化了SPI接口(用于与MAX7219进行通信)和I2C接口(用于与EEPROM进行通信)。SPI接口使用的是SPI(1)
,波特率设定为10MHz,极性和相位均为0。I2C接口设置为I2C1,使用GPIO2作为SDA,GPIO3作为SCL。
def scan_i2c():
devices = i2c.scan()
if len(devices) == 0:
print("没有检测到I2C设备。")
return None
elif len(devices) == 1:
print(f"检测到1个设备,地址: 0x{devices[0]:02X}")
return devices[0]
else:
print("检测到多个I2C设备:")
for i, device in enumerate(devices):
print(f"{i + 1}: 0x{device:02X}")
while True:
try:
choice = int(input("请选择设备 (输入序号): ")) - 1
if 0 <= choice < len(devices):
return devices[choice]
else:
print("无效选择,请重试。")
except ValueError:
print("请输入有效数字。")
scan_i2c
函数用于扫描I2C总线上连接的设备。该函数会返回设备的地址,如果未检测到设备或检测到多个设备,程序会给出提示让用户自行选择一个设备。如果只检测到一个设备那么程序会直接使用。
EEPROM_ADDR = scan_i2c()
if EEPROM_ADDR is None:
raise Exception("未检测到EEPROM设备,程序终止。")
通过调用scan_i2c
函数来确定连接的EEPROM设备。如果未找到设备,程序会抛出异常并终止。
# 初始化MAX7219
matrix = max7219.Matrix8x8(spi, cs, 1)
matrix.brightness(0)
# 显示方向(1=0°,2=90°,3=180°,4=270°)
display_direction = 2 # 默认顺时针旋转90度
在此部分,程序初始化了MAX7219模块并设置亮度为最低。display_direction
变量决定显示的旋转方向,默认值为2,表示旋转90度。
# 定义数字0-9、问号和叉的图案
digits = [
[0x3E, 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x3E], # 0
[0x0C, 0x1C, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F], # 1
[0x3E, 0x63, 0x03, 0x0E, 0x3C, 0x70, 0x63, 0x7F], # 2
[0x3E, 0x63, 0x03, 0x1E, 0x03, 0x03, 0x63, 0x3E], # 3
[0x06, 0x0E, 0x1E, 0x36, 0x66, 0x7F, 0x06, 0x06], # 4
[0x7F, 0x60, 0x7E, 0x03, 0x03, 0x03, 0x63, 0x3E], # 5
[0x1E, 0x30, 0x60, 0x7E, 0x63, 0x63, 0x63, 0x3E], # 6
[0x7F, 0x63, 0x06, 0x0C, 0x18, 0x18, 0x18, 0x18], # 7
[0x3E, 0x63, 0x63, 0x3E, 0x63, 0x63, 0x63, 0x3E], # 8
[0x3E, 0x63, 0x63, 0x63, 0x3F, 0x03, 0x06, 0x3C] # 9
]
question_mark = [0x3E, 0x63, 0x03, 0x0E, 0x1C, 0x00, 0x1C, 0x1C] # ?
cross_mark = [0x63, 0x36, 0x1C, 0x08, 0x1C, 0x36, 0x63, 0x00] # X
在这部分代码中,定义了数字0-9、问号和叉号的图案。这些图案将以字节的形式存储,每个数字或符号由8行数据表示。
def rotate_pattern(pattern, direction):
rotated = [[0] * 8 for _ in range(8)]
for y in range(8):
for x in range(8):
bit = (pattern[y] >> (7 - x)) & 1
if direction == 1:
rotated[y][x] = bit
elif direction == 2:
rotated[x][7 - y] = bit
elif direction == 3:
rotated[7 - y][7 - x] = bit
elif direction == 4:
rotated[7 - x][y] = bit
return [int("".join(str(bit) for bit in row), 2) for row in rotated]
rotate_pattern
函数将数字或符号图案根据direction
参数的值进行旋转。旋转方向包括:0°(不旋转)、90°、180°和270°。
def display_pattern(pattern):
rotated = rotate_pattern(pattern, display_direction)
matrix.fill(0)
for y in range(8):
matrix.buffer[y] = rotated[y]
matrix.show()
display_pattern
函数用于在LED矩阵上显示旋转后的图案。
def write_eeprom(addr, value):
addr_high = (addr >> 8) & 0xFF
addr_low = addr & 0xFF
i2c.writeto(EEPROM_ADDR, bytes([addr_high, addr_low, value]))
time.sleep(0.01)
def read_eeprom(addr):
addr_high = (addr >> 8) & 0xFF
addr_low = addr & 0xFF
i2c.writeto(EEPROM_ADDR, bytes([addr_high, addr_low]))
return int.from_bytes(i2c.readfrom(EEPROM_ADDR, 1), 'big')
write_eeprom
和read_eeprom
函数分别用于向EEPROM写入数据和从EEPROM读取数据。
last_number = -1
while True:
new_number = random.choice([i for i in range(10) if i != last_number])
last_number = new_number
write_eeprom(EEPROM_MEM_ADDR, new_number)
display_pattern(question_mark)
time.sleep(0.5)
read_number = read_eeprom(EEPROM_MEM_ADDR)
if read_number == new_number:
display_pattern(digits[read_number])
else:
display_pattern(cross_mark)
time.sleep(1)
主循环中,程序生成一个新的随机数字(不等于上一个数字),将其写入EEPROM。然后显示一个问号,等待0.5秒后从EEPROM读取数据并与存储的数字进行比较。如果相同,则显示对应的数字;否则,显示叉号。整个过程每秒执行一次。
总结
该程序展示了如何使用MicroPython与Raspberry Pi Pico进行硬件编程,实现了与MAX7219 LED矩阵和24LC64 EEPROM的交互。通过SPI控制LED矩阵显示数字,通过I2C与EEPROM进行数据读写,能够实现数字存储和显示的功能,适用于数字展示、测试等应用场景。
系列文章
- 用Raspberry Pi Pico驱动MAX7219 8x8 LED点阵并实现呼吸灯效果
- 使用MicroPython控制Raspberry Pi Pico与MAX7219和EEPROM的应用【当前文章】
- 使用 MicroPython 控制 74HC595 和 EEPROM 的项目解析