1.8.1. 介紹
8個led按照上圖中的順序排列,並把led的正極接到一塊(共陽級)引出或把led的負極接到一塊(共陰極)引出,這就是數碼管。
數碼管可以用來顯示簡單的字符,如0~9。
當共陽極單位數碼管的公共端接電源正極,段LED的負極為低電平時對應的段顯示,段LED的負極為高電平時對應的段熄滅,編碼表如下:
段碼 |
位碼 |
||||||||
A |
B |
C |
D |
E |
F |
G |
DP |
||
‘0’ |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
‘1’ |
1 |
0 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
‘2’ |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
1 |
1 |
‘3’ |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
1 |
1 |
‘4’ |
1 |
0 |
0 |
1 |
1 |
0 |
0 |
1 |
1 |
‘5’ |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
1 |
‘6’ |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
‘7’ |
0 |
0 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
‘8’ |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
‘9’ |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
1 |
1 |
當共陰極單位數碼管的公共端接電源負極,段LED的負極為高電平時對應的段顯示,段LED的負極為低電平時對應的段熄滅,編碼表如下:
段碼 |
位碼 |
||||||||
A |
B |
C |
D |
E |
F |
G |
DP |
||
‘0’ |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
‘1’ |
0 |
1 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
‘2’ |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
0 |
0 |
‘3’ |
1 |
1 |
1 |
1 |
0 |
0 |
1 |
0 |
0 |
‘4’ |
0 |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
0 |
‘5’ |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
0 |
‘6’ |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
‘7’ |
1 |
1 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
‘8’ |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
‘9’ |
1 |
1 |
1 |
1 |
0 |
1 |
1 |
0 |
0 |
2個數碼管組成的組合數碼管稱為2位數碼管,原理示意圖如下:
其中:A/B/C/D/E/F/G/DP稱為段碼,公共引腳6/9稱為位碼。
1.8.2. 單位數碼管的驅動
案例描述:0~9的循環秒計數器(9s后從0s重新開始計數)
需求分析:粗計時,使用sleep函數
1.8.2.1. 硬件電路
以共陽極數碼管為例,正極接電源(位碼),字段led的負極接單片機IO口(位碼),如下圖所示:
其中R00~R07稱為限流電阻,阻值1K,計算方式同Led。
實例中使用的是2位共陽數碼管管腳定義如下:
使用其中的DIG2用作單位數碼管實驗,故DIG2的公共引腳“5”接Vcc(3.3v)。其他引腳結合原理圖、引腳定義圖接線,切記要接限流電阻。
1.8.2.2. 基於驅動模塊的代碼實現
共陽極單位/雙位數碼管的類已經封裝好,可以從gitee倉庫下載本教程案例代碼。數碼管驅動模塊的目錄:1_7數碼管/exam3/CADT.py或1_7數碼管/exam4/CADT.py。
主程序代碼實現:
from time import sleep,sleep_ms from CADT import digitalCube1 disp = digitalCube1(15,4,5,18,19,21,22,23) #循環計數器 i = 0 j = 0 while True: i = i+1 if(i>999): i=0 j = j+1 if(j>9): j=0 disp.updateDisplay(j) disp.display() sleep(0.001)
1.8.2.3. 直接驅動(靜態顯示)
采用直接驅動方式,驅動單位led的實現代碼:
from machine import Pin from time import sleep #實例化段碼 a = Pin(15,Pin.OUT) b = Pin(4,Pin.OUT) c = Pin(5,Pin.OUT) d = Pin(18,Pin.OUT) e = Pin(19,Pin.OUT) f = Pin(21,Pin.OUT) g = Pin(22,Pin.OUT) dp = Pin(23,Pin.OUT) #關閉段碼 a.on() b.on() c.on() d.on() e.on() f.on() g.on() dp.on() #段碼 duan_ma = [0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09] duan_ctl = [dp,g,f,e,d,c,b,a] #顯存 display_buff = 0b11111111 #顯示函數 def display(): global display_buff for j in range(8): if(display_buff&(1<<j)): duan_ctl[j].on() else: duan_ctl[j].off() #循環計數器 i = 0 while True: display_buff = duan_ma[i] i = i+1 if(i>9): i=0 display() sleep(1)
1.8.3. 雙位數碼管的驅動
案例描述:00~99的循環秒計數器(99s后從0s重新開始計數)
需求分析:粗計時,使用sleep函數。
1.8.3.1. 硬件電路
以共陽極數碼管為例,如下圖所示:
只有Led兩端均有合適的電壓時,Led才會被點亮。多位數碼管情況下,為了減少IO口消耗,段碼、位碼配合工作達到控制到每一位的目的。但是,如果還采用上節的控制方案,數碼管每一個點亮的段的共極腳位電流會同時流經單片機,單片機共極腳將承受較大的電流,增加了損壞的隱患。
而如果每個時間段只顯示一段(只有一個led點亮),只要速度足夠快(大於100hz),肉眼看上去就好像每個需要點亮的段都在點亮一樣,這同樣可以達到顯示效果,但卻能解決掉流程共極端電流過大的隱患。對單片機來說,達到肉眼不可分辨的速度,是很容易實現的。
1.1.3.2. 基於驅動模塊
共陽極單位、雙位數碼管的類已經封裝好,可以從gitee倉庫下載本教程案例代碼,數碼管類目錄:1_7數碼管/exam3/CADT.py或1_7數碼管/exam4/CADT.py。
from time import sleep,sleep_ms from CADT import digitalCube2 disp = digitalCube2(15,4,5,18,19,21,22,23,25,33) #循環計數器 i = 0 j = 0 while True: i = i+1 if(i>999): i=0 j = j+1 if(j>9): j=0 disp.updateDisplay(j) disp.display() sleep(0.001) 1.8.3.3. 直接驅動(動態顯示) 采用直接驅動方式,驅動單位led的實現代碼: from machine import Pin from time import sleep,sleep_ms #實例化段碼 a = Pin(15,Pin.OUT) b = Pin(4,Pin.OUT) c = Pin(5,Pin.OUT) d = Pin(18,Pin.OUT) e = Pin(19,Pin.OUT) f = Pin(21,Pin.OUT) g = Pin(22,Pin.OUT) dp = Pin(23,Pin.OUT) gao = Pin(25,Pin.OUT) di = Pin(33,Pin.OUT) #關閉段碼 a.on() b.on() c.on() d.on() e.on() f.on() g.on() dp.on() gao.on() di.on() #段碼 duan_ma = [0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09] duan_ctl = [dp,g,f,e,d,c,b,a,dp,g,f,e,d,c,b,a] #顯存 display_buff = 0b1111111111111111 #顯示函數 def display(index): global display_buff for i in range(8): duan_ctl[i].on() if(index > 7): gao.on() di.off() else: gao.off() di.on() if(display_buff&(1<<index)): duan_ctl[index].on() else: duan_ctl[index].off() #更新顯存 def updateDisplayBuff(value): global display_buff temp_shi = int(value/10) temp_ge = (value%10) display_buff = (0x00ff|(duan_ma[temp_shi]<<8))&\ (0xff00|duan_ma[temp_ge]) #循環計數器 i = 0 j = 0 while True: i = i+1 if(i>999): i=0 j = j+1 updateDisplayBuff(j) #display_buff = 0x2503 if(j>99): j=0 display(i%16) sleep(0.001)
1.8.4. 驅動模塊源碼
共陽極單位、雙位數碼管的類已經封裝好,可以從gitee倉庫下載本教程案例代碼,數碼管類目錄:1_7數碼管/exam3/CADT.py或1_7數碼管/exam4/CADT.py,源碼如下:
from machine import Pin #共陽單位數碼管 class digitalCube1: ''' 類的接口函數,輸入參數段碼IO口. ''' def __init__(self,a,b,c,d,e,f,g,dp): self.duan_ctl = [Pin(dp,Pin.OUT),\ Pin(g,Pin.OUT),\ Pin(f,Pin.OUT),\ Pin(e,Pin.OUT),\ Pin(d,Pin.OUT),\ Pin(c,Pin.OUT),\ Pin(b,Pin.OUT),\ Pin(a,Pin.OUT)] self.duan_code = [0x03,\ 0x9f,\ 0x25,\ 0x0d,\ 0x99,\ 0x49,\ 0x41,\ 0x1f,\ 0x01,\ 0x09] self.disp_buff = 0b111111 ''' 更新要顯示的內容value ''' def updateDisplay(self,value): self.disp_buff = self.duan_code[value] ''' 顯示函數,在時間片中調用 ''' def display(self): for i in range(8): if (self.disp_buff & (1<<i)): self.duan_ctl[i].on() else: self.duan_ctl[i].off() #共陽雙位數碼管 class digitalCube2: ''' 類的接口函數,輸入參數段碼IO口. ''' def __init__(self,a,b,c,d,e,f,g,dp,ge,shi): self.duan_ctl = [Pin(dp,Pin.OUT),\ Pin(g,Pin.OUT),\ Pin(f,Pin.OUT),\ Pin(e,Pin.OUT),\ Pin(d,Pin.OUT),\ Pin(c,Pin.OUT),\ Pin(b,Pin.OUT),\ Pin(a,Pin.OUT),\ Pin(dp,Pin.OUT),\ Pin(g,Pin.OUT),\ Pin(f,Pin.OUT),\ Pin(e,Pin.OUT),\ Pin(d,Pin.OUT),\ Pin(c,Pin.OUT),\ Pin(b,Pin.OUT),\ Pin(a,Pin.OUT)] self.duan_code = [0x03,\ 0x9f,\ 0x25,\ 0x0d,\ 0x99,\ 0x49,\ 0x41,\ 0x1f,\ 0x01,\ 0x09] self.ge_ctl = Pin(ge,Pin.OUT) self.shi_ctl = Pin(shi,Pin.OUT) self.disp_buff = 0b111111 self.index = 0 ''' 更新要顯示的內容value ''' def updateDisplay(self,value): temp_shi = int(value/10) temp_ge = (value%10) self.disp_buff = (0x00ff|(self.duan_code[temp_shi]<<8))&\ (0xff00|self.duan_code[temp_ge]) ''' 顯示函數,在時間片中調用 ''' def display(self): #關閉所有段 for i in range(8): self.duan_ctl[i].on() if(self.disp_buff&(1<<self.index)): self.duan_ctl[self.index].on() else: self.duan_ctl[self.index].off() if(self.index > 7): self.shi_ctl.on() self.ge_ctl.off() else: self.shi_ctl.off() self.ge_ctl.on() self.index = self.index + 1 if self.index > 15: self.index = 0