单片机原理与应用
综合实验报告
电子万年历设计
专业班级: 电子09-1
姓 名:
学 号:
时 间:
指导教师:
20 年 月 日
电子万年历
电子09-1
摘要:本设计是电子万年历。具备三个功能:能显示:年、月、日、时、分、秒及星期信息,并具有可调整日期和时间功能。
我选用的是单片机ATC52来实现电子万年历的功能。该万年历可实现时钟显示、日期星期显示以及日期
时间更改等功能。
该电子万年历使用12MHZ晶振与单片机ATC52相连接,通过软件编程的方法实现了以24小时为一个周期,同时显示小时、分钟和秒的要求。利用单片机定时器及计数器产生定时效果通过编程形成数字钟效果,再
利用数码管动态扫描显示单片机内部处理的数据。同时通过端口读入当前外部控制状态来改变程序的不同状态,
实现不同功能。
电子万年历设计与制作可采用数字电路实现,也可以采用单片机来完成。若用数字电路完成,所设计的电路相
当复杂,大概需要十几片数字集成块,其功能也主要依赖于数字电路的各功能模块的组合来实现,焊接的过程比较
复杂,成本也非常高。若用单片机来设计制作完成,由于其功能的实现主要通过软件编程来完成,这样一来就降低了硬件电路的复杂性,从而使得其成本降低,更适合我们大学生自主研发。硬件部分主要由ATC52单片机,LCD显示电路,以及调时按键电路等组成。在单片机的选择上本人使用了ATC52单片机,该单片机适合于许多较为复杂控制应用场合。因此,采用单片机ATC52原理制作的电子万年历,不仅仅在原理上能够成功实现计时等功能,也更经济,更适用,更符合我们实际生活的需要,对我们大学生来说也更加有用。
关键词:电子万年历 52系列单片机时钟芯片 FLASH存储器液晶显示
1引言
在日新月异的21世纪里,家用电子产品得到了迅速发展。许多家电设备都趋于人性化、智能化,这些电器设备大部分都含有CPU控制器或者是单片机。单片机以其高可靠性、高性价比、低电压、低功耗等一系列优点,近几年得到迅猛发展和大范围推广,广泛应用于工业控制系统、通讯设备、日常消费类产品和玩具等。并且已经深入到工业生产的各个环节以及人民生活的各个方面,如车间流水线控制、自动化系统等、智能型家用电器(冰箱、空调、彩电)等。用单片机来控制的小型家电产品具有便携实用,操作简单的特点。
本文设计的电子万年历属于小型智能家用电子产品。利用单片机进行控制,实时时钟芯片进行记时,外加显示电路,和温度显示电路,可实现时间的调整和和温度的显示。电子万年历既可广泛应用于家庭,也可应用于银行、邮电、宾馆、医院、学校、企业、商店等相关行业的大厅,以及单位会议室、门卫等场所。因而,此设计具有相当重要的现实意义和实用价值。
2总体设计方案
2.1设计思路
2.1.1方案1——基于ATS52单片机的电子万年历设计
不使用时钟芯片,而直接用ATS52单片机来实现电子万年历设计。ATS52是一种带8K字节闪烁可编程可擦除只读存储器的低电压,高性能CMOS8位微处理器,俗称单片机。单片机的可擦除只读存储器可以反复擦写1000余次。由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的ATS52是一种高效微控制器,为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。
若采用单片机计时,利用它的一个16位定时器/计数器每50ms产生一个中断信号,中断20次后产生一个秒信号,然后根据时间进制关系依次向分、时、日、星期、月、年进位。这样就实
2
现了直接用单片机来实现电子万年历设计。
用单片机来实现电子万年历设计,无须外接其他芯片,充分利用了单片机的资源。但是精度
不够高,误差较大,掉电后丢失所有数据,软件编程较复杂。
2.1.2方案2——基于DS1302的电子万年历设计
在以单片机为核心构成的装置中,经常需要一个实时的时钟和日历,以便对一些实时发生事
件记录时给予时标,实时时钟芯片便可起到这一作用。过去多用并行接口的时钟芯片,如MC146818,DS12887等。它们已能完全满足单片机系统对实时时钟的要求,但是这些芯片与单片机接口复杂、占用地址,数据总线接线多、芯片体积大占用空间多、近年来串行接口的各种芯片在单片机系统中应用愈来愈多,串行接口的实时时钟芯片也出现了不少,DS1302是一个综合性能较好且价格便宜的串行接口实时时钟芯片。
利用单片机ATC52进行控制,采用DS1302作为实时时钟芯片,其三线接口SCLK、I/O、/RST与单片机进行同步通信,外加掉电存储电路、显示电路、键盘电路,即构成一个基本的电子万年历系统,若还要添加其他功能,在这基础上外扩电路即可。
由于在系统设计时,需要考虑以下几点因素:功耗低、精确度高、软件编程较简单,芯片的体积小、芯片成本低等,而DS1302芯片有上面所述的诸多优点,所以本设计采用方案2。
2.1.3方案3——基于ATC52单片机的电子万年历设计
本方案选用的是单片机(ATC52)来实现电子万年历的功能,DS1302作为实时时钟芯片。共具备两个功能:
(1)显示年月日及时分秒、星期、温度、农历日期等信息
(2)具有可调整日期和时间功能(具有闹钟调节模块,但是未能成功实现闹钟功能)。
该电子万年历能够成功实现时钟运行,调整功能,且精确度经调试一天的误差在2S内。
2.2设计方框图
该设计的硬件电路的总体框图如图4所示:
图4设计方框图
3
3设计原理分析
3.1时钟电路的设计
实时时钟芯片DS1302采用串行数据传输,可为掉电保护电源提供可编程的充电功能,也可以关闭充电功能,芯片采用32768Hz晶振。要特别说明的是,备用电源BT1可以用电池或超级电容(10万μF以上)。虽然DS1302在主电源掉电后耗电很小,但如果要长时间保证时钟正常,最好选用小型充电电池。如果断电时间较短(几小时或几天),可以用漏电较小的普通电解电容代替(100μF就可以保证1小时的正常走时)
。DS1302在第一次加电后,需进行初始化操作。初始化后就可以按正常方法调整时间及闹铃。DS1302的时钟电路如图5所示。
图5DS1302时钟电路
3.2控制电路的设计
ATS52单片机为40引脚双列直插芯片,有四个I/O口P0,P1,P2,P3,MCS-51单片机共有4个8位的I/O口(P0、P1、P2、P3),每一条I/O线都能地作输出或输入。18引脚和19引脚接时钟电路,XTAL1接外部晶振和微调电容的一端,在片内它是振荡器倒相放大器的输入,XTAL2接外部晶振和微调电容的另一端,在片内它是振荡器倒相放大器的输出.第9引脚为复位输入端,接上电容,电阻及开关后够上电复位电路,20引脚为接地端,40引脚为电源端。如图6所示:
图6万年历控制电路
4
1.微处理器
在设计过程中我使用单片机ATC52,通过软件编程的方法实现了以24小时为一个周期同时显示小时,分钟和秒的要求,该定时闹钟设有四个按键,使之具备了校时、定时功能。利用单片机定时器及计数器产生定时效果通过编程形成数字钟效果,再利用数码管动态扫描显示单片机内部处理的数据。同时通过端口读入当前外部控制状态来改变程序的不同状态,实现不同功能。在PROTEUS软件环境下的ATC52单片机如图1所示:
图1PROTEUS软件环境下的ATC52芯片
2.显示电路
就时钟而言,通常可采用液晶显示或数码管显示。由于一般的段式液晶屏,需要专门的驱动电路,而且液晶显示作为一种被动显示,可视性相对较差;对于具有驱动电路和微处理器接口的液晶显示模块(字符或点阵),一般多采用并行接口,对微处理器的接口要求较高,占用资源多。另外,ATC52本身无专门的液晶驱动接口,故使用液晶显示LGM121BS1R,对于显示文字比较适合。初始化时,由软件编写的指令就集中在显示功能的设置上。LGM121BS1R的指令可带一个、两个参数,或无参数。若指令中含有参数,则每条指令执行时均须先送入参数,再送入指令代码。由于状态位作用不一样,因此执行不同指令必须检测不同状态位。液晶显示模块LGM121BS1R如图2所示:
图2 液晶显示电路LGM121BS1R
3.按键电路
由于设计的是电子万年历,需要实现多种功能的显示,并要能够切换显示和调节年月日,故在设计过程中按键的设计就显得尤为重要。
5
在设计过程中我一共采用了4个按键,尽量在小的空间里实现最多的功能。其中return键是设置功能返回键,按下一次就能够直接退出功能设置模块。在调整显示环境下UP和DOWN键是显示调整位的的加1和减1键,FUNCTION键进入模块设置界面,以及“确定”功能。按键电路如图3所示:
图3 按键电路
3.3电路原理图
电路原理图如图7所示:
图7 万年历设计总原理图
6
3.4电路原理图
该设计主程序流程图如图8所示:
CPU初始化 启动走时
定时器0初始化变量初始化
定时器1初始化 判时分变化否?
Y
串口初始化刷新显示
显示待机指示符 判1秒到否?
Y
设置年秒指示
Y
设定月 时间显示
Y
显示刷新年代显示
星期显示
图8 主程序流程图
3.5软件仿真
加载源程序运行,顺利实现了单片机数字电子钟的“小时”、“分钟”、“秒”的显示。该
电子万年历的显示效果及电子万年历时间和日期的调节效果分别如图9和图10所示:
图9 电子万年历的运行效果
7
图10 电子万年历时间和日期的调节效果
3.6功能测试
表1 功能测试
-
计时功能 | LCD 能显示当前的时、分、和秒,具体是时跟分一起显示,分跟秒一起显示,通过按键来切换 |
星期显示功能 | 通过按键可以切换到星期显示的界面,按返回键则重新回到主界面显示 |
时间调整功能 | 通过按键可以调整或设定年、月、日、星期、时、分,且能实现秒的微调功能 |
室温检测并显示功能 | 通过智能传感器DS18B20 能够实现检测功能,并通过LCD 能完成液晶显示功能 |
闰年功能 | 能计时到万年,且能自动判断闰年与平年,并实现正确的计时操作 |
4结束语
通过这一周的课程设计,加深了我对于单片机和数字电路的认识,通过查阅大量的资料,我获得了以前在课堂上学不到的东西,我想这对于以后的毕业设计,或者工作也好,都是很有帮助的。
在设计电路中,往往是先仿真后连接实物图,但有时候仿真和电路连接并不是完全一致的,例如仿真的连接示意图中,往往没有接高电平的16脚或14脚以及接低电平的7脚或8脚,因此在实际的电路连接中往往容易遗漏。在设计的过程中遇到了很多问题,本来自己的单片机基础就比较弱,又是第一次做这样的设计,难免会遇到过各种各样的问题。同时在设计的过程中发现了自己的不足之处,比如对以前所学过的知识理解得不够深刻,掌握得不够牢固,对单片机汇编语言掌握得不好。此次的电子万年历设计重在于仿真和接线,虽然能把电路图接出来,并能正常显示,但对于电路本身的原理并不是十分熟悉.总的来说,通过这次的设计实验更进一步地增强了实验的动手能力。
8
参考文献
[1]李建忠.单片机原理及应用.西安电子科技大学出版2006.02
[2]余发山.单片机原理及及应用技术.中国矿业大学出版社 2003.12
[3]何立民.单片机应用技术选编.北京航空航天大学出版社2000.08
[4]周航慈.单片机程序设计基础.北京航空航天大学出版社 1991.11
[5]黄遵熹.单片机原理接口与应用.西北工业大学出版社 1997.05
附1 源程序代码
主程序代码
#include< reg52.h >
#include< character.h >
#include< lcd.h >
#include< clock.h >
#include< sensor.h>
#include< calendar.h >
#include< key.h >
/*****************************预定义**************************************/#define uchar unsigned char
#defineuint unsigned int
/****************************************************************************/sbit bell = P2 ^ 0; //定义蜂鸣器端口
sbitin = P2 ^ 7; //定义红外检测端口
/****************************************************************************** 名称:Timer0_Service() inturrupt 1
*功能:中断服务程序整点报时3声嘟嘟的声音
*****************************************************************************/void Timer0_Service() interrupt 1
{
static uchar count = 0;
static uchar flag = 0; //记录鸣叫的次数
count = 0;
TR0 = 0;
//关闭Timer0TH0 = 0x3c;
TL0 = 0XB0; //延时50ms
TR0 = 1 ; //启动Timer0
count ++;
if( count == 20 ) //鸣叫1秒
{
bell= ~ bell;
count= 0;
flag++;
9
}
if( flag == 6 )
{
flag= 0;
TR0= 0; //关闭Timer0
}
}
/****************************************************************************** 名称:Timer2_Servie() interrupt 5
*功能:中断服务程序整点报时一分钟
*****************************************************************************/void Timer3_Service() interrupt 5
{
static uchar count;
TF2 = 0; //软件清除中断标志
count ++;
if( in == 1 )
{
count= 0; //计算清0
TR2= 0; //关闭Timer2
bell= 1; //关闭蜂鸣器
}
if( count == 120 ) // 一分钟后关闭报警
{
count= 0; //计算清0
TR2= 0; //关闭Timer2
bell= 1; //关闭蜂鸣器
}
}
/******************************************************************************* 函数名称:main()
********************************************************************************/void main( void )
{
ucharclock_time[7] = { 0x00, 0x00, 0x12, 0x29, 0x06, 0x08 }; //定义时间变量秒分时日月年ucharalarm_time[2] = { 0, 0}; //闹钟设置 alarm_time[0]:分钟 alarm_time[1]:小时
uchartemperature[2]; //定义温度变量 temperature[0] 低8位 temperature[1] 高8位
Lcd_Initial(); //LCD初始化
clock_Initial(clock_time ); //时钟初试化
/***********************中断初始化***************************/
EA= 1; //开总中断
ET0= 1; //Timer0 开中断
10
ET2= 1; //Timer2 开中断
TMOD= 0x01 ; //Timer0 工作方式1
RCAP2H= 0x3c;
RCAP2L= 0xb0; //Timer2 延时50ms
while(1 )
{
switch( Key_Scan() )
{
caseup_array:
{
Key_Idle();
}
break;
casedown_array:
{
Key_Idle();
}
break;
case clear_array:
{
Key_Idle();
}
break;
case function_array:{
Key_Function(clock_time, alarm_time );
}
case null:
{
Clock_Fresh(clock_time ); //时间刷新
Lcd_Clock(clock_time ); //时间显示
Sensor_Fresh(temperature ); //温度更新
Lcd_Temperture( temperature ); //温度显示
Calendar_Convert(0 , clock_time );
Week_Convert( 0, clock_time );
//整点报时
if( ( * clock_time == 0x59 ) && ( * ( clock_time + 1 ) ==0x59 ) )
{
bell= 0;
TR2 = 1; //启动Timer2
}
//闹钟报警
11
if(* alarm_time == * ( clock_time + 1 ) ) //分钟相吻合
if(* ( alarm_time + 1 ) == *( clock_time + 2 ) ) //小时相吻合 {
bell= 0;
TR2= 1; //启动Timer2
}
}
break;
}
}
}
12