单片机课程设计报告数字钟的设计.docx
《单片机课程设计报告数字钟的设计.docx》由会员分享,可在线阅读,更多相关《单片机课程设计报告数字钟的设计.docx(32页珍藏版)》请在冰豆网上搜索。
单片机课程设计报告数字钟的设计
物理机电学院课程设计报告
课程名称:
单片机原理
专业班级:
10电本
(2)班
学生姓名:
王树泉
学号:
2010041629
指导教师:
王清辉
完成时间:
2013.04.07
报告成绩:
评阅意见:
评阅教师日期
单片机课程设计报告
目录
一、设计任务与要求-1-
1.1设计任务-1-
1.2数字时钟的设计-1-
二、方案设计与论证-2-
方案一:
-2-
方案二:
-2-
三、硬件电路设计-4-
3.1最小系统部分。
-4-
3.2外围电路部分。
-5-
四、软件设计-6-
4.1程序框图-6-
4.2实验程序(见附录2)-6-
五、仿真过程与仿真结果-7-
5.1仿真原理图:
-7-
5.2仿真结果-7-
六、安装与调试-8-
6.1安装:
-8-
6.2实物图:
-8-
6.3调试:
-9-
6.4调试结果:
-9-
七、结论与心得-10-
八、参考文献-11-
附录1:
主要器件清单:
-12-
附录2:
实验程序-13-
单片机课程设计报告
一、设计任务与要求
1.1设计任务
通过课程设计的教学实践,进一步学习、掌握单片机应用系统的有关知识,加深了解单片机的工作原理。
初步掌握简单单片机应用系统的设计、制作、调试的方法。
提高动手实践能力、提高科学的思维能力。
1.2数字时钟的设计
设计基本要求:
(1)能显示小时、分钟、秒;
(2)具有时间设置功能;
(3)在进入系统时显示自己的学号并闪烁两下;
扩展要求:
具备闹钟功能,有声音提示。
二、方案设计与论证
本设计基于单片机技术原理,以单片机芯片AT89S51作为核心控制器,通过硬件电路的制作以及软件程序的编制,计制作出一个多功能数字时钟系统。
单片机扩展的LED显示器用来显示秒、分、时计数单元中的值。
整个设计包括两大部分:
硬件部分和软件部分,以单片机为核心,配以一定的外围电路和软件。
硬件是整个系统的基础,软件部分则要合理、充分地支持和使用系统的硬件,从而完成系统所要完成的任务。
该时钟系统主要由时钟模块、液晶显示模块、键盘控制模块组成。
设计以硬件软件化为指导思想充分发挥单片机功能大部分功能通过软件编程来实现,路简单明了,统稳定性高。
方案一:
利用AT89S52单片机内部的定时/计数器进行中断定时,合软件延时实现时、分、秒的计时。
该方案节省硬件成本且能使读者在定时/计数器的使用、中断及程序设计方面得到锻炼与提高,对单片机的指令系统能有更深入的了解,而对学好单片机技术这门课程起到一定的作用。
方案二:
利用DS2302(其引脚如图2.1.1所示)时钟芯片连接AT89S51单片机,提供当前日期和时间数据,并将实时的日期数据在字符型液晶显示器LCD1602(其引脚如图2.1.2所示,显示编码如图2.1.3所示)上显示出来。
图2.1.1DS2302引脚图
图2.1.2LCD1602引脚图图2.1.3LCD1602编码显示
分析:
方案一直接利用AT89S51单片机内部定时/计数器进行中断定时,和软件延时实现时、分、秒的计时。
此方法虽然可以有效的节约成本,但产生的误差也较大,
不能达到精确定时的目的。
相比于方案一,方案二由于利用标准的时钟芯片进行设计,可以有效的减小产生的误差,达到准确定时的目的。
想比较之下,选择方案二进行设计较合适。
三、硬件电路设计
将硬件部分分为最小系统部分和外围电路部分。
3.1最小系统部分。
3.1.1原理图
图3.1.1
3.1.2PCB图
图3.1.2
3.2外围电路部分。
3.2.1原理图
图3.2.1
3.2.2PCB图
图3.2.2
四、软件设计
4.1程序框图
图4.1.1b按键扫描程序框
图4.1.1a主程序框图
4.2实验程序(见附录2)
五、仿真过程与仿真结果
5.1仿真原理图:
图5.1.1
5.2仿真结果
a.星期:
b.日期:
c.时间:
d.闹钟:
图5.1.2
六、安装与调试
6.1安装:
a.在keil软件中新建工程,芯片选择AT89S51,保存工程;打开数字钟C语言程序,保存,编译无误后生成HEX文件。
b.打开STC-ISP-烧写软件并选择好芯片型号,COM口,波特率等;取出最小系统模块,将串口连接电脑USB接口,连接好啊电源,并将下载跳线短接;
c.在烧写软件中选择好第一步中生成的HEX文件,点击下载按钮,将数字钟程序烧写进最小系统板的单片机中;
d.程序烧写完成后,将最小系统模块与外围电路模块对应原理图用杜邦线一一连接起来,接上电源(注意电源正负极),进行调试。
6.2实物图:
图6.2.1
6.3调试:
a.确认无误后接上电源,发现1602液晶显示屏亮但无显示,通过调节电位器W后改变1602的对比度后,问题解决。
b.调节W后液晶屏有现显示,但不能正常现实时钟。
重新检查连线并无错误,回仿真图进行仿真调试也一切正常。
经反复查证是DS2302时钟芯片无参考电压以致不能正常工作所致,通过在DS2302时钟芯片的3个引出脚分别外接1K上拉电阻并连接电源VCC。
重新接上电源后,问题解决。
c.通过外围电路的4个按键调节系统时间,日期,星期,闹钟。
测试各个系统功能是否正常
6.4调试结果:
经过反复调试与论证,本数字时钟系统能够正确的显示时间,日期,星期等基本要求,且时间误差在1S以内;在进入系统时可以显示自己的学号并闪烁2次;可以进行时间,日期,星期调节,并具有闹钟设定功能。
七、结论与心得
历时一个星期的实训结束了,从最开始的选定任务,到仿真,画原理图,画PCB,制板,焊接,调试,检测——。
一路走来,看着自己的作品一步步的从“理想”变为“现实”。
那种喜悦心情是无法用语言形容的!
其实最重要的不是结果,而是过程。
结果是生硬的,而过程永远值得我们慢慢回味。
在这几天的实训过程当中,有欢笑过,也有失落过。
这其中的点点滴滴现在仔细回味起来不免苦笑一番。
经过一个星期的实训令我受益良多。
上个学期学习了《单片机原理》,学语法,背指令。
但由于自己没有开发板,不能将理论付诸实践。
只有在实验课上才有几次动手的机会,但也只有为数不多的几次罢了。
且能像这次这样自己亲自动手制版更是机会难得。
这次实践让我对C51开发板的硬件结构有了进一步的连接,同时也认识了DS2302时钟芯片和LCD1602液晶显示屏的引脚及功能。
进一步熟悉了ISIS软件和ALTIUM软件是的使用。
特别是仿真软件的使用,以前我只能简单的按照老师给的那一套步骤,自己一点都不知道变通。
而在这次实训中遇到了些许问题,通过虚心请教其他的同学,经过同学们的热心帮助,我的问题一个个都迎刃而解了。
这才发现其实这套软件的功能其实非常强大,不是我过去简简单单的那一套路而已,这其中的许多功能还有待开发。
这次实训也让我体会到团队协作的重要性。
遇到问题大家一起讨论,最终取得最好的解决方案。
自己有不懂的问题虚心向他人请教,开始觉得不好意思,觉得别人会不耐烦,但其实发现大家都是很热情的,都会耐心的把方法讲解给我听,直到我会为止。
想当初如果自己因为种种原因不把自己的问题去请教他人,那么自己不懂的到现在还是不懂。
自己也就不能学到那么多东西了。
虽然这次实训让我学到了很多,但也发现了自己在很多方面的不足。
比如C程序不能自己独立完成,仿真软件用得不够熟练等。
而这些都只怨自己平时不够努力。
在今后的学习生活中,我要加倍努力,在编程上多下点功夫,从最简单的开始,一步一步的积累。
因为自己基础较差。
人要逼下自己,才会发现自己的潜能原来这么大。
让自己多学点,多懂点,只有这样才不会愧对自己的大学四年!
八、参考文献
[1]单片机原理及应用/张毅刚,彭喜元,彭宇编著.—2版[M].北京:
高等教育出版社,2010.5[2011.12重印].
[2]单片机C51设计教程与实验/祁伟,杨亭编著[M].北京:
航空航天大学出版社,2006.
[3]单片机C程序设计实例指导/李光飞等编著[M].航空航天大学出版社,2005.
[4]例说51单片机:
C语言版/张义和等编著:
袁彩霞改编[M].北京:
人民邮电出版社,2008.4.
附录1:
主要器件清单:
器件名称
器件型号
数量
备注
单片机
STC12C5A60S2
1
液晶屏
LCD1602
1
时钟芯片
DS1302
40
单排针
40PIN2.54MM
40
单排母
40PIN2.54MM
40
按钮
6*6*5-4脚
4
LED灯
红色绿色各1个/人
3
晶振
12MHZ
1
蜂鸣器
1
三极管
9013
1
覆铜板
A4
制板耗材
转印纸
制板耗材
腐蚀液
4
制板耗材
常规电阻电容
诺干
杜邦线
400
附录2:
实验程序
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitrs=P2^0;//数据、命令选择端
sbitlcden=P2^2;//使能信号
sbitlcdew=P2^1;//读写选择端
sbits1=P1^5;//功能键设定
sbits2=P1^6;//增大键设定
sbits3=P1^7;//减小键设定
sbits4=P1^4;//关闭蜂鸣器
sbitbeep=P2^3;//蜂鸣器设定*/
sbitRST=P2^5;//ds1302设定
sbitSCLK=P2^7;
sbitIO=P2^6;
sbitACC0=ACC^0;
sbitACC7=ACC^7;//位寻址寄存器定义
bitflag;
ucharcodetable1[]="wangshuquan";
ucharcodetable2[]="2010041611";
ucharcodetable3[]="";
ucharcodetable4[]="";
ucharnum[8],enter,shi,fen,miao,nian,yue,ri,week,shi1,fen1,flag1=0,flag2=0,flag3,choice,
time[]="20XX-XX-XXXXX",//年月日字符数组
time1[]="xx:
xx:
xx",//时分秒字符数组
time3[]="@NO00:
00:
00";//闹钟设定时显示的时间数组
voiddelay(uintz)//1ms延时函数
{uintx,y;
for(x=z;x>0;x--)
for(y=500;y>0;y--);
}
voiddi()//蜂鸣设定函数
{
beep=0;
delay(80);
beep=1;
}
ucharread(ucharx)//读ds1302数据
{
uchari;
RST=0;
SCLK=0;
RST=1;
ACC=(x|0x01);
for(i=8;i>0;i--)//循环8次移位
{
IO=ACC0;
SCLK=1;
SCLK=0;
ACC=ACC>>1;//右移
}
for(i=8;i>0;i--)//循环8次移位
{ACC=ACC>>1;
ACC7=IO;
SCLK=1;
SCLK=0;
}
SCLK=1;
RST=0;
returnACC;
}
voidwrite(ucharaddr,uchardat)//向ds1302写数据
{
uchari;
RST=0;
SCLK=0;
RST=1;
ACC=addr;
for(i=8;i>0;i--)
{
IO=ACC0;
SCLK=1;
SCLK=0;
ACC=ACC>>1;
}
ACC=dat;
for(i=8;i>0;i--)
{
IO=ACC0;
SCLK=1;
SCLK=0;
ACC=ACC>>1;
}
SCLK=1;
RST=0;
}
voidgetnum()//接收ds1302的数据
{
ucharj;
for(j=0;j<7;j++)
{
num[j]=read(0x80+0x02*j);
}
time[2]=((num[6]&0x70)>>4)+'0';//年
time[3]=(num[6]&0x0f)+'0';nian=((num[6]&0x70)>>4)*10+(num[6]&0x0f);
time[5]=((num[4]&0x70)>>4)+'0';//yue
time[6]=(num[4]&0x0f)+'0';yue=((num[4]&0x70)>>4)*10+(num[4]&0x0f);
time[8]=((num[3]&0x70)>>4)+'0';//ri
time[9]=(num[3]&0x0f)+'0';ri=((num[3]&0x70)>>4)*10+(num[3]&0x0f);
time[13]=(num[5]&0x0f)+'0';//week
week=(num[5]&0x0f);
switch(time[13])//星期字符数组赋值
{
case'1':
time[12]='S';time[13]='u';time[14]='n';
break;
case'2':
time[12]='M';time[13]='o';time[14]='n';
break;
case'3':
time[12]='T';time[13]='u';time[14]='e';
break;
case'4':
time[12]='W';time[13]='e';time[14]='d';
break;
case'5':
time[12]='T';time[13]='h';time[14]='u';
break;
case'6':
time[12]='F';time[13]='r';time[14]='i';
break;
case'7':
time[12]='S';time[13]='a';time[14]='t';
break;
}
time1[5]=((num[2]&0x70)>>4)+'0';//shi
time1[6]=(num[2]&0x0f)+'0';shi=((num[2]&0x70)>>4)*10+(num[2]&0x0f);
time1[8]=((num[1]&0x70)>>4)+'0';//fen
time1[9]=(num[1]&0x0f)+'0';fen=((num[1]&0x70)>>4)*10+(num[1]&0x0f);
time1[11]=((num[0]&0x70)>>4)+'0';//miao
time1[12]=(num[0]&0x0f)+'0';miao=((num[0]&0x70)>>4)*10+(num[0]&0x0f);
}
voidwrite_com(ucharcom)//写入lcd显示方式
{
rs=0;
P0=com;
delay
(1);
lcden=1;
delay
(1);
lcden=0;
}
voidwrite_data(uchardate)//向lcd1602写入数据
{
rs=1;
P0=date;
delay
(1);
lcden=1;
delay
(1);
lcden=0;
}
voidchuxian1()
{ucharnum1;
write_com(0x80);//将数据指针定位到第一行第一个字节
for(num1=0;num1<15;num1++)
{
write_data(table1[num1]);
delay(20);
}
write_com(0x80+0x40);
for(num1=0;num1<14;num1++)
{
write_data(table2[num1]);
delay(20);
}
delay(1500);
write_com(0x01);
}
voidchuxian2()
{ucharnum1;
write_com(0x80);//将数据指针定位到第一行第一个字节
for(num1=0;num1<15;num1++)
{
write_data(table3[num1]);
delay(20);
}
write_com(0x80+0x40);
for(num1=0;num1<14;num1++)
{
write_data(table4[num1]);
delay(20);
}
delay(50);
write_com(0x01);
}
voiddisplay()//显示数据
{
uchari;
write_com(0x0c);//显示方式设定为:
无光标,且不闪烁
if(flag2==1)
time1[0]='@';//闹钟图标设定
else
time1[0]='';
if(flag1==0)//flag为0时正常显示年、月、日、时、分、秒等
{
write_com(0x80);
for(i=0;time[i]!
='\0';i++)
{
write_data(time[i]);
}
write_com(0xc0);
for(i=0;time1[i]!
='\0';i++)
{
write_data(time1[i]);
}
}
if(flag1==1)//flag为1时进入时间设定界面
{
time3[8]=fen1/10+'0';time3[9]=fen1%10+'0';
time3[5]=shi1/10+'0';time3[6]=shi1%10+'0';
if(choice==0)
{
time3[2]='N';time3[3]='O';
}
if(choice==1)
{
time3[2]='O';time3[3]='K';
}
write_com(0xc0);
for(i=0;time3[i]!
='\0';i++)
{
write_data(time3[i]);
}
}
}
voidkeyscan()//扫描键盘
{
getnum();
if(s1==0)//功能键被按下write_com(0x0c);
{
delay
(1);
if(s1==0)
{
enter++;//记录摁下次数
if(flag1==1&&enter==6)
enter=2;
if(flag1==0&&enter==9)
enter=0;
while(s1==0);di();//按键放下时响一下
}
}
switch(enter)
{
case0:
write_com(0x0c);break;
case1:
write_com(0xcc);write_com(0x0f);delay(100);//按秒时有光标
break;
case2:
write_com(0xc9);write_com(0x0f);delay(100);//分
break;
case3:
write_com(0xc6);write_com(0x0f);delay(100);//时
break;
case4:
if(flag1==0)
{
write_com(0x8e);write_com(0x0f);delay(100);//星期
}
if(flag1==1)
{
write_com(0xc3);write_com(0x0f);delay(100);//NO、OK选项闪烁
}
break;
case5:
if(flag1==0)
{
write_com(0x89);write_com(0x0f);delay(100);//日闪烁
}
if(flag1==1)
{
write_com(0xc0);write_com(0x0f);delay(100);//时钟标志闪烁
}
break;
case6:
write_com(0x86);write_com(0x0f);delay(100);//月
break;
case7:
write_com(0x83);write_com(0x0f);delay(100);//年
break;
case8:
write_com(0x0c);write_com(0xc0);write_data('@');
if(flag1==0)write_com(0xc0);
elsewrite_com(0xc9);wri