📄 4位2051闹钟.c
字号:
//目标器件AT89C2051晶振12M
//单键操作实现校时和每天任意两个时间点定闹
//在有闹铃响时按键则停闹
//在正常模式时按键则开启或关闭闹铃功能
//查看闹铃时间:在正常模式时第1次按键显示第1闹铃时间,第2次按键显示第2闹铃时间,3秒后返回正常模式
//设置闹铃时间:在正常模式时在3秒内连按3次键进入闹钟设定模式,此时若不按键5秒后返回正常模式
//继续按键则时数跳变,再按键分数跳变,再按键完成第1闹铃时间设置等待确认
//继续按键则进入第2闹铃时间设置否则5秒后返回正常模式
//设置时钟时间:在正常模式时长按键5秒则进入校时模式,设置过程与闹铃模式相似,设置完成后返回正常模式
//2008年10月12日 I2C
//头文件包含
#include <reg52.h>
//宏定义
#define uchar unsigned char
#define uint unsigned int
#define CYCLE0 50240 //每隔CYCLE0微秒T0产生中断
#define CYCLE1 20000 //每隔CYCLE1微秒T1产生中断
#define DISTIME 400 //显示扫描延时量
#define Second 0 //时钟秒单元
#define Minute 1 //时钟分单元
#define Hour 2 //时钟时单元
#define MinuteTiming_1 3 //闹铃时单元
#define HourTiming_1 4 //闹铃分单元
#define MinuteTiming_2 5 //闹铃时单元
#define HourTiming_2 6 //闹铃分单元
#define DispOut P1 //字符码由P1输出
#define DisScan P3 //位扫描码输出
//数据缓冲区
uchar TimeData[7]; //时间数据缓冲区
uchar DispData[4]; //显示缓冲区
//共阴数码管0~9字符表
uchar code Disp[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x27,0x7f,0x6f};
//全局变量定义
uchar KeyVal; //键值单元
//内部可寻址位定义
bit SecondFlag; //时钟秒信号位
bit SecondFlashFlag; //时钟秒闪信号位
bit AddFlag; //设定模式增量信号位
bit TimeSetFlag; //校时模式标志位
bit TimingSetFlag; //闹铃模式标志位
bit SetModeFlag; //设置模式标志位
bit TimingFunFlag; //闹铃功能的标志位
bit TimingSuitedFlag; //闹铃时间匹配标志位
bit BeeNopFlag; //闹铃输出反相信号位
bit BeeMusicFlag; //闹铃声次数信号位
bit BeeSpaceFlag; //闹铃声间隔信号位
bit TimingDisSelectFlag; //闹铃时间显示选取择控制位
bit KeyTimeOutFlag; //连续击键超时计数控制位
bit UnpressKeyTimeFlag; //无按键计时控制位
//输出连接定义
sbit Hour_SWei= P3^0; //时十位驱动
sbit Hour_GWei= P3^1; //时个位驱动
sbit Min_SWei= P3^2; //分十位驱动
sbit Min_GWei= P3^3; //分个位驱动
sbit Timing_LED= P3^4; //模式指示长亮时表示闹钟功能启动
sbit Button_S1= P3^5; //按键S1
sbit Bee_Out= P3^7; //闹铃输出
//函数声明
void Delay(uint i); //延时函数
void System_init(void); //系统初始化函数
void TimerMake(void); //计时函数
void Display(void); //显示函数
void KeyScan(void); //键值产生函数
void KeyFunction(void); //键功能处理函数
void TimeCompate(void); //时间比较函数
void ChangeData(uchar *x); //设置模式自动增量函数
void TimeDisData(void); //时钟数据显示处理函数
void TimingDisData(void); //闹铃数据显示处理函数
void ClearFlag(void);
void StartBuzze(void);
void T0_intermit(void); //T0中断函数
void T1_intermit(void); //T1中断函数
//主函数
void main(void)
{
uchar DispScanTime;
uchar KeyTimeOut;
uchar UnpressKeyTime;
System_init();
while(1)
{
DispScanTime++;
//显示扫描
if(DispScanTime%25==0)
Display();
//键盘扫描
if(DispScanTime>250)
{
DispScanTime=0;
Bee_Out=0; //关闭蜂鸣声
KeyScan();
KeyFunction();
}
//计时
if(SecondFlag)
{
SecondFlag=0;
//时钟计时
TimerMake();
//连续击键超时计时
if(KeyTimeOutFlag)
{
if(++KeyTimeOut>=3)
ClearFlag(); //返回正常模式
}
else
KeyTimeOut=0;
//无按键计时
if(UnpressKeyTimeFlag)
{
if(++UnpressKeyTime>=5)
ClearFlag();
}
else
UnpressKeyTime=0;
}
//闹铃启动
if(TimingFunFlag&&!SetModeFlag&&!TimingSuitedFlag)
{
TimeCompate(); //时间比较
Timing_LED=0; //LED亮表示闹铃功能生效
} //声光闹铃输出
else if(TimingSuitedFlag&&BeeSpaceFlag)
{
BeeNopFlag=BeeMusicFlag;
Bee_Out=!BeeNopFlag; //取反再输出
Timing_LED=!BeeSpaceFlag; //闹铃输出时LED闪烁
}
else
Timing_LED=1;
}
}
//初始化函数
void System_init(void)
{
//置显示初值
TimeData[Hour]=22;
TimeData[Minute]=52;
TimeData[HourTiming_1]=22;
TimeData[MinuteTiming_1]=53;
TimeData[HourTiming_2]=22;
TimeData[MinuteTiming_2]=54;
//初始化P3口
P3=0xff;
//设T0,T1为方式1
TMOD=0x11;
//装T0初值
TH0=(-CYCLE0)/256;
TL0=(-CYCLE0)%256;
//装T1初值
TH1=(-CYCLE1)/256;
TL1=(-CYCLE1)%256;
//开中断及启动T0
EA =1;
ET0=1;
TR0=1;
}
//延时函数
void Delay(uint i)
{
while(i--);
}
//函数功能:时钟计时
void TimerMake(void)
{
if(++TimeData[Second]>=60)
{
TimeData[Second]=0;
if(++TimeData[Minute]>=60)
{
TimeData[Minute]=0;
if(++TimeData[Hour]>=24)
TimeData[Hour]=0;
}
}
}
//时钟显示数据放入显示缓冲区
void TimeDisData(void)
{
DispData[0]=Disp[TimeData[Hour]/10];
if(SecondFlashFlag)
{
//每半秒加小数点用于秒闪
DispData[1]=Disp[TimeData[Hour]%10]|0x80;
DispData[2]=Disp[TimeData[Minute]/10]|0x80;
}
else
{
DispData[1]=Disp[TimeData[Hour]%10];
DispData[2]=Disp[TimeData[Minute]/10];
}
DispData[3]=Disp[TimeData[Minute]%10];
}
//闹铃显示数据放入显示缓冲区
void TimingDisData(void)
{
if(TimingDisSelectFlag)
{
//第2定时时间
DispData[0]=Disp[TimeData[HourTiming_2]/10];
DispData[1]=Disp[TimeData[HourTiming_2]%10]|0x80; //加小数点以区别
DispData[2]=Disp[TimeData[MinuteTiming_2]/10];
DispData[3]=Disp[TimeData[MinuteTiming_2]%10];
}
else
{
//第1定时时间
DispData[0]=Disp[TimeData[HourTiming_1]/10];
DispData[1]=Disp[TimeData[HourTiming_1]%10];
DispData[2]=Disp[TimeData[MinuteTiming_1]/10]|0x80; //加小数点以区别
DispData[3]=Disp[TimeData[MinuteTiming_1]%10];
}
}
//函数功能:显示
//两种显示程序都可行,生成的代码量相当
void Display(void)
{
/* uchar i;
uchar databat;
uchar ScanStart=0x0e; //扫描初值,由低位开始扫描
//选择显示数据
if(TimingSetFlag)
TimingDisData();
else
TimeDisData();
//动态扫描显示
for(i=0;i<4;i++)
{
databat=DisScan&0xf0; //保存P3口当前状态
DisScan=databat|0x2f; //清屏
DispOut=DispData[i]; //输出字符码
DisScan=databat|(ScanStart&0x2f); //输出位扫描码
Delay(DISTIME); //延时
ScanStart=(ScanStart<<1)+1; //产生下一位扫描码
}*/
//选择显示数据
if(TimingSetFlag)
TimingDisData();
else
TimeDisData();
//显示时十位
Hour_SWei=0;
DispOut=DispData[0];
Delay(DISTIME);
Hour_SWei=1;
//显示时个位
Hour_GWei=0;
DispOut=DispData[1];
Delay(DISTIME);
Hour_GWei=1;
//显示分十位
Min_SWei=0;
DispOut=DispData[2];
Delay(DISTIME);
Min_SWei=1;
//显示分个位
Min_GWei=0;
DispOut=DispData[3];
Delay(DISTIME);
Min_GWei=1;
}
//函数功能:定闹时间比较
void TimeCompate(void)
{
//时分相等且秒为0时启动闹铃输出
if(TimeData[Second]==0)
{
if((TimeData[HourTiming_1]==TimeData[Hour])&&(TimeData[MinuteTiming_1]==TimeData[Minute]))
StartBuzze(); else if((TimeData[HourTiming_2]==TimeData[Hour])&&(TimeData[MinuteTiming_2]==TimeData[Minute]))
StartBuzze();
}
}
//函数功能:启动闹铃输出
void StartBuzze(void)
{
TimingSuitedFlag=1;
ET1=1;
TR1=1; //用TR1控制闹铃声响
}
//按键扫描函数:产生键值
void KeyScan(void)
{
uint KeyLongTime;
if(!Button_S1)
{
//启动按键声
Bee_Out=1;
//有闹铃输出时
if(TimingSuitedFlag)
{
TimingSuitedFlag=0;
Bee_Out=0; //闹铃停闹
TR1=0; //关闭TR1
ET1=0;
}
else
{
while(!Button_S1) //等待按键松开
{
KeyLongTime++; //长按键计时开始
if(KeyLongTime>300)
{
Bee_Out=0; //关闭按键声
Display(); //保持显示
}
if(KeyLongTime>600) //长按键超过5秒
{
TimeSetFlag=1; //进入校时模式
SecondFlashFlag=1; //使秒闪长亮
KeyVal=12; //键值置12指向校时模式起始键值
} //校时设定模式的后续键值由KeyVal++产生
}
//按键松开
KeyVal++; //产生键值
KeyLongTime=0; //清长按键计时
TimingFunFlag=!TimingFunFlag; //闹铃功能开或关
}
}
}//键功能函数:执行键值功能
void KeyFunction(void)
{
uchar *j; //定义指针
switch(KeyVal)
{
//第1次按键
case 1:
KeyTimeOutFlag=1; //启动按键超时计数
TimingSetFlag=1;
break;
//第2次按键
case 2:
TimingDisSelectFlag=1; //显示第2定时时间
TimingFunFlag=1;
break;
//第3次按键进入闹铃模式
case 3:
KeyTimeOutFlag=0; //关闭按键超时计数
TimingSetFlag=1; //进入闹铃设置模式
TimingDisSelectFlag=0;
UnpressKeyTimeFlag=1; //启动无按键计时
SetModeFlag=1;
break;
//第4次按键时数跳变(闹铃模式)
case 4:
UnpressKeyTimeFlag=0;
j=&TimeData[HourTiming_1]; //指针指向时间单元
ChangeData(j); //调用增量函数改变时间值
break;
//第5次按键分数跳变(闹铃模式)
case 5:
j=&TimeData[MinuteTiming_1];
ChangeData(j);
break;
//第6次按键等待确认
case 6:
UnpressKeyTimeFlag=1; //启动无按键计时
break;
//第7次按进入第2定时时间设置
case 7:
TimingDisSelectFlag=1;
break;
//
case 8:
UnpressKeyTimeFlag=0;
j=&TimeData[HourTiming_2]; //指针指向时间单元
ChangeData(j); //调用增量函数改变时间值
break;
//第9次按键分数跳变(闹铃模式)
case 9:
j=&TimeData[MinuteTiming_2];
ChangeData(j);
break;
//
case 10:
UnpressKeyTimeFlag=1; //启动无按键计时
break;
//第11次按键完成并返回正常模式
case 11:
ClearFlag();
break;
//
case 12:
break;
//长按键后键值=13进入校时模式
case 13:
SetModeFlag=1;
break;
//校时模式第1次按键时数跳变
case 14:
j=&TimeData[Hour];
ChangeData(j);
break;
//校时模式第2次按键分数跳变
case 15:
j=&TimeData[Minute];
ChangeData(j);
break;
//校时模式第3次按键等待对时
case 16:
TimeData[Second]=0;
break;
//校时模式第4次按键完成并返回正常模式
case 17:
TimeSetFlag=0;
SetModeFlag=0;
KeyVal=0;
break;
default:
break;
}
}
//函数功能:设置模式时自动增量改变所设项目
void ChangeData(uchar *x)
{
uchar i;
i=*x; //取出数据
if(AddFlag) //检测半秒增量标志位
{
AddFlag=0;
if((KeyVal==4)||(KeyVal==8)||(KeyVal==14))
{
if(++i>=24) //时数增加
i=0;
}
else if(++i>=60) //分数增加
i=0;
}
*x=i; //保存数据}
//函数功能:清各个相关控制位返回正常模式
void ClearFlag(void)
{
UnpressKeyTimeFlag=0;
KeyTimeOutFlag=0;
SetModeFlag=0;
TimingSetFlag=0;
TimingDisSelectFlag=0;
KeyVal=0; //返回正常模式
}
//函数功能:T0中断服务子程序(产生秒脉冲等)
void T0_intermit(void) interrupt 1
{
uchar TimeT0;
TH0=(-CYCLE0)/256;
TL0=(-CYCLE0)%256;
TimeT0++;
if(TimeT0%10==0)
{
AddFlag=1; //设置模式的增量标志位置1
if(!TimeSetFlag)
SecondFlashFlag=!SecondFlashFlag; //秒闪脉冲
}
if(TimeT0>=20) //累计20次为1秒
{
TimeT0=0;
if(!TimeSetFlag)
SecondFlag=1; //秒位置1
}
}
//函数功能:T1中断服务子程序(产生闹铃声响)
//产生宽度为100ms和600ms的方波
void T1_intermit(void) interrupt 3
{
uchar TimeT1;
TH1=(-CYCLE1)/256;
TL1=(-CYCLE1)%256;
TimeT1++;
if(TimeT1%5==0)
BeeMusicFlag=!BeeMusicFlag; //100ms
if(TimeT1>=30)
{
TimeT1=0;
BeeSpaceFlag=!BeeSpaceFlag; //600ms
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -