2021年9月29日 星期三

环球今日报丨单片机入门之数码管定时闹钟(1)

时间:2023-06-27 20:55:50来源 : 爱瑞单片机

在之前的文章中我们学习了多位数码管时钟,既然有了时间,那我们为何不将他变为一个可以定时的闹钟呢,这样不就更加的方便我们了吗。这一章我们将开始对数码管定时闹钟的学习。


(相关资料图)

一、功能概述

既然我们已经可以实现多位数码管显示时间,那么我们在这个时间的基础上加上一个蜂鸣器,用按键的方式来调整我们所需要定时的时间,当时间到时进入外部中断来控制蜂鸣器,而按键同样也是外部中断的方法。外部中断的触发方法有电平触发和边沿触发两种方式,这两种方式都可以我们人为的去设定它。

二、显示原理

使用AT89C51单片机来对数码管进行时间的显示,外加蜂鸣器起到闹钟的作用。这一章节我们先了解按键外部中断的原理以及如何对按键控制时间的增减。

外部中断分为两个部分,中断初始化部分和外部中断服务函数。初始化部分是对中断进行设定,确定所选用的中断是哪一个,以及触发中断的条件,还有中断的优先级顺序。

//中断初始化void Interrupt_eint(){EX0 = 1;        //开启外部中断0IT0 = 1;                //设置外部中断0触发模式:下降沿触发EX1 = 1;        //开启外部中断1IT1 = 1;            //设置外部中断1触发模式EA = 1;             //开启总中断PX0 = 1;            //将外部中断的优先级提高}//外部0中断服务函数void int0() interrupt 0{uchar j = 0;for(j = 0;j<=3;++j)  {DisplayNum(j);delay_ms(1000);  }}

我们以代码的方式进行中断的解读,之后的学习我们也可以利用这两段代码来进行运用外部中断。

三、电路连接

这里我们选用P3.0、P3.1、P3.2作为我们三个按键控制的引脚

定义代码如下:

voidkey(){while(key2==0){input();break;}if(key1==0){delayms(200);if(key1==0)//{while(!key1){TR0=0;display(time[0]/10,time[0]%10,time[1]/10,time[1]%10,time[2]/10,time[2]%10);}TR0=1;}{TR0=!TR0;while(!key1)display(time[0]/10,time[0]%10,time[1]/10,time[1]%10,time[2]/10,time[2]%10);}//else if(TR0==0)TR0=1;}else if(key1==1){mode++;if(mode==2)mode=0;}}if(key3==0){delayms(200);if(key3==0){if(mode==0{time[0]=0;time[1]=0;time[2]=0;num=0;while(!key3)display(time[0]/10,time[0]%10,time[1]/10,time[1]%10,time[2]/10,time[2]%10);}else if(mode==1){time_clk[0]=0;time_clk[1]=0;time_clk[2]=0;while(!key3)display(time_clk[0]/10,time_clk[0]%10,time_clk[1]/10,time_clk[1]%10,time_clk[2]/10,time_clk[2]%10);}}else if(key3==1){buffer=1;/*P1=1;*/} } }

当我们在使用按键的时候还需要对按键进行扫描,按键扫描的目的是为了让设备知道我们的按键是按下了还是松开,避免产生错误。

按键扫描代码:

uchar keyscan()//矩阵键盘扫描函数{keyvalue=99;P3=0xfe;temp=P3;   temp=temp&0xf0;//判断是否还等于0xf0while(temp!=0xf0){delayms(5);temp=P3;temp=temp&0xf0;while(temp!=0xf0){temp=P3;switch(temp){case 0xee:{keyvalue=0;keydown=1;break;}case 0xde:{keyvalue=1;keydown=1;break;}case 0xbe:{keyvalue=2;keydown=1;break;}case 0x7e:{keyvalue=3;keydown=1;break;}}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}P3=0xfd;temp=P3;   temp=temp&0xf0;//判断是否还等于0xf0while(temp!=0xf0){delayms(5);temp=P3;temp=temp&0xf0;while(temp!=0xf0){temp=P3;switch(temp){case 0xed:{keyvalue=4;keydown=1;break;}case 0xdd:{keyvalue=5;keydown=1;break;}case 0xbd:{keyvalue=6;keydown=1;break;}case 0x7d:{keyvalue=7;keydown=1;break;}}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}P3=0xfb;temp=P3;   temp=temp&0xf0;//判断是否还等于0xf0while(temp!=0xf0){delayms(5);temp=P3;temp=temp&0xf0;while(temp!=0xf0){temp=P3;switch(temp){case 0xeb:{keyvalue=8;keydown=1;break;}case 0xdb:{keyvalue=9;keydown=1;break;}case 0xbb:{keyvalue=10;keydown=1;break;}case 0x7b:{keyvalue=11;keydown=1;break;}}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}P3=0xf7;temp=P3;   temp=temp&0xf0;//判断是否还等于0xf0while(temp!=0xf0){delayms(5);temp=P3;temp=temp&0xf0;while(temp!=0xf0){temp=P3;switch(temp){case 0xe7:{keyvalue=12;keydown=1;break;}case 0xd7:{keyvalue=13;keydown=1;break;}case 0xb7:{keyvalue=14;keydown=1;break;}case 0x77:{keyvalue=15;keydown=1;break;}}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}return keyvalue;}

同时中断中也需要对我们每一下按键的按下进行一定的描述,当按键被触发情况发生的时候,程序应该干嘛。

代码如下:

void T0_time() interrupt 1//中断函数{TH0=(65536-45872)/256;TL0=(65536-45872)%256;num++;if(num==20)//循环20次为一秒{num=0;time[2]++;//秒加一if(time[2]==60)//秒到60进位{time[2]=0;//秒清零分钟加一time[1]++;if(time[1]==60)//分钟到60进位{time[1]=0;//分钟清零小时加一time[0]++;  soundTime();//整点报时if(time[0]==24)//小时满24清零time[0]=0;}}if((time[0]==time_clk[0])&&(time[1]==time_clk[1])&&(time[2]==time_clk[2])){buffer=0;/*P1=0;*/}}}

蜂鸣器也是在中断中实现的,当到达我们所设定的时间后,对它的电平进行改变就可以实现发声了。

代码如下:

voidsoundTime(){buffer=0;delayms(10);buffer=1;}

四、总结

本章我们先对按键以及外部中断进行学习,外部中断的两种触发方式,以及对中断服务程序的学习,这样对于将来设计我们的数码管闹钟的时候能提供更加广阔的思路,不在局限于用一个循环或者一个主函数去完成一个设计,毕竟一个设计都是分为一步一步去完成的,每个模块相互结合也能让我们的设计更加的富有逻辑。

关键词:

(责任编辑:黄俊飞)

推荐内容

Back to Top