万年历设计嵌入式.docx
《万年历设计嵌入式.docx》由会员分享,可在线阅读,更多相关《万年历设计嵌入式.docx(27页珍藏版)》请在冰豆网上搜索。
万年历设计嵌入式
教师评阅:
□设计思路正确;□仿真结果正确可信;□设计成果符合要求;□设计报告规范;
□设计过程原始记录(元件参数、原理图、计算等)符合要求;□设计分析总结全面;评分:
摘要
随着经济的腾飞、科技的发展,信息起着越来越重要的作用。
计算机、网络和嵌入式等信息技术在各个领域的应用也愈来愈广泛,尤其是嵌入式技术。
在如今办、公生活领域,随处可见各种嵌入式设备,如手表、微波炉、录像机、汽车等,都使用嵌入式系统。
21世纪,是信息化的时代,是科学技术日新月异时代。
随着科技的不断进步与更新,以及人们对智能时代的向往,嵌入式技术将迎来属于它的春天。
本文以电子万年历为例,采用AT89C51作为主控芯片,选择DS1302作为时钟芯片,利用LCD1302液晶作为显示器件为主要部件。
实现了以时间、年份、星期的实时显示功能,并可对其进行修改保存。
关键词:
嵌入式;电子万年历;AT89C51。
ABSTRACT
Withtherapideconomicgrowth,technologicaldevelopment,informationplaysanincreasinglyimportantrole.Computers,networks,andembeddedinvariousfieldssuchasinformationtechnologyapplicationsareincreasinglywidespread,especiallyinembeddedtechnology.Intoday'soffice,thepublicareasoflife,youcanseeavarietyofembeddeddevices,suchaswatches,microwaves,VCRs,cars,etc.,alluseembeddedsystems.21stcenturyistheeraofinformationtechnology,istheeraofscienceandtechnology.Astechnologycontinuestoprogressandupdates,aswellaspeople'sdesireforsmartera,embeddedtechnologywillusherinapartofitsspring.
Inthispaper,electroniccalendar,forexample,usingAT89C51asthemasterchip,selectDS1302clockchipasusingLCD1302asadisplaypieceforthemaincomponents.Implementationofatime,year,week,real-timedisplayfunction,andcanbemodifiedtosave.
Keywords:
Embedded;Electroniccalendar;AT89C51.
一、系统基本方案选择与论证
1.1单片机芯片的选择方案与论证
AT89C51是一种带4K字节FLASH存储器(FPEROM—FlashProgrammableandErasableReadOnlyMemory)的低电压、高性能CMOS8位微处理器,俗称单片机。
它是一种带2K字节闪存可编程可擦除只读存储器的单片机。
单片机的可擦除只读存储器可以反复擦除1000次。
该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,AT89C2051是它的一种精简版本。
AT89C51单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。
1.2时钟芯片选择
方案一:
选择AT89C51单片机内部的定时器0或定时器1来提供基准的秒信号。
比如选择定时0的方式1来计数50ms,然后循环20次,便可提供1秒的基准信号,从而实现年、月、日、时、分等。
优点:
采用这种方案的话,系统外围的的器件比较少,且实现起来比较方便,成本也比较低。
但是这种方案也有其不足之处,作为万年历的设计,不仅要求简单实用,最重要的是要时间准确,误差极小。
缺点:
误差比较大,且没有掉电保护的功能,也就是说在掉电之后,需要手动再调准时间,使用上不是很方便。
方案二:
选择DS1302时钟芯片。
DS1302是DALLAS公司推出的涓流充电时钟芯片内含有一个实时,时钟/日历和31字节静态RAM,可通过简单的串行接口与单片机进行通信。
可提供:
--秒、分、时、日、月、年的信息;
--每月的天数和闰年的天数可自动调整;
--可通过AM/PM指示决定采用24或12小时格式;
--保持数据和时钟信息时功率小于1mW。
芯片的工作电压为2.0至5.0V,提供主电源和备用电源双电源引脚。
可以对后备电源进行涓细电流充电。
芯片采用串行接口方式和外部单片机进行同步通信,数据可以每次以一个字节或多个字节形式传送时钟信号或RAM数据。
综上所述,选择方案二。
1.3显示模块的选择
方案一:
选择LED数码管动态扫描。
优点:
数码管作为平时最常见的一种的显示器件,原理与实现方法相对比较简单,对于显示数字来说是不错的选择。
缺点:
增加外围设备的负担,显得不是很直观。
另外,虽说原理简单,但对于本设计来说,实现起来稍显复杂。
方案二:
选择LCD12864液晶显示模块。
LCD12864液晶显示模块是128×64点阵的汉字图形型液晶显示模块,可显示汉字及图形,内置8192个中文汉字(16X16点阵)、128个字符(8X16点阵)及64X256点阵显示RAM(GDRAM)。
可与CPU直接接口,提供两种界面来连接微处理机:
8-位并行及串行两种连接方式。
具有多种功能:
光标显示、画面移位、睡眠模式等。
LCD12864显示的信息很大,但随之带来的就是比较复杂的程序。
方案三:
选择LCD1602液晶显示模块。
LCD1602是字符点阵系列液晶模块,它是一类专门用于显示字母、数字、符号等的点阵型液晶显示模块,分为四位和八位数据传输方式,提供5*7点阵+光标和5*10点阵+光标的显示模式,提供显示数据缓冲区DDRAM、字符发生器CGRAM、CGROM,可以使用CGRAM来存储自己定义的最多8个5*8点阵的图形的字模数据。
程序设计相对LCD12864简单一些。
由于本设计要显示基本的时间信息,但又不需要显示汉字,综合考虑,选择方案三——LCD1302液晶显示模块。
二、系统硬件设计与实现
2.1系统总体框图
如图1所示,本设计从整体的框图上来看是比较简单的。
主要包括AT89C51主控单片机芯片、键盘模块、液晶显示模块、时钟芯片。
主控芯片AT89C51是整个系统的核心,接收键盘传入的信息,控制显示液晶,从DS13202中读取和写入数据等等一系列的操作和控制都在这里完成;键盘主要是为了纠正时间,对时间进行修改;液晶模块则是显示时间,星期,年月日;时钟芯片部分主要是进行计时。
2.2主控单元和按键部分设计
1.主控部分:
对于主控方面的设计,其实就是一个单片机的最小系统。
主控芯片使用的是AT89C51,可降至0Hz的静态逻辑操作,并支持两种软件可选的节电工作模式。
空闲方式停止CPU的工作,但允许RAM,定时/计数器,串行通信口及中断系统继续工作。
掉电方式保存RAM中的内容,但振荡器停止工作并禁止其它所有部件工作直到下一个硬件复位。
该系统主要包含两部分:
时钟部分和复位电路。
下面简单介绍一下这两部分。
时钟部分:
单片机工作时,从取指令到译码再进行微操作,必须在时钟信号控制下才能有序地进行,时钟电路就是为单片机工作提供基本时钟的。
单片机的时钟信号通常有两种产生方式:
内部时钟方式和外部时钟方式。
在本设计中显然采取的是外部时钟的方式。
选择的是12MHz,其机器周期是1us,也就是说执行一条单周期指令只需要1us,执行一条双周期指令则需要2us。
复位电路部分:
无论是在单片机刚开始接上电源时,还是运行过程中发生故障都需要复位。
复位电路用于将单片机内部各电路的状态恢复到一个确定的初始值,并从这个状态开始工作。
单片机的复位条件:
必须使其RST引脚上持续出现两个(或以上)机器周期的高电平。
2.按键部分:
按键部分的主要功能是,对时间进行修改,包含三个按键和三个上拉电阻。
功能键的作用是选择要改变的数据,按下增量键则是对数据在原来的基础上加一,减量键则是相反的共能。
2.3LCD1602显示模块
1.连接说明:
LCD1602显示器部分的电路原理以及连接方式如图3所示。
其中LCD1602的RS端口连接在单片机的P2.0口;使能端连接在P2.1口上;数据端口D7至D0则连接在单片机的P0口上。
2.引脚功能简介及说明。
表1:
LCD1602引脚功能
第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脚:
背光源负极。
3.LCD指令:
表2:
指令表
2.4DS1302时钟部分
上图示出DS1302电路原理图,其中Vcc1为后备电源,Vcc2为主电源。
在主电源关闭的情况下,也能保持时钟的连续运行。
DS1302由Vcc1或Vcc2两者中的较大者供电。
当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。
当Vcc2小于Vcc1时,DS1302由Vcc1供电。
X1和X2是振荡源,外接32.768KHz晶振。
RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。
RST输入有两种功能:
首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。
当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。
如果在传送过程中RSTS置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。
上电动行时,在Vcc大于等于2.5V之前,RST必须保持低电平。
中有在SCLK为低电平时,才能将RST置为高电平,I/O为串行数据输入端(双向)。
SCLK始终是输入端。
1.工作原理:
DS1302时钟芯片主要有寄存器、控制寄存器、振荡器、实时时钟以及RAM组成。
为了对任何数据传送进行初始化,需要将/RST置为高电平且将8位地址和命令信息装入移位寄存器。
数据在SCLK的上升沿沿串行输入,前8位指定访问地址,命令字装入移位寄存器后,在之后的时钟周期,读操作输出数据,写操作输入数据。
时钟的个数在单字节方式下为8加8(8位地址加8位数据),在多字节方式下为8加最多可达248的数据。
DS1302在每次进行读、写程序前都必须初始化,先把SCLK端置“0”,接着把RST端置“1”,最后才给予SCLK脉冲;读/写时序如下图2.3.3所示。
表2-1为DS1302的控制字,此控制字的位7必须置1,若为0则不能把对DS1302进行读写数据。
对于位6,若对程序进行读/写时RAM=1,对时间进行读/写时,
=0。
位1至位5指操作单元的地址。
位0是读/写操作位,进行读操作时,该位为1;该位为0则表示进行的是写操作。
控制字节总是从最低位开始输入/输出的。
表2-2为DS1302的日历、时间寄存器内容:
“CH”是时钟暂停标志位,当该位为1时,时钟振荡器停止,DS1302处于低功耗状态;当该位为0时,时钟开始运行。
“WP”是写保护位,在任何的对时钟和RAM的写操作之前,WP必须为0。
当“WP”为1时,写保护位防止对任一寄存器的写操作。
2.DS1302的控制字节
DS1302的控制字如表2.1所示。
控制字节的高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。
表3DS1302的控制字格式
RAMRD
1
A4A3A2A1A0
3.数据输入输出(I/O)
在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
如下图所示:
图5
4.DS1302的寄存器
DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字见表2.2。
此外,DS1302还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM相关的寄存器等。
时钟突发寄存器可一次性顺序读写除充电寄存器外的所有寄存器内容。
DS1302与RAM相关的寄存器分为两类:
一类是单个RAM单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;另一类为突发方式下的RAM寄存器,此方式下可一次性读写所有的RAM的31个字节,命令控制字为FEH(写)、FFH(读)。
表4DS1302寄存表
三、系统软件设计与实现
3.1系统总体软件流程图
从系统的总体流程图可以看出,在整个程序设计中,主要涉及到LCD1602初始化,DS1302初始话,定时器0的初始化以及按键的处理子程序;其实还有一些其他的辅助程序,例如BCD码与十六进制之间的转换函数等。
3.2LCD1602部分
1.初始化的流程图
2.涉及到的函数:
1)BCD码与十六进制之间的转换函数。
因为字符信息在LCD1602中是已BCD码的形式存储的。
所以需要将十六进制的数据转换成BCD码的形式,在传到液晶里去。
将BCD转十六进制的方法:
原高4位数据*10+低4位即可。
反过来的方法:
将十六进制数除以10,所得整数部分乘以16再加上原数据的个位即可。
2)延时函数:
延时函数相对比较简单,直接使用两个循环即可。
3)液晶写入指令和数据函数:
这两个函数的实现也是很简单的,设定相应模式,直接使用赋值语句即可。
比如说写如数据的函数:
先将RS口置一,然后将数据赋值给数据端口,延时一段时间,拉高使能端,再延时一段时间,最后再拉低使能端即可完成。
相应的写入指令函数,也可类似操作。
3.3DS1302部分
1.初始化的流程图:
2.涉及到的函数:
1)1302字节写函数:
主要实现往DS1302中写入一个字节的数据。
实现方法:
首先启动读写操作,使用循环,从最低位开始,一位一位的往里写,每写一位数据后,要制造一个时钟上升沿,这样数据采用写入。
2)字节读函数:
此函数的功能与写函数的正好相反,是从DS1302中读出一个数据。
只不过在读出的时候,是要制造一个下降沿才有效。
3)液晶地址、数据读函数。
在这个函数中,首先一样,得启动读写操作,然后调用写函数写入地址,再调用读函数,读出数据即可。
3.4按键处理子程序
1.功能键程序流程图:
当判断到功能键按下时,使用一个延时来消去抖动。
然后将标志加1,判断标志是否为9,如果为9将其置为1,这位做的原因是,总共需要修改的数据只有8位,因此以8为周期。
然后根据不同的标志,使用switch,case语句来判断需要修改的到底是哪个数据。
2.增、减量键程序流程图,以增量键为例:
增量键和减量键只有在功能键按下的时候才有效,其他情况不会产生任何操作。
当功能键按下的时候,程序扫描这两个按键。
比如当增量键按下的时候,同样会利用以个延时来消去抖动。
然后等待按键释放,按键释放后根据不同的标志值,将相应的数据加1,然后送至液晶显示并送至DS1302芯片存贮。
而相应的减量键则是一样的。
3.5定时器部分
定时器部分主要使用的是AT89C51内部的定时器中断。
在本设计中选定的定时器为定时器0,并选择其工作方式为方式1。
设定为每隔0.5ms读取一次DS1302中的数据并送至液晶显示器显示。
在中断处理程序中调用上面写好的数据读取函数即可。
四、设计心得
五、参考文献
[1]徐敏,等.单片机原理及其应用[M].北京:
机械工业出版社,2012.
[2]郑锋,等.51单片机典型应用开发范例大全[M].北京:
中国铁道出版社,2011.
[3]赵建领,等.精通51单片机开发技术与应用实例[M].北京:
电子工业出版社,2012.
[4]戴佳,等.51单片机C语言应用程序设计实例精讲[M].北京:
电子工业出版社,2006.
[5]郭天祥.新概念51单片机C语言教程[M].北京:
电子工业出版社,2009.
附录:
主要程序代码
#include
#defineuintunsignedint
#defineucharunsignedchar
//-------初始设置--------
ucharSecond,Minute,Hour,Date,Month,Year,week=0;//定义时间等变量
#defineone0x80//第一行的初始位置
#definetwo0xc0//第二行的初始位置
sbitRS_1602=P2^0;//1602RS端
sbitE_1602=P2^1;//1602使能端
sbitIO_1302=P2^4;//1302I/O端
sbitCLK_1302=P2^3;//1302时钟端
sbitRST_1302=P2^2;//1302复位端
sbitkey_mode=P1^0;//功能按键
sbitkey_up=P1^1;//增量键
sbitkey_down=P1^2;//减量键
sbitACC0=ACC^0;
sbitACC7=ACC^7;
ucharcodetab1[]={"20--week"};//液晶第一行默认显示数据
ucharcodetab2[]={":
:
"};//液晶第二行默认显示数据
//-------函数声明----------
voidinit();//定时器0初始化
ucharBCD_Decimal(ucharbcd);//BCD转16进制数
ucharDec_BCD(ucharDec);//16进制数转BCD
voiddelay(uintxms);//延时函数
write_1602com(ucharcom);//液晶写入指令函数
write_1602dat(uchardat);//液晶写入数据函数
voidwrite_hms(ucharadd,uchardat);//1602写时分秒
voidwrite_ymd(ucharadd,uchardat);//1602写年月日
voidwrite_week(ucharweek);//1602写星期函数
lcd_init();//液晶初始化函数
voidwrite_byte(uchardat);//1302字节写
ucharread_byte();//1302字节读
voidwrite_1302(ucharadd,uchardat);//1302地址写
ucharread_1302(ucharadd);//1302地址读
voidds1302_init();//1302初始化
voidkeyscan();//按键处理子程序
//-----------主函数----------
main()
{
lcd_init();
ds1302_init();
init();
while
(1)
keyscan();
}
//-------定时器0初始化--------
voidinit()
{
TMOD=0x01;//定时器0,16位定时器模式
TH0=0xFF;
TL0=0x06;
EA=1;//总中断使能
ET0=1;//定时器0中断使能
TR0=1;//定时器0启动
}
//--------BCD转16进制数----------
ucharBCD_Decimal(ucharbcd)
{
ucharDecimal;
Decimal=bcd>>4;//高4位移到低4位
return(Decimal=Decimal*10+(bcd&=0x0F));//原高4位数据*10+低4位
}
//--------16进制数转BCD----------
ucharDec_BCD(ucharDec)
{
ucharBCD;
BCD=(Dec)/10*16+(Dec)%10;
return(BCD);
}
//----------延时函数-----------
voiddelay(uintxms)
{
uinti,j;
for(i=xms;i>0;i--)
for(j=100;j>0;j--);
}
/******************液晶1602写入************************/
//--------液晶写入指令函数--------
write_1602com(ucharcom)
{
RS_1602=0;//置RS为0,写入命令
P0=com;//送入数据
delay
(1);
E_1602=1;//拉高使能端,为写操作做准备
delay
(1);
E_1602=0;//完成高脉冲
}
//--------液晶写入数据函数--------
write_1602dat(uchardat)
{
RS_1602=1;//置RS为1,写入数据
P0=dat;//送入数据
delay
(1);
E_1602=1;//拉高使能端
delay
(1);
E_1602=0;//完成高脉冲
}
//--------1602