人人范文网 范文大全

单片机万年历实训报告

发布时间:2020-03-02 18:07:44 来源:范文大全 收藏本文 下载本文 手机版

单片机万年历实训报告

部:电气自动化系

级:13电信2班

名:周祝福

指导老师:黄丽英、侯聪玲

实训时间:2015年1月19日~23日

用AT89C51与LCD1602设计 的可调式电子日历时钟

一、总体设计

1.1、设计目的

为巩固所学的单片机知识,把所学理论运用到实践中,用LCD1602与AT89C51 设计可调式电子日历时钟。

1.2、设计要求

(1)显示:年、月、日、时、分、秒和星期;

(2)设置年、月、日、时、分、秒和星期的初始状态;

(3)能够用4个按键调整日历时钟的年、月、日、时、分、秒和星期 ;

完成可调式电子日历时钟的硬件和软件的设计,包括单片机的相关内容;日历时钟模块的设计,液晶显示模块的设计,按键模块的设计。控制程序的编写等。

1.3、系统基本方案选择和论证

1.3.1、单片机芯片的选择方案

方案一:

采用89C51芯片作为硬件核心,采用Flash ROM,内部具有4KB ROM 存储空间,能于3V的超低压工作,而且与MCS-51系列单片机完全兼容。 方案二:

采用STC12C5A60S2系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,是高速/低功耗/超强抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8-12倍。内部集成MAX810专用复位电路,2路PWM,8路高速10位A/D转换(250K/S),针对电机控制,强干扰场合。但造价较高。 1.3.2 、显示模块选择方案和论证:

方案一:

采用点阵式数码管显示,点阵式数码管是由八行八列的发光二极管组成,对于显示文字比较适合,如采用显示数字显得太浪费,且价格也相对较高。所以不用此种作为显示。 方案二:

采用LED数码管动态扫描,虽然LED数码管价格适中,但要显示多个数字所需要的个数偏多,功耗较大,显示出来的只是拼音,而不是汉字。所以也不用此种作为显示。 方案三:

采用LCD液晶显示屏,液晶显示屏的显示功能强大,可显示大量字符,且视觉效果较好,外形美观。LCD1602可实现显示2行十六个字符。 1.3.4、电路设计最终方案决定

综上各方案所述,对此次作品的方案选定:采用80C51作为主控制系统; LCD1602液晶带汉字库显示屏作为显示部分。

二、硬件设计

2.1、电路设计模块图如图

AT89C51 块按键控制模LCD162

2.3、用proteus仿真软件仿真并抓图。

三、软件设计

3.1、画出各个函数流程图。

3.1.1、LCD1602液晶显示控制流程图如图

入口 对1602初始化写入显示设置命令 延时一段时间 检查忙标志 BF= 7>? 设置字符显示位置 延时一段时间 向1602中写入数据 LCD显示内容 返回主程序

是 3.1.2、调时函数控制流程如图

开始 控制键有效,调整年 控制键有效,调整月 等待按键程序 等待按键程序 加有效 减有效 加有效 减有效 年加 1 年减 1 月加 1 月减 1 控制键有效,调整日 控制键有效,调整星期 等待按键程序 等待按键程序 加有效 减有效 加有效 减有效 日加 1 日减 1 星期加 1 星期减 1 控制键有效,调整时 等待按键程序 加有效 时加 1 减有效 时减 1 控制键有效,调整分 等待按键程序 加有效 分加 1 减有效 分减 1 按键有效跳出调时程序,进入主循环

实训心得:通过为期一周的单片机实训,是我们对这门课有了许多新的了解,弥补了在课堂上学习的不足。相信这对我们以后的学习和工作都会有很大的帮助。我们一定要在最短的时间里对这些不足加以改正! 在试训中有苦有甜,当我们为一个很难攻破的程序找出路时,心情烦躁,感觉自己很不可理喻,当程序一点一点编好后,自己从心底感觉到一点小小的安慰,看着自己的成果。感觉很欣慰。总而言之,单片机课程设计对于我们有很大的帮助,我们从中受益匪浅。

程序代码。

#include #define uchar unsigned char #define uint unsigned int

uchar a,count,S1num,xqnum; uchar yue,ri,shi,fen,miao; uint nian;

sbit lcdrs=P2^5; sbit lcdrw=P2^4; sbit lcden=P2^3;

sbit S1=P3^0;

//定义键--进入设置 sbit S2=P3^1;

//定义键--增大 sbit S3=P3^2;

//定义键--减小 sbit S4=P3^3;

//定义键--退出设置

uchar code table0[]=\"2015-01-11 SUN\"; uchar code table1[]=\"00:00:00\"; uchar code xingqi[][3]={\"MON\",\"TUE\",\"WED\",\"THU\",\"FRI\",\"SAT\",\"SUN\"};

void delay(uint z) { uint x,y; for(x=z;x>0;x--)

for(y=110;y>0;y--); }

/************************************************** 1602液晶显示器模块

*************************************************/ void write_com(uchar com)

//液晶写指令 { lcdrw=0; lcdrs=0; P0=com; delay(5); lcden=1; delay(5); lcden=0; }

void write_data(uchar dat)

//液晶写数据 { lcdrw=0; lcdrs=1; P0=dat; delay(5); lcden=1; delay(5); lcden=0; }

/******************************************** 年月日写入1602函数

********************************************/ void write_sfm(uchar add,uchar dat)

//写时分秒函数 { uchar shi,ge; shi=dat/10; ge=dat%10; write_com(0x80+0x40+add); write_data(0x30+shi); write_data(0x30+ge); } void write_yr(uchar add,uchar dat)

//写月日函数 { uchar shi,ge; shi=dat/10; ge=dat%10; write_com(0x80+add); write_data(0x30+shi); write_data(0x30+ge); } void write_nian(uchar add,uint dat)

//写年函数 { uint qian,bai,shi,ge; qian=dat/1000; bai=dat%1000/100; shi=dat%100/10; ge=dat%10; write_com(0x80+add); write_data(0x30+qian); write_data(0x30+bai); write_data(0x30+shi); write_data(0x30+ge); } /*************************************************** 1602初始化

***************************************************/ void init_lcd()

//液晶初始化 { lcden=0;

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 }

void init()

//初始化函数 { init_lcd();

//液晶初始化

write_com(0x80);

//设置显示初始坐标

for(a=0;a

//显示年月日初始值

{

write_data(table0[a]);

delay(5); } write_com(0x80+0x40);

//设置显示初始坐标

for(a=0;a

//显示时分秒初始值

{

write_data(table1[a]);

delay(5); }

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 }

/************************************************** 独立键盘

*************************************************/ void keyscan() { if(S1==0) {

delay(5);

//确认定义键被按下

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)

//只有定义键按下后S

2、S

3、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;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)

{

ri=1;

}

//星期加调整

//日加调整

} } else if(yue

if(yue%2==0&yue!=2)

{

if(ri==31)

{

ri=1;

}

}

else if(yue%2!=0&yue!=2)

{

if(ri==32)

{

ri=1;

}

} } else if(yue>=8) {

if(yue%2==0)

{

if(ri==32)

{

ri=1;

}

}

else if(yue%2!=0)

{

if(ri==31)

{

ri=1;

}

} } 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) { delay(5); if(S3==0)

//确认按键被按下

{

while(!S3);

if(S1num==1)

{

miao--;

//调整秒减1

if(miao==-1)

//减到00后再减重新设置为59

miao=59;

write_sfm(6,miao);

write_com(0x80+0x40+6);

}

if(S1num==2)

{

fen--;

//调整分减1

if(fen==-1)

fen=59;

write_sfm(3,fen);

write_com(0x80+0x40+3);

}

if(S1num==3)

{

shi--;

//调整时减1

if(shi==-1)

shi=23;

write_sfm(0,shi);

write_com(0x80+0x40);

}

if(S1num==4)

{

xqnum--;

//调整星期减一

if(xqnum==-1)

xqnum=6; write_com(0x80+0x0b); for(a=0;a

write_data(xingqi[xqnum][a]);

delay(5); } } if(S1num==5)

//调整日 { ri--;

if(yue==2) {

if(nian%400==0)

{

if(ri==0)

{

ri=29;

}

}

if(nian%400!=0)

{

if(ri==0)

{

ri=28;

}

} } else if(yue

{

if(yue%2==0&yue!=2)

{

if(ri==0)

{

ri=30;

}

}

else if(yue%2!=0&yue!=2)

{

if(ri==0)

{

ri=31;

}

}

}

else if(yue>=8)

{

if(yue%2==0)

{

if(ri==0)

{

ri=31;

}

}

else if(yue%2!=0)

{

if(ri==0)

{

ri=30;

}

}

}

write_yr(8,ri);

}

if(S1num==6)

{

yue--;

if(yue==0)

yue=12;

write_yr(5,yue);

}

if(S1num==7)

{

nian--;

if(nian==2013)

nian=2018;

write_nian(0,nian);

} } } if(S4==0)

{ delay(5); if(S4==0) {

S1num=0;

TR0=1;

write_com(0x0c);

//调整月

//调整年

//退出设置、开启中断

}

} } }

/************************************************** 定时器0 *************************************************/ void timer0() interrupt 1

//定时器0中断服务程序 { TH0=(65535-50000)/256;

//重装定时器初始值

TL0=(65535-50000)%256; 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;

xqnum++;

ri++;

if(yue==2)

//如果是二月

{

if(nian%400==0)

//闰年判断

{

if(ri==30)

{

ri=1;

yue++;

write_yr(5,yue);

}

}

if(nian%400!=0)

//平年判断

{

if(ri==29)

{

ri=1;

yue++;

write_yr(5,yue);

}

}

}

else if(yue

//一月到七月

{

if(yue%2==0) //偶数月(除二月)

{

if(ri==31)

{

ri=1;

yue++;

}

}

else if(yue%2!=0)

//奇数月

{

if(ri==32)

{

ri=1;

yue++;

}

}

write_yr(5,yue);

}

else if(yue>=8)

//八月到12月

{

if(yue%2==0) //偶数月(除二月)

{

if(ri==32)

{

ri=1;

yue++;

if(yue==13)

//如果判断月份为12月,则加一后重新定义月份为1

{

yue=1;

nian++;

write_nian(0,nian);

}

write_yr(5,yue);

}

}

else if(yue%2!=0)

//奇数月

{

if(ri==31)

{

ri=1;

yue++;

write_yr(5,yue);

}

}

}

write_yr(8,ri);

if(xqnum==7)

//星期写入

xqnum=0;

write_com(0x80+0x0b);

for(a=0;a

{

write_data(xingqi[xqnum][a]);

delay(5);

}

}

write_sfm(0,shi);

//重新写入数据

}

write_sfm(3,fen);

//重新写入数据

}

write_sfm(6,miao);

//重新写入数据

} } /************************************************* 主函数

*************************************************/ void main() { init(); while(1) {

keyscan();

//不停的检测按键是否被按下

} }

万年历单片机课程设计报告

单片机实训报告

单片机实训报告

单片机实训报告

单片机实训报告

单片机实训

单片机实训

51单片机实训报告

单片机应用实训报告

单片机实训报告样本

单片机万年历实训报告
《单片机万年历实训报告.doc》
将本文的Word文档下载到电脑,方便编辑。
推荐度:
点击下载文档
点击下载本文文档