1. 數碼管介紹
1.1 簡介
數碼管是一種半導體發光器件,其基本單元是發光二極管。數碼管按段數可分為七段數碼管和八段數碼管,八段數碼管比七段數碼管多一個發光二極管單元,也就是多一個小數點(DP),使用這個小數點可以更方便地表示想要顯示的內容;按能顯示多少個(8)可分為1位、2位、3位、4位、5位、6位、7位等數碼管。按發光二極管單元連接方式可分為共陽極數碼管和共陰極數碼管。
共陰段碼:
段碼 | 字符 | 段碼 | 字符 | 段碼 | 字符 | 段碼 | 字符 |
0x3f | 0 | 0x6d | 5 | 0x77 | A | 0x71 | F |
0x06 | 1 | 0x7d | 6 | 0x7c | B | 0x00 | 無顯示 |
0x5b | 2 | 0x07 | 7 | 0x39 | C | ||
0x4f | 3 | 0x7f | 8 | 0x5e | D | ||
0x66 | 4 | 0x6f | 9 | 0x79 | E |
1.2 動態顯示原理
LED數碼管顯示器工作方式有兩種:靜態顯示方式和動態顯示方式。
靜態顯示的特點是每個數碼管的段選必須接一個8位數據線來保持顯示的字形碼。當送入一次字形碼后,顯示字形可一直保持,直到送入新字形碼為止。這種方法的優點是占用CPU時間少,顯示便於監測和控制。缺點是硬件電路比較復雜,成本較高,比如使用4個靜態數碼管,那么就需要32個IO來控制。
動態顯示的特點是將所有數碼管的段選線並聯在一起,由位選線控制是哪一位數碼管有效。選亮數碼管采用動態掃描顯示。所謂動態掃描顯示即輪流向各位數碼管送出字形碼和相應的位選,利用發光管的余輝和人眼視覺暫留作用,使人感覺各位數碼管同時都在顯示。動態顯示的亮度比靜態顯示要差一些,所以在選擇限流電阻時應略小於靜態顯示電路中的。
2. 74HC164
74HC164是高速硅門CMOS器件,與TTL器件的引腳兼容。74HC164是8位邊沿觸發式移位寄存器,串行輸入數據,然后並行輸出。數據通過兩個輸入端(DSA或DSB)之一串行輸入;任一輸入端可以用作高電平使能端,控制另一輸入端的數據輸入。兩個輸入端或者連接在一起,或者把不用的輸入端接高電平,一定不要懸空。時鍾(CP)每次由低變高時,數據右移一位,輸入到Q0,Q0是兩個數據輸入端(DSA或DSB)的邏輯與,它將上升時鍾沿之前保持一個建立時間的長度。
工作電壓范圍:2.0V-6.0V
3. 硬件設計
4. 軟件設計
4.1 smg.c
/* * smg.c * * Created on: 2020-4-9 * Author: Administrator */ #include "smg.h" unsigned char smgduan[16]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71};//0~F 數碼管段選數據 void SMG_Init(void) { EALLOW; SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1;// 開啟GPIO時鍾 //SMG數據控制端口配置 GpioCtrlRegs.GPBMUX2.bit.GPIO56=0; GpioCtrlRegs.GPBDIR.bit.GPIO56=1; GpioCtrlRegs.GPBPUD.bit.GPIO56=0; GpioCtrlRegs.GPBMUX2.bit.GPIO54=0; GpioCtrlRegs.GPBDIR.bit.GPIO54=1; GpioCtrlRegs.GPBPUD.bit.GPIO54=0; GpioCtrlRegs.GPCMUX1.bit.GPIO70=0; GpioCtrlRegs.GPCDIR.bit.GPIO70=1; GpioCtrlRegs.GPCPUD.bit.GPIO70=0; GpioCtrlRegs.GPCMUX1.bit.GPIO71=0; GpioCtrlRegs.GPCDIR.bit.GPIO71=1; GpioCtrlRegs.GPCPUD.bit.GPIO71=0; GpioCtrlRegs.GPCMUX1.bit.GPIO72=0; GpioCtrlRegs.GPCDIR.bit.GPIO72=1; GpioCtrlRegs.GPCPUD.bit.GPIO72=0; GpioCtrlRegs.GPCMUX1.bit.GPIO73=0; GpioCtrlRegs.GPCDIR.bit.GPIO73=1; GpioCtrlRegs.GPCPUD.bit.GPIO73=0; EDIS; GpioDataRegs.GPCCLEAR.bit.GPIO70=1; GpioDataRegs.GPCCLEAR.bit.GPIO71=1; GpioDataRegs.GPCCLEAR.bit.GPIO72=1; GpioDataRegs.GPCCLEAR.bit.GPIO73=1; } //74HC164數據發送函數 //dat:所要發送的數據 void HC164SendData(unsigned char dat) { char i=0; for(i=0;i<8;i++) { SPICLKA_SETL; if(dat&0x80) SPISIMOA_SETH; else SPISIMOA_SETL; SPICLKA_SETH; dat<<=1; } } //數碼管顯示整數函數 //num:整數 void SMG_DisplayInt(Uint16 num) { unsigned char buf[4]; unsigned char i=0; buf[0]=smgduan[num/1000];//千位 buf[1]=smgduan[num%1000/100];//百位 buf[2]=smgduan[num%100/10];//十位 buf[3]=smgduan[num%10];//個位 for(i=0;i<4;i++) { HC164SendData(buf[i]); switch(i) { case 0: SEG1_SETH;SEG2_SETL;SEG3_SETL;SEG4_SETL;break; case 1: SEG1_SETL;SEG2_SETH;SEG3_SETL;SEG4_SETL;break; case 2: SEG1_SETL;SEG2_SETL;SEG3_SETH;SEG4_SETL;break; case 3: SEG1_SETL;SEG2_SETL;SEG3_SETL;SEG4_SETH;break; } DELAY_US(5000); } } //數碼管顯示小數函數 //num:小數 //dotnum:小數點后面有效位數(最大3) void SMG_DisplayFloat(float num,unsigned char dotnum) { unsigned char buf[4]; unsigned char i; Uint16 value=0; if(dotnum==1) { value=num*10; buf[0]=smgduan[value/1000]; buf[1]=smgduan[value%1000/100]; buf[2]=smgduan[value%100/10]|0x80; buf[3]=smgduan[value%10]; } else if(dotnum==2) { value=num*100; buf[0]=smgduan[value/1000]; buf[1]=smgduan[value%1000/100]|0x80; buf[2]=smgduan[value%100/10]; buf[3]=smgduan[value%10]; } else if(dotnum==3) { value=num*1000; buf[0]=smgduan[value/1000]|0x80; buf[1]=smgduan[value%1000/100]; buf[2]=smgduan[value%100/10]; buf[3]=smgduan[value%10]; } for(i=0;i<4;i++) { HC164SendData(buf[i]); switch(i) { case 0: SEG1_SETH;SEG2_SETL;SEG3_SETL;SEG4_SETL;break; case 1: SEG1_SETL;SEG2_SETH;SEG3_SETL;SEG4_SETL;break; case 2: SEG1_SETL;SEG2_SETL;SEG3_SETH;SEG4_SETL;break; case 3: SEG1_SETL;SEG2_SETL;SEG3_SETL;SEG4_SETH;break; } DELAY_US(5000); } }
4.2 smg.h
/* * smg.h * * Created on: 2020-4-9 * Author: Administrator */ #ifndef SMG_H_ #define SMG_H_ #include "DSP2833x_Device.h" // DSP2833x 頭文件 #include "DSP2833x_Examples.h" // DSP2833x 例子相關頭文件 //數碼管位選信號線管腳定義 #define SEG1_SETH (GpioDataRegs.GPCSET.bit.GPIO70=1) #define SEG1_SETL (GpioDataRegs.GPCCLEAR.bit.GPIO70=1) #define SEG2_SETH (GpioDataRegs.GPCSET.bit.GPIO71=1) #define SEG2_SETL (GpioDataRegs.GPCCLEAR.bit.GPIO71=1) #define SEG3_SETH (GpioDataRegs.GPCSET.bit.GPIO72=1) #define SEG3_SETL (GpioDataRegs.GPCCLEAR.bit.GPIO72=1) #define SEG4_SETH (GpioDataRegs.GPCSET.bit.GPIO73=1) #define SEG4_SETL (GpioDataRegs.GPCCLEAR.bit.GPIO73=1) //74HC164時鍾管腳定義 #define SPICLKA_SETH (GpioDataRegs.GPBSET.bit.GPIO56=1) #define SPICLKA_SETL (GpioDataRegs.GPBCLEAR.bit.GPIO56=1) //74HC164數據管腳定義 #define SPISIMOA_SETH (GpioDataRegs.GPBSET.bit.GPIO54=1) #define SPISIMOA_SETL (GpioDataRegs.GPBCLEAR.bit.GPIO54=1) void SMG_Init(void); void SMG_DisplayInt(Uint16 num); void SMG_DisplayFloat(float num,unsigned char dotnum); #endif /* SMG_H_ */
4.3 main.c
10s計時。
/* * main.c * * Created on: 2020年4月8日 * Author: lenovo */ #include "DSP2833x_Device.h" // DSP2833x Headerfile Include File #include "DSP2833x_Examples.h" // DSP2833x Examples Include File #include "smg.h" /******************************************************************************* * 函 數 名 : main * 函數功能 : 主函數 * 輸 入 : 無 * 輸 出 : 無 *******************************************************************************/ void main() { InitSysCtrl(); SMG_Init(); float i=0.0; char n; while(1) { for(n=0;n<5;n++) { SMG_DisplayFloat(i,1); } if(i>9.9) i=0.0; else i+=0.1; } }
5. 效果