📄 原始.txt
字号:
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 + -