我們學(xué)習(xí)了如何利用74HC595這塊顯示驅(qū)動芯片來驅(qū)動1位8段數(shù)碼管的方法。并逐一講解了該芯片各引腳的功能。細(xì)心的童鞋可能注意到了,上次我們有一個Q7S引腳沒有用到。這一篇我們就用這個引腳來級聯(lián)兩塊74HC595芯片同時驅(qū)動8個8段數(shù)碼管。在兩塊74HC595芯片的配合下,同樣只需要3個GPIO口就能驅(qū)動八只8段數(shù)碼管。而如果直接用GPIO驅(qū)動則需要至少16個GPIO口,節(jié)省了13個GPIO!而且按照本文的方法,你還可以級聯(lián)更多的74HC595芯片,每多級聯(lián)一片就能多驅(qū)動8只數(shù)碼管,而需要的IO口仍然只有3個!媽媽再也不用擔(dān)心我的IO口不夠用了。
最終效果
視頻演示
硬件
- 74HC595顯示芯片 X 2
- 共陽(或共陰)4位數(shù)碼管 X 2
硬件圖 由于大面包板已經(jīng)被我插滿了,所以用另一塊小面包板來安放第二片74HC595
原理說明
- 我們已經(jīng)知道,每次制造一次移位寄存器時鐘引腳的上升沿,74HC595都會在這個上升沿將DS引腳上的數(shù)據(jù)存入內(nèi)部的移位寄存器D0,同時D0原來的數(shù)據(jù)會順移到D1,D1的數(shù)據(jù)位移到D2。。。D6的數(shù)據(jù)位移到D7。而D7的數(shù)據(jù)會被輸出到引腳Q7S上,如果Q7S引腳沒有被使用,那么這一位數(shù)據(jù)就被丟掉了。
- 如果我們將Q7S引腳連接上另一塊74HC595的DS引腳并保證兩塊芯片上的移位時鐘的上升沿同時發(fā)生(將兩塊芯片的SHCP連在一起即可)的話,第一塊74HC595的串行輸出引腳Q7S就變成了第二塊74HC595的串行輸入數(shù)據(jù)源。Q7S上的數(shù)據(jù)會繼續(xù)移位到第二塊74HC595芯片的移位寄存器D0里(同樣的,D0→D1→D2→…→D6→D7→Q7S)。
- 16位數(shù)據(jù)全部這樣串行傳輸完畢后,制造兩塊芯片的鎖存時鐘STCP的上升沿(跟SHCP一樣,兩塊芯片的STCP連在一起即可)即可同時輸出16位數(shù)據(jù)。
- 利用上述級聯(lián)原理加上前一篇學(xué)習(xí)的內(nèi)容,我們可以這樣靜態(tài)驅(qū)動2只數(shù)碼管:兩只數(shù)碼管的共陽(陰)極連接VCC(GND),第一片595的Q0-Q7連到第一個數(shù)碼管的A-G,Dp上,級聯(lián)的第二片595的Q0-Q7連到第二只數(shù)碼管的A-G,Dp上,然后用3根GPIO口驅(qū)動兩片級聯(lián)的74HC595芯片,連續(xù)串行輸入兩個數(shù)字的顯示碼共16位數(shù)據(jù),然后同時制造鎖存上升沿,將兩個數(shù)字的顯示碼分別輸出到兩只數(shù)碼管上即可。這樣連接的話,N片級聯(lián)的74HC595就能驅(qū)動N只數(shù)碼管了。(咦,說好的驅(qū)動8位數(shù)碼管的呢)
- 上面的做法當(dāng)然沒問題,而且有一個優(yōu)點(diǎn)是靜態(tài)顯示所以顯示很穩(wěn)定,有興趣自己試著做一下。缺點(diǎn)是浪費(fèi)芯片,價格倒不貴可是連線復(fù)雜,占用電路板面積太多。本文采用動態(tài)掃描(原理參見本系列第5篇)的方式來使用兩塊級聯(lián)的74HC595芯片驅(qū)動8位數(shù)碼管。原理也很簡單,稍微調(diào)整一下硬件的連接方式和傳輸數(shù)據(jù)的方式即可。
- 依然是兩塊74HC595級聯(lián),第一塊595的輸出引腳連到所有數(shù)碼管的段引腳上(8只數(shù)碼管的A-G,Dp引腳連在一起),第二塊595的輸出引腳Q0-Q7分別連上8只數(shù)碼管的共陽(陰)極上。第一塊芯片的輸出決定了數(shù)碼管上顯示什么數(shù)字。而8只數(shù)碼管中哪一只會被點(diǎn)亮則取決于第二塊芯片哪只數(shù)碼管的共陽(陰)端是高(低)電平。
- 由于在我的硬件連接里,級聯(lián)的第二塊74HC595是負(fù)責(zé)位選的,所以應(yīng)該先發(fā)送8位位選信號,再發(fā)送8位段選信號,在連續(xù)發(fā)完了16位數(shù)據(jù)以后,第一塊74HC595的移位寄存器里保存著8位的段選信息,而在第二塊74HC595的移位寄存器里保存著8位的位選信息。由于兩片芯片的STCP是連在同一個GPIO口的,這個時候如果制造一次STCP的上升沿,兩塊595的位移寄存器里的數(shù)據(jù)會同時保存到自己的鎖存器里,由于我的使能端OE連在GND始終有效,鎖存器里的數(shù)據(jù)就直接輸出到了芯片的輸出引腳上。第二塊芯片的8根輸出引腳連接的是8位數(shù)碼管的共陽端。只有輸出高電平的引腳連接的數(shù)碼管才會被點(diǎn)亮。
- 當(dāng)然如果你喜歡,你也可以讓8個數(shù)碼管全部同時點(diǎn)亮,你只要讓第二塊595輸出11111111就行了。不過顯示的數(shù)字都是一樣的。想顯示不同的數(shù)字就要進(jìn)行動態(tài)掃描,每次輸出一個數(shù)字的顯示碼跟一個位選碼,快速循環(huán)切換顯示即可。
跟上一篇一樣,我也做了一個動畫幫助你理解級聯(lián)的過程。這個動畫一開始已經(jīng)是傳輸完前8位位選數(shù)據(jù)的狀態(tài)了,動畫里的位選數(shù)據(jù)是1000000,點(diǎn)亮第一個數(shù)碼管,顯示的內(nèi)容由后8位段選數(shù)據(jù)決定,動畫里是數(shù)字5。74HC595
硬件連接
模塊1引腳模塊2引腳74HC595_1Q0數(shù)碼管1/2DP74HC595_1Q1數(shù)碼管1/2G74HC595_1Q2數(shù)碼管1/2F74HC595_1Q3數(shù)碼管1/2E74HC595_1Q4數(shù)碼管1/2D74HC595_1Q5數(shù)碼管1/2C74HC595_1Q6數(shù)碼管1/2B74HC595_1Q7數(shù)碼管1/2A74HC595_1Q7S74HC595_2DS74HC595_2Q0數(shù)碼管1DIG1的共陽極74HC595_2Q1數(shù)碼管1DIG2的共陽極74HC595_2Q2數(shù)碼管1DIG3的共陽極74HC595_2Q3數(shù)碼管1DIG4的共陽極74HC595_2Q4數(shù)碼管2DIG1的共陽極74HC595_2Q5數(shù)碼管2DIG2的共陽極74HC595_2Q6數(shù)碼管2DIG3的共陽極74HC595_2Q7數(shù)碼管2DIG4的共陽極樹莓派GPIO1374HC595_1DS樹莓派GPIO1974HC595_1/2SHCP樹莓派GPIO2674HC595_1/2SHTP樹莓派VCC74HC595_1/2VCC,MR樹莓派GND74HC595_1/2GND,OE代碼(Python)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
#!/usr/bin/env python# encoding: utf-8import RPi.GPIOimport time# 串行數(shù)據(jù)輸入引腳連接的GPIO口DS = 13# 移位寄存器時鐘控制引腳連接的GPIO口——上升沿有效SHCP = 19# 數(shù)據(jù)鎖存器時鐘控制引腳連接的GPIO口——上升沿有效STCP = 26RPi.GPIO.setmode(RPi.GPIO.BCM)RPi.GPIO.setup(DS, RPi.GPIO.OUT)RPi.GPIO.setup(STCP, RPi.GPIO.OUT)RPi.GPIO.setup(SHCP, RPi.GPIO.OUT)RPi.GPIO.output(STCP, False)RPi.GPIO.output(SHCP, False)# 通過串行數(shù)據(jù)引腳向74HC595的傳送一位數(shù)據(jù)def setBitData(data):# 準(zhǔn)備好要傳送的數(shù)據(jù)RPi.GPIO.output(DS, data)# 制造一次移位寄存器時鐘引腳的上升沿(先拉低電平再拉高電平)# 74HC595會在這個上升沿將DS引腳上的數(shù)據(jù)存入移位寄存器D0# 同時D0原來的數(shù)據(jù)會順移到D1,D1的數(shù)據(jù)位移到D2。。。D6的數(shù)據(jù)位移到D7# 而D7的數(shù)據(jù)已經(jīng)沒有地方儲存了,這一位數(shù)據(jù)會被輸出到引腳Q7S上# 如果Q7S引腳沒有被使用,那么這一位的數(shù)據(jù)就被丟掉了。# 而如果將Q7S引腳連接到另一塊74HC595上的DS引腳,# 那么這一位數(shù)據(jù)就會繼續(xù)位移到第二塊595芯片的位移寄存器里去。# 這就是多塊595芯片級聯(lián)的原理。RPi.GPIO.output(SHCP, False)RPi.GPIO.output(SHCP, True)# 指定第dig位(1-8)數(shù)碼管顯示數(shù)字num(0-9),參數(shù)showDotPoint是顯示不顯示小數(shù)點(diǎn)(true/false)# 由于我使用的數(shù)碼管是共陽數(shù)碼管,所以設(shè)置為低電平的段才會被點(diǎn)亮# 如果你用的是共陰數(shù)碼管,那么要將下面的True和False全部顛倒過來,或者統(tǒng)一在前面加上notdef showDigit(dig, num, showDotPoint):# 由于在我的硬件連接里,級聯(lián)的第二塊74HC595是負(fù)責(zé)位選的,# 所以應(yīng)該先發(fā)送8位位選信號,再發(fā)送8位段選信號,在連續(xù)發(fā)完了16位數(shù)據(jù)以后,# 第一塊74HC595的移位寄存器里保存著8位的段選信息,而在第二塊74HC595的移位寄存器里保存著8位的位選信息。# 由于兩片芯片的STCP是連在同一個GPIO口的,這個時候如果制造一次STCP的上升沿,# 兩塊595的位移寄存器里的數(shù)據(jù)會同時保存到自己的鎖存器里,由于我的使能端OE連在GND始終有效,鎖存器里的數(shù)據(jù)就直接輸出到了芯片的輸出引腳上。# 第一塊芯片的8根輸出引腳連接的是所有數(shù)碼管共用的abcdefg,dp引腳,決定了數(shù)碼管上顯示什么數(shù)字。而8只數(shù)碼管中哪一只會被點(diǎn)亮則取決于哪只數(shù)碼管的共陽端是高電平。# 第二塊芯片的8根輸出引腳連接的是8位數(shù)碼管的共陽端。只有輸出高電平的引腳連接的數(shù)碼管會點(diǎn)亮。# 當(dāng)然如果你喜歡,你也可以讓8個數(shù)碼管全部同時點(diǎn)亮,你只要讓第二塊595輸出11111111就行了。不過顯示的數(shù)字都是一樣的。# 想顯示不同的數(shù)字就要進(jìn)行動態(tài)掃描,原理不再說明請參考本系列教程第5篇。for x in range(1,9):if (x == dig):setBitData(True)else:setBitData(False)if (num == 0) :setBitData(not showDotPoint) # DPsetBitData(True) # GsetBitData(False) # FsetBitData(False) # EsetBitData(False) # DsetBitData(False) # CsetBitData(False) # BsetBitData(False) # Aelif (num == 1) :setBitData(not showDotPoint)setBitData(True)setBitData(True)setBitData(True)setBitData(True)setBitData(False)setBitData(False)setBitData(True)elif (num == 2) :setBitData(not showDotPoint)setBitData(False)setBitData(True)setBitData(False)setBitData(False)setBitData(True)setBitData(False)setBitData(False)elif (num == 3) :setBitData(not showDotPoint)setBitData(False)setBitData(True)setBitData(True)setBitData(False)setBitData(False)setBitData(False)setBitData(False)elif (num == 4) :setBitData(not showDotPoint)setBitData(False)setBitData(False)setBitData(True)setBitData(True)setBitData(False)setBitData(False)setBitData(True)elif (num == 5) :setBitData(not showDotPoint)setBitData(False)setBitData(False)setBitData(True)setBitData(False)setBitData(False)setBitData(True)setBitData(False)elif (num == 6) :setBitData(not showDotPoint)setBitData(False)setBitData(False)setBitData(False)setBitData(False)setBitData(False)setBitData(True)setBitData(False)elif (num == 7) :setBitData(not showDotPoint)setBitData(True)setBitData(True)setBitData(True)setBitData(True)setBitData(False)setBitData(False)setBitData(False)elif (num == 8) :setBitData(not showDotPoint)setBitData(False)setBitData(False)setBitData(False)setBitData(False)setBitData(False)setBitData(False)setBitData(False)elif (num == 9) :setBitData(not showDotPoint)setBitData(False)setBitData(False)setBitData(True)setBitData(False)setBitData(False)setBitData(False)setBitData(False)# 移位寄存器的8位數(shù)據(jù)全部傳輸完畢后,制造一次鎖存器時鐘引腳的上升沿(先拉低電平再拉高電平)# 74HC595會在這個上升沿將移位寄存器里的8位數(shù)據(jù)復(fù)制到8位的鎖存器中(鎖存器里原來的數(shù)據(jù)將被替換)# 到這里為止,這8位數(shù)據(jù)還只是被保存在鎖存器里,并沒有輸出到數(shù)碼管上。# 決定鎖存器里的數(shù)據(jù)是否輸出是由“輸出使能端口”O(jiān)E決定的。當(dāng)OE設(shè)置為低電平時,鎖存器里數(shù)據(jù)才會被輸出到Q0-Q7這8個輸出引腳上。# 在我的硬件連接里,OE直接連接在了GND上,總是保持低電平,所以移位寄存器的數(shù)據(jù)一旦通過時鐘上升沿進(jìn)入鎖存器,也就相當(dāng)于輸出到LED上了。RPi.GPIO.output(STCP, True)RPi.GPIO.output(STCP, False)try:# 測試代碼while (True):# 8位數(shù)碼管顯示1-8,不顯示小數(shù)點(diǎn)for dig in range(1,9):showDigit(dig, 9-dig, False)time.sleep(0.001)except KeyboardInterrupt:pass# 最后清理GPIO口RPi.GPIO.cleanup()
評論