单片机电子钟实训报告.docx
《单片机电子钟实训报告.docx》由会员分享,可在线阅读,更多相关《单片机电子钟实训报告.docx(23页珍藏版)》请在冰豆网上搜索。
单片机电子钟实训报告
单
片
机
电
子
钟
实
训
报
告
学院:
河南工程学院
系别:
电气信息工程系
专业班级:
通信技术1032
姓名:
叶永柏
学号:
201020707259
前言
单片机自20世纪70年代问世以来,以其极高的性能价格比,受到人们的重视和关注,应用很广、发展很快。
单片机体积小、重量轻、抗干扰能力强、环境要求不高、价格低廉、可靠性高、灵活性好、开发较为容易。
由于具有上述优点,在我国,单片机已广泛地应用在工业自动化控制、自动检测、智能仪器仪表、家用电器、电力电子、机电一体化设备等各个方面,而51单片机是各单片机中最为典型和最有代表性的一种。
这次毕业设计通过对它的学习、应用,以AT89S51芯片为核心,辅以必要的电路,设计了一个简易的电子时钟,它由直流电源供电,通过数码管能够准确显
数字时钟是现代社会应用广泛的计时工具,在航天、电子等科研单位,工厂、医院、学校等企事业单位,各种体育赛事及至我们每个人的日常生活中都发挥着重要的作用。
本系统是基于AT89C51单片机设计的一个具有六位LED显示的数字时实时钟,采用独立式按键进行时间调整,同时引入一个内部充电电源在停止外部供电时,仍具有内部计时的功能。
该系统同时具有硬件设计简单、工作稳定性高、价格低廉等优点。
本文以对单片机的学习和认识,并通过本次课程设计加以应用,从而达到一个对所学知识的巩固、更深一步的理解,面对一个电子设计,应对出系统的方案,分析出各个板块来,再对各个板块进一步的具体的设计,先进行硬件电路设计,此时一定要考虑好要用什么元件、各个元件的具体参数、是否能实现应有功能,从而得到一个完整的硬件电路。
目录
第一章设计任务
1.1设计目的
1.2设计要求
第二章总体设计
2.1硬件部分
2.2电子时钟电路图
2.3电子时钟程序设计
第三章电子时钟调试
3.1软件调试
3.2硬件调试
第四章总结
第五章参考文献
第一章设计任务
1.1设计目的
课程设计的主要目的是通过对电子时钟的设计实践,了解单片机系统控制过程、设计要求、应完成的工作内容和具体设计方法。
通过设计也有助于复习、巩固以往所学的知识,达到灵活应用的目的。
课程设计应强调能力培养为主,在独立完成设计任务的同时,还要注意其他方面的能力的培养与提高,如独立工作能力与创造力;综合运用专业及基础知识的能力,解决实际工程技术问题的能力;差于图书资料、产品手册和各种工具书的能力;工程绘图的能力;书写技术报告和编制技术资料的能力。
1.2设计要求
在课程设计中,学生是主体,应充分发挥他们的主动性和创造性。
教师的主导作用是引导其掌握完成设计内容的方法。
为保证顺利完成设计任务还应做到以下几点:
1、在接受设计任务后,应根据设计要求和应完成的设计内容进度计划,确定各阶段应完成的工作量,妥善安排时间。
2、在方案确定过程中应主动提出问题,以取得指导老师的帮助,同时要广泛讨论,依据充分。
在具体设计过程中要多思考,尤其是主要参数,要经过计算论证。
3、说明书要求文字通顺、简练,字迹端正、整洁。
4、应在规定的时间内完成所有的设计任务。
5、如果条件允许,应对自己的设计线路进行实验讨论,考虑进一步改进的可能性。
第二章总体设计
2.1硬件部分
1、系统设计总框图
图2-1设计总框图
此次课程设计的的电子钟由单片机AT89C51、时钟电路、动态数码管显示电路组成。
运用C语言来控制单片机AT89C51来实现动态数码管显示,并在此基础上综合运用,时间电子钟的设计(包括时钟、秒表、显示)。
2、电路组成及工作原理
本文数字时钟设计原理主要利用AT89C51单片机,P2口控制LCD1602显示,P1口与按键相接用于时间的校正。
整个系统工作时,秒信号产生器是整个系统的时基信号,它直接决定计时系统的精度,将标准秒信号送入“秒计数器”,“秒计数器”采用60进制计数器,每累计60秒发出一个“分脉冲”信号,该信号将作为“分计数器”的时钟脉冲。
“分计数器”也采用60进制计数器,每累计60分钟,发出一个“时脉冲”信号,该信号将被送到“时计数器”。
“时计数器”采用24进制计时器,可实现对一天24小时的累计。
显示电路将“时”、“分”、“秒”计数器的输出,通过LCD1602显示器显示出来。
校时电路是直接加一个脉冲信号到时计数器或者分计数器或者秒计数器来对“时”、“分”、“秒”显示数字进行校对调整。
3、单片机AT89C51
(1)AT89C51简介
单片机是一种集成电路芯片,采用超大规模技术把具有数据处理能力(如算术运算,逻辑运算、数据传送、中断处理)的微处理器(CPU),随机存取数据存储器(RAM),只读程序存储器(ROM),输入输出电路(I/O口),可能还包括定时计数器,串行通信口(SCI),显示驱动电路(LCD或LED驱动电路),脉宽调制电路(PWM),模拟多路转换器及A/D转换器等电路集成到一块单块芯片上,构成一个最小然而完善的计算机系统。
这些电路能在软件的控制下准确、迅速、高效地完成程序设计者事先规定的任务。
(2)AT89C51的主要性能参数
与MCS-51产品指令系统完全兼容,4k字节可重擦写FLASH闪速存储器。
1000次擦写周期。
全静态操作:
0Hz—24MHz。
三级加密程序存储器,128×8字节内部RAM32个可编程I/O口线,2个16位定时/计数器6个中断源,可编程串行URAR通道,低功耗空闲和掉电模式。
AT89C51提供以下标准功能:
4k字节FLASH闪速存储器,128字节内部RAM,32个I/O口线,2个16位定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。
同时,AT89C51降至0Hz的静态逻辑操作,并支持两种可选的节电工作模式。
空闲方式体制CPU的工作,但允许RAM,定时/计数器,串行通信口及中断系统继续工作。
掉电方式保存RAM中的内容,但振荡器体制工作并禁止其他所有不见工作直到下一个硬件复位。
下图为单片机AT89C51各管脚图:
图2-2单片机AT89C51管脚图
4、1602LCD显示部分
1602LCD分为带背光和不带背光两种,基控制器大部分为HD44780,带背光的比不带背光
的厚,是否带背光在应用中并无差别
1602LCD主要技术参数:
显示容量:
16×2个字符
芯片工作电压:
4.5—5.5V
工作电流:
2.0mA(5.0V)
模块最佳工作电压:
5.0V
字符尺寸:
2.95×4.35(W×H)mm
引脚功能说明
1602LCD采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如表10-13
所示:
编号符号引脚说明编号符号引脚说明
1VSS电源地9D2数据
2VDD电源正极10D3数据
3VL液晶显示偏压11D4数据
4RS数据/命令选择12D5数据
5R/W读/写选择13D6数据
6E使能信号14D7数据
7D0数据15BLA背光源正极
8D1数据16BLK背光源负极
表10-13:
引脚接口说明表
第1脚:
VSS为地电源。
第2脚:
VDD接5V正电源。
第3脚:
VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对
比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。
第4脚:
RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
第5脚:
R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。
当RS和R/W
共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W为高电平时可以读忙信
号,当RS为高电平R/W为低电平时可以写入数据。
第6脚:
E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。
第7~14脚:
D0~D7为8位双向数据线。
第15脚:
背光源正极。
第16脚:
背光源负极。
2.2电子时钟电路图
图2-3线路连接图
2.3电子时钟程序设计
1、程序流程图
如图2-4所示
图2-4
2、电路元器件清单
低压电源4.5V
导线
若干
AT89C51单片机
1
微动开关按钮
4
LCD1602显示器
1
NPN三极管
1
电阻10K
1
滑动变阻器10K
1
电容10uF
1
电容30pF
2
晶振12MHZ
1
3、电子时钟C语言源程序
/***********************************
使用LCD1602与单片机实现的时钟与日期
显示年、月、日、时、分、秒(24小时制)
时间可调,年份2000——9999
jiahuhenan
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;
//flag
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;
for(i=123;i>=0;i--);
}
//向写指令函数
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("WK",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);
}
}
}
//显示字符串
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(