大连理工大学单片机课程设计智能电子钟Word文件下载.docx
《大连理工大学单片机课程设计智能电子钟Word文件下载.docx》由会员分享,可在线阅读,更多相关《大连理工大学单片机课程设计智能电子钟Word文件下载.docx(35页珍藏版)》请在冰豆网上搜索。
2.3、方案讨论
方案一:
采用实时时钟芯片
实时时钟芯片具备年、月、日、时、分、秒计时功能和多点计时功能,计时数据的更新每秒自动进行一次,不需程序干预。
计算机可通过中断或查询方式读取计时数据进行显示,因此计时功能的实现无需占用CPU的时间,程序简单。
此外,实时时钟芯片多数带有锂电池做后备电源,具备永不停止的计时功能;
具有可编程方波输出功能,可用做实时测控系统的采样信号等;
有的实时时钟芯片内部还带有非易失性RAM,可用来存放需长期保存但有时也需变更的数据,由于功能完善,精度高,软件程序设计相对简单,且计时不占用CPU时间,因此,在工业实时测控系统中多采用这一类专用芯片来实现实时时钟功能。
方案二:
软件控制
利用单片机内部的定时/计数器进行中断定时,配合软件延时实现时、分、秒的计时与秒表计时。
该方案节省硬件成本,且能使设计者对单片机的指令系统能有更深入的了解,从而掌握单片机应用技术MCS-51汇编语言程序设计方法,因此,本系统设计采用此种软件控制方法来实现计时。
而由于Atmel公司的AT89C51是一种自带4KBFlash存储器的低电压、高性能的CMOS8位微处理器。
该器件采用Atmel高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出引脚相兼容。
AT89C51将多功能8位CPU和闪存集成在单个芯片中,是一种高效的微控制器,使用也更方便,寿命更长,可以反复擦除1000次。
形成了功能强大、使用灵活和具有较高性能价格比的微控制器。
它的功能强大,而且也比较容易购买,故本设计中所选的单片机为AT89C51单片机。
2.4、明晰任务
采用AT89C51单片机作为系统的控制核心。
时钟数据通过市场上流行的时钟芯片DS1302来获取。
DS1302是DALLAS公司推出的涓流充电时钟芯片,内含一个实时时钟/日历和31字节静态RAM,可以通过串行接口与计算机进行通信,使得管脚数量减少。
实时时钟/日历电路能够计算2100年之前的秒、分、时、日、星期、月、年的,具有闰年自动判断调整的能力。
定时电路能够实现自定任意时刻自动开/关屏,采用LCDLM016L显示年、月、周、天、时、分、秒。
通过按键开关实现微调,确保计时精度:
误差≤1秒/月。
DS1302时钟芯片的主要功能特性:
(1)能计算2100年之前的年、月、日、星期、时、分、秒的信息;
每月的天数和闰年的天数可自动调整;
时钟可设置为24或12小时格式。
(2)31B的8位暂存数据存储RAM。
(3)串行I/O口方式使得引脚数量最少。
(4)DS1302与单片机之间能简单地采用同步串行的方式进行通信,仅需3根线。
(5)宽范围工作电压2.0-5.5V。
(6)工作电流为2.0A时,小于300nA。
(7)功耗很低,保持数据和时钟信息时功率小于1mW。
3.电路原理图
4.程序框图
4.1、显示子程序流程图
4.2、实时时钟芯片1302读/写数据流程图
5.编程序
源程序见附录部分
6.调试
6.1、软件调试
目前设计过程中容易造成元件和仪器仪表的损坏,而借助Keil和Proteus进行单片机系统的开发,可以节省设计成本,提高设计速度。
Keil软件包是一个功能强大的开发平台,它包括项目管理器、CX51编译器、AX51宏汇编器、BL51/LX51连接定位器、RTX51实时操作系统、Simulator软件模拟器与Monitor51硬件目标调试器。
它是一种集成化程度高的文件管理编译环境,主要功能为编译C语言源程序,汇编程序或混合语言源程序,连接和定位目标文件和库,创建HEX文件,调试目标程序等。
Keil是目前最好的51单片机开发工具之一。
Keil支持软件模拟仿真(Simulator)和用户目标调试(Monitor51)两种工作模式。
前者不需要任何单片机硬件即可完成用户程序仿真、调试,后者利用硬件目标板中的监控程序可以直接调试目标硬件系统。
Proteus是一个完整的嵌入式系统软件、硬件设计仿真平台,它包括原理图输入系统ISIS、带扩展的Prospice混合模型仿真器、动态元件库、高级图形分析模块和处理器虚拟系统仿真模型VSM。
ISIS是Proteus系统的中心,具有超强的控制原理设计环境。
ProteusVSM最重要的特点是能把微处理器软件作用在处理器上,并和该处理器的任何模拟和数字元件协同仿真,仿真执行目标码就像在真正的单片机系统上运行一样,VSMCPU模型能完整仿真I/O接口、中断、定时器、通用外部设备口与其他与CPU有关的外部设备,甚至能仿真多个处理器。
6.2、仿真调试
Keil仿真:
Proteus仿真:
7.自我感想
经历过这么多天不间断的课程设计,我们有挺多感触的,从最基本上说我们看到了,也意识到了自己的不足,对于不断克服的各种阻碍也让我们体会到了课程设计的意义所在。
对于只接触课本只动笔杆的我们,面临实际的设计尺寸,让我们很是尴尬,都说理论联系实际,真正到联系的时候才发现挺困难的,不过正是理论知识的各种补充才让我们能最终完成任务,然后深深地体会到理论对现实的指导作用。
我们现在最缺乏的就是实际工作经验,而理论联系实践并不像我们想象的那么简单,他需要坚实的理论基础和实际工作经验。
坚实的理论基础决定了我必须坚持学习新的知识新的理论,完善了自己的知识结构,才能在以后的实际中轻松面对,才能设计出更好的更有益于人们生活与工作的机械,才能跟上时代的步伐,不被淘汰。
在这个一边忙着复习忙着考试又要准备课程设计的日子里,真真正正的体会到了时间的宝贵,有点像高中忙忙碌碌的生活,不过能按时完成课程设计对我们来说也是一个莫大的安慰。
严谨和细心是做机械设计的必要态度,要想做好一件事,就必须一丝不苟、态度认真。
俗话说:
“失之毫厘,谬之千里。
”在机械设计上尤其应该注意。
在以后的工作中,你的很小的一个疏忽将会造成一个公司很大的损失,甚至给用户带去生命危险,而自己也会为自己的不负责任行为付出代价。
再者就是设计中要严谨和细心,对于机械是不能出差错的,任何的微小误差都可能产生不可预计的后果,当然对于我们来说就是设计中要走一些弯路,而且在这个严重缺少时间又惦记回家问题的我们来说也是一个很严重的后果。
不过,困难虽是难免的,但我们有信心就能并且已经战胜了困难,完成了这个无比揪心的课程设计。
因为时间等各种关系设计中难免有些不足还请老师助教给予批评和帮助。
8.参考书目
《单片机原理与其应用教程》张元良主编
《MCS-51系列单片机原理与应用》孙涵芳主编
《新概念51单片机C语言教程》郭天祥主编
《51单片机课程设计》周向红主编
9.附录:
C语言编程源程序
#include<
reg51.H>
intrins.h>
//---------------------------------------
#defineuintunsignedint
#defineucharunsignedchar
/*ucharcode
table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x98,0x88,0x83,0xc6,0xa1,0x86,0x8e};
//共阳极数码管代码*/
ucharcode
xingqi[8]={0x00,0x07,0x01,0x02,0x03,0x04,0x05,0x06};
//星期显示代码
uchar
miao,shi,fen,date,month,day,year,year10,set,mun,set_shi,set_fen,time_flag;
//全局定义
uintyear_data,t;
//------------------------------------
sbitSCLK=P3^5;
//DS1302通讯线定义
sbitDIO=P3^6;
sbitRST=P3^7;
sbitspeak=P0^0;
sbitDS=P2^0;
//595通讯线定义
sbitSH_CP=P2^1;
sbitST_CP1=P2^2;
sbitST_CP2=P2^3;
sbitST_CP3=P2^4;
sbitST_CP4=P2^5;
sbitST_CP5=P2^6;
sbitST_CP6=P2^7;
sbitST_CP7=P3^0;
sbitST_CP8=P3^1;
sbitOE1=P1^0;
sbitOE2=P1^1;
sbitOE3=P1^2;
sbitOE4=P1^3;
sbitOE5=P1^4;
sbitOE6=P1^5;
sbitOE7=P1^6;
sbitOE8=P1^7;
sbitK1=P3^2;
//按键接口定义
sbitK2=P3^3;
sbitK3=P3^4;
sbitK4=P0^1;
sbitK5=P0^2;
//------------------------------------
voidwrite_595(uchartemp)//写74HC595一个字节
{
uchartemp_595,i;
temp_595=temp;
for(i=0;
i<
8;
i++)
{
SH_CP=0;
_nop_();
_nop_();
if(temp_595&
0x80)
DS=1;
}
else
DS=0;
}
SH_CP=1;
temp_595<
<
=1;
//---------------------------------------------
voiddelay(uintz)//Nms延时
uintx,y;
for(x=z;
x>
0;
x--)
for(y=112;
y>
y--);
//--------------------------------------------
voiddelaynus(uintz)//ums延时
for(y=10;
//----------------------------------------------
voidwrite(uchardate)//写入DS1302一个字节
uchartemp,i;
RST=1;
SCLK=0;
temp=date;
i++)
{SCLK=0;
if(temp&
0x01)
DIO=1;
DIO=0;
SCLK=1;
temp>
>
ucharread()//读出DS1302一个字节
uchara,temp;
for(a=8;
a>
a--)
if(DIO)
temp=temp|0x80;
temp=temp|0x00;
return(temp);
//----------------------------------
voidwrite_1302(ucharadd,uchardat)//写DS1302数据
RST=0;
write(add);
write(dat);
//-----------------------------------------
ucharread_1302(ucharadd)//读DS1302数据
uchartemp;
temp=read();
return(temp);
//-------------------------------------------
voiddisplay()//显示子程序
miao=read_1302(0x81);
//读秒
fen=read_1302(0x83);
//读分
shi=read_1302(0x85)&
0x3f;
//读时
date=read_1302(0x87);
//读日
month=read_1302(0x89);
//读月
year=read_1302(0x8d);
//读年
day=read_1302(0x8B);
//读星期
write_595(miao);
//显示秒
ST_CP1=0;
ST_CP1=1;
delaynus(10);
write_595(fen);
//显示分
ST_CP2=0;
ST_CP2=1;
write_595(shi);
//显示时
ST_CP3=0;
ST_CP3=1;
write_595(date);
//显示日
ST_CP4=0;
ST_CP4=1;
write_595(month);
//显示月读
ST_CP5=0;
ST_CP5=1;
write_595(year);
//显示年
ST_CP6=0;
ST_CP6=1;
write_595(xingqi[day]);
//显示星期
ST_CP7=0;
ST_CP7=1;
//-----------------------------------------
voidds1302_init()//1302初始化
/*
write_1302(0x80,0x00);
//设置初始值SEC
write_1302(0x82,0x00);
//设置初始值MIN
write_1302(0x84,0x00);
//设置初始值HR
write_1302(0x86,0x00);
//设置初始值DATE
write_1302(0x88,0x00);
//设置初始值MONTH
write_1302(0x8A,0x00);
//设置初始值DAY
*/
write_1302(0x8C,0x10);
//设置初始值YEAR
//---------------------------------------------
voidPORT_INIT()//端口初始化
P0=0XFE;
P1=0X00;
P2=0X00;
P3=0XFC;
voidtime_init()//定时器初始化
TMOD=0x11;
//设置定时器0\1都为工作方式1
TH0=(65536-50000)/256;
//装入初值
TL0=(65536-50000)%256;
TH1=(65536-10000)/256;
TL1=(65536-10000)%256;
PT0=1;
//T0定时器优先级最高
EA=1;
//开总中断
ET0=1;
//开定时器0中断
ET1=1;
//开定时器1中断
TR0=1;
//启动定时器0
TR1=1;
//启动定时器1
voidmain(void)//主程序
{
PORT_INIT();
ds1302_init();
time_init();
//读年数据
year_data=0x2000|year;
write_595(year_data>
8);
//显示2010年的20字样
ST_CP8=0;
ST_CP8=1;
set_shi=0x09;
//闹钟初始值设定
set_fen=0x39;
time_flag=0;
//标志位
set=0;
while
(1)
switch(set)
case0:
//设置秒
display();
//显示子程序
if((shi==set_shi)&
&
(fen==set_fen)&
(time_flag==0))//闹钟设定只设定小时和分钟
speak=~speak;
if((K2==0)&
(time_flag==0))//按键K2停止闹钟响
P0&
=0XFE;
time_flag=1;
delay(10);
break;
if(fen==set_fen+1)//当不按下闹钟停止按键,一分钟后自动停止闹钟
time_flag=0;
voidtime0()interrupt1//定时器0中断
TR0=0;
mun++;
if(mun==15)
mun=0;
switch(set)
case1:
//设置秒闪烁
{OE1=1;
delay(300);
OE1=0;
case2:
//设置分闪烁
OE2=1;
OE2=0;
case3:
//设置时闪烁
OE3=1;
OE3=0;
case4:
//设置日闪烁
OE4=1;
OE4=0;
}
case5:
//设置月闪烁
OE5=1;
OE5=0;
case6:
//设置年闪烁
OE6=1;
OE8=1;
OE6=0;
OE8=0;
case7:
//设置星期闪烁
OE7=1;
delay(200);
OE7=0;
case8:
//设置闹钟闪烁
de