功能效果:1.时分秒的动态显示。2.用三个按键实现时分秒的修改,调节的数字闪烁提示。
一、仿真图:
二、源码
版本一:
#include <reg52.h>#define u8 unsigned char#define u16 unsigned intu8 WeiMa[6]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF};u8 DuanMa[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//函数声明void Delay_ms(u16 xms);void ShuMaGuan(u8 wei,u8 duan);void Display_Timer(u8 hour,u8 min,u8 sec);u8 Key_Scan();//引脚定义sbit SW1=P3^2;sbit SW2=P3^3;sbit SW3=P3^4;//函数功能:定时器初始化void Time0init(){TMOD|=0x01;//设置定时器模式TF0=0;//清除TF0标志TH0=(65536-50000)/256; //设置定时初值TL0=(65536-50000)%256;//设置定时初值TR0=1;//定时器0允许计时ET0=1;//中断允许EA=1;//CPU中断允许位打开}u8 Hour,Min,Sec;//全局变量,时分秒u8 mode;//全局变量:状态切换,0:时钟显示,1:调节时;2:调节分;3:调节秒bit flash_tip=1;//数码管闪烁标志,为0时数码管熄灭,为一时数码管显示//主函数void main(){u8 keynum;Time0init();//定时器Hour=0;Min=0;Sec=0;mode=0;//初始化while(1){keynum=Key_Scan();//按键返回值if(keynum) //非0表示有按键按下{switch(keynum) //判断是哪个按键按下,按键一调节模式,按键2自加,按键3自减{case 1:if(++mode>=4) mode=0;break; //++mode为先自增再判断是否大于4case 2:if(mode==1) {Hour++;if(Hour>=24)//溢出判断{Hour=0;}}if(mode==2) {Min++;if(Min>=60)//溢出判断{Min=0;}}if(mode==3) {Sec++;if(Sec>=60)//溢出判断{Sec=0;}}break;case 3:if(mode==1) {Hour--;if(Hour==255)//溢出判断{Hour=23;}}if(mode==2) {Min--;if(Min==255)//溢出判断{Min=59;}}if(mode==3) {Sec--;if(Sec==255)//溢出判断{Sec=59;}}break;default:break;}}Display_Timer(Hour,Min,Sec);//数码管显示}}//软件延时函数//xms为延时多少毫秒void Delay_ms(u16 xms){unsigned char i, j;while(xms--){i = 2;j = 135;do{while (--j);} while (--i);}}//静态显示一位//参数:wei控制位选duan控制段选,表示要显示的一个数字void ShuMaGuan(u8 wei,u8 duan){P1=WeiMa[wei]; //位选P2=DuanMa[duan]; //段选Delay_ms(1); //间隔一段时间扫描P1=0xFF; P2=0xFF; //消隐}//函数功能:数码管动态显示//flash_tip为数码管闪烁标志,为0时数码管熄灭,为一时数码管显示//flash_tip每4.5秒进行取反void Display_Timer(u8 hour,u8 min,u8 sec){if(mode!=1 || flash_tip==1) //mode=1时,左边的条件一直为假,当flash_tip=1时,或运算为真,进入if,数码管显示{ShuMaGuan(5,hour/10);ShuMaGuan(4,hour%10);}else P1=0xFF;if(mode!=2 || flash_tip==1)//mode=2时,左边的条件一直为假,当flash_tip=1时,或运算为真,进入if,数码管显示{ShuMaGuan(3,min/10);ShuMaGuan(2,min%10);}else P1=0xFF; if(mode!=3 || flash_tip==1)//mode=3时,左边的条件一直为假,当flash_tip=1时,或运算为真,进入if,数码管显示{ShuMaGuan(1,sec/10);ShuMaGuan(0,sec%10);}else P1=0xFF; }//独立按键检测u8 Key_Scan(){static u8 key_up=1; //按键按松开标志if(key_up && (SW1==0 || SW2==0 || SW3==0)){Delay_ms(10); //去抖动key_up=0; //松手标志为0,那么下次再检测,if结果为0,则不会进入这里的语句if(SW1==0) return 1;if(SW2==0) return 2;if(SW3==0) return 3;}else if(SW1 == 1 && SW2 == 1 && SW3 == 1) key_up=1; //松手标志return 0; // 无按键按下}//定时器中断服务函数void Time0() interrupt 1{static unsigned char flag_1,flag_2; TH0=(65536-50000)/256; TL0=(65536-50000)%256;//重新赋初值if(mode==0)flag_1++; //mode为0时,数码管正常显示else flag_2++; if(flag_1==20 && mode==0) //每秒执行一次{flag_1=0;Sec++;{if(Sec>=60){Sec=0;Min++;if(Min>=60){Min=0;Hour++;if(Hour>=24){Hour=0;}}}}}if(flag_2==9){flash_tip=~flash_tip;//每4.5秒进行取反flag_2=0;}}
版本二:
#include <reg52.h>#define u8 unsigned char#define u16 unsigned intu8 WeiMa[6]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF};u8 DuanMa[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//函数声明void Delay_ms(u16 xms);void ShuMaGuan(u8 wei,u8 duan);void Display_Timer(u8 hour,u8 min,u8 sec);u8 Key_Scan();//引脚定义sbit SW1=P3^2;sbit SW2=P3^3;sbit SW3=P3^4;//函数功能:定时器初始化void Time0init(){TMOD|=0x01;//设置定时器模式TF0=0;//清除TF0标志TH0=(65536-50000)/256; //设置定时初值TL0=(65536-50000)%256;//设置定时初值TR0=1;//定时器0允许计时ET0=1;//中断允许EA=1;//CPU中断允许位打开}u8 Hour,Min,Sec;//全局变量,时分秒u8 mode;//全局变量:状态切换,0:时钟显示,1:调节时;2:调节分;3:调节秒bit flash_tip=1;//数码管闪烁标志,为0时数码管熄灭,为一时数码管显示//主函数void main(){u8 keynum;Time0init();//定时器Hour=0;Min=0;Sec=0;mode=0;//初始化while(1){keynum=Key_Scan();//按键返回值if(keynum) //非0表示有按键按下{switch(keynum) //判断是哪个按键按下,按键一调节模式,按键2自加,按键3自减{case 1:if(++mode>=4) mode=0;break; //++mode为先自增再判断是否大于4case 2:if(mode==1) if(++Hour>=24) Hour=0;//++mode为先自增再判断是否大于4if(mode==2) if(++Min>=60) Min=0;//++Min先自增再判断是否大于60if(mode==3) if(++Sec>=60) Sec=0;//++Sec先自增再判断是否大于60break;case 3:if(mode==1)if(--Hour==255) Hour=23;//--Hour先自增再判断是否溢出if(mode==2) if(--Min==255) Min=59;//--Min先自增再判断是否大溢出if(mode==3) if(--Sec==255) Sec=59;//--Sec先自增再判断是否大溢出break;default:break;}}Display_Timer(Hour,Min,Sec);}}//软件延时函数//xms为延时多少毫秒void Delay_ms(u16 xms){unsigned char i, j;while(xms--){i = 2;j = 135;do{while (--j);} while (--i);}}//静态显示一位//参数:wei控制位选duan控制段选,表示要显示的一个数字void ShuMaGuan(u8 wei,u8 duan){P1=WeiMa[wei]; //位选P2=DuanMa[duan]; //段选Delay_ms(1); //间隔一段时间扫描P1=0xFF; P2=0xFF; //消隐}//函数功能:数码管动态显示//flash_tip为数码管闪烁标志,为0时数码管熄灭,为一时数码管显示//flash_tip每4.5秒进行取反void Display_Timer(u8 hour,u8 min,u8 sec){if(mode!=1 || flash_tip==1) //mode=1时,左边的条件一直为假,当flash_tip=1时,或运算为真,进入if,数码管显示{ShuMaGuan(5,hour/10);ShuMaGuan(4,hour%10);}else P1=0xFF;if(mode!=2 || flash_tip==1)//mode=2时,左边的条件一直为假,当flash_tip=1时,或运算为真,进入if,数码管显示{ShuMaGuan(3,min/10);ShuMaGuan(2,min%10);}else P1=0xFF; if(mode!=3 || flash_tip==1)//mode=3时,左边的条件一直为假,当flash_tip=1时,或运算为真,进入if,数码管显示{ShuMaGuan(1,sec/10);ShuMaGuan(0,sec%10);}else P1=0xFF; }//独立按键检测u8 Key_Scan(){static u8 key_up=1; //按键按松开标志if(key_up && (SW1==0 || SW2==0 || SW3==0)){Delay_ms(10); //去抖动key_up=0; //松手标志为0,那么下次再检测,if结果为0,则不会进入这里的语句if(SW1==0) return 1;if(SW2==0) return 2;if(SW3==0) return 3;}else if(SW1 == 1 && SW2 == 1 && SW3 == 1) key_up=1; //松手标志return 0; // 无按键按下}//定时器中断服务函数void Time0() interrupt 1{static unsigned char flag_1,flag_2; TH0=(65536-50000)/256; TL0=(65536-50000)%256;//重新赋初值if(mode==0)flag_1++; //mode为0时,数码管正常显示else flag_2++; if(flag_1==20 && mode==0) //每秒执行一次{flag_1=0;if(++Sec>=60) //++Sec先自增再判断是否大于60 {Sec=0;if(++Min>=60)//++Min先自增再判断是否大于60{Min=0;if(++Hour>=24)//++Hour先自增再判断是否大于60{Hour=0;}}}}if(flag_2==9){flash_tip=~flash_tip;//每4.5秒进行取反flag_2=0;}}
如果觉得《51单片机实验三:数码管显示时钟 按键调节时间时闪烁提示》对你有帮助,请点赞、收藏,并留下你的观点哦!