使用 MAX7219 驅動 8x8 矩陣式顯示器
除了用於驅動七段顯示器,MAX7219 另一種常見的應用為驅動 8x8 矩陣式 LED 顯示器。此教學文章將介紹如何使用單顆 MAX7219 驅動 8x8 矩陣式顯示器,以及如何串聯 (daisy-chain) 數個 MAX7219 以驅動多個 8x8 顯示矩陣。為了降低電路複雜度,本文使用 8x8 矩陣式顯示模組 (內建 MAX7219) 作為範例使用元件。
目錄
目錄
七段顯示器與矩陣顯示器的對應關係
硬體接線
範例一:使用單個顯示器
範例二:串連多個顯示器
範例三:字串跑馬燈
結論
七段顯示器與矩陣顯示器的對應關係
雖然七段顯示器與 8x8 矩陣式顯示器在外型上有極大的差異,但本質上兩者是相同的東西:皆為內含多顆 LED 的顯示裝置。一個七段顯示器含有 8 顆 LED (筆畫部分使用 7 顆 LED、小數點使用 1 顆 LED),而且根據之前的教學,得知 MAX7219 可同時驅動 8 組七段顯示器,也就是說,MAX7219 最多可驅動 8x8 = 64 顆 LED,而這個數字,正好就是 8x8 矩陣式顯示器內所具有的 LED 數目。因此,讓 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 暫存器作為顯示用的原始資料。
硬體接線
需使用 LinkIt 7697 的下列五隻腳位:
5V
GND
P15
P16
P17
分別將它們連接至顯示模組上的:
VCC
GND
CLK
CS
DIN
接線示意圖如下:
完成硬體線路連接後,接下來的文章將示範如何在顯示器上顯示圖案。
範例一:使用單個顯示器
第一個範例將依照前面章節介紹的點陣圖定義方式,在單個 8x8 矩陣式顯示器上顯示不同字元。下面的 sketch 程式碼會驅動顯示器顯示 "Hello, LinkIt7697" 字樣,並呈現如同影片中的效果:
這段程式碼是以之前七段顯示器教學的 sketch 為基礎,修改為驅動矩陣顯示器的版本:
程式說明
不同於七段顯示器,當使用 MAX7219 驅動矩陣式顯示器時,程式所要控制的是每個「欄位」的內容、而非每個「數字」的內容。所以為了增加可讀性,程式中將 Digit 暫存器的名稱改為 Column 暫存器:
並定義顯示器及圖形等相關基本參數:
注意
由於每個字元只使用 4x8 個像素,所以定義點陣圖資訊時,只定義了其中 4 個欄位,其他欄位則保持空白、不顯示任何東西。
為了顯示自訂的點陣圖,MAX7219 需將每個 Column 暫存器皆設定為以原始資料模式運作:
接著依序將點陣圖資訊送進各個 Column 暫存器,進而組成欲顯示的圖形:
由於只使用 8x8 矩陣中的 4x8 點陣範圍 (並置中顯示),所以程式碼從顯示器的第 2 欄開始更新暫存器資訊,並且一共更新 BYTE_PER_MAP 個欄位。此外,由於顯示器「每一欄」的內容對應到點陣圖資料的「一個 byte」,因此 char_pattern 陣列中每張點陣圖的起始位置,都會是以 BYTE_PER_MAP 為倍數間隔開來。
範例二:串連多個顯示器
MAX7219 支援以串連模式 (daisy-chain) 連接數個 MAX7219 以驅動多個顯示器。當多個 MAX7219 IC 串連在一起時,送進第一顆 IC 的資料會在 16 個時脈訊號 (cycle) 後輸出至下一顆 IC;這個數字剛好與 MAX7219 收取一筆指令所花費的時間相同,因此這也是為何 MAX7219 被稱作為 shift register 的原因:當 IC 本身花 16 個時脈訊號的時間、將資料收進內部的 16-bit 儲存空間後,若還有更多的資料持續送進來,則 IC 會依「先進先出」的順序,開始將內部的 16-bit 資料以 bit 為單位往外輸出。所以,當欲傳送指令給串連在一起的 MAX7219 時,開發者需依「從遠到近」的順序發出給各個 MAX7219 的指令,才能正確地讓指令到達其所對應的 MAX7219。以下用動畫說明此傳輸過程:
此動畫中有三個 MAX7219 串聯在一起,所以若要傳送指令到所有的 MAX7219,則需要 16x3 = 48 個時脈訊號的時間。傳送流程一開始 LOAD 訊號被拉低,使 MAX7219 進入等待指令更新的狀態;在前 16 個時脈訊號中,開發板送出給 MAX7219 #2 (接線上離開發板最遠的 MAX7219) 的指令進入首個節點,接下來的 16 個時脈訊號,再送出給 MAX7219 #1 的指令。此時原本存在首個節點中的指令會被往後推出進到下一個節點。在最後一組的 16 個時脈訊號裡,開發板送出給 MAX7219 #0 的指令,並觸發原本存在首兩個節點中的指令繼續向後推進至最終的目的地。當所有指令都到達正確位置後,將 LOAD 訊號拉高,讓 MAX7219 依收到的指令進行動作。此流程即說明了當串聯在一起的 MAX7219 需接收新指令時,資料傳遞的順序及運作機制。但如果串連在一起的 MAX7219 中,只有單個 MAX7219 需要更新指令、其他的不需新指令,又該如何進行呢?
MAX7219 裡有一個特殊的暫存器,稱為 No-Op 暫存器 (位址為 0,請參閱 datasheet 中的 Table 2)。當 MAX7219 在 LOAD 訊號為 HIGH 時看到 No-Op 指令,將不會進行任何動作、狀態也不會改變。下面的動畫展示「只有 MAX7219 #1 需收取新指令、其他節點皆不改變狀態」的狀況:
在接下來的多個矩陣顯示器串連範例中,會將前一個範例擴充為五個顯示器的組態,並透過使用 No-Op 指令,讓每個顯示器單獨顯示與上例相同的圖像:
硬體接線
將每個顯示模組的 DOUT 腳位接至下個顯示模組的 DIN 腳,而其他腳位則直接連接到下個模組的相同腳位即可。

注意
當串連多個矩陣顯示器時,請確保 5V 供電源能提供足夠的電流輸出,以免顯示模組因供電不足而無法正常運作。
以驅動單個顯示器的程式碼為基礎,將之修改為可驅動串連顯示器的版本。首先,先定義 No-Op 指令:
接著將 set_register() 擴充為 set_all_registers() 以及 set_single_register(),分別用來對串連在一起的 MAX7219 下指令。set_all_registers() 的作用為對所有 MAX7219 皆發出相同的指令,而 set_single_register() 則是針對單一 MAX7219 進行指令更新 (其他的 MAX7219 則不改變狀態):
綜合上述改動,並利用這兩個 API 取代原本驅動單個顯示器範例中的 set_register() API 後,完整的程式範例如下:
此例使用了 5 個顯示器模組,若要更改模組數目,可直接修改第 34 行的定義:
重點回顧
若要對所有的 MAX7219 下同樣的指令,請使用 set_all_registers() API,就如同 init_max7219() 以及 clear_matrix() 皆為相同的概念。
若只要對特定的 MAX7219 下指令,請使用 set_single_register() API,即可讓其他 MAX7219 不受影響。
範例三:字串跑馬燈
結合前面所述的概念,最後一個範例將展示如何進一步使用 5 個矩陣顯示器產生常見的跑馬燈效果:
完整的範例程式碼如下:
結論
接續前篇的七段顯示器教學,本文完整地介紹了另一種 MAX7219 應用:不只用於驅動七段顯示器,利用原始資料模式的操作,MAX7219 也可用於驅動多個 LED、或是驅動矩陣式 LED。藉由使用 shift register,可大幅簡化建置 LED 顯示應用時的佈線及控制複雜度。
Last updated