学院:xxx 班级:自动化xx班 姓名:xxx 学号:xxx 日期:2013-3-15
单片机LCD1602电子钟设计实习报告
一、引言
1.1设计的背景及目的
随着计算机科学与技术的飞速发展,计算机的应用已经渗透到国民经济与人们生活的各个角落,正在日益改变着传统的人类工作方式和生活方式,而单片机技术又作为计算机技术中的一个独立分支,有着性价比高,集成度高,体积小,可靠性高,控制功能强大,低功耗,低电压,便于生产,便于携带等特点,所以得到越来越广泛的应用,特别是在工业控制和仪表仪器智能化中起极其重要的作用.本文利用单片机强大的控制功能和内部定时器重要部件,设计了一款自行对时间进行调整以及把时、分、秒用LCD显示的电子钟。
电子钟从原理上讲是一种典型的数字电路,其中包括了组合逻辑电路和时序电路。因此,我们此次设计与制做数字钟就是为了了解数字钟的原理,从而学会制作数字钟.而且通过数字钟的制作进一步的了解各种在制作中用到的中小规模集成电路的作用及实用方法.且由于数字钟包括组合逻辑电路和时叙电路.通过它可以进一步学习与掌握各种组合逻辑电路与时序电路的原理与使用方法
1.2设计的内容要求及研究方法 ① 时间以24小时为一个周期; ② 显示时、分、秒;
③ 具有校时功能,可以分别对时及分进行单独校时,使其校正到标准时间;
二、设计的原理图、程序及调试
1、基本原理
本设计基于单片机技术原理,以单片机芯片AT89S51作为核心控制器,通过硬件电路的制作以及软件程序的编制,设计制作出一个多功能数字时钟系统。单片机扩展的LCD显示器用来显示秒、分、时计数单元中的值。整个设计包括两大部分: 硬件部分和软件部分,以单片机为核心, 配以一定的外围电路和软件。硬件是整个系统的基础, 软件部分则要合理、充分地支持和使用系统的硬件, 从而完成系统所要完成的任务。
该时钟系统主要由时钟模块、液晶显示模块、键盘控制模块以及信号提示模块组成。能够准确显示时间(显示格式为时时:分分:秒秒,24小时制),可随时进行时间调整。设计以硬件软件化为指导思想,充分发挥单片机功能,大部分功能通过软件编程来实现,电路简单明了,系统稳定性高。单片机在这种情况下诞生了基于单片机电子时钟。
2、硬件电路原理图
3、原理仿真图
4.硬件模块功能介绍
4.1 AT89S51单片机:AT89S51提供以下标准功能:8k字节Flash闪速存储器,256字节内部RAM,32个I/O口线,3个16位定时/计数器,一个6向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路[2]。同时,AT89S51可降至0HZ的静态逻辑操作,并支持两种软件可选的节电工作模式。空闲方式停止CPU的工作,但允许RAM,定时/计数器,串行通信口及中断系统继续工作。掉电方式保存RAM中的内容,但振荡器停止工作并禁止其它所有部件工作直到下一个硬件复位。
4.2 液晶显示器LCD:液晶显示器简称是利用液晶经过处理后能够改变光线传输方向的特性,达到显示字符或者图形的目的。其特点是体积小、重量轻、功耗极低、显示内容丰富等特点,在单片机应用系统中有着日益广泛的应用。
1602芯片:主要用于显示时间和定时时间。1602芯片由点阵字符液晶显示器件和专用的行、列驱动器、控制及必要的链接件、结构件组装而成,可以显示数字和西文字符,但不能显示图形,已经可以满足本次设计的需要。1602型LCD可以显示2行16个字符,有8位数据总线D0~D7和RS,R/W,EN三个控制端口,工作电压为5V,并且具有字符对比度调节和背光功能。
4.3 键盘控制模块:按键中有一个复位键及定时键、调时键加一键和减一键,一个按键接在复位电路上,另外三个按键接在P3.0——P3.2口,低电平表示有按钮按下;按钮没有接防抖电路,需要设计软件防抖。
1、定时。按下定时键后可以开始定时,过程如下:定时---〉小时加/减---〉按定时---分钟加/减---按定时。
2、调时。按下调时键后可以调时,过程如下:调时---年加/减---调时--月加/减---调时---日加/减---调时---时加/减---调时---分加/减---调时---秒加/减 ---调时。
4.4 直流稳压电源部分:直流稳压电源是给电子设备提供稳定直流电压的电子电路。这次电路需要的是+5V直流电源。 5.软件设计
5.1 代码附录
#include #define uchar unsigned char #define uint unsigned int #define WUFU P2 sbit lcdrs = P1^0; sbit lcdrw = P1^1; sbit lcden = P1^2; sbit key1 = P3^0; sbit key2 = P3^1; sbit key3 = P3^2; sbit key4 = P3^3; sbit bell = P3^7; uchar num, count, keynum;//定义几个变量 uchar week, month,day, nian;//定义几个变量 uchar shi, fen, miao; //定义几个变量
void delay( uint x) { uint i, j; for(i=0; i
uchar code table[]=\" 2013-01-18 MON \"; //定义数组 表示年月日
uchar code table1[]=\" 12-30-16 \"; //定义数组 表示时分秒
//********************写命令******************************** //===========
void write_com(uchar com) { lcdrs = 0;//表示写入的是指令,即对指令进行操作
lcdrw = 0; lcden = 0;//使能信号为0 delay(2); WUFU = com;//向端口传送命令
lcden = 1; delay(2); lcden = 0; } //*********************写数据********************************** //===============
void write_date(uchar date) //写数据初始化 { lcdrw = 0; lcdrs = 1;//表示写入的是数据,即对数据进行操作
delay(2); lcden = 0; WUFU = date; lcden = 1; delay(2); lcden = 0; } //********************函数初始化***************************** //----------------------------
void init()//写入时间函数 {
shi = 12; fen =30; miao = 16; write_com(0x38); //这句意思是用1602 ,5*7,的点整来显示数据 能显示16个字节
write_com(0x0c); //光标不闪烁
write_com(0x06); //输入数据光标制动加1,数据地址制动加1 write_com(0x01); //清屏指令
write_com(0x80);//1602液晶第一行
for(num=0; num
{
write_date(table[num]);//写入数据
delay(5);//延时5秒
} write_com(0xc0);//1602液晶第二行
for(num=0; num
write_date(table1[num]);
delay(5); } TMOD = 0x01; //T0工作模式1 TH0 = (65532-50000)/256;//赋初值高8位 想定时器中写入初始值为50毫秒
TL0 = (65532-50000)%256; //赋初值低8位
EA = 1;//cpu开中断
ET0 = 1;//打开定时器
TR0 = 1;//启动定时器
}
void write_sfm(uchar add, uchar date) { uchar shi,ge; shi= date/10; //把时间的十位分离出来
ge = date%10; //把时间的各位分离出来
write_com(0xc0+add); //显示这个时间的地址,这具体是显示十位的地址,但因为显示了十位地址制动加加所以不用现出显示个位的地址
write_date(0x30+shi); //在1602中要显示1它的地址是0x31,以此类推显示数字9是为0x39,所以前面要加上0x30
write_date(0x30+ge); //与上同理
}
void write_nyr(uchar add, uchar date) { uchar shi,ge; shi= date/10; ge = date%10; write_com(0x80+add); write_date(0x30+shi); write_date(0x30+ge); }
void write_week(uchar we) { write_com(0x80+12); switch(we) {
case 1:
write_date(\'M\');
delay(5);
write_date(\'o\');
delay(5);
write_date(\'N\');
break;
case 2:
write_date(\'T\');
delay(5);
write_date(\'U\');
delay(5);
write_date(\'E\');
break;
case 3:
write_date(\'W\');
delay(5);
write_date(\'E\');
delay(5);
write_date(\'D\');
break;
case 4:
write_date(\'T\');
delay(5);
write_date(\'H\');
delay(5);
write_date(\'U\');
break;
case 5:
write_date(\'F\');
delay(5);
write_date(\'R\');
delay(5);
write_date(\'I\');
break;
case 6:
write_date(\'S\');
delay(5);
write_date(\'A\');
delay(5);
write_date(\'T\');
break;
case 7:
write_date(\'S\');
delay(5);
write_date(\'U\');
delay(5);
write_date(\'N\');
break; } }
void timer0() interrupt 1 { TH0 = (65532-50000)/256; TL0 = (65532-50000)%256; count ++;
if(count == 20) {
count = 0;
miao ++;
if(miao == 60)
{
miao = 0;
fen ++;
if(fen == 60)
{
fen = 0;
shi ++;
if(shi == 24)
{
shi = 0;
}
write_sfm(3,shi); //刷新在屏幕上显示变化的小时数值
}
write_sfm(6,fen); // 刷新在屏幕上显示变化的分钟数值
}
write_sfm(9,miao);// 刷新在屏幕上显示变化的秒的数值
}
}
void keyscan() { if(key1 == 0) {
delay(5);
if(key1 == 0)
{
keynum ++;
while(!key1);
if(keynum == 1)
{
TR0 = 0;//关定时器
write_com(0xc0+9);//光标定位在秒的位置
write_com(0x0f); //光标开始闪烁
}
if(keynum == 2)
{
write_com(0xc0+6);
}
if(keynum == 3)
{
write_com(0xc0+3);//光标定位在时的位置上
}
if(keynum == 4)
{
//keynum = 0;
//write_com(0x0c);//取消光标闪烁
//TR0 = 1;
write_com(0x80+12);
}
if(keynum == 5)
{
write_com(0x80+9);
}
if(keynum == 6)
{
write_com(0x80+6);
}
if(keynum == 7)
{
write_com(0x80+3);
}
if(keynum == 8)
{
keynum = 0;
write_com(0x0c);//光标不闪烁
TR0 = 1;//启动定时器 时间又开始走了
}
} } if(keynum != 0) //如果k1没有按到第四次
{
if(key2 == 0) //如果k2按键按下
{
delay(5);
if(key2 != 0) //松手检测
{
while(!key2);
if(keynum == 1)
{
miao ++; //秒表进行++
if(miao == 60) //当秒加到60秒后
miao = 0; //把秒值为0
write_sfm(9,miao); //把调好的秒值写打屏幕上
write_com(0xc0+9);//把光标还到
原来的位置
}
if(keynum == 2)
{
fen ++;
if(fen == 60)
fen = 0;
write_sfm(6,fen); //把调好的分值写打屏幕上
write_com(0xc0+6); //把光标还到原来的位置
}
if(keynum == 3)
{
shi ++;
if(shi == 24)
shi = 0;
write_sfm(3,shi); //把调好的时值写打屏幕上
write_com(0xc0+3); //把光标还到原来的位置
}
if(keynum == 4)
{
week ++;
if(week == 8)
week = 1;
write_week(week);
write_com(0x80+12);
}
if(keynum == 5)
{
day ++;
if(day == 32)
day = 1;
write_nyr(9,day);
write_com(0x80+9);
}
if(keynum == 6)
{
month ++;
if(month == 13)
month = 1;
write_nyr(6,month);
write_com(0x80+6);
}
if(keynum == 7)
{
nian ++;
if(nian == 100)
nian = 0;
write_nyr(3,nian);
write_com(0x80+3);
}
}
}
if(key3 == 0)
{
delay(5);
if(key3 == 0)
{
while(!key3);
if(keynum == 1)
{
miao --;
if(miao == -1)
miao = 59;
write_sfm(9,miao);
write_com(0xc0+9);
}
if(keynum == 2)
{
fen --;
if(fen == -1)
fen = 59;
write_sfm(6,fen);
write_com(0xc0+6);
}
if(keynum == 3)
{
shi --;
if(shi == -1)
shi = 24;
write_sfm(3,shi);
write_com(0xc0+3);
}
if(keynum == 4)
{
week --;
if(week == -1)
week = 7;
write_week(week);
write_com(0x80+12);
}
if(keynum == 5) //与函数递增函数一样只是按键不同还有就是功能相反了
{
day --;
if(day == 0)
day = 31;
write_nyr(9,day);
write_com(0x80+9);
}
if(keynum == 6) //与函数递增函数一样只是按键不同还有就是功能相反了
{
month --;
if(month == 0)
month = 12;
write_nyr(6,month);
write_com(0x80+6);
}
if(keynum == 7) //与函数递增函数一样只是按键不同还有就是功能相反了
{
nian --;
if(nian == 0)
nian = 100;
write_nyr(3,nian);
write_com(0x80+3);
}
}
} } }
//============================================= //函数主程序
//============================================= void main() { init(); while(1) {
keyscan(); } } 5.2调试过程
调试的主要过程包括硬件调试和软件调试,其中软件调试,也即程序编译与仿真过程处于本次设计调试过程的核心环节。由于本设计已经制作出液晶显示电子钟,所以硬件调试也很重要。两种调试过程并非孤立或者分开的,而是紧密相关。在此我们用到的开发工具是仿真器。 5.3硬件调试
完成仿真器软件仿真后,就要连接上硬件也即液晶显示电子钟成品板进行硬件调试。
将仿真器通过串行电缆连接计算机上,将仿真头接到仿真器,检查接线是否有误,确信没有接错后,接上电源,打开仿真器的电源开关。再进行仿真器和通信设置。
仿真器和仿真头设置正确,并且硬件连接没有错误,出现 “硬件仿真”的对话框,并显示仿真器、仿真头的型号及仿真器的序列号。表明仿真器初始化正确。
硬件调试很重要也很麻烦,由于本次设计硬件非PCB制板,而是手工焊板,焊点质量、布线是否合理等对系统的影响比较大,这无疑增加硬件调试的难度。由于此前没有很多的练习,本次设计我所制作的液晶显示电子钟在质量工艺上很难达到满意程度,不过在调试中还算稳定,基本功能都能较稳定地实现。 5.4软件调试
系统仿真分析电路原理图在ISIS里设计完成,并将系统软件编译成.Hex文件,再进行电子时钟的系统虚拟仿真 。 (1)在ISIS的原理图中,右键单击AT89S51将其选中,然后单击左键打开AT89C51的Edit Component 对话框,如下图所示。(2)选择相应的.Hex文件,再在Proteus ISIS 编辑窗口的File菜单中选择Save Design 选项,保存设计,生成.DSN文件。 5.5测试数据与数据分析
实现功能的具体方法:当进入调整功能时,按第二个键K2进行加运算按第三个键K3进行减运算,。
按下第一个键K1,实现日期\\时间调整及\\定时功能,等数字闪烁后,按二三键进行加减,从而可以进行具体日期时间调整。按下第四个键K4回到原始设计时间,采用24小时制。时间显示格式为:时-分-秒;日期显示格式为:日-月-年。具有显示时间和日期的功能。
三、总结:个人心得体会
微机实习让我对计算机理论知识和自动化专业知识有了一定的了解,但真正操作起来就没有那么容易.纸上得来终觉浅, 绝此事要躬行。经过过去3个星期的实训,我对自己有了新的认识及前进的方向。 1.继续学习,不断提升理论素养。
在信息时代,学习是不断地汲取新信息,获得事业进步的动力。现在通过实习总感觉自己学的不够,要用到知识时总感觉脑袋是空白的。很后悔自己当时在学校为什么不多学一点,多练习一点。总在后悔也没有用,只能自己去努力学习。为了能更好的适应工作,我利用自己空闲时间去附近的书店去看书,希望能弥补不足。 2.加强信心,坚持下去
现在大家都说,能珍惜现在的日子就好好珍惜。等工作了才真的有另外的领悟。每天起早贪黑,忙忙碌碌,做了第一天可能就想回到学校接着做学生。感觉学生时代真是最美好的时间。可是既然真的出来了,就得踏出来了就要继续走下去,因为这一天也终究要来到。
对给自己点信心,多给自己点赞赏,多给自己鼓鼓劲。相信总会走出一条宽敞大道的。
3、友善相处
学生时代都感觉很美好,大家相互嘘寒问暖,不必勾心斗角。我感觉这里才真的有纯洁的友谊。其实想说,这就是一个小型的社会,我们互相的关照,互相体谅,学习上你我照应,工作上你我参与,和谐相处,这样,我们的友谊才会深刻,所以我们应该正确的对待与人之间的关系,友善相处。
最后想说,实习训是开端也是结束。在书本上学过很多理论,但从未付诸实践过,也许等到真正运用时,才会体会到难度有多大。在今后的工作和生活中,自己需要更加努力的奋斗下去。
实训的同时也让我了解到了自己的不足,我会继续努力,完善自我。对于学校的精心安排和指导老师的用心辅导非常感谢。