前面幾篇我們學(xué)習(xí)了如何利用一片或多片級(jí)聯(lián)的74HC595芯片來驅(qū)動(dòng)顯示數(shù)碼管的方法。最開始我們提出的兩個(gè)問題:
第一個(gè)問題已經(jīng)利用級(jí)聯(lián)的74HC595解決了。(不管驅(qū)動(dòng)幾只數(shù)碼管,只用3個(gè)IO即可)
但第二個(gè)問題依然存在,樹莓派仍然需要不停地訪問IO口進(jìn)行動(dòng)態(tài)掃描。
好,既然動(dòng)態(tài)掃描占用CPU資源太多,那這活兒咱包出去讓別人干不就行了?這就是本文主角MAX7219的特長(zhǎng),動(dòng)態(tài)掃描這活兒MAX7219全包了,干的還比咱自己干得還好,一片MAX7219可最多支持顯示8位8段數(shù)碼管,還支持各種設(shè)置如亮度設(shè)置掃描位數(shù)設(shè)置等。而我們只用告訴它顯示的內(nèi)容就行了。
最終效果
視頻演示
硬件
- MAX7219顯示芯片 X 1(2到3元一個(gè))
MAX7219 - 共陰(共陽(yáng)不可以)4位數(shù)碼管 X 2
- 10k電阻一只
- 10uF電容一只
- 0.1uF電容一只
硬件圖
原理說明 未完TODO
注:下面這些圖都是從MAX7219官方資料里截取出來的,官方資料文末提供下載
- 先看一下MAX7219的引腳圖:
MAX7219的引腳圖
MAX7219一共有24根引腳,這里面有一些跟74HC595的引腳功能類似的引腳如下:
可以看出,MAX7219跟74HC595一樣也是通過DIN引腳串行輸入數(shù)據(jù),在CLK引腳的上升沿移入移位寄存器,在LOAD引腳的上升沿將位移寄存器的數(shù)據(jù)復(fù)制到內(nèi)部的各種寄存器里。不同的是:
我們?cè)倏匆幌鹿俜轿臋n里關(guān)于各引腳的功能說明:
MAX7219各引腳的功能說明
上面提過的不再贅述,說一下MAX7219特有的引腳。- DIG0-DIG7這8個(gè)引腳作為位選端,分別連到8位數(shù)碼管的共陰極,MAX7219在做動(dòng)態(tài)掃描時(shí)會(huì)依次向共陰極DIG0-DIG7輸出低電平,所以MAX7219不能驅(qū)動(dòng)共陽(yáng)極的數(shù)碼管。其實(shí)也不是絕對(duì)不能,將位選端和段選端逆接就可以了,不過這樣做的話,有3個(gè)弊端:
- 不能使用MAX7219內(nèi)部的譯碼功能,需要自己編寫數(shù)字的字形碼。增加了代碼的復(fù)雜度。
- 需要以段單位來傳輸數(shù)據(jù),而不能以位單位來傳輸數(shù)據(jù)。(即每次傳輸?shù)氖歉魑粩?shù)碼管的某一段的數(shù)據(jù),而不是某位數(shù)碼管各段的數(shù)據(jù)。第一次傳所有數(shù)碼管的A段數(shù)據(jù),第二次傳所有數(shù)碼管的B段數(shù)據(jù)一直到8段數(shù)據(jù)全部傳完)無疑進(jìn)一步增加了代碼的復(fù)雜度。
- 無法限制掃描位數(shù),只能所有8位數(shù)碼管同時(shí)掃描。(變成了限制掃描段數(shù),如可以只顯示所有數(shù)碼管的A-C段。。。)
- ISET通過一只電阻連上VCC,通過調(diào)整這只電阻的阻值可以調(diào)整通過這只電阻的電流I,而最后輸出到數(shù)碼管上的最大電流就是這個(gè)電流I的100倍。如果這只電阻太小,導(dǎo)致輸出到數(shù)碼管的電流過大會(huì)燒壞數(shù)碼管,所以官方文檔里推薦這只電阻最小應(yīng)該設(shè)置為9.7K歐,我手頭上只有10K的電阻也是一樣,只要?jiǎng)e低于這個(gè)阻值就可以了。根據(jù)這個(gè)原理我們也可以接一個(gè)可調(diào)電阻在ISET上,可以隨時(shí)調(diào)整數(shù)碼管亮度。這種調(diào)整亮度的方法是通過模擬信號(hào)調(diào)制。MAX7219也支持通過數(shù)字信號(hào)來設(shè)置亮度(有16級(jí)亮度可調(diào))。
MAX7219內(nèi)部的各模塊的示意圖:
MAX7219內(nèi)部的各模塊的示意圖
最下面是一個(gè)16位的移位寄存器D0-D15,跟74HC595一樣,通過DIN引腳串行輸入數(shù)據(jù),在CLK引腳的上升沿移入移位寄存器。
D8-D11這4位數(shù)據(jù)用來指定內(nèi)部寄存器地址。D0-D7是具體要傳到寄存器里的數(shù)據(jù)。
上面的圖看上去有點(diǎn)復(fù)雜,其實(shí)簡(jiǎn)單地說就是我們每次要串行傳輸16位數(shù)據(jù)進(jìn)去,然后在LOAD的上升沿,根據(jù)D8-D11指定的寄存器地址,將D0-D7存放在指定的寄存器里。這樣多次傳輸數(shù)據(jù)就可以給所有的寄存器設(shè)值了。
下面是MAX7219內(nèi)部的寄存器一覽:- 關(guān)斷寄存器
- 譯碼模式寄存器
- 亮度寄存器
- 掃描限值寄存器
顯示器測(cè)試寄存器
每個(gè)寄存器都有自己特殊的功能,后面我們會(huì)逐一介紹。
串行傳輸時(shí)的數(shù)據(jù)格式如下:
MAX7219串行數(shù)據(jù)格式
你可能注意到了這幅圖的順序跟模塊示意圖里移位寄存器的順序是相反的。
D15-D0這個(gè)反向的順序是你寫代碼時(shí)串行傳輸數(shù)據(jù)時(shí)的順序,先傳D15的數(shù)據(jù),再傳D14,D13…D0,這樣傳輸完成后。實(shí)際的數(shù)據(jù)順序就變成了D0,D1,D2…D15。為了便于編碼,除了模塊示意圖是按實(shí)際順序記載的,后面所有數(shù)據(jù)格式的示意圖都是倒序記載的。各寄存器地址如下:
MAX7219寄存器地址
關(guān)斷寄存器的數(shù)據(jù)格式:
MAX7219關(guān)斷寄存器的數(shù)據(jù)格式
譯碼模式寄存器的數(shù)據(jù)格式:
MAX7219譯碼模式寄存器的數(shù)據(jù)格式
譯碼模式下的原碼和譯碼的對(duì)應(yīng)表:
MAX7219譯碼模式下的原碼和譯碼的對(duì)應(yīng)表
非譯碼模式下的數(shù)據(jù)和數(shù)碼管各段的對(duì)應(yīng)表:
MAX7219非譯碼模式下的數(shù)據(jù)和數(shù)碼管各段的對(duì)應(yīng)表
亮度寄存器的數(shù)據(jù)格式:
MAX7219亮度寄存器的數(shù)據(jù)格式
掃描限值寄存器的數(shù)據(jù)格式:
MAX7219掃描限值寄存器的數(shù)據(jù)格式
顯示器測(cè)試寄存器的數(shù)據(jù)格式:
MAX7219顯示器測(cè)試寄存器的數(shù)據(jù)格式
硬件連接TODO
模塊1引腳模塊2引腳MAX7219DIN樹莓派GPIO13MAX7219LOAD樹莓派GPIO26MAX7219CLK樹莓派GPIO19MAX7219GNDX2樹莓派GNDMAX7219V+樹莓派5VMAX7219ISET樹莓派5V(需串聯(lián)一只10k電阻)MAX7219DIG0數(shù)碼管1DIG1(引腳12)MAX7219DIG1數(shù)碼管1DIG2(引腳9)MAX7219DIG2數(shù)碼管1DIG3(引腳8)MAX7219DIG3數(shù)碼管1DIG4(引腳6)MAX7219DIG4數(shù)碼管2DIG1(引腳12)MAX7219DIG5數(shù)碼管2DIG2(引腳9)MAX7219DIG6數(shù)碼管2DIG3(引腳8)MAX7219DIG7數(shù)碼管2DIG4(引腳6)MAX7219SEG DP數(shù)碼管1/2DPMAX7219SEG G數(shù)碼管1/2GMAX7219SEG F數(shù)碼管1/2FMAX7219SEG E數(shù)碼管1/2EMAX7219SEG D數(shù)碼管1/2DMAX7219SEG C數(shù)碼管1/2CMAX7219SEG B數(shù)碼管1/2BMAX7219SEG A數(shù)碼管1/2AMAX7219DOUT(級(jí)聯(lián)用)(不使用)10/0.1uF電容正極MAX7219V+10/0.1uF電容負(fù)極MAX7219GND代碼(Python)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
#!/usr/bin/env python# encoding: utf-8import RPi.GPIOimport time# 串行數(shù)據(jù)輸入DIN = 13# 時(shí)鐘脈沖信號(hào)——上升沿有效LOAD = 26# 打入信號(hào)————上升沿有效CLK = 19RPi.GPIO.setmode(RPi.GPIO.BCM)RPi.GPIO.setup(DIN, RPi.GPIO.OUT)RPi.GPIO.setup(LOAD, RPi.GPIO.OUT)RPi.GPIO.setup(CLK, RPi.GPIO.OUT)# 傳輸一個(gè)8位數(shù)def setByte(byteData):for bit in range(0,8):# 傳入的數(shù)字從高位到低位依次判斷是否為1,若為1則設(shè)置高電平,否則設(shè)置低電平# 判斷的方法是先向左移位,把要判斷的位移動(dòng)到最高位然后跟0x80(1000 0000)相與,# 如果結(jié)果仍然是0x80(1000 0000)就表示最高位是1,否則最高位就是0if ((byteData<
評(píng)論