单片机万年历实训报告Word格式文档下载.docx
《单片机万年历实训报告Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《单片机万年历实训报告Word格式文档下载.docx(24页珍藏版)》请在冰豆网上搜索。
![单片机万年历实训报告Word格式文档下载.docx](https://file1.bdocx.com/fileroot1/2022-12/31/d552a98c-219f-495b-811c-e0b828886bac/d552a98c-219f-495b-811c-e0b828886bac1.gif)
采用LED数码管动态扫描,虽然LED数码管价格适中,但要显示多个数字所需要的个数偏多,功耗较大,显示出来的只是拼音,而不是汉字。
所以也不用此种作为显示。
方案三:
采用LCD液晶显示屏,液晶显示屏的显示功能强大,可显示大量字符,且视觉效果较好,外形美观。
LCD1602可实现显示2行十六个字符。
1.3.4、电路设计最终方案决定
综上各方案所述,对此次作品的方案选定:
采用80C51作为主控制系统;
LCD1602液晶带汉字库显示屏作为显示部分。
二、硬件设计
2.1、电路设计模块图如图
AT89C51
2.3、用proteus仿真软件仿真并抓图。
三、软件设计
3.1、画出各个函数流程图。
3.1.1、LCD1602液晶显示控制流程图如图
3.1.2、调时函数控制流程如图
实训心得:
通过为期一周的单片机实训,是我们对这门课有了许多新的了解,弥补了在课堂上学习的不足。
相信这对我们以后的学习和工作都会有很大的帮助。
我们一定要在最短的时间里对这些不足加以改正!
在试训中有苦有甜,当我们为一个很难攻破的程序找出路时,心情烦躁,感觉自己很不可理喻,当程序一点一点编好后,自己从心底感觉到一点小小的安慰,看着自己的成果。
感觉很欣慰。
总而言之,单片机课程设计对于我们有很大的帮助,我们从中受益匪浅。
程序代码。
#include<
reg52.h>
#defineucharunsignedchar
#defineuintunsignedint
uchara,count,S1num,xqnum;
ucharyue,ri,shi,fen,miao;
uintnian;
sbitlcdrs=P2^5;
sbitlcdrw=P2^4;
sbitlcden=P2^3;
sbitS1=P3^0;
//定义键--进入设置
sbitS2=P3^1;
//定义键--增大
sbitS3=P3^2;
//定义键--减小
sbitS4=P3^3;
//定义键--退出设置
ucharcodetable0[]="
2015-01-11SUN"
;
ucharcodetable1[]="
00:
00"
ucharcodexingqi[][3]={"
MON"
"
TUE"
WED"
THU"
FRI"
SAT"
SUN"
};
voiddelay(uintz)
{
uintx,y;
for(x=z;
x>
0;
x--)
for(y=110;
y>
y--);
}
/**************************************************
1602液晶显示器模块
*************************************************/
voidwrite_com(ucharcom)//液晶写指令
lcdrw=0;
lcdrs=0;
P0=com;
delay(5);
lcden=1;
lcden=0;
voidwrite_data(uchardat)//液晶写数据
lcdrs=1;
P0=dat;
}
/********************************************
年月日写入1602函数
********************************************/
voidwrite_sfm(ucharadd,uchardat)//写时分秒函数
ucharshi,ge;
shi=dat/10;
ge=dat%10;
write_com(0x80+0x40+add);
write_data(0x30+shi);
write_data(0x30+ge);
voidwrite_yr(ucharadd,uchardat)//写月日函数
write_com(0x80+add);
voidwrite_nian(ucharadd,uintdat)//写年函数
uintqian,bai,shi,ge;
qian=dat/1000;
bai=dat%1000/100;
shi=dat%100/10;
write_data(0x30+qian);
write_data(0x30+bai);
/***************************************************
1602初始化
***************************************************/
voidinit_lcd()//液晶初始化
nian=2015;
yue=1;
ri=11;
shi=0;
//初始shi、fen、miao
fen=0;
miao=0;
write_com(0x38);
//设置16x2显示,5x7点阵,8位数据口
write_com(0x0c);
//设置开显示,不显示光标
write_com(0x06);
//写一个字符后地址指针加1
write_com(0x01);
//显示清0,数据指针清0
voidinit()//初始化函数
init_lcd();
//液晶初始化
write_com(0x80);
//设置显示初始坐标
for(a=0;
a<
14;
a++)//显示年月日初始值
{
write_data(table0[a]);
delay(5);
}
write_com(0x80+0x40);
//设置显示初始坐标
8;
a++)//显示时分秒初始值
write_data(table1[a]);
write_nian(0,nian);
write_sfm(6,miao);
//分别将shi、fen、miao送去液晶显示
write_sfm(3,fen);
write_sfm(0,shi);
count=0;
xqnum=0;
S1num=0;
//初始化全局变量count
TMOD=0x01;
//设置定时器0工作模式1
TH0=(65535-50000)/256;
//定时器装初始值
TL0=(65535-50000)%256;
EA=1;
//开总中断
ET0=1;
//开定时器0中断
TR0=1;
//启动定时器0
独立键盘
voidkeyscan()
if(S1==0)
//确认定义键被按下
if(S1==0)
{
S1num++;
//定义键S1按下次数记录
while(!
S1);
//释放按键确认
if(S1num==1)//S1按下一次时
{
TR0=0;
//关闭定时器
write_com(0xc0+7);
//光标定位到秒位置
write_com(0x0f);
//光标闪烁
}
if(S1num==2)//S1按下两次时
write_com(0xc0+4);
//光标定位到分位置
if(S1num==3)//S1按下三次时
write_com(0xc0+1);
//光标定位到时位置
if(S1num==4)//S1按下四次时
write_com(0x80+13);
//光标定位到星期位置
if(S1num==5)//S1按下五次时
write_com(0x80+9);
//光标定位到日位置
if(S1num==6)//S1按下六次时
write_com(0x80+6);
//光标定位到月位置
if(S1num==7)//S1按下七次时
write_com(0x80+3);
//光标定位到年位置
if(S1num==8)//S1按下八次时
S1num=0;
//S1记录按键次数清零
TR0=1;
//开启定时器
write_com(0x0c);
//取消光标闪烁
}
if(S1num!
=0)//只有定义键按下后S2、S3、S4才有效
if(S2==0)
delay(5);
//防抖
if(S2==0)//确认按键被按下
while(!
S2);
if(S1num==1)//S1按下一次时
{
miao++;
//调整秒加1
if(miao==60)//满60清零
miao=0;
write_sfm(6,miao);
//每调节一次送液晶显示一次
write_com(0x80+0x40+6);
//显示位置重新回到调节处
}
if(S1num==2)//S1按下两次时
fen++;
//调整分加1
if(fen==60)
fen=0;
write_sfm(3,fen);
write_com(0x80+0x40+3);
if(S1num==3)//S1按下三次时
shi++;
//调整时加1
if(shi==24)
shi=0;
write_com(0x80+0x40);
write_sfm(0,shi);
if(S1num==4)//星期加调整
xqnum++;
if(xqnum==7)
xqnum=0;
write_com(0x80+0x0b);
for(a=0;
3;
a++)
{
write_data(xingqi[xqnum][a]);
delay(5);
}
if(S1num==5)//日加调整
ri++;
if(yue==2)
if(nian%400==0)
{
if(ri==30)
{
ri=1;
}
}
if(nian%400!
=0)
if(ri==29)
elseif(yue<
=7)
if(yue%2==0&
yue!
=2)
if(ri==31)
elseif(yue%2!
=0&
if(ri==32)
elseif(yue>
=8)
if(yue%2==0)
write_yr(8,ri);
if(S1num==6)//月加调整
yue++;
if(yue==13)
yue=1;
write_yr(5,yue);
}
if(S1num==7)//年加调整
nian++;
if(nian==2019)
nian=2014;
write_nian(0,nian);
if(S3==0)
if(S3==0)//确认按键被按下
S3);
if(S1num==1)
miao--;
//调整秒减1
if(miao==-1)//减到00后再减重新设置为59
miao=59;
if(S1num==2)
fen--;
//调整分减1
if(fen==-1)
fen=59;
if(S1num==3)
shi--;
//调整时减1
if(shi==-1)
shi=23;
if(S1num==4)
xqnum--;
//调整星期减一
if(xqnum==-1)
xqnum=6;
if(S1num==5)//调整日
ri--;
if(ri==0)
ri=29;
ri=28;
=7)
ri=30;
ri=31;
if(S1num==6)//调整月
yue--;
if(yue==0)
yue=12;
if(S1num==7)//调整年
nian--;
if(nian==2013)
nian=2018;
if(S4==0)//退出设置、开启中断
if(S4==0)
定时器0
voidtimer0()interrupt1//定时器0中断服务程序
//重装定时器初始值
count++;
//中断次数累加
if(count==20)//20次50毫秒即一秒
count=0;
miao++;
if(miao==60)//秒加到60时分进位
miao=0;
fen++;
if(fen==60)//分加到60时时进位
fen=0;
shi++;
if(shi==24)//时加到24时清0
shi=0;
if(yue==2)//如果是二月
if(nian%400==0)//闰年判断
yue++;
write_yr(5,yue);
=0)//平年判断
=7&
=2)//一月到七月
if(yue%2==0)//偶数月(除二月)
if(ri==31)
=0)//奇数月