The goal of this session is to understand how hardware is interfaced with software.
Starting from the data sheet of the MAX7219 used to drive an LED matrix, we will first write a kind of
driver
for it, then some functions to address individual
pixels
on it, and finally a program to play the Game of Live on an 8 by 8 display.
We have an ESP32 board and an 8 by 8 LED matrix driven by a MAX7219. Here is the wiring (which may vary depending on the development board you use), for an
ESP32 DevKit V4 board
by Espressif:
Communication with the MAX7219
The MAX7219 communicates through a synchronous serial link according to the following chronogram:
For instance, to write the data 0x01 into register 0x0F of the MAX7219, which puts it in test mode, we should have the following transmission:
This can be achieved with custom code as follows:
import machine
data = 12; # pin connected to the serial input of the MAX7219 (DIN)
load = 14; # pin for loading data (CS)
clk = 27; # pin for the clock of the serial link (CLK)
# Initialize the pins as outputs
dataPin = machine.Pin(data, machine.Pin.OUT)
loadPin = machine.Pin(load, machine.Pin.OUT)
clkPin = machine.Pin(clk, machine.Pin.OUT)
# Set them to level 0
dataPin.off()
loadPin.off()
clkPin.off()
# Send a byte bit by bit to the MAX7219, most significant bit first
def serialShiftByte(data):
# Set the clock to 0 in order to be able to make a rising edge later
clkPin.off()
# Shift the 8 bits of data
for i in range(8):
# left shift the data by i bits and test the most significant bit
value = ((data << i) & 0B10000000) != 0
dataPin.value(value) # set the DIN pin to this value
clkPin.on() # create a rising edge on CLK
clkPin.off() # to send this bit
# Write some data in a register of the MAX7219.
def serialWrite(address, data):
# Set CS to 0 to create a rising edge later
loadPin.off()
# Send the address of the register first
serialShiftByte(address)
# then the data
serialShiftByte(data)
# make a rising edge on CS to load the transmitted data into the register
loadPin.on()
loadPin.off()
This can also be achieved using the SPI bus interface of the ESP32:
import machine
import time
data = 12; # pin connected to the serial input of the MAX7219 (DIN)
miso = 13; # pin for input from the SPI bus (not used here)
load = 14; # pin for loading data (CS)
clk = 27; # pin for the clock of the serial link (CLK)
# Initialize the pins as outputs
dataPin = machine.Pin(data, machine.Pin.OUT)
misoPin = machine.Pin(miso, machine.Pin.OUT)
loadPin = machine.Pin(load, machine.Pin.OUT)
clkPin = machine.Pin(clk, machine.Pin.OUT)
# Set them to level 0
dataPin.off()
loadPin.off()
clkPin.off()
# Use software SPI bus
spi = machine.SPI(-1, sck = clkPin, mosi = dataPin, miso = misoPin)
# Send a byte bit by bit to the MAX7219, most significant bit first
def serialShiftByte(data):
# Set the clock to 0 in order to be able to make a rising edge later
clkPin.off()
spi.write(data)
# Communication buffer
buffer = bytearray(2)
# Write some data in a register of the MAX7219.
def serialWrite(address, data):
buffer[0] = address
buffer[1] = data
# Set CS to 0 to create a rising edge later
loadPin.off()
# Send the address of the register then the data
spi.write(buffer)
# make a rising edge on CS to load the transmitted data into the register
loadPin.on()
loadPin.off()
The rest of the practical session works the same as in the
original version
using the pyboard. You just have to replace calls to
pyb.delay(ms)
by calls to
time.sleep_ms(ms)
.