📄 main.c
字号:
/*--------------------------------------
单片机课程大作业:电子钟
作者:kyflash
QQ:249656058
使用AT89S52(12M)+RT1602
两个独立按键,一个蜂鸣器和一个彩色LED
按键短按实现加一减一,1S以上长按实现功能调整,2S以上长按实现快速加减
可以根据需要使用一个按键或者两个按键
另外为了判断单片机资源利用情况,从而间接验证时钟是否会因为冲突而变缓,
加上了CPU利用率显示,限于个人水平,该数据只有参考意义
由于晶振误差等因素,如果发现一周内时钟偏差较大,可以自行调整,理想的做法是
在1s定时器中断里面加入若干个空操作语句(限于时钟快的情况)
各个功能块按顺序如下:
调整年
调整月
调整日
调整时
调整分
调整秒
调整星期
闹钟1时
闹钟1分
闹钟1是否开
闹钟2时
闹钟2分
闹钟2是否开
关于使用到的引脚,参见各个引脚定义
说明:
本程序仅为了应付单片机课程作业,必然存在一些不合理之处。
程序中的按键扫描放在了定时器中断中,其实放到主循环中更好。
程序中按键部分源自我以前参考computer00师兄在ADUC7027例成中的代码,
做了一点小修改
液晶驱动部分参考了网上一个程序
--------------------------------------*/
#include "main.h"
#include "1602.H"
#include "KEYS.h"
#include "timer.h"
volatile unsigned char menu_status=0,key_time=0;
volatile unsigned char ring_time=0;
volatile unsigned char alarm_hour1=10,alarm_minute1=2,alarm_hour2=10,alarm_minute2=4,alarm_1_ok=0,alarm_2_ok=0,
alarm_1_en=1,alarm_2_en=1,alarm_2_off=0,alarm_1_off=0;
void delayXms(unsigned int x) //延迟x毫秒函数
{
unsigned int i,j;
for(i=0;i<x;i++)
for(j=0;j<130;j++);
}
void short_bell(void)
{
bell_on;
delayXms(50);
bell_off;
}
void long_bell(void)
{
bell_on;
delayXms(30);
bell_off;
delayXms(80);
bell_on;
delayXms(35);
bell_off;
}
void system_initial(void) //系统初始化
{
TMOD=0x11; //定时器工作在模式1
ET0=1; //开定时器0中断
TR0=1; //启动定时器0
ET1=1; //开定时器1中断
TL1=0x10;
TH1=0x20;
TR1=1; //启动定时器1
EA=1; //开总中断
year=2006;
month=6;
day=9; //日期初始化为2005年6月9日
hour=10;
minute=0;
long_bell();
}
void display_alarm_time(unsigned char ID)
{
switch(ID)
{
case 1:
WriteCommandLCM(0x80,0);
LCD_prints("alarm1:");
WriteCommandLCM(0xc2,0);
LCD_printc(alarm_hour1/10%10+48);
LCD_printc(alarm_hour1%10+48);
LCD_printc(':');
LCD_printc(alarm_minute1/10%10+48);
LCD_printc(alarm_minute1%10+48);
if(alarm_1_en)
{
WriteCommandLCM(0xc0,1);
LCD_printc('e');
}
else {
WriteCommandLCM(0xc0,1);
LCD_printc(' ');
}
break;
case 2:
WriteCommandLCM(0x80,0);
LCD_prints("alarm2:");
WriteCommandLCM(0xc2,0);
LCD_printc(alarm_hour2/10%10+48);
LCD_printc(alarm_hour2%10+48);
LCD_printc(':');
LCD_printc(alarm_minute2/10%10+48);
LCD_printc(alarm_minute2%10+48);
if(alarm_2_en)
{
WriteCommandLCM(0xc0,1);
LCD_printc('e');
}
else
{
WriteCommandLCM(0xc0,1);
LCD_printc(' ');
}
break;
default:break;
}
}
void set_fuction(void)
{
//WriteCommandLCM(0x01,1); //显示清屏
WriteCommandLCM(0xcb,1);
switch(menu_status)
{
case 0:
LCD_prints(" "); //WriteCommandLCM(0x01,1); //显示清屏
break;
case 1:
LCD_prints("Year ");
break;
case 2:
LCD_prints("Month");
break;
case 3:
LCD_prints("Date ");
break;
case 4:
LCD_prints("Hour ");
break;
case 5:
LCD_prints("Minut");
break;
case 6:
LCD_prints("Secon");
break;
case 7:
LCD_prints("week ");
display_time();
break;
case 8:
WriteCommandLCM(0x01,1); //显示清屏
// WriteCommandLCM(0x8c,0);
WriteCommandLCM(0xcb,1);
LCD_prints("hour");
display_alarm_time(1);
break;
case 9:
//WriteCommandLCM(0x01,1); //显示清屏
// WriteCommandLCM(0x8c,0);
LCD_prints("minu");
display_alarm_time(1);
break;
case 10:
LCD_prints("alarm");
display_alarm_time(1);
break;
case 11:
// WriteCommandLCM(0x8c,0);
LCD_prints("hour");
display_alarm_time(2);
break;
case 12:
// WriteCommandLCM(0x8c,0);
LCD_prints("minu");
display_alarm_time(2);
break;
case 13:
WriteCommandLCM(0x01,1); //显示清屏
LCD_prints("alarm");
display_alarm_time(2);
break;
default: break;
}
}
void key_ctrl(void)
{
if(Key.Value) //如果有按键按下
{
short_bell();
key_time=0;
alarm_1_off=1;
alarm_2_off=1;
led_off;//关LED闪烁
switch(Key.Value)
{
// fuction
case KEY1L:
menu_status++;
if(menu_status>13)
{
menu_status=0;
}
set_fuction();
break;
case KEY1:
//"+"
switch(menu_status)
{
case 0:
WriteCommandLCM(0xcb,0);
LCD_prints("LOCK!");
break;
case 1:
year++;
display_time();
break;
case 2:
month++;
if(month>12)
month=1;
display_time();
break;
case 3:
switch(month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
if(++day>31)
day=1;
break;
case 2:
if(((year%4)==0)&&((year%100)!=0))
{
if(++day>29)
day=1;
}
else
{
if(++day>28)
day=1;
}
break;
case 4:
case 6:
case 9:
case 11:
if(++day>30)
day=1;
break;
default:break;
}
display_time();
break;
case 4:
hour++;
if(hour>23)
hour=0;
display_time();
break;
case 5:
minute++;
if(minute>59)
minute=0;
display_time();
break;
case 6:
second++;
if(second>59)
second=0;
display_time();
break;
case 7:
week++;
if(week>7)
week=1;
display_time();
break;
case 8:
alarm_hour1++;
if(alarm_hour1>23)
alarm_hour1=0;
display_alarm_time(1);
break;
case 9:
alarm_minute1++;
if(alarm_minute1>59)
alarm_minute1=0;
display_alarm_time(1);
break;
case 10:
alarm_1_en=1;
display_alarm_time(1);
break;
case 11:
alarm_hour2++;
if(alarm_hour2>23)
alarm_hour2=0;
display_alarm_time(2);
break;
case 12:
alarm_minute2++;
if(alarm_minute2>59)
alarm_minute2=0;
display_alarm_time(2);
break;
case 13:
alarm_2_en=1;
display_alarm_time(2);
break;
default:break;
}
break;
case KEY2L:
if(menu_status<1)
{
menu_status=13;
}
else
menu_status--;
set_fuction();
break;
case KEY2:
//"-"
switch(menu_status)
{
case 0:
WriteCommandLCM(0xcb,0);
LCD_prints("LOCK!");
break;
case 1:
year--;
display_time();
break;
case 2:
if(month<2)
month=12;
else
month--;
display_time();
break;
case 3:
switch(month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
if(day<2)
day=31;
else
day--;
break;
case 2:
if(((year%4)==0)&&((year%100)!=0))
{
if(day<2)
day=29;
else
day--;
}
else
{
if(day<2)
day=28;
else day--;
}
break;
case 4:
case 6:
case 9:
case 11:
if(day<2)
day=30;
else
day--;
break;
default:break;
}
display_time();
break;
case 4:
if(hour<1)
hour=23;
else
hour--;
display_time();
break;
case 5:
if(minute<1)
minute=59;
else
minute--;
display_time();
break;
case 6:
if(second<1)
second=59;
else
second--;
display_time();
break;
case 7:
if(week<2)
week=7;
else
week--;
display_time();
break;
case 8:
if(alarm_hour1<1)
alarm_hour1=23;
else
alarm_hour1--;
display_alarm_time(1);
break;
case 9:
if(alarm_minute1<1)
alarm_minute1=59;
else alarm_minute1--;
display_alarm_time(1);
break;
case 10:
alarm_1_en=0;
display_alarm_time(1);
break;
case 11:
if(alarm_hour2<1)
alarm_hour2=23;
else
alarm_hour2--;
display_alarm_time(2);
break;
case 12:
if(alarm_minute2<1)
alarm_minute2=59;
else
alarm_minute2--;
display_alarm_time(2);
break;
case 13:
alarm_2_en=0;
display_alarm_time(2);
break;
default:break;
}
default: break;
}
Key.Value=0;
}
}
void main(void) //主函数
{
LCMInit();
KEYBoardInit();
system_initial(); //系统开机初始化
while(1)
{
key_ctrl(); //键盘扫描
if(key_time>=20)//如果20秒内无任何按键按下,则自动返回
{
WriteCommandLCM(0xcb,0);
LCD_prints(" ");//清除相关显示
menu_status=0;
key_time=0;
}
//刷新显示时间
if(time_1s_ok==1)
{
time_1s_ok=0;
key_time++;
if(menu_status<7)
display_time();
if((alarm_1_ok==1)||(alarm_2_ok==1))//如果触发了闹钟,则对闹铃持续时间进行秒计时
ring_time++;
//检测闹铃时间
if((alarm_1_en)&&(alarm_1_ok==0))
{
if(alarm_hour1==hour)
{
if(alarm_minute1==minute)
{
if(second==0)//为了在闹铃被按键取消以后,用户能立即设置,所以强制在秒为0时才匹配/进行检测
{
alarm_1_ok=1;//置闹铃1标志
alarm_1_off=0;
ring_time=0;//清闹铃时间,同时两个闹钟的闹铃时间不叠加
}
}
}
}
if((alarm_2_en)&&(alarm_2_ok==0))//如果开了闹钟且闹钟当前没有正在闹铃,则进行检测
{
if(alarm_hour2==hour)
{
if(alarm_minute2==minute)
{
if(second==0)
{
alarm_2_ok=1; //置闹铃2标志
alarm_2_off=0;
ring_time=0;
}
}
}
}
//执行闹铃声音提示
if(alarm_1_ok==1)
{
if(alarm_1_off==0)//如果用户没有按下停止键
{
if(ring_time<120)
{
WriteCommandLCM(0xc0,0);
LCD_printc('1');
long_bell();
led_on;
}
else
{
ring_time=0;
led_off;
alarm_1_ok=0;
}
}
else
{
ring_time=0;
led_off;
alarm_1_ok=0;
}
}
if(alarm_2_ok==1)
{
if(alarm_2_off==0)
{
if(++ring_time<120)
{
WriteCommandLCM(0xc0,0);
LCD_printc('2');
long_bell();
led_on;
}
else
{
ring_time=0;
led_off;
alarm_2_ok=0;
}
}
else
{
ring_time=0;
led_off;
alarm_2_ok=0;
}
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -