⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 digital_clock.c

📁 基于AT89S52的自动报时数字闹钟. 该数字钟具有整点报时和闹钟功能
💻 C
字号:
#include <absacc.h>
#include <reg51.h>
#include<intrins.h>

#define uchar unsigned char


#define LED1 XBYTE [0xA000]   //数码管地址
#define LED2 XBYTE [0xA001]
#define LED3 XBYTE [0xA002]
#define LED4 XBYTE [0xA003]
#define LED5 XBYTE [0xA004]
#define LED6 XBYTE [0xA005]
#define LED7 XBYTE [0xA006]
#define LED8 XBYTE [0xA007]

#define KEY XBYTE [0xA100]  //键盘地址


/*扫描键盘使用的变量 */
sbit first_row = P1^4;//键盘第一行控制
sbit second_row = P1^3;//键盘第二行控制
bit first_getkey = 0,control_readkey = 0;//读键盘过程中的标志位
bit getkey = 0;//获得有效键值标志位 等于1时代表得到一个有效键值
bit keyon = 0;//防止按键冲突标志位
uchar keynum = 0;//获得的有效按键值寄存器
uchar M_key;
bit set=0;//set键功能切换标志位
bit setalarm=0;//setalarm键功能切换标志位
unsigned char i,j;//循环控制所用


/*数码管显示使用的变量和常量*/
bit pm=0;//上下午标志位
int count;
int t;
char hour=0,min=0,sec=0;//按秒计时显示所用
char hour2=0,min2=0,sec2=0;//使用set,setalarm键时显示所用
char houra=11,mina=59,seca=0;//保存用户设置的闹钟值所用
uchar lednum = 0;  //数码管显示位控制寄存器
uchar led[8] = {0,0,0,0,0,0,0,0};  //数码管显示内容寄存器
uchar code segtab[18] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0x8c,0xff}; //七段码段码表
                      // "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "P" ,"black" 
uchar code segtab2[10] = { 0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10};//八段
                        // "0.", "1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.", "9."


void leddisp(void); //数码管显示函数
void readkey(void); //读键盘函数
void key_deal(void);//处理键盘动作函数
void change_led(void);//跟踪时间的显示控制函数
void change_led2(void);//跟踪按键的显示控制函数
void delay(int t);//延时tms函数
void flash(void);//整点闪烁函数




void intT0() interrupt 1 //T0 定时中断处理函数
{
	TH0 = -2720/256;  //定时器中断时间间隔 4ms
 	TL0 = -2720%256;
	
 	leddisp();  //每次定时中断显示更新一次
	

 	if(control_readkey == 1)  //每两次定时中断扫描一次键盘
   	{	   
	   readkey();
   	}
 	control_readkey = !control_readkey;
}


void intT1() interrupt 3 //T1 定时中断处理函数
{
	TH1=0xF8;
	TL1=0x30;
    count++;
	
	if(count >= 1000)
	{
       if(set==0&&setalarm==0)
	     change_led();
	   else
	     change_led2();
	   count=0;
		
	 }
}



void main(void)
{

	TMOD = 0x11;    
 	TH0 = -2720/256;  //定时器0中断时间间隔 4ms
 	TL0 = -2720%256;
	TCON = 0x50;
    TH1=0xF8;         //定时器中断时间间隔  1ms
	TL1=0x30;    
 	ET0 = 1;
	ET1=1;
 	EA = 1;

	for(i=0;i<=5;i++)//数码管显示初始化
	{
	   led[i]=0;
	 }
    led[6]=10;
	led[7]=17;


	
	while(1)
	{
 		if (min==0&&sec<=5)
	        flash();

        if (sec<=5&&min==mina&&hour==houra)
		    flash();

	    if(getkey==1)  //判断是否获得有效按键
		    key_deal();
  
    }
}

/***************************************************
			键盘扫描函数
原型:   void readkey(void);
功能:  当获得有效按键时,令getkey=1,keynum为按键值

****************************************************/
void readkey(void)
{
	uchar M_key = 0;  

 	first_row = 0;
 	second_row = 0;
 	M_key = KEY;
 	if(M_key != 0xff)  //如果有连续两次按键按下,认为有有效按键按下。消除按键抖动
   	{
    		if(first_getkey == 0)
     		{
   			first_getkey = 1;	
   		    }
  		else    //当有有效按键按下时,进一步识别是哪一个按键
   		{
   			if(keyon == 0)  //防止按键冲突,当还有未释放的按键时不对其它按键动作响应   
   			{
      				first_row = 0;         //扫描第一行按键
      				second_row = 1;
         			M_key = KEY;
         			if(M_key != 0xff)
           			{
            				switch(M_key) 
            				{	
            	 				case 0xfe:
                   					keynum = 0x00;
               						break;
            					case 0xfd:
                       				keynum = 0x01;
                 					break;
               					case 0xfb:
                 		    		keynum = 0x02;
                 					break;
               					case 0xf7:
                      				keynum = 0x03;
                 					break;
               					case 0xef:
                 					keynum = 0x04;
                 					break;
               					case 0xdf:
                 					keynum = 0x05;
                					break;
               					case 0xbf:
                					keynum = 0x06;
                 					break;
              	 				case 0x7f:
                 					keynum = 0x07;
                 					break;
              				}
           			}
         			else
           			{
            				second_row = 0;     //扫描第二行按键
            				first_row = 1;
            				M_key = KEY;
            				switch(M_key)
              				{
               					case 0xfe:
                					keynum = 0x08;
                					break;
               					case 0xfd:
                 					keynum = 0x09;
                 					break;
               					case 0xfb:
                 					keynum = 0x0a;
                 					break;
               					case 0xf7:
                 					keynum = 0x0b;
                 					break;
               					case 0xef:
                 					keynum = 0x0c;
                 					break;
               					case 0xdf:
                 					keynum = 0x0d;
                 					break;
               					case 0xbf:
                 					keynum = 0x0e;
                 					break;
               					case 0x7f:
                 					keynum = 0x0f;
                 					break;
              				}
           			}
				getkey = 1; //获得有效按键数值
                keyon = 1;  //防止按键冲突,当获得有效按键时将其置1
        		} 
     		} 
   	}
 	else
   	{
    		first_getkey = 0;
    		keyon = 0;     //防止按键冲突,当所有的按键都释放时将其清0
    	}
}

/***************************************************
			数码管显示函数
原型:   void leddisp(void);
功能:  每次调用轮流显示一位数码管

****************************************************/
void leddisp(void)
{
	switch(lednum)  //选择需要显示的数码位
 	{
  		case 0:
    		LED1 = segtab[led[0]];
     		break;
  		case 1:
     		LED2 = segtab[led[1]];
     		break;
 		case 2:
     		LED3 = segtab2[led[2]];
     		break;
 		case 3:
     		LED4 = segtab[led[3]];
     		break;
 		case 4:
     		LED5 = segtab2[led[4]];
     		break;
 		case 5:
     		LED6 = segtab[led[5]];
     		break;
 		case 6:
     		LED7 = segtab[led[6]];
     		break;
		case 7:
     		LED8 = segtab[led[7]];
     		break;
  	}

	if(lednum == 0) //更新需要现实的数码位
 	{
		lednum = 7;
 	}
 	else
 	{
		lednum = lednum-1;
	}
}  




/***************************************************
			控制显示函数
函数1:  void change_led(void);
函数2:  void change_led2(void);
功能:  改变LED管应显示的内容,为显示做准备

****************************************************/
void change_led(void)//跟踪当前时间
{
   
   sec++;
   if(sec>=60)
     {
	    min++;
		sec=0;
		if (min>=60)
		   {
		      hour++;
			  min=0;
			  if(hour>=12)
			     {
				   pm=!pm;
				   hour=0;
				  }
			 }
		}
	

	 led[0]=sec%10;
	 led[1]=sec/10;
     led[2]=min%10;
     led[3]=min/10;
     led[4]=hour%10;
     led[5]=hour/10;
	if(pm==0)
	 led[6]=10;
	else
	 led[6]=16;
		  
}



void change_led2(void)//跟踪按键
{
 sec++;
   if(sec>=60)
     {
	    min++;
		sec=0;
		if (min>=60)
		   {
		      hour++;
			  min=0;
			  if(hour>=12)
			     {
				   pm=!pm;
				   hour=0;
				  }
			 }
		}
   
     led[0]=0;
	 led[1]=0;
     led[2]=min2%10;
     led[3]=min2/10;
     led[4]=hour2%10;
     led[5]=hour2/10;
   if(pm==0)
	 led[6]=10;
	else
	 led[6]=16;
}


/***************************************************
			延时函数
原型:  delay(int t);
功能:  延时tms函数

****************************************************/
void delay(int t)
{
  while(t--)
   {
      for(i=0;i<200;i++);
	}
}

/***************************************************
			整点闪烁函数
原型:  void flash(void);
功能:  led[7]以2Hz频率闪烁

****************************************************/
void flash(void)
{
   led[7]=8;
   delay(330);
   led[7]=17;
   delay(330);
}




/***************************************************
		  处理键盘动作函数
原型:  void key_deal(void);
功能:  处理键盘动作

****************************************************/
void key_deal(void)
{
     		   getkey=0;
				
  			   switch(keynum)
				{
                  case 0x03://若按下设置闹钟键
				       if(setalarm==0)
					      {
						     setalarm=1;
                             sec2=sec;
							 min2=min;
							 hour2=hour;
						   }
					    else if (setalarm==1)
							{
                              seca=sec2;
							  mina=min2;
							  houra=hour2;
							  setalarm=0;
							 }
				  break;



				  case 0x04://若按下设置时间键
                       if(set==0)
						   { set=1;
						     sec2=sec;
							 min2=min;
							 hour2=hour;
							}




					   else if(set==1)
					           {
							      sec=0;
								  min=min2;
								  hour=hour2;
								  set=0;
								}
				  break;
				  case 0x05://若按下取消键
				       if(set==1)					   
				          set=0;
					   else if(setalarm==1)	
					      setalarm=0;
				  break;
				  case 0x06://若按下调整小时位按钮 
				       if(set==1||setalarm==1)
					   {
				  
				       hour2++;
					   if(hour2>=12)
					     {
						   hour2=0;
						   pm=!pm;
						  }

						}
				  
				  break;
				  case 0x07://若按下调整分钟位按钮
				       if(set==1||setalarm==1)
					   {
					   min2++;
					   if(min2>=60)
					      min2=0;
					    }
				  
   				  break;
				  
        		}
				
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -