您的位置:控制工程论坛网论坛 » 自动化软件 » [程序源码]小小电子闹钟(图+程序)

mitang

mitang   |   当前状态:离线

总积分:116  2025年可用积分:0

注册时间: 2008-01-18

最后登录时间: 2008-01-23

空间 发短消息加为好友

[程序源码]小小电子闹钟(图+程序)

mitang  发表于 2008/1/19 10:56:05      1072 查看 1 回复  [上一主题]  [下一主题]

手机阅读







点击看大图

一片20引脚的单片机AT89C2051为电子钟主体,其显示数据从P1口分时输出,P3.0~3.3则输出对应的位选通信号。由于LED数码管点亮时耗电较大,故使用了四只PNP型晶体管VT1~VT4进行放大。本来笔者还有一种更简的设计方案(见图2),可省去VT1~VT4及R1~R4八个元件,但这种设计由于单片机输出口的灌入电流有限(约20mA),数码管亮度较暗而不向读者介绍,除非你采用了高亮度的发光数码管。


点击看大图

P3.4、P3.5、3.7外接了三个轻触式按键,这里我们分别命名为:模式设定键set(P3.4)、时调整键hour(P3.5)、分调整键min(P3.7)。C1、R13组成上电复位电路。VT5及蜂鸣器Bz为闹时讯响电路。三端稳压器7805输出的5V电压供整个系统工作。此电子钟可与任何9~20V/100mA的交直流电源适配器配合工作,适应性强。


电子钟功能


1.走时:通过模式设定键set选择为走时,U1、U2显示小时,U3、U4显示分。U2的小数点为秒点,每秒闪烁一次。


2.走时调整:通过模式设定键set选择为走时调整,按下hour键对U1、U2的走时“时”显示进行调整(每0.2秒递加1)。按下min键对U3、U4的走时“分”显示进行调整(每0.2秒递加1)。


3.闹时调整:通过模式设定键set选择为闹时调整,按下hour键对U1、U2的闹时“时”显示进行调整(每0.2秒递加1)。按下min键对U3、U4的闹时“分”显示进行调整(每0.2秒递加1)。


4.闹时启/停设定:通过模式设定键set选择为闹时启/停设定,按下min键U3的小数点点亮,闹时功能启动;按下hour键U3的小数点熄灭,闹时功能关停。


由于电路设计得极其简单,因此丰富的功能只能由软件完成,这里软件设计成为了关键。下面介绍软件设计要点。


图3为主程序状态流程。


图片点击可在新窗口打开查看

 


图3


 


运行时建立的主要状态标志如下:


flag—掉电标志。掉电后,flag内为一随机数;重新设定时间后flag内写入标志数55H。


set—工作模式设定标志。


hour—走时“时”单元。


min—走时“分”单元。


sec—走时“秒”单元。


deda—走时5mS计数单元


t_hour—闹时“时”单元。


t_min—闹时“分”单元。


d_05s—0.5秒位标志。每秒钟的前0.5秒置1,后0.5秒置0,以使秒点闪烁。


o_f—闹时启/停位标志。闹时启动置1,闹时关停置0。


另外将定时器T0设定为5mS的定时中断。这里晶振频率为12MHz,因此5mS的初值为-5000,但实际上程序还要作其它运算,使得时间偏长,经调整为-4800后试验刚好。计时单元deda每次中断均加1。走时函数判断deda>=200时即令秒单元sec加1。同理秒单元sec满60后令分单元min加1。分单元min满60后令时单元hour加1。时单元hour满24后清0。


上电后,首先进行初始化,对各状态标志、输入输出口及定时器T0进行初始化工作,以适应后面程序的要求。


随后程序判断有无set键按下,如按下,则set键值从0起加1。set键值只能从0加到3,然后又回到0。


接下来,根据键值进行散转。若set=0,运行走时程序;若set=1,进入调整闹时时间程序;若set=2,进入调整走时时间程序;若set=3,显示已调好的闹时时间,同时进入启/停闹时程序。


散转完后,进行判断掉电标志flag是否等于55H。若不等,说明刚开机上电或运行过程中掉过电,这时四个数码管以1Hz的频率闪烁四个8字,提示时间不准;若相等,说明未掉电,RAM区内容未变化,时间准确。


再下来程序又转回到初始化之后进行循环运行。


由于使用了四只数码管密集排列,因此只能采用双面印刷板设计,图4、5分别为正面(元件面)、反面的印板图。尺寸3000milx4000mil(7.62cmx10.16cm)。图6为计算机输出的三维仿真印制板。


图片点击可在新窗口打开查看

图4


 


图片点击可在新窗口打开查看

图5


 


图片点击可在新窗口打开查看

图6



元件选用



为了走时准确,晶振X最好选用温漂小的。四个数码管U1~U4可选用发绿光的,这样光泽较柔和。蜂鸣器Bz要购买绕线型的电动式蜂鸣器(市场上有一种加电压即工作的蜂鸣器这里不适用),因驱动信号为脉冲信号。其它元件一般无特殊要求。



使用方法



上电后,四个LED数码管闪烁四个8字。



按一下set键,闪烁现象消失(此时set=1),U1的小数点亮,说明此刻可以调整闹时时间。按下hour键,U1、U2作加法;按下min键,U3、U4作加法。这些调整好的数据被同时送入RAM区的闹时记忆“时”单元t_hour和闹时记忆“分”单元t_min。



再按一下set键,set=2,U2的小数点亮,此刻可以调整走时时间。按下hour键,U1、U2作加法;按下min键,U3、U4作加法。这些调整好的数据也被同步送入RAM区的“时”记忆单元hour和“分”记忆单元min。



再按一下set键,set=3,显示刚才调整的闹时时间,此刻可以选择启动/关停闹时。按下min键,o_f位标志置1,U3的小数点亮,闹时启动;按下hour键,o_f位标志置0,U3的小数点灭,闹时关闭。



若再按一下set键,set=0,电路进入走时状态,U1、U2显示小时,U3、U4显示分。U2的小数点作秒点闪烁。



在闹时启动的情况下,走时到达设定闹时,则蜂鸣器Bz鸣响一分钟进行提醒。



附:用C51编写的源程序清单(已由实验板运行通过)



#i nclude <reg51.h>                        /*°üº¬Æ÷¼þÅäÖÃÎļþ*/
#i 
nclude <stdio.h>

#i nclude <stdlib.h>

sbit  P1_0=P1^0; 
sbit  P1_1=P1^1; 
sbit  P1_2=P1^2; 
sbit  
P1_3=P1^3;  
sbit  P1_4=P1^5; 
sbit  P1_5=P1^5; 
sbit  P1_6=P1^6;  

sbit  P1_7=P1^7; 

sbit  P2_0=P1^0; 
sbit  P2_1=P1^1; 
sbit  P2_2=P1^2; 
sbit  
P2_3=P1^3;  
sbit  P2_4=P1^5; 
sbit  P2_5=P1^5; 
sbit  P2_6=P1^6;  

sbit  P2_7=P1^7; 

sbit  P3_0=P1^0; 
sbit  P3_1=P1^1; 
sbit  P3_2=P1^2; 
sbit  
P3_3=P1^3;  
sbit  P3_4=P1^5; 
sbit  P3_5=P1^5; 
sbit  P3_6=P1^6;  

sbit  P3_7=P1^7;  

#define uchar unsigned char


#define uint unsigned int


char DATA_7SEG[10]={0xC0,0xF9,0xA4,0xB0,0x99,


                    
0x92,0x82,0xF8,0x80,0x90,};/*0~9µÄÊýÂë¹Ü¶ÎÂë*/


uchar hour=0,min=0,sec=0;                /*ʱ¡¢·Ö¡¢Ãëµ¥ÔªÇåÁã*/


uchar deda=0;                                  /*5mS¼ÆÊýµ¥ÔªÇåÁã*/ 


uchar t_hour=0,t_min=0;                   /*ÄÖʱʱ¡¢·Öµ¥ÔªÇåÁã*/


bit d_05s=0;                             /*0.5Ãë±êÖ¾*/


bit o_f=0;                                         
/*ÄÖʱÆô/Í£±êÖ¾*/


uchar set=0;                                      
/*ģʽÉ趨±êÖ¾*/


uchar m=0;


uchar flag=0;                                     /*RAMµôµç±êÖ¾*/


void delay(uint k);                              /*ÑÓʱ×Óº¯Êý*/


void conv();                                       
/*×ßʱµ¥Ôª×ª»»*/


void p_out();                                      
/*ÅбðÄÖʱµ½·ñ×Óº¯Êý*/


void dirve();                                       
/*×ßʱʱ¼äÊä³öÇý¶¯×Óº¯Êý*/


void t_dirve();                                    
/*ÄÖʱʱ¼äÊä³öÇý¶¯×Óº¯Êý*/


 


 


/*ÄÖʱÆô/Í£×Óº¯Êý*/


void time1_of()                                 


{uchar m;


       if(P3_7==0)delay(1);


       if(P3_7==0)o_f=1;


       for(m=0;m<30;m++)


              {


              t_dirve();


              P1=DATA_7SEG[t_min/10];P3=0xfd;delay(1);


              if(P3_1==0){if(o_f==1)P1_7=0;}else P1_7=1;


              delay(1);


              }


             


       if(P3_5==0)delay(1);


       if(P3_5==0)    o_f=0;


       for(m=0;m<30;m++)


              {


              t_dirve();


              P1=DATA_7SEG[t_min/10];P3=0xfd;delay(1);


              if(P3_1==0){if(o_f==1)P1_7=0;else P1_7=1;}


              delay(1);


              }


}


 


/*×ßʱº¯Êý*/


void time()


{


conv();                                              
/*×ßʱµ¥Ôª×ª»»*/


dirve();                                              
/*×ßʱʱ¼äÊä³öÇý¶¯×Óº¯Êý*/


p_out();                                             
/*ÅбðÄÖʱµ½·ñ×Óº¯Êý*/


}


 


 


/*¶¨Ê±Æ÷T0  5mS³õʼ»¯*/


void init_timer()


{


TMOD=0x01;


TH0=-(4800/256);


TL0=-(4800%256);


IE=0x82;


TR0=1;


}


 


/*ɨÃè°´¼ü×Óº¯Êý*/


void scan_key()


{


delay(1);


if(P3_4==0)set++;


if(set>=4)set=0;


if(set==1)flag=0x55;


F0:if(P3_4==0)goto F0;                      
/*°´¼üδÊÍ·Å£¬Ôڴ˵Ⱥò*/


}


 


 


/*ÑÓʱ×Óº¯Êý*/


void delay(uint k)


{


uint i,j;


for(i=0;i<k;i++)

 for(j=0;j<121;j++);

 

}


 


/*5mS¶¨Ê±ÖжϷþÎñ×Óº¯Êý*/


void zd(void) interrupt 1


{


TH0=-(4800/256);


TL0=-(4800%256);


deda++;


}


 


/*µ÷Õû×ßʱʱ¼ä*/


void time_adj()


{uchar m;


       if(P3_5==0)delay(1);


       if(P3_5==0)hour++;


       if(hour==24)hour=0;


       for(m=0;m<30;m++)


              {


              dirve();


              if(P3_2==0)P1_7=0;


              else P1_7=1;


              delay(1);


              }


             


       if(P3_7==0)delay(1);


       if(P3_7==0)min++;


       if(min==60)min=0;


       for(m=0;m<30;m++)


              {


              dirve();


                     if(P3_2==0)P1_7=0;


              else P1_7=1;


              delay(1);


              }


}


 


 


/*µ÷ÕûÄÖʱʱ¼ä*/


void time1_adj()


{uchar m;


       if(P3_5==0)delay(1);


       if(P3_5==0)t_hour++;


       if(t_hour==24)t_hour=0;


       for(m=0;m<30;m++)


              {


              t_dirve();


              }


      


       if(P3_7==0)delay(1);


       if(P3_7==0)t_min++;


       if(t_min==60)t_min=0;


       for(m=0;m<30;m++)


              {


              t_dirve();


              }


}    


 


/*ʱ¡¢·Ö¡¢Ãëµ¥Ôª¼°×ßʱµ¥Ôª×ª»»*/


void conv()


{


if(deda<=100)d_05s=0;


       else d_05s=1;


if(deda>=200){sec++;deda=0;}


if(sec==60){min++;sec=0;}


if(min==60){hour++;min=0;}


if(hour==24){hour=0;}


}


 


/*×ßʱʱ¼äÊä³öÇý¶¯×Óº¯Êý*/


void dirve()


{


P1=DATA_7SEG[hour/10];P3=0xf7;delay(1);


P1=DATA_7SEG[hour%10];P3=0xfb;delay(1);


if(d_05s==1){if(P3_2==0)P1_7=0;else P1_7=1;}


delay(1);


P1=DATA_7SEG[min/10];P3=0xfd;delay(1);


if(o_f==1){if(P3_1==0)P1_7=0;else P1_7=1;delay(1);}


P1=DATA_7SEG[min%10];P3=0xfe;delay(1);


}


 


/*ÄÖʱʱ¼äÊä³öÇý¶¯×Óº¯Êý*/


void t_dirve()


{


P1=DATA_7SEG[t_hour/10];P3=0xf7;delay(1);


if(P3_3==0)P1_7=0;else P1_7=1;


delay(1);


P1=DATA_7SEG[t_hour%10];P3=0xfb;delay(1);


P1=DATA_7SEG[t_min/10];P3=0xfd;delay(1);


P1=DATA_7SEG[t_min%10];P3=0xfe;delay(1);


}


 


 


/*ÅбðÄÖʱµ½·ñ×Óº¯Êý*/


void p_out()


{


if(o_f==1){


       if(t_hour==hour){if(t_min==min)


              if(P3_0==0){P1_7=0;delay(1);}


              else P1_7=1;


                                   }


              }


}


 


/*Ö÷º¯Êý*/


void main()


{


       init_timer();                       /*¶¨Ê±Æ÷T0³õʼ»¯*/


       while(1)                                     /*ÎÞÏÞÑ­»·*/


       {


       if(P3_4==0)scan_key();               
/*Óа´¼ü£¬µ÷Óð´¼üɨÃè×Óº¯Êý*/


switch(set)                                        
/*¸ù¾Ýset¼üֵɢת*/


{


case 0:time();break;                                   
/*×ßʱʱ¼ä³ÌÐò*/


case 1:time1_adj();break;                     /*ÄÖʱʱ¼äµ÷Õû*/


case 2:time_adj();break;                      /*×ßʱʱ¼äµ÷Õû*/


case 3:time1_of();break;                      /*Æô/Í£ÄÖʱ*/


default:break;                                     /*ÆäËüÍ˳ö*/


}


       if(flag!=0x55)                             
/*Åжϵôµç±êÖ¾*/


       {for(m=0;m<100;m++)               /*µãÁÁËĸö8×Ö400mS*/


              {


              P1=0x80;P3=0xf7;delay(1);


              P1=0x80;P3=0xfb;delay(1);


              P1=0x80;P3=0xfd;delay(1);


              P1=0x80;P3=0xfe;delay(1);


              }


             


              P1=0xff;P3=0xff;delay(400); /*ϨÃðËĸö8×Ö400mS*/


       }


       }

1楼 0 0 回复
总共 , 当前 /