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

📄 原始.txt

📁 可设置八个闹钟的智能时钟程序
💻 TXT
📖 第 1 页 / 共 2 页
字号:
1、	程序清单
本程序用C语言编写,经Keil C51编译成二进制码后写入89C51内的EPROM内即可。
#include "atmel\at89x51.h"
#include "intrins.h"

unsigned char hour,min,sec,year,month,day,weekday;   //当前时间、日期、星期
unsigned int  count_down;      //1秒钟计时用

bit led_on;                    //数码管是否点亮的标志
unsigned char display[8];      	//8位数码管要显示的数据
unsigned char attr;            	//八个数码管的闪烁控制字节,当为0时,对应数码管闪
bit flash;                     	//LED 闪烁开关,与attr共同决定数码管是否闪烁
unsigned char show_status;     	//LED 显示状态标志
        // 0:设置闹钟数据
// 1:显示当前日期及星期
							// 2:显示当前时间
// 3:设置当前日期
// 4:设置当前时间

bit km;                      	//按键已去抖动标志
bit kp;                       //按键已处理标志

bit sound;                    //蜂鸣器响标志
bit alarm_stop;                //蜂鸣器响后用户手工按停标志
struct  { unsigned char h;		//小时
        unsigned char m;		//分钟
       } alarm[8];				//8个闹钟项
unsigned char alarm_en;        	//闹钟项启用标志
unsigned char alarm_wk;        //闹钟项周末启用标志
unsigned char cur_alarm_set;   	//当前设置的闹钟项
unsigned char cur_alarm_active;	//当前到点的闹钟项
bit new_alarm_info;            //闹钟项内容已修改标志

sbit sound_output = P1^5;      	//蜂鸣器驱动端口,输出0时蜂鸣器响
sbit SDA_PIN   = P1^6;    	//EEPROM数据线端口
sbit SCL_PIN   = P1^7;    	//EEPROM时钟线端口

void I2cDelay()               	//EEPROM操作时需要的延时函数
{ _nop_();  _nop_();  _nop_();
  _nop_();  _nop_();  _nop_(); 
}

void DelayX1ms(unsigned char count)		//延迟函数,参数为毫秒数
{unsigned char i,j;
  for(i=0;i<count;i++)
    for(j=0;j<240;j++)	  ;
}

void Start()						//I2C启动,24C08使用I2C方式
{ SDA_PIN=1;   I2cDelay(); 
  SCL_PIN=1;   I2cDelay();
  SDA_PIN=0;   I2cDelay();  
  SCL_PIN=0;    
}

void Stop()                    	//I2C停止
{ I2cDelay();  SDA_PIN=0;
  I2cDelay();  SCL_PIN=1; 
  I2cDelay();  SDA_PIN=1; 
  I2cDelay();
}

bit SendByte(unsigned char value)			//发送1字节数据给EEPROM
{unsigned char i;
 bit no_ack=0;

  for(i=0;i<8;i++)                     //发送8位数据
  { I2cDelay();     
if(value&0x80)   SDA_PIN=1;
else            SDA_PIN=0;
    value=value<<1;    	
	I2cDelay();      SCL_PIN=1;         	
	I2cDelay();  	
	I2cDelay();      SCL_PIN=0; 
   }
  
  I2cDelay();        SDA_PIN=1;     //确认脉冲周期,等待EEPROM的确认
  I2cDelay();        SCL_PIN=1;       
  I2cDelay();       
  if(SDA_PIN==1)   no_ack=1;
  I2cDelay();        SCL_PIN=0;

  return no_ack;
}

void mywrite(unsigned char address,unsigned char value)		//向EEPROM写1字节
{ Start();          SendByte(0xa0);     SendByte(address);    
  SendByte(value);  Stop();             DelayX1ms(10);
}

unsigned char ReadByte()			//从EEPROM接收1字节
{unsigned char i,bval;
  bval=0;
  for(i=0;i<8;i++)					//接收8位数据
   { I2cDelay();
     SDA_PIN=1;            		//从P1输入数据时,先往P1输入“1”
     I2cDelay();    SCL_PIN=1;

     I2cDelay();    bval=bval<<1;     if(SDA_PIN)    bval=bval|0x01;
     I2cDelay();    SCL_PIN=0; 
    }
    
	I2cDelay();     SDA_PIN=1; 	//确认脉冲周期,不送出确认
	I2cDelay();     SCL_PIN=1;     
	I2cDelay();      
	I2cDelay();

    return(bval);
}

unsigned char myread(unsigned char address)		//从EEPROM读入1字节数据
{unsigned char tmp;
  Start();        SendByte(0xa0);     SendByte(address);    
  Start();        SendByte(0xa1);     tmp=ReadByte();
  Stop();         DelayX1ms(2);
  return(tmp);
}

void Timer0ISR(void) interrupt 1 using 3	//定时器0中断程序,用于走时,1/8000秒一次
{unsigned char tmp,tmp_days;

  count_down--;
  if(count_down==1 || count_down==2001 || count_down==4001 || count_down==6001)
   { flash=~flash;            				//数码管闪烁的开关量
     if(sound && flash) sound_output=0;		//驱动蜂鸣器
     else             sound_output=1;		//关闭蜂鸣器
	 return;
	}

	              /*** 计算当前日期为星期几***/  
  if(count_down==3000)
   { if(year==0)       weekday=5;		  //2000年1月1日为星期六
    else { tmp=(year-1)/4+1;   tmp=(year-tmp)+tmp*2;
         weekday=(tmp+5)%7;           //计算出当前年的1月1日为星期几
        }
     tmp_days=0;
     for(tmp=1;tmp<month;tmp++)
       if(tmp==1 || tmp==3 || tmp==5 || tmp==7 || tmp==8 || tmp==10)
          tmp_days=tmp_days+31;
       else if(tmp==4 || tmp==6 || tmp==9 || tmp==11)
	      tmp_days=tmp_days+30;
       else if(tmp==2)
	      { if(year%4==0) tmp_days=tmp_days+29;
            else         tmp_days=tmp_days+28;
           }
     tmp_days=tmp_days+day-1;    weekday=(weekday+tmp_days%7)%7+1;
	 return;
	}

                  /***  查询是否有闹钟时间项符合触发条件 ***/
  if(count_down==5000)
  { if((alarm_stop || sound) && alarm[cur_alarm_active].m!=min) 	//触发后1分钟
      { alarm_stop=0; sound=0; }							//自动关蜂鸣器

    if(sound==0 && alarm_stop==0)           //没有已触发的闹钟项
     for(tmp=0;tmp<8;tmp++)				  //则查询8个闹钟项内是否有符合条件的
	  { if(((alarm_en>>tmp)&1)==0) continue;    //该闹钟项不启用
	    if(((alarm_wk>>tmp)&1)==1)           //该闹钟项周末有效
		  { if(weekday!=6 && weekday!=7) continue;  }	//当前不是星期六或星期天
		else
		  { if(weekday==6 || weekday==7) continue;  }

        if(alarm[tmp].h==hour && alarm[tmp].m==min) 	  	//比较当前时间与该
          { sound=1;  cur_alarm_active=tmp; break; }		//闹钟项的时间
	   }
    return;
   }

  if(count_down==0)  				//过了一秒钟
   { count_down=8000;
     sec++;
     if(sec==60)
      { sec=0;
        min++;
        if(min==60)
          { min=0;
            hour++;
            if(hour==24)
              { hour=0;   day++;
				switch(day)
				{ case 29: if(month==2 && year%4)    { day=1; month=3; }
				           break; 
				  case 30: if(month==2 && year%4==0) { day=1; month=3; }
				           break; 
				  case 31: if(month==4 || month==6 || month==9 || month==11)
				           { day=1; month++; }
					       break; 
				  case 32: day=1;          month++;
				         if(month==13) { month=1; year++; }
				 }
               }
           }
       }
     }
}

⌨️ 快捷键说明

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