单片机万年历实训.docx
- 文档编号:7090215
- 上传时间:2023-01-17
- 格式:DOCX
- 页数:15
- 大小:53.72KB
单片机万年历实训.docx
《单片机万年历实训.docx》由会员分享,可在线阅读,更多相关《单片机万年历实训.docx(15页珍藏版)》请在冰豆网上搜索。
单片机万年历实训
单片机万年历实训
仿真图:
原理图:
程序:
/******************************************
使用LCD1602与单片机实现的时钟与日期
显示年、月、日、时、分、秒(24小时制)
时间可调,年份2000——9999
2012年10月9日
*******************************************/
#include
/******全局变量的定义与设置******/
sbitkey_mean=P1^0;//按键的定义
sbitkey_ok=P1^1;
sbitkey_set=P1^2;
sbitRS=P1^5;//LCD控制端口
sbitRW=P1^6;
sbitE=P1^7;
sfrPORT=0xa0;
charflag_sec=0;//值为20代表1s
charflag_en_ok=0;
charflag_en_key=0;//值为1表示键盘有效,否则无效
charflag_ok=0;//key_up与key_down的功能选择
charflag_mean=0;
charflag_set=0;//key_up与key_down的功能标识
charflag_year_leap=0;
//短语
//codecharstring_time[]="Settingtime?
\0";
codecharstring_year[]="Settingyear?
\0";
codecharstring_month[]="Settingmonth?
\0";
codecharstring_mday[]="Settingday?
\0";
codecharstring_week[]="Settingweek?
\0";
codecharstring_hour[]="Settinghour?
\0";
codecharstring_minute[]="Settingminute?
\0";
codecharstring_second[]="Settingsecond?
\0";
//年月日时分秒的定义
structDATA_TIME
{
shortyear;//待选
charmonth;
charmday;
charweek;
charhour;
charminute;
charsecond;
}time;
structtime_char//time的字符型
{
charch_year[4];
charch_month[2];
charch_mday[2];
charch_week[1];
charch_hour[2];
charch_minute[2];
charch_second[2];
}time_ch;
/***************子函数****************/
//LCD的延时程序
voidLCD_delay(void)
{
chari,j;
for(i=100;i>=0;i--)for(j=0;j<20;j++);
}
//向LCD写指令函数
voidwcmd(charcmd)
{
RS=0;
RW=0;
E=1;
LCD_delay();
PORT=cmd;
LCD_delay();
E=0;
}
//向LCD写数据函数
voidwdata(charDATA)
{
RS=1;
RW=0;
E=1;
LCD_delay();
PORT=DATA;
LCD_delay();
E=0;
}
//写字符串
voidwstring(char*pt,chari)//i为字符的个数,不带\0
{
charj;
for(j=0;j
{
wdata(pt[j]);
}
}
//时间数据的格式转换
voidtran_2_ch(char*pt,charDATA)
{
pt[0]=DATA/10+0x30;
pt[1]=DATA-pt[0]*10+0x10;
}
voidtran_4_ch(char*pt,intDATA)
{
pt[0]=DATA/1000;
pt[1]=DATA/100-pt[0]*10;
pt[2]=DATA/10-pt[0]*100-pt[1]*10;
pt[3]=DATA-pt[0]*1000-pt[1]*100-pt[2]*10;
pt[0]+=0x30;
pt[1]+=0x30;
pt[2]+=0x30;
pt[3]+=0x30;
}
//格式转换的实现
voidtran_ch(void)
{
tran_4_ch(time_ch.ch_year,time.year);
tran_2_ch(time_ch.ch_month,time.month);
tran_2_ch(time_ch.ch_mday,time.mday);
//tran_2_ch(time_ch.ch_week,time.week*10+1);
time_ch.ch_week[0]=time.week+0x30;
tran_2_ch(time_ch.ch_hour,time.hour);
tran_2_ch(time_ch.ch_minute,time.minute);
tran_2_ch(time_ch.ch_second,time.second);
}
//是否是闰年
charleep_year(intyear)//如果是闰年则flag_year_leep=1,否则=0
{
if((year%400==0)||year%4==0&&year%100!
=0)return1;
elsereturn0;
}
//星期的判断
voidde_week(void)
{
inti,j,day=0;
charmweek;
for(i=2000;i { if(leep_year(i))day+=366; elseday+=365; } for(j=1;j { if(j==1||j==3||j==5||j==7||j==8||j==10||j==12) day+=31; if(j==4||j==6||j==9||j==11) day+=30; if(flag_year_leap&&j==2)day+=29; if((! flag_year_leap)&&j==2)day+=28; } day+=time.mday; mweek=day%7; switch(mweek) { case0: time.week=5;break; case1: time.week=6;break; case2: time.week=7;break; case3: time.week=1;break; case4: time.week=2;break; case5: time.week=3;break; case6: time.week=4;break; } time_ch.ch_week[0]=time.week+0x30; } //月份的进位处理 voidtime_carry_mon_year(void) { flag_year_leap=leep_year(time.year);//判断闰年 if(time.mday>=30) { if(time.month==1||time.month==3||time.month==5||time.month==7\ ||time.month==8||time.month==10||time.month==12) //天数为31天的月,1、3、5、7、8、10、12 { if(time.mday==32) {time.mday=1;time.month++;} } if(time.month==4||time.month==6||time.month==9||time.month==11) { if(time.month==31) {time.mday=1;time.month++;} } tran_ch(); } if(time.month==2&&time.mday>=28) { if(flag_year_leap&&(time.mday==30)) {time.mday=1;time.month++;} if((! flag_year_leap)&&(time.mday==29)) {time.mday=1;time.month++;} tran_ch(); } if(time.month==13) {time.month=1;time.year++;tran_ch();}//年的进位 } //时间的进位 voidtime_carry(void) { if(time.second==60) {time.minute++;time.second=0;} if(time.minute==60) {time.hour++;time.minute=0;} if(time.hour==24) {time.mday++;time.hour=0;time_carry_mon_year();de_week();} } //屏幕的显示函数 voiddsp(void) { if(flag_en_key==0)//非设置模式下的显示 { tran_ch(); wcmd(0x02);//returncursor wstring(time_ch.ch_hour,2); wdata(': '); wstring(time_ch.ch_minute,2); wdata(': '); wstring(time_ch.ch_second,2); wstring("",3); wcmd(0x80+0x40); wstring("",3); wstring(time_ch.ch_year,4); wdata('-'); wstring(time_ch.ch_month,2); wdata('-'); wstring(time_ch.ch_mday,2); wstring("W",2); wdata(time_ch.ch_week[0]); } if(flag_en_key==1)//设置模式下的显示 { if(flag_set<=2) { tran_ch(); wcmd(0x02);//returncursor wstring(time_ch.ch_year,4); wdata('-'); wstring(time_ch.ch_month,2); wdata('-'); wstring(time_ch.ch_mday,2); } if(flag_set>2) { tran_ch(); wcmd(0x02);//returncursor wstring(time_ch.ch_hour,2); wdata(': '); wstring(time_ch.ch_minute,2); wdata(': '); wstring(time_ch.ch_second,2); wstring("",3); } } } //显示字符串string_… voiddsp_string(char*pt) { chari=0; wcmd(0x80+0x40);//将光标调整至第二行 while(pt[i]) { wdata(pt[i]); i++; } } //退出按键模式 voidexit_key(void) { chari; flag_en_key=0; flag_en_ok=0; flag_ok=0; flag_mean=0; flag_set=0;//清除所有标记 wcmd(0x80+0x40); for(i=0;i<=16;i++) wdata('\0'); } //按键的处理子函数(由外中断调用) intsolve_key(void) { //if(key_mean==0); if(key_ok==0)//确定或退出 { if(flag_ok) { exit_key(); time_carry_mon_year(); de_week(); return0; } elseflag_ok=1; } if(key_set==0) { if(flag_ok==0)//时分秒的选择 { flag_set++; if(flag_set==6)flag_set=0; switch(flag_set) { case0: dsp_string(string_year);break; case1: dsp_string(string_month);break; case2: dsp_string(string_mday);break; case3: dsp_string(string_hour);break; case4: dsp_string(string_minute);break; case5: dsp_string(string_second);break; } } if(flag_ok==1)//时分秒的设置 { switch(flag_set) { case0: {time.year++;if(time.year==10000)time.year=2000;break;} case1: {time.month++;time_carry_mon_year();break;} case2: {time.mday++;time_carry_mon_year();break;} case3: {time.hour++;if(time.hour==24)time.hour=0;break;} case4: {time.minute++;if(time.minute==60)time.minute=0;break;} case5: {time.second++;if(time.second==60)time.second=0;break;} } } } if(flag_ok==1)//是否更改数据是显示OK否显示? { wcmd(0x80+0x4e); wdata('O'); wdata('K'); } else { wcmd(0x80+0x4e); wdata('\0'); wdata('? '); } return0; } //MCU的秒中断函数与显示函数的执行 voidINT_sec()interrupt1using0 { if(flag_sec==20)//flag_sec==20代表1s { flag_sec=0; TH0=0x3c; TL0=0xb0+10;//定时器再次进入0.05s的中断 //加10是为了抵消中断与前两个指令消耗的时间(不精确) time.second++; flag_en_ok=0;//去掉key_ok的特殊优先权 time_carry(); dsp(); } else { flag_sec++; TH0=0X3C; TL0=0XB0+10;//定时器再次进入0.05s的中断 } } //外中断0,键盘中断 INT_X0(void)interrupt0using0 { LCD_delay();//去抖 TR0=0;//关闭定时计数器0 if(key_mean==0) { flag_en_ok=1; flag_ok=0; dsp_string(string_year); } if(flag_en_ok&&key_ok==0) {flag_en_key=1;flag_en_ok=0;} if(flag_en_key==1) { solve_key(); } TR0=1;//启动定时计数器0 } //LCD的初始化 voidinit(void) { E=0;//确定E在初始化时为0 wcmd(0x01); wcmd(0x06); wcmd(0x0c); wcmd(0x38); } /************main函数*****************/ intmain() { //单片机的初始化 EA=1; ET0=1;//定时计数器0的使能 EX0=1;//外中断0的使能 IT0=1;//下降沿触发中断 IP=0x02;//定时计数器0的中断优先级最高 TMOD=0x01;//定时计数器0为工作模式1 TH0=0x3c; TL0=0xb0;//定时计数器参数为0x3cb0,0xffff-0x3cb0=50000,一个中断中期为0.05s TR0=1;//MCU初始化后直接启动定时计数器0 time.year=2000;//数据的初始化 time.month=1; time.mday=1; time.week=6; time.hour=0; time.minute=0; time.second=0; init();//LCD初始化 while (1);//单片机等待中断 }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 单片机 万年历