模組介紹
當你走在街上,你看到的各種LED霓虹燈看板只是N x N個點矩陣。現在讓我們看一下8*8點矩陣的工作原理。點矩陣的內部結構和外觀如下。8x8點陣由64個發光二極體組成,每個發光二極體位於行與列的交點上。當對應的行為高電位,列為低電位時,對應的發光二極體為亮。
我們嘗試在實驗中顯示一個心形的圖形, 所以我們將紅色部分設置為高電位, 另一部分設置為低電位,LED動態掃描後會顯示一個心形的圖形。因為這是動態掃描,我們需要注意兩個點的重影和閃爍。對人眼的殘留影響為25Hz。但通常掃頻為50Hz效果較好,因此每一列的延遲時間不能超過1000/50/8=2.5ms。如果我們將延遲設置為2ms,效果會更好。 將介紹如何使用單顆 MAX7219 驅動 8x8 矩陣式顯示器。當使用 MAX7219 的原始資料模式時 (若不熟悉 MAX7219 運作模式,可參考之前的教學範例),矩陣顯示器的每個欄位可對應到一個 Digit 暫存器,也就是說,第 0 欄對應到 Digit 0、第 1 欄對應到 Digit 1... 以此類推。而矩陣的每一列則對應到七段顯示器中的不同筆劃,從顯示器最上方開始,第 0 列對應到 Digit 暫存器資料的第 0 個位 (LSB)、第 1 列對應到 Digit 暫存器的第 1 個位... 依序下去,直到第 7 列對應到 Digit 暫存器的 MSB (第 7 位)。以實際範例說明,例如要在矩陣顯示器上顯示數位 "7" 的圖像:
根據圖上的位元資訊,可知 "7" 的位圖樣可被表示為:
const byte bitmap_7[] =
{
// define the dot pattern from column 0 ~ column 7
B00000000, B00000000, B01100001, B00010001, B00001001, B00000111, B00000000, B00000000
};
而這些資訊就是後續會送進 Digit 暫存器作為顯示用的原始資料。
電路圖
程式列表
Python - MAX7219.py
# Reference:
# Micropython driver for the max7219 with Matrix8x8 display
# https://micropython-max7219.readthedocs.io/en/latest/matrix.html
# https://github.com/adafruit/micropython-adafruit-max7219
REG_NO_OP = 0x00
REG_DIGIT_BASE = 0x01
REG_DIGIT0 = 0x01
REG_DIGIT1 = 0x02
REG_DIGIT2 = 0x03
REG_DIGIT3 = 0x04
REG_DIGIT4 = 0x05
REG_DIGIT5 = 0x06
REG_DIGIT6 = 0x07
REG_DIGIT7 = 0x08
REG_DECODE_MODE = 0x09 #Decode-Mode Register
# 0x00: No decode for digits 7¡V0
# 0x01: Code B decode for digit 0,No decode for digits 7¡V1
# 0x0F: Code B decode for digits 3¡V0, No decode for digits 7¡V4
# 0xFF: Code B decode for digits 7¡V0,
REG_INTENSITY = 0x0A #Intensity Register Format
# MAX7219 MAX7221
# 0x00: 1/16 1/32
# 0x01: 3/32 2/16
# 0x02: 5/32 3/16
# 0x03: 7/32 4/16
# 0x04: 9/32 5/16
# 0x05: 11/32 6/16
# 0x06: 13/32 7/16
# 0x07: 15/32 8/16
# 0x08: 17/32 9/16
# 0x09: 19/32 10/16
# 0x0A: 21/32 11/16
# 0x0B: 23/32 12/16
# 0x0C: 25/32 13/16
# 0x0D: 27/32 14/16
# 0x0E: 29/32 15/16
# 0x0F: 15/16 31/32
REG_SCAN_LIMIT = 0x0B #Scan-Limit Register Format
# 0x00: Display digits 0 X X X X X X X
# 0x01: Display digits 0 1 X X X X X X
# 0x02: Display digits 0 1 2 X X X X X
# 0x03: Display digits 0 1 2 3 X X X X
# 0x04: Display digits 0 1 2 3 4 X X X
# 0x05: Display digits 0 1 2 3 4 5 X X
# 0x06: Display digits 0 1 2 3 4 5 6 X
# 0x07: Display digits 0 1 2 3 4 5 6 7
REG_SHUTDOWN = 0x0C #Shutdown Register Format
# 0x00 Shutdown Mode
# 0x01 Normal Operation
REG_DISPLAY_TEST = 0x0F #Display-Test Register Format
# 0x00 Normal Operation
# 0x01 Display Test Mode
NUM_DIGITS = 8
class Matrix8x8:
def __init__(self, spi, intensity=7):
self.spi = spi
self.buffer = bytearray(NUM_DIGITS)
self.intensity = intensity
self.init()
def init(self):
for command, data in (
(REG_SHUTDOWN, 0),
(REG_DECODE_MODE, 0),
(REG_INTENSITY, self.intensity),
(REG_SCAN_LIMIT, 7),
(REG_DISPLAY_TEST, 0),
(REG_SHUTDOWN, 1),
):
self.set_register(command, data)
def set_register(self, register, value):
self.spi.write(bytearray([value, register]))
def brightness(self, value):
if not 0 <= value <= 15:
raise ValueError("Brightness out of range")
self.set_register(REG_INTENSITY, value)
def fill(self, color):
data = 0xff if color else 0x00
for y in range(8):
self.buffer[y] = data
def pixel(self, x, y, color=None):
if color is None:
return bool(self.buffer[y] & 1 << x)
elif color:
self.buffer[y] |= 1 << x
else:
self.buffer[y] &= ~(1 << x)
def show(self):
for y in range(0,NUM_DIGITS):
self.set_register(REG_DIGIT_BASE + y, self.buffer[y])
Python - fonts_8x8.py
# bit patterns for the CP437 font
# Reference: http://www.gammon.com.au/forum/?id=11516
fonts_8x8 = [
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ], # 0x00
[ 0x7E, 0x81, 0x95, 0xB1, 0xB1, 0x95, 0x81, 0x7E ], # 0x01
[ 0x7E, 0xFF, 0xEB, 0xCF, 0xCF, 0xEB, 0xFF, 0x7E ], # 0x02
[ 0x0E, 0x1F, 0x3F, 0x7E, 0x3F, 0x1F, 0x0E, 0x00 ], # 0x03
[ 0x08, 0x1C, 0x3E, 0x7F, 0x3E, 0x1C, 0x08, 0x00 ], # 0x04
[ 0x18, 0xBA, 0xFF, 0xFF, 0xFF, 0xBA, 0x18, 0x00 ], # 0x05
[ 0x10, 0xB8, 0xFC, 0xFF, 0xFC, 0xB8, 0x10, 0x00 ], # 0x06
[ 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00 ], # 0x07
[ 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF ], # 0x08
[ 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00 ], # 0x09
[ 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF ], # 0x0A
[ 0x70, 0xF8, 0x88, 0x88, 0xFD, 0x7F, 0x07, 0x0F ], # 0x0B
[ 0x00, 0x4E, 0x5F, 0xF1, 0xF1, 0x5F, 0x4E, 0x00 ], # 0x0C
[ 0xC0, 0xE0, 0xFF, 0x7F, 0x05, 0x05, 0x07, 0x07 ], # 0x0D
[ 0xC0, 0xFF, 0x7F, 0x05, 0x05, 0x65, 0x7F, 0x3F ], # 0x0E
[ 0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99 ], # 0x0F
[ 0x7F, 0x3E, 0x3E, 0x1C, 0x1C, 0x08, 0x08, 0x00 ], # 0x10
[ 0x08, 0x08, 0x1C, 0x1C, 0x3E, 0x3E, 0x7F, 0x00 ], # 0x11
[ 0x00, 0x24, 0x66, 0xFF, 0xFF, 0x66, 0x24, 0x00 ], # 0x12
[ 0x00, 0x5F, 0x5F, 0x00, 0x00, 0x5F, 0x5F, 0x00 ], # 0x13
[ 0x06, 0x0F, 0x09, 0x7F, 0x7F, 0x01, 0x7F, 0x7F ], # 0x14
[ 0x40, 0xDA, 0xBF, 0xA5, 0xFD, 0x59, 0x03, 0x02 ], # 0x15
[ 0x00, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x00 ], # 0x16
[ 0x80, 0x94, 0xB6, 0xFF, 0xFF, 0xB6, 0x94, 0x80 ], # 0x17
[ 0x00, 0x04, 0x06, 0x7F, 0x7F, 0x06, 0x04, 0x00 ], # 0x18
[ 0x00, 0x10, 0x30, 0x7F, 0x7F, 0x30, 0x10, 0x00 ], # 0x19
[ 0x08, 0x08, 0x08, 0x2A, 0x3E, 0x1C, 0x08, 0x00 ], # 0x1A
[ 0x08, 0x1C, 0x3E, 0x2A, 0x08, 0x08, 0x08, 0x00 ], # 0x1B
[ 0x3C, 0x3C, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00 ], # 0x1C
[ 0x08, 0x1C, 0x3E, 0x08, 0x08, 0x3E, 0x1C, 0x08 ], # 0x1D
[ 0x30, 0x38, 0x3C, 0x3E, 0x3E, 0x3C, 0x38, 0x30 ], # 0x1E
[ 0x06, 0x0E, 0x1E, 0x3E, 0x3E, 0x1E, 0x0E, 0x06 ], # 0x1F
[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ], # ' '
[ 0x00, 0x06, 0x5F, 0x5F, 0x06, 0x00, 0x00, 0x00 ], # '!'
[ 0x00, 0x07, 0x07, 0x00, 0x07, 0x07, 0x00, 0x00 ], # '"'
[ 0x14, 0x7F, 0x7F, 0x14, 0x7F, 0x7F, 0x14, 0x00 ], # '#'
[ 0x24, 0x2E, 0x6B, 0x6B, 0x3A, 0x12, 0x00, 0x00 ], # '$'
[ 0x46, 0x66, 0x30, 0x18, 0x0C, 0x66, 0x62, 0x00 ], # '%'
[ 0x30, 0x7A, 0x4F, 0x5D, 0x37, 0x7A, 0x48, 0x00 ], # '&'
[ 0x04, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 ], # '''
[ 0x00, 0x1C, 0x3E, 0x63, 0x41, 0x00, 0x00, 0x00 ], # '('
[ 0x00, 0x41, 0x63, 0x3E, 0x1C, 0x00, 0x00, 0x00 ], # ')'
[ 0x08, 0x2A, 0x3E, 0x1C, 0x1C, 0x3E, 0x2A, 0x08 ], # '*'
[ 0x08, 0x08, 0x3E, 0x3E, 0x08, 0x08, 0x00, 0x00 ], # '+'
[ 0x00, 0x80, 0xE0, 0x60, 0x00, 0x00, 0x00, 0x00 ], # ','
[ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00 ], # '-'
[ 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00 ], # '.'
[ 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00 ], # '/'
[ 0x3E, 0x7F, 0x71, 0x59, 0x4D, 0x7F, 0x3E, 0x00 ], # '0'
[ 0x40, 0x42, 0x7F, 0x7F, 0x40, 0x40, 0x00, 0x00 ], # '1'
[ 0x62, 0x73, 0x59, 0x49, 0x6F, 0x66, 0x00, 0x00 ], # '2'
[ 0x22, 0x63, 0x49, 0x49, 0x7F, 0x36, 0x00, 0x00 ], # '3'
[ 0x18, 0x1C, 0x16, 0x53, 0x7F, 0x7F, 0x50, 0x00 ], # '4'
[ 0x27, 0x67, 0x45, 0x45, 0x7D, 0x39, 0x00, 0x00 ], # '5'
[ 0x3C, 0x7E, 0x4B, 0x49, 0x79, 0x30, 0x00, 0x00 ], # '6'
[ 0x03, 0x03, 0x71, 0x79, 0x0F, 0x07, 0x00, 0x00 ], # '7'
[ 0x36, 0x7F, 0x49, 0x49, 0x7F, 0x36, 0x00, 0x00 ], # '8'
[ 0x06, 0x4F, 0x49, 0x69, 0x3F, 0x1E, 0x00, 0x00 ], # '9'
[ 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00 ], # ':'
[ 0x00, 0x80, 0xE6, 0x66, 0x00, 0x00, 0x00, 0x00 ], # ';'
[ 0x08, 0x1C, 0x36, 0x63, 0x41, 0x00, 0x00, 0x00 ], # '<'
[ 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00 ], # '='
[ 0x00, 0x41, 0x63, 0x36, 0x1C, 0x08, 0x00, 0x00 ], # '>'
[ 0x02, 0x03, 0x51, 0x59, 0x0F, 0x06, 0x00, 0x00 ], # '?'
[ 0x3E, 0x7F, 0x41, 0x5D, 0x5D, 0x1F, 0x1E, 0x00 ], # '@'
[ 0x7C, 0x7E, 0x13, 0x13, 0x7E, 0x7C, 0x00, 0x00 ], # 'A'
[ 0x41, 0x7F, 0x7F, 0x49, 0x49, 0x7F, 0x36, 0x00 ], # 'B'
[ 0x1C, 0x3E, 0x63, 0x41, 0x41, 0x63, 0x22, 0x00 ], # 'C'
[ 0x41, 0x7F, 0x7F, 0x41, 0x63, 0x3E, 0x1C, 0x00 ], # 'D'
[ 0x41, 0x7F, 0x7F, 0x49, 0x5D, 0x41, 0x63, 0x00 ], # 'E'
[ 0x41, 0x7F, 0x7F, 0x49, 0x1D, 0x01, 0x03, 0x00 ], # 'F'
[ 0x1C, 0x3E, 0x63, 0x41, 0x51, 0x73, 0x72, 0x00 ], # 'G'
[ 0x7F, 0x7F, 0x08, 0x08, 0x7F, 0x7F, 0x00, 0x00 ], # 'H'
[ 0x00, 0x41, 0x7F, 0x7F, 0x41, 0x00, 0x00, 0x00 ], # 'I'
[ 0x30, 0x70, 0x40, 0x41, 0x7F, 0x3F, 0x01, 0x00 ], # 'J'
[ 0x41, 0x7F, 0x7F, 0x08, 0x1C, 0x77, 0x63, 0x00 ], # 'K'
[ 0x41, 0x7F, 0x7F, 0x41, 0x40, 0x60, 0x70, 0x00 ], # 'L'
[ 0x7F, 0x7F, 0x0E, 0x1C, 0x0E, 0x7F, 0x7F, 0x00 ], # 'M'
[ 0x7F, 0x7F, 0x06, 0x0C, 0x18, 0x7F, 0x7F, 0x00 ], # 'N'
[ 0x1C, 0x3E, 0x63, 0x41, 0x63, 0x3E, 0x1C, 0x00 ], # 'O'
[ 0x41, 0x7F, 0x7F, 0x49, 0x09, 0x0F, 0x06, 0x00 ], # 'P'
[ 0x1E, 0x3F, 0x21, 0x71, 0x7F, 0x5E, 0x00, 0x00 ], # 'Q'
[ 0x41, 0x7F, 0x7F, 0x09, 0x19, 0x7F, 0x66, 0x00 ], # 'R'
[ 0x26, 0x6F, 0x4D, 0x59, 0x73, 0x32, 0x00, 0x00 ], # 'S'
[ 0x03, 0x41, 0x7F, 0x7F, 0x41, 0x03, 0x00, 0x00 ], # 'T'
[ 0x7F, 0x7F, 0x40, 0x40, 0x7F, 0x7F, 0x00, 0x00 ], # 'U'
[ 0x1F, 0x3F, 0x60, 0x60, 0x3F, 0x1F, 0x00, 0x00 ], # 'V'
[ 0x7F, 0x7F, 0x30, 0x18, 0x30, 0x7F, 0x7F, 0x00 ], # 'W'
[ 0x43, 0x67, 0x3C, 0x18, 0x3C, 0x67, 0x43, 0x00 ], # 'X'
[ 0x07, 0x4F, 0x78, 0x78, 0x4F, 0x07, 0x00, 0x00 ], # 'Y'
[ 0x47, 0x63, 0x71, 0x59, 0x4D, 0x67, 0x73, 0x00 ], # 'Z'
[ 0x00, 0x7F, 0x7F, 0x41, 0x41, 0x00, 0x00, 0x00 ], # '['
[ 0x01, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00 ], # backslash
[ 0x00, 0x41, 0x41, 0x7F, 0x7F, 0x00, 0x00, 0x00 ], # ']'
[ 0x08, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x08, 0x00 ], # '^'
[ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 ], # '_'
[ 0x00, 0x00, 0x03, 0x07, 0x04, 0x00, 0x00, 0x00 ], # '`'
[ 0x20, 0x74, 0x54, 0x54, 0x3C, 0x78, 0x40, 0x00 ], # 'a'
[ 0x41, 0x7F, 0x3F, 0x48, 0x48, 0x78, 0x30, 0x00 ], # 'b'
[ 0x38, 0x7C, 0x44, 0x44, 0x6C, 0x28, 0x00, 0x00 ], # 'c'
[ 0x30, 0x78, 0x48, 0x49, 0x3F, 0x7F, 0x40, 0x00 ], # 'd'
[ 0x38, 0x7C, 0x54, 0x54, 0x5C, 0x18, 0x00, 0x00 ], # 'e'
[ 0x48, 0x7E, 0x7F, 0x49, 0x03, 0x02, 0x00, 0x00 ], # 'f'
[ 0x98, 0xBC, 0xA4, 0xA4, 0xF8, 0x7C, 0x04, 0x00 ], # 'g'
[ 0x41, 0x7F, 0x7F, 0x08, 0x04, 0x7C, 0x78, 0x00 ], # 'h'
[ 0x00, 0x44, 0x7D, 0x7D, 0x40, 0x00, 0x00, 0x00 ], # 'i'
[ 0x60, 0xE0, 0x80, 0x80, 0xFD, 0x7D, 0x00, 0x00 ], # 'j'
[ 0x41, 0x7F, 0x7F, 0x10, 0x38, 0x6C, 0x44, 0x00 ], # 'k'
[ 0x00, 0x41, 0x7F, 0x7F, 0x40, 0x00, 0x00, 0x00 ], # 'l'
[ 0x7C, 0x7C, 0x18, 0x38, 0x1C, 0x7C, 0x78, 0x00 ], # 'm'
[ 0x7C, 0x7C, 0x04, 0x04, 0x7C, 0x78, 0x00, 0x00 ], # 'n'
[ 0x38, 0x7C, 0x44, 0x44, 0x7C, 0x38, 0x00, 0x00 ], # 'o'
[ 0x84, 0xFC, 0xF8, 0xA4, 0x24, 0x3C, 0x18, 0x00 ], # 'p'
[ 0x18, 0x3C, 0x24, 0xA4, 0xF8, 0xFC, 0x84, 0x00 ], # 'q'
[ 0x44, 0x7C, 0x78, 0x4C, 0x04, 0x1C, 0x18, 0x00 ], # 'r'
[ 0x48, 0x5C, 0x54, 0x54, 0x74, 0x24, 0x00, 0x00 ], # 's'
[ 0x00, 0x04, 0x3E, 0x7F, 0x44, 0x24, 0x00, 0x00 ], # 't'
[ 0x3C, 0x7C, 0x40, 0x40, 0x3C, 0x7C, 0x40, 0x00 ], # 'u'
[ 0x1C, 0x3C, 0x60, 0x60, 0x3C, 0x1C, 0x00, 0x00 ], # 'v'
[ 0x3C, 0x7C, 0x70, 0x38, 0x70, 0x7C, 0x3C, 0x00 ], # 'w'
[ 0x44, 0x6C, 0x38, 0x10, 0x38, 0x6C, 0x44, 0x00 ], # 'x'
[ 0x9C, 0xBC, 0xA0, 0xA0, 0xFC, 0x7C, 0x00, 0x00 ], # 'y'
[ 0x4C, 0x64, 0x74, 0x5C, 0x4C, 0x64, 0x00, 0x00 ], # 'z'
[ 0x08, 0x08, 0x3E, 0x77, 0x41, 0x41, 0x00, 0x00 ], # '{'
[ 0x00, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0x00 ], # '|'
[ 0x41, 0x41, 0x77, 0x3E, 0x08, 0x08, 0x00, 0x00 ], # '}'
[ 0x02, 0x03, 0x01, 0x03, 0x02, 0x03, 0x01, 0x00 ], # '~'
[ 0x70, 0x78, 0x4C, 0x46, 0x4C, 0x78, 0x70, 0x00 ], # 0x7F
] # end of cp437_font
Python - MAX7219_Matrix_Test.py
from machine import Switch #獲取按鍵KEY庫
from machine import SPI
import MAX7219
import fonts_8x8
import utime
ePyCloud = [0x08, 0xFE, 0x6A, 0x5F, 0x5F, 0x6A, 0x7E, 0x08]
symbol=[
[0x00, 0x98, 0xE4, 0x1F, 0x1F, 0xE4, 0x98, 0x00],
[0x00, 0x90, 0xCB, 0x2F, 0x1D, 0x24, 0x44, 0x88],
[0x00, 0x90, 0xDB, 0x2F, 0x1D, 0x24, 0x44, 0x88],
[0x00, 0x00, 0xDB, 0x2F, 0x1D, 0x64, 0x88, 0x00],
[0x00, 0x00, 0x03, 0x1F, 0x7D, 0xE8, 0x80, 0x00],
[0x00, 0x00, 0xDB, 0x2F, 0x1D, 0x64, 0x88, 0x00]]
face = [
[0x3C, 0x42, 0xA5, 0x81, 0xA5, 0x98, 0x42, 0x3C],
[0x3C, 0x42, 0xA5, 0x81, 0xBD, 0x81, 0x42, 0x3C],
[0x3C, 0x42, 0xA5, 0x81, 0x99, 0xA5, 0x42, 0x3C]]
spi0 = None
spi0 = SPI(0, SPI.MASTER, baudrate=5000000, polarity=1, phase=0, bits=16) #For Hardware SPI bus
# Start Function
if __name__ == '__main__':
display = MAX7219.Matrix8x8(spi0)
# display.brightness(7)
display.fill(False)
display.show()
utime.sleep(1)
# display.fill(False)
# display.pixel(4, 4, True)
# display.show()
# utime.sleep(1)
for y in range(8):
display.buffer[y] = ePyCloud[y]
display.show()
utime.sleep(2)
for y in range(8):
display.buffer[y] = symbol[0][y]
display.show()
utime.sleep(2)
for z in range(20):
for x in range(1,6):
for y in range(8):
display.buffer[y] = symbol[x][y]
display.show()
utime.sleep_ms(200)
for x in range(10):
for y in range(8):
display.buffer[y] = fonts_8x8.fonts_8x8[x+0x30][y]
display.show()
utime.sleep_ms(1000)
for x in range(26):
for y in range(8):
display.buffer[y] = fonts_8x8.fonts_8x8[x+0x41][y]
display.show()
utime.sleep_ms(1000)
display.fill(False)
display.show()
utime.sleep(1)
spi0 .deinit()
執行結果