|
发表于 2023-10-31 23:38:40
|
显示全部楼层
第十集数码管的动态显示知识梳理
本集的知识是基于前一集的静态显示实现的。
静态显示以末尾的单个数码管为例,展示了如何利用数组点亮LED二极管,来顺次显示0-9数字。此处的数组表示的是显示0-90数字的段码
1、动态显示的原理
本开发板共八个数码管,每个结构都如上所示,此结构为共阳极,需要先为公共端设置低电平表示输出,再为需要点亮的LED二极管对应线路设置低电平进行点亮
数码管每次点亮需要设置端口,即控制哪个数码管的公共端设为低电平,一次只能设置一个。
同时,控制数码管内LED的引脚为P6,控制各数码管电平的引脚为P7
(1)所以,设置一个数码管点亮需要先设置P7对应端口信号确认使用的数码管,再设置P6端口信号确认显示的图像
P7=0xfe;P6=0xc0;则末尾数码管显示0
(2)动态显示,则是切换P7对应端口位置信号,切换P6显示信号电平
整理出各端口位置信号,即位码的具体数据,也可存入数组中使用
为避免系统出错,在切换过程中加入延时操作,依次为P7和P6配置不同位码与段码,并进行延时切换,便可实现动态显示
(3)延时操作
由于人眼视觉很难识别50hz以上的动态显示,只要我们将延时设置为每个切换1ms,一次总循环不超过20ms,人眼就会将顺次动态显示的数码管识别为同时显示的数据
2、练习:制作简易10s免单计数器(含两位小数显示)
(1)分析
本项目本质为秒表,默认设置每次显示切换为1ms,则每10ms数据+1
秒表需要小数点,由于各数码管小数点对应位置dp,位于二进制进制的第八位,则每个数字-0x80便得到对应数字带小数点的显示信号,将数据顺次存入数组。纯数字检索对应下标恰好+10即可得到带小数点数字
为方便显示,设置数组将每位数码管需要显示的信号对应下标存入,两位小数对应小数点属于第六个数码管即显示数组下标【5】,将其存入的数据+10得到带小数点形式
设置按键控制计数器的启动与暂停,对按键进行消抖与单次按键识别,设置状态量用于记录设备的启动与停止,每按下一次状态改变一次。同时,避免数据紊乱,按下停止后再启动,原始数据会直接清空,故初始化显示数组此时应该均为0
(2)实现(核心代码)
#define KEY1 P32 //定义一个按键 引脚选择P32
#define KEY2 P33 //定义一个按键 引脚选择P33
#define BEEP P54 //定义一个按键 引脚选择P54
#define SEG_Delay 1 //延时多少ms
#define MAIN_Fosc 24000000UL //定义主时钟
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
u8 SEG_Tab[20] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //0-9段码,0-9带小数点
u8 COM_Tab[8] = { 0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe }; //0-7的位码数组
u8 Show_Tab[8] = {3,0,0,0,0,10,0,0};
u32 TimCount = 0; //计数单位1ms
bit RUN_State = 0; //开始运行/结束运行
u8 num = 0;
void sys_init(); //函数声明
void delay_ms(u16 ms); //unsigned int
void SEG_Fre( void ) -----》定义函数,用于刷新显示,在人眼无法识别的时间内,将变化的数据显示到数码管
{
//位码选择第一位,段码选择0
P7 = COM_Tab[num]; //位码的选择
P6 = SEG_Tab[Show_Tab[num]];//需要显示的数字的内码 赋给 P6 NUM =0 -> Show_Tab[num]] = 1 -> p6 = oxF9
delay_ms(SEG_Delay);
num++;
if( num >7 )----》数码管只有8个
num = 0;
}
void main() //程序开始运行的入口
{
sys_init(); //USB功能+IO口初始化
usb_init(); //usb库初始化
EA = 1; //CPU开放中断,打开总中断。
while(1) //死循环
{
if( DeviceState != DEVSTATE_CONFIGURED ) //
continue;
if( bUsbOutReady )
{
usb_OUT_done();
}
Show_Tab[0] = 1; //末尾初始显示 1
Show_Tab[1] = 10; //倒数第二位显示 0.(带小数点)
Show_Tab[2] = 0; //选择 0
Show_Tab[3] = 0; //选择 0 ------》用于显示10.00定时数据
if( RUN_State==1 )----》状态为运行时数据才能累加
{
TimCount++;
Show_Tab[4] = TimCount/10000%10; -------》显示十位
Show_Tab[5] = TimCount/1000%10+10; -----》显示数据,同时显示小数点
Show_Tab[6] = TimCount/100%10; //显示秒表小数点后一位
Show_Tab[7] = TimCount/10%10; //取10位 ,timecount每+1位1ms,10次为10ms,显示秒表最低位
}
SEG_Fre();---》将计算结果显示
if( KEY1 ==0 )
{
delay_ms(10);
if( KEY1 ==0 )---》按键消抖
{
BEEP = 0;---》蜂鸣器提示
delay_ms(10);
BEEP = 1;
while( KEY1 ==0 )
{
SEG_Fre();
}
if( RUN_State==0 )
TimCount = 0;----》清零
RUN_State = !RUN_State;
}
}
3、拓展
(1)-的显示,其实就是只点亮g,即1011 1111=0xbf,在段码数组内再填入此数据,并初始化第三个和第六个数码管为此段码一直显示如此
(2)计算数据时,num运行1000次秒区域+1,num/1000%60;num运行60000次分区域+1,num/60000%60;num运行3600000次,时区域数据+1,num/3600000%24
(3)进行if判断,当s=30,m=0,h=0时,蜂鸣器P54端口低电平启动,延时3s再设为高电平关闭
|
|