串連多個MAX7219 LED點矩陣模組建立捲動文字,及C語言複製陣列語法說明

本文旨在補充《超圖解Arduino互動設計入門》第八章「LED矩陣動畫與多維陣列程式設計」單元,示範串連多個MAX7219 LED點矩陣模組建立捲動文字。

串連MAX7219 LED點矩陣模組

MAX7219 IC第1和24腳,分別是序列資料輸入及資料輸出,因此這個IC和74HC595一樣,都能串接在一起(請參閱「串入並出的IC 74HC595補充說明:串聯多個74HC595 的Arduino程式示範」)。

IC 74HC595

採用MAX7219的LED點矩陣模組,背後有資料輸出的引腳:

MAX7219的LED點矩陣模組

串連兩個MAX7219模組的電路圖如下:

串連兩個MAX7219模組的電路圖

與Arduino板相連的麵包板接線參考:

串連兩個MAX7219模組的麵包板接線

使用MaxMatrix程式庫建立捲動文字的程式

香港城市大學的區建忠教授(Kin-Chung Au)寫了一個MaxMatrix程式庫,可大幅簡化LED點矩陣的程式碼、支援串連顯示並提供四種移動效果:

  • shiftLeft(左移)
  • shiftRight(右移)
  • shiftUp(上移)
  • shiftDown(下移)

本文將使用這個程式庫,完成多個MAX7219 LED點矩陣模組的捲動文字效果。

複製陣列元素

使用MaxMatrix程式庫建立文字捲動程式,需要用到複製陣列元素指令,在此先說明,複製陣列不像複製簡單型變數,無法用一個指派(“=”)運算子搞定。

假設程式中宣告了兩個字元陣列:

宣告兩個字元陣列

我們想要把CH複製給buffer變數,若在Arduino軟體中編譯底下的程式碼:

編譯器將回報“invalid array assignment”(無效的陣列指派)錯誤

"invalid array assignment"(無效的陣列指派)錯誤

正確的作法是「個別複製」陣列元素:

「個別複製」陣列元素

因此,我們可以用一個for迴圈執行所有複製敘述。底下的程式碼透過sizeof()函數,取得CH陣列的元素數目(此處為4);由於CH是字元陣列,因此也可以用strlen()取得CH字串的字元數(此處為3,結尾的NULL字元不算)

在Arduino編譯並執行以上程式碼的結果如下:

複製陣列元素程式的執行結果

使用memcpy()與memcpy_P()複製陣列元素

C語言具有複製記憶體內容的memcpy()函數,能將指定範圍的陣列元素,複製到某個記憶體空間,指令語法如下:

複製陣列的memcpy()語法

底下的範例程式宣告兩個陣列,並透過memcpy()敘述,把CH陣列元素複製給buffer陣列,其執行結果和上一節的程式碼相同:

memcpy()用於複製主記憶體中的資料:

複製陣列的memcpy()示範

另有一個memcpy_P()函數用於從程式記憶體區(快閃記憶體),複製資料到主記憶體。

定義LED點矩陣字元

《超圖解Arduino互動設計入門》第八章的LED點矩陣,採用二維陣列定義圖像資料;MaxMatrix程式庫使用一維陣列,除了點矩陣的外觀,其資料內容還包含字元佔用的寬、高數,以數字1為例:

"1"字元的點矩陣定義

其點矩陣資料值寫成:

"1"字元的點矩陣定義

MaxMatrix程式庫的範例點矩陣字元,最大寬度僅5個點陣(如下圖的"@"),因此每個字元資料統一為7個元素值(請參閱下文的程式原始碼):

"@"字元的點矩陣定義

捲動點矩陣文字效果的完整程式碼

請先從Google Code網站下載MaxMatrix程式庫,將它放在Arduino安裝路徑裡的”libraries”資料夾,或者「我的文件」裡的”Arduino\libraries”路徑;Mac OS X的讀者,請將程式庫存入「文件」文件夾裡的“libraries”裡面。

存放MaxMatrix程式庫

底下的程式碼修改自MaxMatrix的範例程式,將它編譯並上傳到Arduino板,兩個MAX7219 LED點矩陣模組將呈現往左移動的“https://swf.com.tw ”字串:

其中需要特別說明的是printCharWithShift()自訂函數。以上程式碼當中的點矩陣字元,也是依照ASCII編碼排列;排在第一個(索引編號0)的是空白字元(space),其ASCII值是32(十進位),所以,傳入此函數的字元編碼值,要先扣掉32,才能對應到實際的點陣字元。

透過memcp_P()複製點矩陣字元資料

由於一個點矩陣字元由7個位元組構成,因此,從程式記憶體區複製資料時,要以7為單位。

延伸閱讀

71 thoughts on “串連多個MAX7219 LED點矩陣模組建立捲動文字,及C語言複製陣列語法說明

  1. 老師您好:
    有一事向您請教…
    如果設一零矩陣(一維陣列)為 5×1的零矩陣
    另一陣列為 假設 a[] = {1,2,3,4,5}
    其結果加設迴圈跑一次
    b[10] —>結果為 [0,1,2,3,4,5,0,0,0,0];
    迴圈跑第二次—>結果為 [0,0,1,2,3,4,5,0,0,0];
    跑到第五次時…結果為 [0,0,0,0,0,1,2,3,4,5]
    可以怎麼寫…,想了整晚還是寫不出我要的…
    於是來請老師指點迷津阿…
    請您們幫幫忙…感謝..!

    1. hi 阿凱:

      右移陣列元素最簡單的方式,就是從最後一個元素開始,把前一個元素的值複製過來。

      假設有一個包含5個元素的整數陣列arr:

      int arr[] = {1, 2, 3, 0, 0};

      最後一個元素值,複製前一個元素值:

      arr[4] = arr[3];

      倒數第二個元素,複製前一個元素值:

      arr[3] = arr[2];

      第一個元素值設定成0:

      arr[0] = 0;

      以上敘述寫成迴圈,右移一次就像這樣:

      其他程式部份請自行發揮。

      thanks,
      jeffrey

  2. 老師您好:
    有一事向您請教…
    如四有個8X8的零矩陣
    我要如何指定他們顯示:
    例如
    第一個顯示 A
    第二個顯示 B
    第三個顯示 C
    第四個顯示 D
    想了很久很久很久寫不出…
    於是來請老師指點,謝謝 … !!!

    1. hi neo:

      請問你有試過上文的程式嗎?

      第109行:
      char msg[] = “https://swf.com.tw “; // 要顯示的字串內容
      改成你要的字串。

      thanks,
      jeffrey

  3. 老師你好 請問要怎麼設計出貪食蛇這樣的功能 我認為是用點亮時間控制 但不知道實際寫法 麻煩老師指導 謝謝

  4. 老師您好,
    我把這個頁面150行的那個程式複製貼上之後compile都不會過,
    游標停在144行,然後給出錯誤訊息,說delay(shift_speed);這行有問題,
    merry2_sketch_fab17a:143: error: stray ‘\343’ in program
    merry2_sketch_fab17a:143: error: stray ‘\200’ in program

    請問老師這可能是什麼的問題呢? 麻煩老師回覆了

    1. hi 阿華:

      應該是第143行的delay()以及第144行的註解前面的空白,包含其他控制字元。另請修改這幾個地方:

      1. 程式庫 maxmatrix.h 名稱改成 MaxMatrix.h
      2. 第5行的 PROGMEM unsigned char CH[] 改成:PROGMEM const unsigned char CH[]
      3. 刪除143和144行前面的空白,再重新輸入。

      thanks,
      jeffrey

  5. 老師您好,
    請問一下,我的LED矩陣顯示出來的樣式是順時針90度,有甚麼方式可以讓它逆時針旋轉90度顯示呢?

    1. hi jimmy:

      如果不能把LED矩陣轉90度裝設的話,那只能著手修改矩陣文字和圖像的定義了。
      請問你有嘗試過修改shiftLeft()的參數值嗎?

      m.shiftLeft(true, false);

      thanks,
      jeffrey

  6. 老師您好
    我把這個頁面150行的那個程式複製貼上之後,執行上傳後,二塊8X8矩陣都出現相同字元,只是速度差3排
    謝謝您的回覆

  7. 老師您好!
    最近參考您的書照作,請問但如果我要怎麼將字轉向90度,要在那邊修改,都找不到~希望指導

    1. hi 小周:

      因為書本內容主要是說明Arduino與週邊電路原理,以及程式運作邏輯,無法包含所有應用範例,你可以參考8-34頁的動態LED矩陣程式分析,自行編寫一個。或者,參考其他範例程式或程式庫,像這個”Parola for Arduino“,就具有許多動態LED矩陣特效:水平左、右捲動,上、下滾動…雖然可能和你想要的不同,但是你可以參考他的程式寫法。

      have fun!
      jeffrey

  8. 老師您好,我使用這個方法修改之後OK,但是當我串接到5個模組的時候,最右邊的LED模組的最右邊四行就會出現亂碼,已經試過網路上和老師提供的code總共三組使用maxmatrix程式,都是這樣,也打開過maxmatrix.h來看,也看不出什麼問題。硬體也更換過,都沒問題。不知道為什麼會這樣。

    有使用其他的串聯跑馬燈方法,使用max7219內的NO-OP來做,比maxmatrix的方法更直觀,但是對於輸入的message的修改就比較麻煩一點。

    謝謝老師~

    1. 若排除硬體的問題,有可能是電流不足或雜訊導致。

      這是另一個LED矩陣的程式庫,裡面包含一個arduino_led_matrix_sketch.ino範例檔,提供你參考。範例程式預設串連兩個LED矩陣,若要改成4個,請修改底下的定義:

      #define NBR_MTX 4 // 串接4個LED矩陣

      thanks,
      jeffrey

  9. 因我現在專題也是要弄貪吃蛇? 我有幾個問題想問… 希望你可以email給我3q…
    ○○○○@yahoo.com.hk

    1. hi小楊:

      首先你要把顯示內容定義在一個陣列裡面,然後透過SPI通訊格式傳遞MAX7219的指令…詳細請參閱第八章「認識SPI介面與MAX7219」。

      thanks,
      jeffrey

  10. 老師您好:
    不好意思想請教您,前面的max matrix.h己經建立在資料庫,但是另一個avr /ph space.h就不是很了解,
    是否去下載還是其它可以取得呢?
    感謝了!

    1. hi michael兄:

      AVR相關的程式庫都內建在Arduino IDE(整合開發工具)軟體,位於Arduino程式安裝路徑的”\hardware\tools\avr\avr\include”路徑裡面,所以不用再安裝。

      thanks,
      jeffrey

  11. 老師你好:
    我想請問一下有些程式有m.開頭是甚麼意思呢?
    像是m.writeSprite、m.setColumn、m.clear
    謝謝

  12. 老師,我想請問一下,有沒有ARDUINO 讓LED矩陣讀取SMS簡訊的內容範例??
    還有想問一個問題是Linkit One跟AEDUINO的差別點是在哪裡?? 程式方面又差在哪裡呢?

    1. hi pang:

      你可以搭配GSM擴展板來收發簡訊,這個網頁有接收簡訊的範例程式。你也可以連接Android手機,自行撰寫接收簡訊的App,將訊息內容透過藍牙、Wi-Fi或者USB轉發給Arduino。

      Linkit One,據我了解,就是功能加強的Arduino Yun,或者相當於Arduino TIAN。它們都是在一塊控制板搭載兩個微處理器,一個是負責執行Linux系統(OpenWRT)的32位元系統級晶片(SoC),另一個則是負責控制週邊的8位元微控器,兩者用序列埠或其他方式連結。

      Linkit One控制板概念

      換句話說,就是把Linux微電腦和Arduino控制板整合在一個電路板(其實更像是把Wi-Fi無線網路分享器和Arduino結合在一起,請參閱這一篇文章說明)。

      Linux系統部份的程式可用C/C++, Python, Node.js等語言開發程式,可執行完整的網路程式功能,例如:網站伺服器,也具備多媒體處理能力,例如:傳送串流影音。

      thanks,
      jeffrey

  13. 老師您好,我想請問一下這網址的內容(這是LINKIT ONE的GSM的實做) http://goo.gl/WJMaLW
    我按照他的方式去做,上傳程式後打開視窗只有顯示GSM OK,試傳了簡訊卻都沒反應,不知道是什麼問題
    是板子沒支援我們現在的SIM卡(4G)嗎?還是說跟這無關係呢? 研究好幾天研究不出個所以然
    還請老師幫忙一下!!
    謝謝

    1. hi pang:

      拍謝~我沒用過Linkit One,也未曾購買GSM模組,相關問題再麻煩你請教原作者,謝謝!

      thanks,
      jeffrey

  14. 老師您好~我想請問一下如果沒有MAX7219,只有8x8LED點矩陣的話上述這些做法是不是不能引用,手邊只有Arduino跟麵包板

    1. hi penny:

      不行,因為:
      1. Arduino的控制腳位有限,必須要透過一個IC轉接。
      2. Arduino的輸出電流有限,必須透過電晶體或者MAX7219內部的電路,才能驅動64個LED。

      thanks,
      jeffrey

  15. 老師您好
    那如果把文字圖檔放在網路(網頁或網站)上,讓ARDUNIO搜尋後執行,這樣的方式可以嗎??
    如果可以的話有相關的範例嗎?

    1. 並不是讓Arduino搜尋,而是建立一個網頁,讓使用者把資料「提交」給Arduino動態執行。
      我在《超圖解物聯網IoT實作入門》第五章有製作一個類似的範例,請參閱章節導讀介紹

      thanks,
      jeffrey

  16. 請問為什麼我沒辦法include avr/pgmspace.h
    他無法像MaxMatrix.h被include
    然後\hardware\tools\avr\avr\include 也有放檔案在裡面
    但是匯入程式庫裡沒有那個選項

    1. 請問你編譯引用avr/pgmspace.h程式庫的程式碼時有出現錯誤訊息嗎?
      或者佔用的主記憶體空間沒有減少嗎?
      你怎麼確定引用無效?

      thanks,
      jeffrey

  17. 老師你好~如:好幾片串接起來跑文字數字 就像字幕機這樣,請問要如何在手機app上輸入文字數字透過wifi模組就能顯示在LED 字幕上呢? (app採用App inventor 2 來設計)

  18. 老師您好
    我與上面幾位有差不多的問題
    Arduino:1.8.0 (Windows 7), 開發板:”Arduino/Genuino Uno”

    C:\Users\york\Documents\Arduino\test\sketch_dec24a\sketch_dec24a.ino:2:27: fatal error: avr /pgmspace.h: No such file or directory

    #include

    ^

    compilation terminated.

    exit status 1
    開發板 Arduino/Genuino Uno 編譯錯誤。

    This report would have more information with
    “Show verbose output during compilation”
    option enabled in File -> Preferences.

    這是編譯完成後的錯誤碼 好像是找不到avr/pgmspace.h 這個檔案

  19. 老師你好 我自己有加一個Sensor
    我把Sensor的值宣告為int
    請問我能把int的值放進msg[]裡嗎

    1. 超商裡的茶葉蛋電鍋,不會允許你投入關東煮。
      同理,char類型的變數,不可以存入int,請自行轉換。

      thanks,
      jeffrey

  20. 老師您好:
    不好意思想請教您,我照著您上面給的程式碼編譯了一次
    結果出現以下錯誤訊息不是很了解哪裡出了問題
    煩請老師如果有空可以幫我解惑一下。

    錯誤訊息:
    Arduino:1.6.9 (Windows 7), 板子:”Arduino/Genuino Uno”
    C:\Users\UCER\Documents\Arduino\sketch_feb03a\sketch_feb03a.ino:1:22: fatal error: maxmatrix.h: No such file or directory
    exit status 1
    Error compiling for board Arduino/Genuino Uno.

  21. 老師您好:
    今天有一事向您請教
    我想做一個三個符號,然後能夠分別讓它們上下左右移動的點矩陣圖。
    我知道可以使用MaxMatrix程式庫,但不是很懂要怎麼把圖調整改成往其他方向(Ex:往上跑、往右跑…)
    範例網站寫的方法看不是很懂……
    希望老師有空能夠替我解答。

  22. 老師您好:
    不好意思跟您請教一下如果我今天想要做一個LED矩陣時鐘
    要讓LED矩陣顯示DS1302時鐘模組傳回的時間
    使用MaxMatrix函式庫可以做到嗎?
    我不曉得怎麼將時間放入字串內,麻煩老師指點迷津一下,感謝!

    1. Matrix程式庫只負責處理顯示畫面,至於你要顯示那些內容,跟它無關。你可以宣告一個String類型的變數,即可在其中儲存、連結字串和數字。

      thanks,
      jeffrey

  23. 老師您好:
    之前聽您的推薦去看了Parola程式庫
    裡面確實是很多的功能,可是我研究了很久還看不太懂…
    功能太多反而覺得很雜很難懂

    今天是想問如果想要採用MaxMatrix程式庫去讓點矩陣的圖形上下左右移動的話
    那程式要怎麼修改才行呢?
    煩請老師有空可以替我解答

    1. Parola把各種動態效果都寫成函式,例如,setTextEffect(設定文字效果)、setInvert(反相顯示)、setPause(效果的間隔時間)…,完整的指令說明可參閱Parola的線上說明文件

      如果不打算使用現成的程式庫,就只能拿出筆和紙,自行推敲移動點陣的程式邏輯了。

      thanks,
      jeffrey

  24. 請問老師
    如果要用開關來切換點矩陣功能
    那開關輸出狀態要接在MAX7219模組的哪裡才能達到切換功能的目的?

    1. 我不太確定你指的切換點矩陣功能是什麼。如果你指的是「關閉或開啟顯示器」的話,請參閱8-18頁的「停機暫存器」說明,若透過8-20頁的max7219自訂函式操控的話,你可以執行 max7219(SHUTDOWN, 0); 來關閉螢幕(參閱8-24頁的程式)。

      thanks,
      jeffrey

  25. 請問:
    要組成16×16矩陣顯示器的話,是否有建議的線路?
    是否和MAX7219依樣能串接成更大的顯示器?
    要如何取中文字形轉成Font array呢?

    1. 可以用四組MAX7219串接成16×16的顯示器。

      中文字型轉換我就不清楚了,不過,在Arduino之前的單晶片應用,相信已經有許多前輩做過類似的專案。台灣的技職教育體系大多使用8048/8051系列單晶片,請嘗試找尋相關書籍或者搜尋8051 keil C語言,甚至用PC控制的例子,或許可以查到相關的應用,再把程式邏輯套用到Arduino上。中文點陣字體轉換的話,請搜尋倚天中文或者國喬中文試試看,這兩者是早期在IBM PC XT/AT執行MS-DOS系統採用的中文字體(它們本身就是點陣格式),應該也有轉換程式可用。

      good luck!
      jeffrey

  26. 如果四組MAX7291串接在一起,顯示字母是否一定要經由第一組左移之後,第二組才會顯示?
    是否能指定更新第三組顯示內容?
    還是1,2,3,4組的CS必須用4 個GPIO來控制達成?

  27. 老師你好
    請問一下
    Arduino:1.6.13 (Windows 10), 開發板:”Arduino/Genuino Uno”

    C:\Users\AA\Desktop\arduino\88??暺?MAX7219\sketch_may17a\sketch_may17a.ino: In function ‘void loop()’:

    sketch_may17a:121: error: ‘printStringWithShift’ was not declared in this scope

    C:\Users\AA\Desktop\arduino\88??暺?MAX7219\sketch_may17a\sketch_may17a.ino: In function ‘void printStringWithShift(char*, int)’:

    sketch_may17a:128: error: ‘printCharWithShift’ was not declared in this scope

    exit status 1
    ‘printStringWithShift’ was not declared in this scope

    This report would have more information with
    “Show verbose output during compilation”
    option enabled in File -> Preferences.
    是什麼意思
    因為他是說’printStringWithShift’未在此範圍內聲明
    不知道該怎麼改

  28. 老師您好
    我有將MaxMatrix的程式庫移至libraries中了
    可是按照150行的code編譯出現下面訊息
    還請老師解惑 十分感謝

    Arduino:1.6.11 (Windows 7), 板子:”Arduino Nano, ATmega328″

    sketch\MaxMatrix.cpp.o (symbol from plugin):(.text+0x0): first defined here

    collect2.exe: error: ld returned 1 exit status

    exit status 1
    板子Arduino Nano編譯錯誤

    This report would have more information with
    “Show verbose output during compilation”
    option enabled in File -> Preferences.

    1. 請將程式開頭引用程式庫的敘述改成:

      thanks,
      jeffrey

  29. 老師:請問要同時接六個8×8要如何接?有沒有接線圖可提供參考?是不是在程式const byte maxInUse = 2; // 代表串連兩個MAX7219模組,要改成六?這樣就可以了。

    1. 是的。硬體就按照連接兩個模組的模式,繼續將序列輸出和序列輸入串接在一起,其他接腳照舊;LED電源要外接。

      thanks,
      jeffrey

    1. 從你提供的圖片看起來,接線正確。你是指連接兩個點陣LED,顯示正常,接4個顯示亂碼?

      thanks,
      jeffrey

  30. 電路圖中,Max7219 Module#2 應該是Dout(Data)連到Max7219 Module#1 Din(Data) 才對, Module#1的Din則連到Arduino 的D11。
    因為字串是要從右至左顯示,右邊module為#1為頭,左邊module為#2為尾。

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *