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; } }