多功能电子万年历.docx

上传人:b****5 文档编号:5755318 上传时间:2023-01-01 格式:DOCX 页数:76 大小:647.51KB
下载 相关 举报
多功能电子万年历.docx_第1页
第1页 / 共76页
多功能电子万年历.docx_第2页
第2页 / 共76页
多功能电子万年历.docx_第3页
第3页 / 共76页
多功能电子万年历.docx_第4页
第4页 / 共76页
多功能电子万年历.docx_第5页
第5页 / 共76页
点击查看更多>>
下载资源
资源描述

多功能电子万年历.docx

《多功能电子万年历.docx》由会员分享,可在线阅读,更多相关《多功能电子万年历.docx(76页珍藏版)》请在冰豆网上搜索。

多功能电子万年历.docx

多功能电子万年历

 

兰州理工大学第六届大学生电子设计竞赛

 

题目:

多功能电子万年历

学院:

计算机与通信学院

班级:

xxxxxxxx12级1班

姓名:

xxxx、xxxxxx、xxxxxx

学号:

12xx0xxx、12xx01xx、12xx01xx

 

兰州理工大学

目录

摘要2

1系统方案3

1.1比较与选择3

1.1.1界面显示和语音提示:

3

1.1.2时间的实现3

1.1.3处理器的选择3

1.2方案描述4

2理论分析与计算4

2.1日程设定与日期计算4

2.1.1日期计算4

3电路与程序设计7

3.1硬件设计7

3.1.1硬件系统分析7

3.1.2硬件描述7

3.2软件系统设计12

3.2.1软件流程图12

3.2.2各模块功能主程序设计14

4测试方案与测试结果17

4.1各模块调试方案17

4.1.1STC89C52主芯片调试17

4.1.2DS1302时钟芯片调试18

4.1.3蜂鸣器调试19

4.1.4AT24C08数据存储器调试20

4.1.512864LCD显示模块调试20

4.1.6总体调试21

结论22

系统功能22

操作说明:

23

参赛总结23

参考文献24

附录25

附录一系统原理图25

附录二原程序代码26

多功能电子万年历

摘要

电子万年历是一种非常广泛日常计时工具。

它可以对年、月、日、周日、时、分、秒进行精确计时,同时可显示闰年农历温度信息,在日常生活中极为实用,DS1302是常用的时钟芯片,价格低廉,精度高且对于数字电子万年历采用直观的数字显示,还具有时间校准等功能。

该系统以STC89C52单片机作为系统控制处理器,采用具有涓细电流充电能的低功耗实时时钟电路DS1302。

它可以对年、月、日、周日、时、分、秒进行计时。

同时通过蜂鸣器进行半整点报时和闹钟提示,并采用AT24C08数据存储器实现掉电数据存储功能.系统各个界面通过LCD12864显示。

关键词:

STC89C52,LCD12864,蜂鸣器,AT24C08,DS1302

1系统方案

1.1比较与选择

1.1.1界面显示和语音提示:

方案一:

用LCD1602显示,蜂鸣器定时语音提示。

用LCD1602显示,黄绿色背光,价格便宜,操作简单,但是无法显示汉字,无法完成题目阴历显示要求。

用蜂鸣器实现定时语音提示功能,成本较低,且控制容易。

方案二:

用12864液晶显示,ISD4004语音芯片或蜂鸣器实现语音提示。

12864液晶显示,蓝色背光,显示分辨率为128×64,具有灵活的接口方式和简单、方便的操作指令。

可以显示4行8列共32个汉字,且具有低电压低功耗的特点。

用ISD语音芯片,录音时间长,音质好,保存长久,控制功能灵活等优点。

另通过LM386功放和8欧0.5W喇叭播放实现语音提示,语音效果良好,且更具人性化,但是价格较高,难度较大,对初学者来说难以实现;所以最终选择蜂鸣器实现语音提示,用lcd12864显示。

1.1.2时间的实现

方案一:

用DS12C887实现时钟计数。

DS12C887内部带有锂电池和晶振,无外围器件,掉电可自动行走,并带有闹钟功能、内带114字节RAM等功能。

但是要控制Intel或Motorola总线时序复杂,并行通信占用I/O口多,而且体积大,管脚多,价格昂贵。

方案二:

用DS1302实现时钟计数。

DS1302是DALLAS公司推出的涓流充电时钟芯片内含有一个实时时钟/日历和31字节静态RAM。

采用SPI方式进行通信仅需用到三个I/O口。

DS1302需外加32.768MHZ晶振和3V纽扣电池,故其体积小,占用管脚少,功耗低,价格便宜操作简单。

1.1.3处理器的选择

AT89S52和STC89C52单片机都兼容标准MCS-51指令系统及80C51引脚结构,32KBytesFlash片内ROM,512Bytes的片内RAM,32个的I/O口,5个中断优先级2层中断嵌套中断,3个16位可编程定时计数器,2个全双工串行通信口,看门狗电路,片内时钟振荡器等功能。

其中AT公司的稳定性好,但价格偏贵,下载复杂,不便于最后调试。

而STC芯片价格比较便宜,且下载器制作简单(只需使用MAX232电平转换和连接串行口),体积少,下载方便。

1.2方案描述

●该方案以STC89C52单片机作中央处理器,采用keil软件和C语言程序作软件设计,控制其I/O口。

●时间获取通过模拟SPI通信方式控制DS1302时钟芯片的时间设定与读取,并通过LCD12864液晶显示,同时可通过控制四个按键来实现对时间、闹钟的设定与修改。

闹钟功能是通过不断的读取设定时间与当前时间相比较,一旦符合条件就调用相应的子程序来实现特定的显示或语音提示。

●语音报时是MCU根据当前的时间,发送控制指令实现蜂鸣器在指定的时间放音。

●最后用AT24C08数据存储器,实现掉电后对闹钟时间和相关的变量等数据进行保存。

 

2理论分析与计算

2.1日程设定与日期计算

2.1.1日期计算

2.1.1.1阳历计算

阳历通过DS1302时钟芯片读取。

首先用MCU驱动时钟芯片,设置其片内时间,然后再分别读取年、月、日、时、分、秒读出来的年月日都是BCD码,则应在将它们送到LCD显示之前得先把他们转换为十进制形式。

●先读秒寄存器的数据,然后将其赋给变量time,因为秒的数据寄存器有一个字节的大小,即8位,其中低四位是用来存放秒的个位的,5、6、7位是用来存放秒的十位的,最高位CH是控制时钟的启动的当CH=1时,时钟振荡停止,CH=0时,时钟启动。

转换为十进制则秒的十位为(time&0x70)>>4,个位为(time&0x0f),十位跟个位组合起来后赋给变量miao=((time&0x70)>>4)*10+(time&0x0f);

●同理根据分、小时,星期、日期、月份、年份分别根据相应的数据寄存器读出来分别赋给一个变量,再送到LCD显示出来

fen=((time&0x70)>>4)*10+(time&0x0f);//分的十进制形式

shi=((time&0x70)>>4)*10+(time&0x0f);//小时的十进制形式

day=(time&0x07);//星期的十进制形式

ri=((time&0x30)>>4)*10+(time&0x0f);//日期的十进制形式

yue=((time&0x10)>>4)*10+(time&0x0f);//月份的十进制形式

nsg=((time&0xf0)>>4)*10+(time&0x0f)//年份的十进制形式

●DS1302保存的年份数据寄存器的数据范围为0~99,因此读出来之后不能直接放到LCD显示,得加上年份的千百位,比如要显示2009,得先往年份寄存器写入9,再读出来,加上2000,再放到LCD显示。

所以要真正的做到时钟显示年份正确还得设置年的千百位变量(unsignedchar)nqb,将其乘上100即nqb*100,再加上从ds1302读出来的年份的十个位nsg,才是完整的年份的时间。

要达到保存的效果,在断电之前还得将年份的千百位保存到AT24C04,在恢复电源时将其读回来,加上从ds1302读回来的年份的十个位在赋给(unsignedint)nian=nqb*100+nsg.再将其送到LCD显示。

阳历计算流程图

2.1.1.2阴历计算

通过查找资料,找到阴阳历转化方法,经过整理修改,最终合成我们需要的函数。

●阳历年对应的阴历数据,每年三字节,例如:

0x0C,0x96,0x45,//2000年

0x5C,0x95,0xBA,//2009年

●第一字节BIT7-4位表示闰月月份,值为0为无闰月,BIT3-0对应阴历第1-4月的大小

第二字节BIT7-0对应阴历第5-12月大小,

第三字节BIT7表示阴历第13个月大小,月份对应的位为1表示本阴历月大(30天),为0表示小(29天)

第三字节BIT6-5表示春节的阳历月份,BIT4-0表示春节的阳历日期

●首先,先读取我们当前阳历时间:

2009-5-20;然后代入以下函数转换

(具体函数见附录程序)

3电路与程序设计

3.1硬件设计

3.1.1硬件系统分析

3.1.1.1硬件选择

51单片机STC89C52,实时时钟DS1302,IIC芯片AT24C08,蜂鸣器,液晶12864。

3.1.1.2硬件框图

 

图3.1硬件框图

3.1.2硬件描述

3.1.2.1DS1302时钟芯片

DS1302是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。

采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。

它有主电源/后背电源双电源引脚,同时提供了对后背电源进行涓细电流充电的能力。

●X1X232.768KHz晶振管脚

●GND地

●RST复位脚

●I/O数据输入/输出引脚

●SCLK串行时钟

●Vcc1,Vcc2电源供电管脚

图3.3DS1302引脚图

图3.4DS1302单字节读时序

图3.5DS1302读写时序图

图3.6DS1302电路图

3.1.2.3蜂鸣器

图3.7蜂鸣器电路图

3.1.2.4数据存储器

串行E2PROM是基于I2C-BUS的存储器件,遵循二线制协议,其具有接口方便,保存时间长,体积小,数据掉电不挥发等特点,

●A0A1A2器件地址选择

●SDA串行数据/地址

●SCL串行时钟

●WP写保护

●Vcc+1.8V6.0V工作电压

●Vss地

图3.8AT24C08数据存储器

图3.9任一地址写入数据格式

图3.10任一地址读取数据格式

图3.11AT24C08电路图

3.1.2.5LCD显示

该模块采用带中文字库的128X64是一种具有4位/8位并行、2线或3线串行多种接口方式,内部含有国标一级、二级简体中文字库的点阵图形液晶显示器,其显示分辨率为128×64,内置8192个16*16点汉字,和128个16*8点ASCII字符集。

利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。

可以显示8×4行16×16点阵的汉字,也可完成图形显示,且具有低电压低功耗的特点。

图3.14lcd12864引脚功能

图3.13LCD12864电路图

3.2软件系统设计

3.2.1软件流程图

图3.14总程序流程图

图3.15阳历计算程序流程图

图3.16时间调整程序流程图

3.2.2各模块功能主程序设计

3.2.2.1DS1302时钟芯片的读写

voidWriteDs1302Byte(unsignedchartemp)

{

unsignedchari;

for(i=8;i>0;i--)

{

DS1302_IO=temp&0x01;

DS1302_CLK=0;

DS1302_CLK=1;

temp>>=1;

}

}

voidWriteDs1302(unsignedcharaddress,unsignedchardat)

{

DS1302_RST=0;

DS1302_CLK=0;

DS1302_RST=1;

delay

(1);

WriteDs1302Byte(address);

WriteDs1302Byte(dat);

DS1302_RST=0;

}

unsignedcharread_byte()

{unsignedchari;

for(i=8;i>0;i--)

{

if(DS1302_IO)

temp0=temp0|0x80;

DS1302_CLK=1;

DS1302_CLK=0;

temp0=temp0>>1;

}

returntemp0;

}

unsignedcharReadDs1302(unsignedcharaddress)

{

unsignedchartemp;

DS1302_RST=0;

DS1302_CLK=0;

DS1302_RST=1;

WriteDs1302Byte(address);

temp=read_byte();

DS1302_RST=0;

DS1302_CLK=1;

returntemp;

}

3.2.2.2LCD12864

voidWriteDataLCD(unsignedchardat)

{

LCD_RS=1;

LCD_RW=0;

LCD_E=0;

delay

(2);

LCD_Data=dat;

delay

(2);

LCD_E=1;

delay(5);

LCD_E=0;

delay(5);

}

voidWriteCommandLCD(unsignedcharudat)

{

LCD_RS=0;

LCD_RW=0;

LCD_E=0;

delay

(2);

LCD_Data=udat;

delay

(2);

LCD_E=1;

delay(5);

LCD_E=0;

delay(5);}

voidLCDInit(void)

{

WriteCommandLCD(0x30);

WriteCommandLCD(0x01);

WriteCommandLCD(0x06);

WriteCommandLCD(0x0C);

}

voidLCDClear(void)

{

WriteCommandLCD(0x01);

WriteCommandLCD(0x34);

WriteCommandLCD(0x30);

}

voidLCDSendWord(unsignedchar*p)

{

while(*p>0)

{

WriteDataLCD(*p);

p++;

}

}

voidLCDTestWord(biti,unsignedcharword)

{

if(i==0)

{

WriteCommandLCD(word);

}

else

{

WriteDataLCD(word);

}

}

3.2.2.3AT24C08数据存储器

voidstart()

{

sda=1;

scl=1;

delays();

sda=0;

delays();

}

voidstop()

{

sda=0;

scl=1;

delays();

sda=1;

delays();

}

voidresponse()

{

uchari;

while((sda==1)&&i<255)i++;//给应答信号sda=0;错误(while((sda==0)|i<255)i++;)程序进入while死循环

scl=1;

delays();

scl=0;//没有这一步出错,如果sda=0状态,一直处于应答中。

程序停止。

delays();

}

voidwrite24c02(uchardate)

{

uchartemp,i;

temp=date;

for(i=0;i<8;i++)

{

scl=0;

sda=temp&0x80;

delays();

scl=1;

delays();

temp=temp<<1;

}

scl=0;

delays();

sda=1;

delays();

}

ucharread24c02()

{

uchark,i;

scl=0;

delays();

sda=1;//仅仅是释放数据线,可有可无

for(i=0;i<8;i++)

{

scl=1;

delays();

k=k<<1;

if(sda)

k++;

scl=0;

delays();

}

returnk;

}

voidwrite_24c02add(ucharaddress,uchardate)

{

start();

write24c02(0xa0);

response();

write24c02(address);

response();

write24c02(date);

response();

stop();

}

ucharread_24c02add(ucharaddress)

{

uchara;

start();

write24c02(0xa0);

response();

write24c02(address);

response();

start();

write24c02(0xa1);

response();

a=read24c02();

stop();

returna;

}

4测试方案与测试结果

4.1各模块调试方案

采用先分别上网查找各芯片的资料,找到经典接法,然后在面包板上连接好电路,调试各单元模块,成功后再进行整个系统连调的方法,方便寻找错误,提高效率。

4.1.1STC89C52主芯片调试

主要测试STC89C52的内存大小,通过下载器和烧录软件将多功能万年历程序下载到单片机中,看能否装下程序。

在通过单片机开发板和其它外围电路及相应程序测试单片机工作是否正常。

图4.1单片机最小系统电路图

4.1.2DS1302时钟芯片调试

出现问题:

从DS1302读出来的数据放到显示屏显示的时候发现不正确,秒钟不是从0到59之间跳变,而是在0到89之间跳变。

问题解决:

●刚开始读得出数据以为DS1302的读写程序写对了。

以为是其他程序出现了问题,但是通过反复查找程序的问题无结果时,又开始继续转向DS1302的程序问题。

通过进一步查看DS1302的数据手册发现,DS1302存放时间(秒、分、时、星期、日期、月份、年份)的寄存器并不是以十进制的形式存放的,而是以BCD码的形式存放的,如下图:

⏹秒寄存器地址秒的数据寄存器

●秒的数据寄存器的大小占一个字节,共8位,其中“低四位”用来存放秒的“个位”,“高四位”的低三位用来存放秒的“十位”。

因此若把数据读出来直接放到LCD显示,会发现数据范围变大了就是这个原因。

所以在把秒数据读出来后放到LCD显示之前得先把它转换为十进制的形式,假设将它读出来的数据赋给一个变量time,则秒的十位通过取它的数据寄存器的高四位的低三位即((time&0x70)>>4)获得,秒的个位通过取出秒的低四位,即(time&0x0f)获得,最后秒的十进制形式为((time&0x70)>>4)*10+(time&0x0f)。

●通过查数据手册可知秒的最高位CH是暂停位,当CH=1时,时钟振荡停止,器件被置入低功率备份方式,其电源电流小于100NA,当CH=0时,时钟启动。

分寄存器地址分的数据寄存器

同理读出来的分钟的BCD码转换为十进制为((time&0x70)>>4)*10+(time&0x0f)。

小时寄存器地址小时数据寄存器

读出来的小时的BCD码转换为十进制为((time&0x70)>>4)*10+(time&0x0f)。

日期寄存器地址日期数据寄存器

读出来的日期的BCD码转换为十进制为((time&0x30)>>4)*10+(time&0x0f)。

星期寄存器地址星期数据寄存器

读出来的星期的BCD码转换为十进制为(time&0x07).。

月份寄存器地址月份数据寄存器

读出来的月份的BCD码转换为十进制为((time&0x10)>>4)*10+(time&0x0f)。

年份寄存器地址年份数据寄存器

读出来的年份的BCD码转换为十进制为((time&0xf0)>>4)*10+(time&0x0f)。

写保护寄存器

●写保护寄存器中的最高位WP是写保护位。

在对时钟进行写操作前WP必须为0,否则不可写入,在读操作时总是读0。

当WP=1时,可防止如何寄存器进行写操作。

4.1.3蜂鸣器调试

将下图蜂鸣器电路在万能板上连好后,下载程序到STC89C52中,观察蜂鸣器声音是否正常。

图4.2蜂鸣器电路

4.1.4AT24C08数据存储器调试

出现问题:

AT24C08内存大小为1024字节(1024×8位)。

但是当往AT24C08保存数据的地址超过511(例如地址512、513)的时候,发现把保存在AT24C08的低地址(例如地址1、2)的数据给覆盖了,即地址超过511后又默认从地址1开始保存。

问题解决:

经过分析思考,可能是把AT24C02(256个字节)的操作用在AT24C08的操作上了,即两者的操作有所不同。

从内容可知AT24C02是传送8位的内部器件地址进行寻址,而AT24C08的是传送10位的内部器件地址进行寻址,这时才知道,确实跟猜测的一样,一直把AT24C08当AT24C02来用。

●AT24C08的外部器件寻址只用到了8位,其中高四位1010是固定地址,A2跟A1是可编程地址,即最多可以并联4个AT24C04。

A0没有用到。

P0是AT24C08九位内部器件寻址中的最高位,即当进行器件内部寻址超过511的时候,要将最高位地址P0置1,再减去511,放在另外低8位的地址。

●具体如下,首先把要寻址的地址赋给一个无符号整形(unsignedint)变量add。

p=add>>8;//取出地址的高八位

p=p<<1;//高八位右移一位

start();//发出起始信号

write(0xa0|p);//外部器件寻址

respond();//响应

write(add&0xff);//地址的低八位,器件内部寻址

respond();//响应

write(date);//写数据

respond();//响应

stop();//停止

这样当要进行器件内部寻址超过255的时候P0将变为1,剩下的减去255将是储存在器件内部地址低八位地址。

这样就完成了9位寻址。

4.1.512864LCD显示模块调试

编写程序使LCD12864显示多功能电子万年历中要显示的所有汉字和符号,看是否都能正常显示。

问题出现:

通过测试发现本次使用的LCD12864液晶屏不能显示汉字“三”。

问题解决:

方案一:

测试看LCD12864能否显示汉字“叁”,若能显示则用汉字“叁”替代汉字“三”。

方案二:

使用LCD12864汉字取模软件获取汉字“三”的代码。

4.1.6总体调试

下载多功能电子万年历程序到单片机中,通电观察万年历是否工作正常,按键是否正常等,如发现问题,根据问题修改程序,反复修改直到电子万年历功能和操作达到最佳。

 

结论

系统功能

大赛要求:

1、基本要求

(1)能显示阳历年、月、日、星期、小时、分、秒

(2)显示模块采用LCD液晶显示,要求能用按键调整时间。

(3)能显示阴历月、日,在显示阴历时间时能标明是否为闰年。

(4)具有定时报警功能,能够进行整点和半点语音报时。

(5)具有闹铃设定功能

2、发挥部分

(1)掉电存储功能,可存储掉电前用户定时设置。

(2)具有日程管理,可以设定指定

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1