2021-08-02

Raspberry Pi Pico 控制 MAX7219 8位七段顯示器

Raspberry Pi Pico 購買了一段時間,但因為讀書關係,沒有太多時間可以使用
最近課程終於完成,可以測試之前購買的零件

8位七段顯示器

見下文
8位七段顯示器實際是 2個4位七段顯示器

見下文
正面顯示5支引腳

見下文
MAX7219 晶片

見下文
背面顯示另外5支引腳
(LODA 是錯字,查證資料後,正確是 LOAD)

接駁線路

見下文
線路原型,方便設計

見下文
正式線路

見下文
執行效果
由於在下以前曾經編寫過 Arduino AVR-C 的 MAX7219 程式
因此只需要將之前的 AVR-C 原始碼 修改成 CircuitPython 便可以運作

注意
顯示的資料會 由右至左排序,最右是第一位值,最左是第八位值

七段顯示器亦會以 八位元 方式控制 8個LED
數值 七段顯示器
二進制 十進制 十六進制 LED名稱 圖示位置
B00000001 1 0x01 G
B00000010 2 0x02 F
B00000100 4 0x04 E
B00001000 8 0x08 D
B00010000 16 0x10 C
B00100000 32 0x20 B
B01000000 64 0x40 A
B10000000 128 0x80 P

並列連接

見下文
見下文
見下文
並列連接很簡單,直接從微控制器的引腳連接到 MAX7219 的引腳即可同步輸出資料

見下文
見下文
見下文
使用 2支CS引腳 分別連接到 2個MAX7219裝置 ,可以輸出2種不同資料

串列連接

見下文
見下文
串列連接 正式稱為 菊花鏈連接 (Daisy Chain)
  • 第一個 MAX7219 輸出 VCC 連接到 第二個 MAX7219 輸入 VCC (或連接到 VCC BUS 亦可)
  • 第一個 MAX7219 輸出 GND 連接到 第二個 MAX7219 輸入 GND (或連接到 GND BUS 亦可)
  • 第一個 MAX7219 輸出 DOUT 連接到 第二個 MAX7219 輸入 DIN
  • 第一個 MAX7219 輸出 LOAD 連接到 第二個 MAX7219 輸入 CS (或連接到 CS BUS 亦可)
  • 第一個 MAX7219 輸出 CLK 連接到 第二個 MAX7219 輸入 CLK (或連接到 CLK BUS 亦可)

見下文
見下文
顯示資料的效果與 並列連接 相同
但如果將顯示速度減慢,會發現資料顯示速度並非同步
第一MAX7219裝置 比 第二MAX7219裝置 快,因此當速度減慢會有異步狀態
但只要保持高速,以人眼是無法看到分別

見下文
見下文
見下文
雖然 並列連接 可以同步顯示所有資料,但 串列連接 都有另一種好處
串列連接 可以在不需要增加 CS引腳 的使用數量下,可以令多個 MAX7219裝置 顯示不同資料
對引腳數量較少的 微控制器 可以較方便控制大量 MAX7219裝置
但需要在編寫的程式中增加一些針對 MAX7219 串列連接 的程式碼

串列連接運作方式

先重溫 MAX7219 指令及運作方式
第一 位元組 (指令) 第二 位元組 (參數) 指令 數數 描述
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 HEX DEC HEX DEC
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x00 0 0x00 0 無效操作
0 0 0 0 0 0 0 1 * * * * * * * * 0x01 1 * * 設定第0位
0 0 0 0 0 0 1 0 * * * * * * * * 0x02 2 * * 設定第1位
0 0 0 0 0 0 1 1 * * * * * * * * 0x03 3 * * 設定第2位
0 0 0 0 0 1 0 0 * * * * * * * * 0x04 4 * * 設定第3位
0 0 0 0 0 1 0 1 * * * * * * * * 0x05 5 * * 設定第4位
0 0 0 0 0 1 1 0 * * * * * * * * 0x06 6 * * 設定第5位
0 0 0 0 0 1 1 1 * * * * * * * * 0x07 7 * * 設定第6位
0 0 0 0 1 0 0 0 * * * * * * * * 0x08 8 * * 設定第7位
0 0 0 0 1 0 0 1 * * * * * * * * 0x09 9 * * 設定B編碼
0 0 0 0 1 0 1 0 0 0 0 0 * * * * 0x0A 10 * * 設定光度
0 0 0 0 1 0 1 1 0 0 0 0 0 * * * 0x0B 11 * * 設定位數
0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 * 0x0C 12 * * 設定啟動
0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 * 0x0F 15 * * 設定測試
當中的 無效操作 指令可以將設定略過到下一個 MAX7219裝置

引腳 初始化 MAX7219裝置 結束
第一 位元組 (指令) 第二 位元組 (參數)
SS
SCK
MOSI 高/低 高/低
這是 MAX7219裝置 最基本的運作方式
當中的 指令 及 參數 就是控制 MAX7219裝置 的資料
當有超過一個 MAX7219裝置,用同樣的操作 都可以控制所有 MAX7219裝置
在下編寫一個簡單的 MAX7219 類別
# max7219.py

import digitalio

class MAX7219:

	def __init__(self, csPin, clkPin, dinPin):
		self.__cs = digitalio.DigitalInOut(csPin)
		self.__cs.direction = digitalio.Direction.OUTPUT
		self.__cs.value = True
		self.__clk = digitalio.DigitalInOut(clkPin)
		self.__clk.direction = digitalio.Direction.OUTPUT
		self.__din = digitalio.DigitalInOut(dinPin)
		self.__din.direction = digitalio.Direction.OUTPUT

	def transfer(self, command, value):
		data = (command << 8) | value
		self.__cs.value = False
		for i in reversed(range(16)):
			self.__clk.value = False
			self.__din.value = (data & (1 << i)) > 0
			self.__clk.value = True
		self.__cs.value = True
# code.py

import board
from max7219 import MAX7219

max7219 = MAX7219(board.GP2, board.GP1, board.GP0)
max7219.transfer(0x09, 0xFF)
max7219.transfer(0x0A, 0x0F)
max7219.transfer(0x0B, 0x07)
max7219.transfer(0x0C, 0x01)
max7219.transfer(0x0F, 0x00)

while True:
	for i in range(8):
		max7219.transfer(i + 1, i)
執行 code.py (CircuitPython) 後可以將所有 MAX7219顯示 顯示相同資料

MCU MAX7219
(1)
MAX7219
(2)
MAX7219
(3)
...... MAX7219
(x)
...... MAX7219
(n)
一般 串列連接 都是類似方式
微控制器 (Micro Controller (MCU)) 接駁第一個 MAX7219裝置,第一個MAX7219裝置 連接到 第二個MAX7219裝置,如此類推
當要個別控制某個 MAX7219裝置 時,便需要改變一些操作流程

引腳 初始化 MAX7219
(n)
MAX7219
(n-1)
MAX7219
(n-2)
...... MAX7219
(x)
...... MAX7219
(1)
結束
略過 略過 略過 略過 指令 參數 略過 略過
SS
SCK
MOSI 高/低 高/低
注意:
接駁的次序與運作的次序是相反,即是與 MCU 接駁的 第一個MAX7219裝置 編寫程式時是排最後;最後的 MAX7219裝置 則是排第一
當使用 串列連接 時,有點操作模式有點像 單向連結串列 (Singly Linked List)
MAX7219 接收 略過 指令,會指向下一個 MAX7219
在下將之前的 MAX7219 類別稍作修改
# max7219.py

import digitalio

class MAX7219:

	def __init__(self, csPin, clkPin, dinPin, count = 1):
		self.__cs = digitalio.DigitalInOut(csPin)
		self.__cs.direction = digitalio.Direction.OUTPUT
		self.__cs.value = True
		self.__clk = digitalio.DigitalInOut(clkPin)
		self.__clk.direction = digitalio.Direction.OUTPUT
		self.__din = digitalio.DigitalInOut(dinPin)
		self.__din.direction = digitalio.Direction.OUTPUT
		self.__count = count

	def transfer(self, command, value, index = None):
		data = [(command << 8) | value]
		if index is not None:
			data = [0x00] * self.__count
			data[index] = (command << 8) | value
			# data = reversed(data)
		self.__cs.value = False
		for d in data:
			for i in reversed(range(16)):
				self.__clk.value = False
				self.__din.value = (d & (1 << i)) > 0
				self.__clk.value = True
		self.__cs.value = True
# code.py

import board
from max7219 import MAX7219

max7219 = MAX7219(board.GP2, board.GP1, board.GP0, 2)
max7219.transfer(0x09, 0xFF)
max7219.transfer(0x0A, 0x0F)
max7219.transfer(0x0B, 0x07)
max7219.transfer(0x0C, 0x01)
max7219.transfer(0x0F, 0x00)

while True:
	for i in range(8):
		max7219.transfer(i + 1, i, 0)
	for i in range(8):
		max7219.transfer(i + 1, i + 8, 1)
便可以簡單地個別操作 MAX7219

總結

由於在下希望明白 MAX7291 的原理及使用方法,而不是學習使用別人的函式庫
因此花了2日時間再次閱讀 MAX7291 的資料表 及 一些函式庫,才理解操作方法
因為 Arduino 有很多開發人員參與,比較多完備的函式庫,在下參考了 LedControl.h 的函式庫
將 LedControl.h 原始碼改良成支援 CircuitPython 的程式碼

參考資料

沒有留言 :

張貼留言