LedControl 庫最初是為基于 8 位 AVR 處理器的 Arduino 板編寫的。用于通過MAX7219芯片控制LED矩陣和7段數碼管。但由于該代碼不使用處理器的任何復雜的內部功能,因此具有高度可移植性,并且應該在任何支持 和 功能的 Arduino(類似)板上pinMode()
運行digitalWrite()
?。
單個 MAX72XX Led 驅動器能夠控制 64 個 Led。該庫支持多達 8 個菊花鏈式 MAX72XX 驅動程序。控制 512 個 LED 對于大多數用途來說應該綽綽有余。
庫初始化
要將庫包含到 Arduino 代碼中,您必須編寫幾行初始化代碼。
將庫添加到您的草圖中
這與任何其他 Arduino 庫一樣工作,您可以使用?Include Library
IDE 中的菜單功能,或者只需添加一個
#include "LedControl.h"
在草圖的頂部聲明。
創建 LedControl 變量
所有庫 API 函數都是通過類型變量調用的,?LedControl
該變量應該在草圖的頂部定義,以便項目代碼的其余部分可以訪問它。
庫初始化的典型代碼如下所示:
/* 包含 LedControl 庫 */
#include "LedControl.h"/* 創建一個新的 LedControl 變量。
* 我們使用 Arduino 上的引腳 12,11 和 10 作為 SPI 接口
* 引腳 12 連接到第一個 MAX7221 的 DATA IN 引腳
* 引腳 11 連接到第一個 MAX7221 的 CLK 引腳
* 引腳 10 連接到到第一個 MAX7221 的 LOAD(/CS) 引腳
* 只有一個 MAX7221 連接到 arduino
*/
LedControl lc1 = LedControl ( 12 , 11 , 10 , 1 );
我們與 MAX72XX 器件通信的變量的初始化代碼有 4 個參數。前 3 個參數是 Arduino 上連接到 MAX72XX 的引腳號。這些可以是 arduino 上的任何數字 IO 引腳。在示例中12
,引腳 、11
和10
任意選擇。庫代碼不會以任何方式對引腳號進行完整性檢查以確保其?有效。傳遞一些愚蠢的東西(pin?123
??),或者只是?錯誤的pin號會破壞代碼,而不會發出通知或錯誤消息。您不必將 IO 引腳初始化為輸出或將它們設置為特定狀態,庫將為您完成這些工作。
第四個參數LedControl(dataPin,clockPin,csPin,numDevices)
是與此一起使用的級聯 MAX72XX 器件的數量LedControl
。該庫可以通過單個變量尋址最多 8 個設備LedControl
。添加到鏈中的每個設備都會帶來一些性能損失,但無論您設置多少個設備,庫代碼使用的內存量都將保持不變。由于LedControl
無法尋址超過 8 個設備,因此此處僅允許使用 1..8 之間的值。
如果您的草圖需要控制超過 8 個 MAX72XX,則?LedControl
需要創建另一個使用 arduino 板上 3 個不同引腳的變量。
#include "LedControl.h"
// 為前 8 個設備創建一個 LedControl...
LedControl lc1 = LedControl ( 12 , 11 , 10 , 8 );
// ...以及接下來 8 個設備的另一個。
LedControl lc2 = LedControl ( 9,8,7,8 ) ; _ _ _ _ _
獲取連接設備的數量
無法從代碼中讀取 IO 引腳編號,但有一個函數可以獲取連接到LedControl
.
/* 獲取連接到此 LedControl 的最大設備數。
* 返回 :
* int 連接到此 LedControl 的設備數量 */
int LedControl : :getDeviceCount ();
該函數用于循環訪問所連接的 MAX72XX 器件的完整列表。下面是一段代碼,用于將所有 MAX72XX 器件從省電模式切換到正常工作模式。即使shutdown(addr)稍后介紹該函數,這段代碼背后的想法也應該很清楚。
#include "LedControl.h"lc1=LedControl(12,11,10,5);void setup() { for(int index=0;index<lc1.getDeviceCount();index++) {lc1.shutdown(index,false); } }
我們通過從 0 到 的索引迭代設備列表?getDeviceCount()-1
。索引是每個設備的地址。該地址是每個在設備上設置功能或 (Led-) 值的函數的第一個參數。請注意,getDeviceCount()
返回連接的設備數量,但 設備的地址從第一個設備的 0 開始,第二個設備的地址從 1 開始,最后一個設備的地址從?getDeviceCount()-1
0 開始。
省電模式
LED 點亮時會消耗相當多的能量。電池供電的設備需要一種節省電量的方法,可以在用戶不需要時關閉整個顯示屏。MAX72XX 支持電源關斷模式。
在關機模式下,設備會關閉顯示屏上的所有 LED,但數據會保留。當設備退出關閉模式時,相同的 LED 將像進入睡眠狀態之前一樣亮起。甚至可以在關閉模式期間發送新數據。當設備重新激活時,新數據將出現在顯示屏上。以下是7 段顯示屏上不可見倒計時的示例:
void countDown() { int i=9; lc.setDigit(0,(byte)i,false); //The digit '9' appears on the display delay(1000); //Go into shutdown mode lc.shutdown(0,true); //and count down silently while(i>1) { //data is updated, but not shownlc.setDigit(0,(byte)i,false); i--; delay(1000); } //Coming out of shutdown mode we have already reached '1' lc.shutdown(0,false);lc.setDigit(0,(byte)i,false); }
這是方法的原型LedControl.shutdown(addr,status)
/* * Set the shutdown (power saving) mode for the device* Params :* addr The address of the display to control* status If true the device goes into power-down mode. Set to false* for normal operation.*/void shutdown(int addr, bool status);
注意:當 Arduino 上電時,始終MAX72XX
處于關閉模式。
限制位數 (ScanLimit)
這是一種專家功能,大多數圖書館用戶并不真正需要。由于該庫將其初始化?MAX72XX
?為安全的默認值,因此您不必僅僅為了讓您的硬件正常工作而閱讀本節
當創建新的 LedControl 時,它將激活所有設備上的所有 8 位數字。每個亮起的數字將由驅動數字的多路復用器電路打開 1/8 秒。如果您有任何理由限制掃描數字的數量,則 LED 會更頻繁地打開,因此會打開更長的時間。
將掃描限制設置為 4 的效果是,點亮的 LED 現在打開 1/4 秒,而不是標準的 1/8 秒。必須MAX72XX
在較長的時間內為分段驅動器提供電流。
您應該仔細閱讀數據表的相關部分MAX72XX
!實際上,通過選擇錯誤的電阻器組合,限制流過 LED 的電流和設備掃描的位數,可能會損壞 LED。調整掃描限制的唯一原因是顯示器看起來太暗。但這很可能是由于啟動時強度沒有提高。這是原型,供有需要的人使用:MAX72XX
RSet
setScanLimit()
/* 設置要顯示的位數(或行數)。
* 有關掃描限制對顯示器亮度的副作用,請參閱數據表。
* 參數: * addr 要控制的顯示器的地址* limit 要顯示的位數*/
void setScanLimit ( int addr , int limit ) ;
設置顯示亮度
決定顯示器亮度的三個因素。
- Rset限制流過 LED 的最大電流的電阻值。
- 顯示器的掃描限制。(如果您閱讀了本節,您已經知道我建議將此選項保留為安全默認值。)
- 以及一個允許通過軟件控制 LED 亮度的命令。
通過該setIntensity(int addr, int intensity)
方法,LED 的亮度可以按 16 個離散步驟進行設置 (?0..15
)。值越高,顯示越亮。大于 15 的值將被丟棄,而不改變亮度。即使是最低值也0
不會完全關閉顯示屏。
/* Set the brightness of the display.* Params:* addr the address of the display to control* intensity the brightness of the display. void setIntensity(int addr, int intensity);
設備初始化
當創建新的庫時,LedControl
庫將使用以下命令初始化硬件
- 顯示清除
- 強度設置為最小值
- 設備處于省電模式
- 激活設備上的最大位數
啟動時顯示空白可能是每個人都想要的。但當強度處于最低且設備處于關閉模式時,在啟動配置中不會點亮任何 LED。大多數用戶將在函數內進行自己的初始化setup()
。下面是一段代碼,可用作創建一個模板,LedControl
一旦顯示數據到達,該代碼就可以以中等亮度點亮 LED。
#include "LedControl.h"LedControl lc=LedControl(12,11,10,1);void setup() { //wake up the MAX72XX from power-saving modelc.shutdown(0,false); //set a medium brightness for the Ledslc.setIntensity(0,8); }
LED矩陣
所有初始化代碼就位后,現在可以控制一些 LED 了。
清除顯示
該函數的名稱LedControl.clearDisplay(addr)
已經暗示了它的作用。
/* 關閉顯示屏上的所有 LED。
* Params:
* addr 要控制的顯示器的地址
*/
void clearDisplay ( int * addr ) ;
所選設備上的所有 LED 均關閉。重要的是要了解這與保留數據的關閉模式不同。
控制單個 LED
這是打開或關閉單個 Led 的函數原型。
/* 設置單個 LED 的狀態。
* 參數 :
* 顯示器的地址
* row Led 的行 (0..7)
* col Led 的列 (0..7)
* state 如果為 true,則 LED 打開,如果為 false,則打開off
*/
void setLed ( int addr , int row , int col , boolean state ) ;
addr
和參數背后的想法state
應該很清楚,但是row
和column
參數指的是什么?這取決于矩陣MAX72XX
和矩陣之間的接線。-libraryLedControl
假定此示意圖中使用的設置:
矩陣中有 8 行(索引從 0..7 開始)和 8 列(索引也從 0..7 開始)。如果要點亮位于頂部第三行最右側的 Led,則2.7
必須使用 Led 的索引作為行和列參數。
此代碼摘錄顯示了第一個 MAX72XX 器件上的 LED 數量設置情況
//打開addr=0處設備第3行第8列的LED
lc.setLed(0,2,7,true);
//現在 LED 位于第 0 行,從左側數第二個
lc.setLed(0,0,1,true);
延遲(500);
//關閉第一個LED燈(第二個保持打開狀態)
lc.setLed(0,2,7,false);
該setLed()
函數適合點亮幾個 LED,但如果需要更新更多 LED,則需要很多行代碼。因此,庫中還有兩個函數,可以使用單個命令控制完整的行和列。
控制矩陣的行
- 函數setRow(addr,row,value)
有 3 個參數。第一個是我們已經熟悉的設備地址。第二個是需要更新的行,第三個是要為此行設置的值。
該value
參數采用 8 位寬字節,其中設置的每個位1
?代表一個點亮的 LED,設置為0
要關閉的 LED 的每個位。
例如,標記為紅色的 LED 將打開,所有其他 LED 將關閉。
要更新的行的索引為2
(從頂部數)。必須將參數value
?設置為字節值才能點亮 LED。最簡單的方法是將標準頭文件包含<binary.h>
到您的草圖中。該值以二進制編碼寫入,是設置的位1
和要打開的 LED 之間的精確映射。
//將此文件包含在草圖的頂部
<二進制.h>// ...省略初始化代碼...//設置第一個設備的第三行(索引=2)的LED
lc.setRow(0,2,B10110000);
當無法以二進制編碼指定值時,將每個位的十進制值映射到其影響的 Led 的簡單表會有所幫助。底部的兩行顯示要計算的示例的十進制值。
Led2.0 | Led2.1 | Led2.2 | Led2.3 | Led2.4 | Led2.5 | Led2.6 | Led2.7 | |
---|---|---|---|---|---|---|---|---|
Bit-Value | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
Led On? | Yes | No | Yes | Yes | No | No | No | No |
Row-Value | 128 | 0 | 32 | 16 | 0 | 0 | 2 | 0 |
value=176 (128+32+16)
該語句更新了Arduino 附加的lc.setRow(0,2,176)
第一行的第三行。MAX72XX
顯然?,對所有 LED 連續setRow()
調用八次要快得多。setLed()
a 的硬件MAX72XX
?使得該函數也比下一節中介紹的函數setRow()
快 8 倍 。setColumn()
如果草圖代碼的性能是重要因素,請setRow()
?盡可能使用該函數。
函數原型
/* 將一行中的所有 8 個 Led 設置為新狀態
* 參數:
* 顯示器的地址
* 要設置的行行 (0..7)
* 每個位設置為 1 的值將點亮相應的 Led。
*/
void setRow ( int addr , int row , 字節 值) ;
控制矩陣的列
-setColumn()
函數的工作方式與該命令類似setRow()
,但會更新垂直列中的 8 個 LED。
同樣,紅色標記的 LED 燈將打開,所有其他 LED 燈將關閉。
這次,第 6 列底部的 4 個 LED 將被點亮。對于二進制編碼,值中最左邊的位指的是列頂部的 LED。
//將此文件包含在草圖的頂部
<二進制.h>// ...省略初始化代碼...//設置第一個設備的第三行(索引=2)的LED
lc.setRow(0,2,B00001111);
setRow()
如果值的二進制編碼不是一種選擇,則與 參考資料部分中的表類似的表會有所幫助。
LED2.0 | LED2.1 | LED2.2 | LED2.3 | LED2.4 | LED2.5 | LED2.6 | LED2.7 | |
---|---|---|---|---|---|---|---|---|
位值 | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
帶領 | 是的 | 不 | 是的 | 是的 | 不 | 不 | 不 | 不 |
行值 | 128 | 0 | 32 | 16 | 0 | 0 | 2 | 0 |
=15 (8+4+2+1)
函數原型:
/* 將一列中的所有 8 個 Led 設置為新狀態
* 參數:
* 顯示器的地址
* 要設置的列列 (0..7)
* 每個位設置為 1 的值將點亮相應的 Led。
*/
void setColumn ( int addr , int col , 字節 值) ;
控制 7 段顯示器
在 7 段顯示器上打印數字
7 段顯示器最常見的用途是打印數字。LedControl 庫有一個函數,只需接受字節類型的參數并在指定列上打印相應的數字。數字的有效值為從0
到15
,以允許顯示十六進制值。大于 15(或負值)的值將被默默丟棄。該函數還提供了一個參數來打開或關閉列上的小數點。
以下是在顯示屏上以 4 位數字打印 int 值 (-999..999) 的代碼摘錄。
void printNumber(int v) { int ones; int tens; int hundreds; boolean negative=false;if(v < -999 || v > 999) return; if(v<0) { negative=true; v=v*-1; }ones=v%10; v=v/10; tens=v%10; v=v/10; hundreds=v; if(negative) { //print character '-' in the leftmost column lc.setChar(0,3,'-',false); } else {//print a blank in the sign column lc.setChar(0,3,' ',false); } //Now print the number digit by digit lc.setDigit(0,2,(byte)hundreds,false);lc.setDigit(0,1,(byte)tens,false); lc.setDigit(0,0,(byte)ones,false); }
該函數的原型:
/* Display a (hexadecimal) digit on a 7-Segment Display* Params:* addr address of the display* digit the position of the digit on the display (0..7)* value the value to be displayed. (0x00..0x0F)* dp sets the decimal point. */ void setDigit(int addr, int digit, byte value, boolean dp);
- 參數digit
必須在 0..7 范圍內,因為 MAX72XX 可以控制 7 段顯示器上最多 8 位數字。
在 7 段顯示器上打印字符
在 7 段顯示器上具有(視覺)意義的字符集有限。常見的用途是在-
前面添加負值的字符以及表示整數十六進制值的 'A'..'F' 中的 6 個字符。
-setChar(addr,digit,value,dp)
函數接受 7 位 ASCII 編碼范圍內的 char 類型值。由于可識別的模式有限,大多數定義的字符都會打印 -char?<SPACE>
。但有相當多的字符在 7 段顯示器上有意義。
這是可打印字符集:
0 1 2 3 4 5 6 7 8 9
A a
(打印大寫字母)B b
(打印小寫)C c
(打印小寫)D d
(打印小寫)E e
(打印大寫字母)F f
(打印大寫字母)H h
(打印大寫字母)L l
(打印大寫字母)P p
(打印大寫字母)-
(減號). ,
(點亮小數點)_
(下劃線)<SPACE>
(空白或空格字符)
十六進制字符 (?0..F
) 已在字符值 0x00...0x0F 處重新定義。這使得混合數字和字符值成為可能。- 函數的字節值setDigit()
可以與 一起使用setChar()
,并將打印該值的十六進制表示形式。
該函數的原型看起來與顯示數字的函數原型非常相似。
/* Display a character on a 7-Segment display.* Params:* addr address of the display* digit the position of the character on the display (0..7)* value the character to be displayed.* dp sets the decimal point. */ void setChar(int addr, int digit, char value, boolean dp);
完整的代碼:
#include "LedControl.h"LedControl lc=LedControl(11,13,10,1);unsigned long delaytime=10;void setup() {lc.shutdown(0,false);lc.setIntensity(0,15);lc.clearDisplay(0);}void writeArduinoOnMatrix() {byte a[5]={B01111110,B10001000,B10001000,B10001000,B01111110};byte r[5]={B00111110,B00010000,B00100000,B00100000,B00010000};byte d[5]={B00011100,B00100010,B00100010,B00010010,B11111110};byte u[5]={B00111100,B00000010,B00000010,B00000100,B00111110};byte i[5]={B00000000,B00100010,B10111110,B00000010,B00000000};byte n[5]={B00111110,B00010000,B00100000,B00100000,B00011110};byte o[5]={B00011100,B00100010,B00100010,B00100010,B00011100};lc.setRow(0,0,a[0]);lc.setRow(0,1,a[1]);lc.setRow(0,2,a[2]);lc.setRow(0,3,a[3]);lc.setRow(0,4,a[4]);delay(delaytime);lc.setRow(0,0,r[0]);lc.setRow(0,1,r[1]);lc.setRow(0,2,r[2]);lc.setRow(0,3,r[3]);lc.setRow(0,4,r[4]);delay(delaytime);lc.setRow(0,0,d[0]);lc.setRow(0,1,d[1]);lc.setRow(0,2,d[2]);lc.setRow(0,3,d[3]);lc.setRow(0,4,d[4]);delay(delaytime);lc.setRow(0,0,u[0]);lc.setRow(0,1,u[1]);lc.setRow(0,2,u[2]);lc.setRow(0,3,u[3]);lc.setRow(0,4,u[4]);delay(delaytime);lc.setRow(0,0,i[0]);lc.setRow(0,1,i[1]);lc.setRow(0,2,i[2]);lc.setRow(0,3,i[3]);lc.setRow(0,4,i[4]);delay(delaytime);lc.setRow(0,0,n[0]);lc.setRow(0,1,n[1]);lc.setRow(0,2,n[2]);lc.setRow(0,3,n[3]);lc.setRow(0,4,n[4]);delay(delaytime);lc.setRow(0,0,o[0]);lc.setRow(0,1,o[1]);lc.setRow(0,2,o[2]);lc.setRow(0,3,o[3]);lc.setRow(0,4,o[4]);delay(delaytime);lc.setRow(0,0,0);lc.setRow(0,1,0);lc.setRow(0,2,0);lc.setRow(0,3,0);lc.setRow(0,4,0);delay(delaytime);}void rows() {for(int row=0;row<8;row++) {delay(delaytime);lc.setRow(0,row,B10100000);delay(delaytime);lc.setRow(0,row,(byte)0);for(int i=0;i<row;i++) {delay(delaytime);lc.setRow(0,row,B10100000);delay(delaytime);lc.setRow(0,row,(byte)0);}}}void columns() {for(int col=0;col<8;col++) {delay(delaytime);lc.setColumn(0,col,B10100000);delay(delaytime);lc.setColumn(0,col,(byte)0);for(int i=0;i<col;i++) {delay(delaytime);lc.setColumn(0,col,B10100000);delay(delaytime);lc.setColumn(0,col,(byte)0);}}}void single() {for(int row=0;row<8;row++) {for(int col=0;col<8;col++) {delay(delaytime);lc.setLed(0,row,col,true);delay(delaytime);for(int i=0;i<col;i++) {lc.setLed(0,row,col,false);delay(delaytime);lc.setLed(0,row,col,true);delay(delaytime);}}}}void loop() {writeArduinoOnMatrix();rows();columns();single();}