📄 日历.txt
字号:
#include<AT89S5X.H>
#define SAVEKEY P32 //显示器件电源开关,自锁开关,低电平有效,按下去有效
#define SECLED P00 //秒计数LED灯;
#define SEG20 P33 //数码管显示20控制位
#define BUZZ P01 //蜂鸣器控制位,高电平有效
#define K1_SURE P25
#define K2_MIN P24
#define K3_HOUR P23
#define K4_DAY_COUNT P22
#define K5_MON_ALARM P21
#define K6_YEAR_TIME P20
#define uchar unsigned char
/*移位寄存器引脚输入定义*/
#define CP_1 P26
#define CP_2 P36
#define B_1 P27
#define B_2 P37
/* 十二个数码管选通端口定义*/
sbit WEI1 = P1^0;
sbit WEI2 = P1^1;
sbit WEI3 = P1^2;
sbit WEI4 = P1^3;
sbit WEI5 = P1^4;
sbit WEI6 = P1^5;
sbit WEI7 = P1^6;
sbit WEI8 = P1^7;
sbit WEI9 = P3^0;
sbit WEI10 = P3^1;
sbit WEI11 = P3^4;
sbit WEI12 = P3^5;
uchar SEG[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; /*共阳数码管0-9 16进制代码*/
uchar DC=0,SEC =0,MIN = 59, HOUR = 23,DAY = 19,MON = 4,YEAR=8; //存放十毫秒、1秒、1分钟、1小时、1天、1月、1年变量
uchar RUNNIAN = 1;DAXIAOYUE = 0; // 闰年标志,大小月标志,仅用于中断;
uchar TIME_=40; /* 扫描次数变量 */
/***************************************************************************************************/
/*延时程序*/
/***************************************************************************************************/
void DELAY(uchar TIME)
{
uchar P;
for(;TIME != 0;TIME--)
{
for(P=0;P<112;P++);
}
}
/*************************************************************
*******定时器0和1初始化*****************************************
**************************************************************/
void ET0_ET1()
{
TMOD=0X11; //T0模式1,T1模式1 相当于00010001B
ET0=1; //T0开中断
ET1=1; //T1开中断
PT0=0; //T0为低优先级
PT1=1; //T1为高优先级
EA=1; //中断总开关打开
TH0=0Xd8; //T0装入初值,实现10ms定时
TL0=0Xf0;
TH1=0Xfe; //T1装入初值,实现50ms定时
TL1=0X0c;
// TR0=1; //开启T0
TR1=1; //开启T1
}
/*************************************************************************************************/
/*8位数据从74HC164_1的串行输入端输入,从输出端并行输出*/
/*************************************************************************************************/
void HC164_1(unsigned char DATA_1)
{
uchar X;
for (X = 0;X < 8;X ++) //移位8次
{
B_1 = (bit)(DATA_1 & 0x01); //按位输出
CP_1 = 1; CP_1 = 0; //移位寄存器CP脉冲
DATA_1 = DATA_1 >> 1;
}
}
/*************************************************************************************************/
/*8位数据从74HC164_2的串行输入端输入,从输出端并行输出*/
/*************************************************************************************************/
void HC164_2(unsigned char DATA_2)
{
uchar Y;
for (Y = 0;Y < 8;Y ++) //移位8次
{
B_2 = (bit)(DATA_2 & 0x01); //按位输出
CP_2 = 1; CP_2 = 0; //移位寄存器CP脉冲
DATA_2 = DATA_2 >> 1;
}
}
/****************************************************************************************************/
/*动态扫描显示程序*/
/****************************************************************************************************/
void DISPALYSEG()
{
uchar DISPLY[13]; //存放显示变量
/***************************************************
*******转换显示数据*********************************
***************************************************/
/*下面的低六位由164_1输出*/
DISPLY[1] = SEC % 10;
DISPLY[2] = SEC / 10;
DISPLY[3] = MIN % 10;
DISPLY[4] = MIN / 10;
DISPLY[5] = HOUR % 10;
DISPLY[6] = HOUR / 10;
/*下面高六位由164_2输出*/
DISPLY[7] = DAY % 10;
DISPLY[8] = DAY / 10;
DISPLY[9] = MON % 10;
DISPLY[10] = MON / 10;
DISPLY[11] = YEAR % 10;
DISPLY[12] = YEAR / 10;
/********************************
转换完毕,开始显示
**********************************/
//低六位显示秒,分钟,小时
HC164_1(SEG[DISPLY[1]]);
WEI1 = 1;
DELAY(1);
WEI1 = 0;
HC164_1(SEG[DISPLY[2]]);
WEI2 = 1;
DELAY(1);
WEI2 = 0;
HC164_1(SEG[DISPLY[3]]);
WEI3 = 1;
DELAY(1);
WEI3 = 0;
HC164_1(SEG[DISPLY[4]]);
WEI4 = 1;
DELAY(1);
WEI4 = 0;
HC164_1(SEG[DISPLY[5]]);
WEI5 = 1;
DELAY(1);
WEI5 = 0;
HC164_1(SEG[DISPLY[6]]);
WEI6 = 1;
DELAY(1);
WEI6 = 0;
//高六位显示天,月,年
HC164_2(SEG[DISPLY[7]]);
WEI7 = 1;
DELAY(1);
WEI7 = 0;
HC164_2(SEG[DISPLY[8]]);
WEI8 = 1;
DELAY(1);
WEI8 = 0;
HC164_2(SEG[DISPLY[9]]);
WEI9 = 1;
DELAY(1);
WEI9 = 0;
HC164_2(SEG[DISPLY[10]]);
WEI10 = 1;
DELAY(1);
WEI10 = 0;
HC164_2(SEG[DISPLY[11]]);
WEI11 = 1;
DELAY(1);
WEI11 = 0;
HC164_2(SEG[DISPLY[12]]);
WEI12 = 1;
DELAY(1);
WEI12 = 0;
}
/***************************************************************************************************/
/* 定时计数器0的中断服务子程序 */
/***************************************************************************************************/
/*void ET_0() interrupt 1 using 1
{
TH1 = 0Xd8; //T0重新装入初值,继续10ms定时
TL1 = 0Xf0;
}
*/
/***************************************************************************************************/
/* 定时计数器1的中断服务子程序 ,控制数码管时间变量,判断闰年,大小月*/
/***************************************************************************************************/
void ET_1() interrupt 3 using 2
{
TH1 = 0Xfe; //T1重新装入初值,继续50ms定时
TL1 = 0X0c;
DC=DC + 1; //50毫秒计数
if(DC == 20) //满1秒?
{
SEC= SEC + 1; //秒计数加1
if(SAVEKEY == 0) //显示器件开关是否打开?打开了
{
SECLED = 0; //LED亮
}
if(SAVEKEY == 1) //没打开
{
SECLED = 1; //LED灭
}
}
if(DC == 40) //满2秒?
{
DC = 0; //清零十毫秒计数
SEC= SEC + 1; //秒计数加1
if(SAVEKEY == 0) //显示器件开关是否打开?打开了。
{
SECLED = 1; //LED灭
}
if(SAVEKEY == 1) //没有打开
{
SECLED = 1; //LED灭
}
}
if(SEC == 60) //满一分钟?
{
SEC = 0; //清零秒计数
MIN = MIN + 1; //分钟计数加1
}
if(MIN == 60) //满一小时?
{
MIN = 0; //清零分计数
HOUR = HOUR+1; //小时计数加1
}
if(HOUR == 24) //满1天?
{
HOUR = 0; //清0小时计数
DAY = DAY +1; //天计数加1
}
/*闰年判断,大小月判断,*/
RUNNIAN = YEAR % 4;
if(RUNNIAN == 0) //是闰年?
{
if(MON == 2) //二月到了?
{
if (DAY > 28) //超过28天了?
{
DAY = 1; //天初始化
MON = 3; //月+1
}
}
}
if(RUNNIAN != 0 ) //不是闰年
{
if(MON == 2) //2月到了?
{
if (DAY > 29) //超过29天了?
{
MON = 3; //月+1
DAY = 1; //天初始化
}
}
}
switch(MON)
{
case 1: DAXIAOYUE = 1;
case 3: DAXIAOYUE = 1;
case 4: DAXIAOYUE = 0;
case 5: DAXIAOYUE = 1;
case 6: DAXIAOYUE = 0;
case 7: DAXIAOYUE = 1;
case 8: DAXIAOYUE = 1;
case 9: DAXIAOYUE = 0;
case 10: DAXIAOYUE = 1;
case 11: DAXIAOYUE = 0;
case 12: DAXIAOYUE = 1;
}
if (DAXIAOYUE == 1) //大月
{
if(DAY > 31) //超过31天了
{
MON = MON + 1; //月+1
DAY = 1;
}
}
if(DAXIAOYUE == 0) //小月
{
if(DAY > 30) //超过30天了?
{
MON = MON+1; //月+1
DAY = 1;
}
}
if (MON > 12) //超过1年了
{
YEAR = YEAR + 1;
MON = 1;
}
if (YEAR > 28) //超过2028年?溢出
{
YEAR = 8; //初始化
}
}
/****************************************************************************************************
/***************************************蜂鸣器嘟嘟两声程序******************************************/
/****************************************************************************************************/
void BUZZ_TWO()
{
uchar ii;
BUZZ = 1; //蜂鸣器发声
for(ii = 0;ii < 50;ii++) //通过扫描数码管延时一段时间,实现延时
{
DISPALYSEG();
}
BUZZ = 0; //蜂鸣器关闭
for(ii = 0;ii < 50;ii++) //通过扫描数码管延时一段时间,实现延时
{
DISPALYSEG();
}
BUZZ = 1; //蜂鸣器发声
for(ii = 0;ii < 50;ii++) //通过扫描数码管延时一段时间,实现延时
{
DISPALYSEG();
}
BUZZ = 0; //蜂鸣器关闭
}
/***************************************************************************************************/
/* 键盘设置 */
/***************************************************************************************************/
void KEY_()
{
uchar jj,RUNNIANBIAOZHI, DAXIAOYUE_, END = 0;
ET1 = 0;TR1 = 0; //首先关闭定时器1中断,和定时开关
for (;END == 0;)
{
/* 判断K6是否按下*/
if (K6_YEAR_TIME == 0) //K6按下?
{
YEAR = YEAR +1;
if (YEAR > 28) //年溢出2028?
{
YEAR = 8; //超过出则初始化
}
RUNNIANBIAOZHI = YEAR % 4; //此标志与定时器1中断的标志位有区别
for(jj = 0;jj < TIME_;jj++) //通过扫描数码管延时一段时间,实现延时
{
DISPALYSEG();
}
}
/* 判断K5是否按下*/
if(K5_MON_ALARM == 0) //k5按下?
{
MON = MON + 1; //月加1
if (MON == 13) //超过1年了?
{
MON = 1; //超过出则初始化
}
for(jj = 0;jj < TIME_;jj++) //通过扫描数码管延时一段时间,实现延时
{
DISPALYSEG();
}
}
/* 判断K4是否按下*/
if(K4_DAY_COUNT == 0) //k4按下?
{
DAY = DAY + 1; //天+1
if (RUNNIANBIAOZHI == 0) //是闰年?
{
if (MON == 2) //是二月?
{
if (DAY >28) //超过28天了?
{
DAY = 1; //超过出则初始化
}
}
}
if (RUNNIANBIAOZHI == 1) //不是闰年?
{
if (MON == 2) //是二月?
{
if (DAY >29) //超过29天了?
{
DAY = 1; //超过出则初始化
}
}
}
switch(MON)
{
case 1: DAXIAOYUE_ = 1;
case 3: DAXIAOYUE_ = 1;
case 4: DAXIAOYUE_ = 0;
case 5: DAXIAOYUE_ = 1;
case 6: DAXIAOYUE_ = 0;
case 7: DAXIAOYUE_ = 1;
case 8: DAXIAOYUE_ = 1;
case 9: DAXIAOYUE_ = 0;
case 10: DAXIAOYUE_ = 1;
case 11: DAXIAOYUE_ = 0;
case 12: DAXIAOYUE_ = 1;
}
if (DAXIAOYUE_ == 1) //大月
{
if(DAY > 31) //超过31天了
{
DAY = 1;
}
}
if(DAXIAOYUE_ == 0) //小月
{
if(DAY > 30) //超过30天了?
{
DAY = 1;
}
}
for(jj = 0;jj < TIME_;jj++) //通过扫描数码管延时一段时间,实现延时
{
DISPALYSEG();
}
}
/* 判断K3是否按下*/
if (K3_HOUR == 0) //k3按下?
{
HOUR = HOUR + 1; //小时加1
if (HOUR == 24) //超过24小时了?
{
HOUR = 0; //小时初始化
}
for(jj = 0;jj < TIME_;jj++) //通过扫描数码管延时一段时间,实现延时
{
DISPALYSEG();
}
}
/* 判断K2是否按下*/
if(K2_MIN == 0) //k2按下?
{
MIN = MIN + 1; //小时加1
if (MIN == 60) //超过60分钟了?
{
MIN = 0; //分钟初始化
}
for(jj = 0;jj < TIME_;jj++) //通过扫描数码管延时一段时间,实现延时
{
DISPALYSEG();
}
}
/* 判断K1是否按下*/
if (K1_SURE == 0) //k1按下?
{
BUZZ_TWO(); //蜂鸣器嘟嘟两声
ET1 = 1;TR1 = 1; //开启定时器1中断,和定时开关
for(jj = 0;jj < TIME_;jj++) //通过扫描数码管延时一段时间,实现延时
{
DISPALYSEG();
}
END = 1;
}
/*没有按键按下,则只扫描显示*/
for(jj = 0;jj < TIME_;jj++) //通过扫描数码管延时一段时间,实现延时
{
DISPALYSEG();
}
}
}
/***************************************************************************************************/
/* 按键设置时间程序 */
/***************************************************************************************************/
void TIME_SHEZHI()
{
uchar jj;
/****************************时间设置开关K6是否按下*************************************************/
if(K6_YEAR_TIME == 0) //K6按下?开始设置时间
{
for(jj = 0;jj < TIME_;jj++) //通过扫描数码管延时一段时间,实现延时
{
DISPALYSEG();
}
KEY_(); //开始进行设置
}
}
/***************************************************************************************************/
/* 按键设置闹钟程序 */
/***************************************************************************************************/
void ALARM_SHEZHI()
{
uchar jj;
/****************************时间设置开关K6是否按下*************************************************/
if(K5_MON_ALARM == 0) //K5按下?开始设置闹钟
{
for(jj = 0;jj < TIME_;jj++) //通过扫描数码管延时一段时间,实现延时
{
DISPALYSEG();
}
KEY_(); //开始进行设置
}
}
/***************************************************************************************************/
/*主程序*/
/***************************************************************************************************/
void main()
{
SAVEKEY = 1; //初始化节电开关SAVEKEY,
SEG20 = 0; //关闭数码管"20"位
P2 = 0XFF; //初始化P2,P2的0~5引脚作为输入
ET0_ET1(); //初始化定时器0、1
while(1) //无穷循环
{
if (SAVEKEY == 1) //进入省电模式?
{
SEG20 = 0; //20显示开关关闭
}
if (SAVEKEY == 0) //显示器件打开?
{
SEG20 = 1; //20显示开关打开
DISPALYSEG();
TIME_SHEZHI();
ALARM_SHEZHI();
}
/* WDTRST = 0X1E; //开启WDT,循环执行,不断喂狗
WDTRST = 0XE1;*/
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -