兰州理工大学第六届大学生电子设计竞赛
题目:学院:班级:姓名:学号:
多功能电子万年历 计算机与通信学院 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.1 STC89C52主芯片调试....................................... 17 4.1.2 DS1302时钟芯片调试...................................... 18 4.1.3 蜂鸣器调试 ............................................... 19 4.1.4 AT24C08数据存储器调试................................... 20 4.1.5 12864LCD显示模块调试..................................... 20 4.1.6 总体调试 ................................................. 21 结论 ............................................................. 22 系统功能 ......................................................... 22 操作说明: ....................................................... 23 参赛总结 ......................................................... 23 参考文献 ......................................................... 24 附录 ............................................................. 25 附录一 系统原理图 ............................................... 25 附录二 原程序代码 ................................................ 26
- 1 -
多功能电子万年历
摘要
电子万年历是一种非常广泛日常计时工具。它可以对年、月、日、周日、时、分、秒进行精确计时,同时可显示闰年农历温度信息,在日常生活中极为实用,DS1302是常用的时钟芯片,价格低廉,精度高且对于数字电子万年历采用直观的数字显示,还具有时间校准等功能。
该系统以STC89C52单片机作为系统控制处理器,采用具有涓细电流充电能的低功耗实时时钟电路DS1302。它可以对年、月、日、周日、时、分、秒进行计时。同时通过蜂鸣器进行半整点报时和闹钟提示,并采用AT24C08数据存储器实现掉电数据存储功能.系统各个界面通过LCD12864显示。
关键词:STC89C52, LCD 12864, 蜂鸣器, AT24C08, DS1302
2
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引脚结构,32K Bytes Flash片内ROM,512Bytes的片内RAM,32个的I/O口,5个中断优先级2层中断嵌套中断,3个16位可编程定时计数器,2个全双工串行通信
3
口,看门狗电路,片内时钟振荡器等功能。其中AT公司的稳定性好,但价格偏贵,下载复杂,不便于最后调试。而STC芯片价格比较便宜,且下载器制作简单(只需使用MAX232电平转换和连接串行口),体积少,下载方便。
1.2 方案描述
该方案以STC89C52单片机作中央处理器,采用keil软件和C语言程序作
软件设计,控制其I/O口。
时间获取通过模拟SPI通信方式控制DS1302时钟芯片的时间设定与读取,并通过LCD12864液晶显示,同时可通过控制四个按键来实现对时间、闹钟的设定与修改。闹钟功能是通过不断的读取设定时间与当前时间相比较,一旦符合条件就调用相应的子程序来实现特定的显示或语音提示。
语音报时是MCU根据当前的时间,发送控制指令实现蜂鸣器在指定的时间放音。
最后用AT24C08数据存储器,实现掉电后对闹钟时间和相关的变量等数据进行保存。
DS1302 AT24C08
STC89C52 LCD12864 蜂鸣器 2 理论分析与计算
2.1 日程设定与日期计算
2.1.1 日期计算
2.1.1.1 阳历计算
阳历通过DS1302时钟芯片读取。首先用MCU驱动时钟芯片,设置其片内
4
时间,然后再分别读取年、月、日、时、分、秒读出来的年月日都是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显示。所以要真正的做到时钟显示年份正确还得设置年的千百位变量(unsigned char)nqb,将其乘上100即nqb*100,再加上从ds1302读出来的年份的十个位nsg,才是完整的年份的时间。要达到保存的效果,在断电之前还得将年份的千百位保存到AT24C04,在恢复电源时将其读回来,加上从ds1302读回来的年份的十个位在赋给(unsigned int)nian=nqb*100+nsg.再将其送到LCD显示。
5
阳历计算流程图
2.1.1.2 阴历计算
通过查找资料,找到阴阳历转化方法,经过整理修改,最终合成我们需要的函数。
阳历年对应的阴历数据,每年三字节, 例如:
0x0C,0x96,0x45, //2000年 0x5C,0x95,0xBA, //2009年
第一字节BIT 7-4位表示闰月月份,值为0为无闰月,BIT 3-0对应阴历第1-4
月的大小
第二字节BIT 7-0对应阴历第5-12月大小,
第三字节BIT 7表示阴历第13个月大小,月份对应的位为1 表示本阴历月大(30天),为0表示小(29天)
第三字节BIT 6-5 表示春节的阳历月份,BIT 4-0表示春节的阳历日期
首先,先读取我们当前阳历时间:2009-5-20;然后代入以下函数转换
(具体函数见附录程序)
6
3 电路与程序设计
3.1 硬件设计
3.1.1 硬件系统分析
3.1.1.1 硬件选择
51单片机STC89C52,实时时钟DS1302,IIC芯片AT24C08,蜂鸣器,液晶12864。
3.1.1.2 硬件框图
LCD12864 蜂鸣器 选择 STC89C52 DS1302 AT24C08 上调 确定 下调 图3.1 硬件框图
3.1.2 硬件描述
3.1.2.1 DS1302时钟芯片
DS1302是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。它有主电源/后背电源双电源引脚,同时提供了对后背电源进行涓细电流充电的能力。
●
X1 X2 32.768KHz 晶振管脚
7
GND 地 ●RST 复位脚
●I/O 数据输入/输出引脚 ●SCLK 串行时钟
●Vcc1,Vcc2 电源供电管脚
图3.3 DS1302引脚图
●
图3.4 DS1302单字节读时序
图3.5 DS1302读写时序图
图3.6 DS1302电路图
3.1.2.3 蜂鸣器
8
图3.7 蜂鸣器电路图
3.1.2.4 数据存储器
串行E2PROM是基于I2C-BUS的存储器件,遵循二线制协议,其具有接口方便,保存时间长,体积小,数据掉电不挥发等特点,
A0 A1 A2 器件地址选择 SDA 串行数据/地址 SCL 串行时钟 WP 写保护
Vcc +1.8V 6.0V 工作电压
Vss 地
图3.8 AT24C08数据存储器
图3.9 任一地址写入数据格式
9
图3.10 任一地址读取数据格式
图3.11 AT24C08电路图
3.1.2.5 LCD显示
该模块采用带中文字库的128X64是一种具有4位/8位并行、2线或3线串行多种接口方式,内部含有国标一级、二级简体中文字库的点阵图形液晶显示器,其显示分辨率为128×64, 内置8192个16*16点汉字,和128个16*8点ASCII字符集。利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。可以显示8×4行16×16点阵的汉字,也可完成图形显示,且具有低电压低功耗的特点。
图3.14 lcd12864引脚功能
10
图3.13 LCD12864电路图
11
3.2 软件系统设计
3.2.1 软件流程图
图3.14 总程序流程图
12
图3.15 阳历计算程序流程图
13
图3.16 时间调整程序流程图
3.2.2 各模块功能主程序设计
3.2.2.1 DS1302时钟芯片的读写 void WriteDs1302Byte(unsigned DS1302_CLK=1; char temp) temp>>=1; {
} unsigned char i; }
for (i=8;i>0;i--) void WriteDs1302( unsigned {
address,unsigned char dat ) DS1302_IO=temp&0x01; {
DS1302_CLK=0;
DS1302_RST=0;
14
char
DS1302_CLK=0; } DS1302_RST=1; return temp0; delay(1); } WriteDs1302Byte(address); unsigned char ReadDs1302(unsigned WriteDs1302Byte(dat); char address) DS1302_RST=0; { } unsigned char temp; unsigned char read_byte() DS1302_RST=0; { unsigned char i; DS1302_CLK=0; for(i=8;i>0;i--) DS1302_RST=1; { WriteDs1302Byte(address); if(DS1302_IO) temp=read_byte(); temp0=temp0|0x80; DS1302_RST=0; DS1302_CLK=1; DS1302_CLK=1; DS1302_CLK=0; return temp;
} temp0=temp0>>1;
3.2.2.2 LCD12864 void WriteDataLCD(unsigned char delay(5);} dat) void LCDInit(void) { { LCD_RS=1; WriteCommandLCD(0x30); LCD_RW=0; WriteCommandLCD(0x01); LCD_E=0; WriteCommandLCD(0x06); delay(2); WriteCommandLCD(0x0C); LCD_Data=dat; } delay(2); void LCDClear(void) LCD_E=1; { delay(5); WriteCommandLCD(0x01); LCD_E=0; WriteCommandLCD(0x34); delay(5); WriteCommandLCD(0x30); } } void WriteCommandLCD(unsigned void LCDSendWord(unsigned char char udat) *p) { { LCD_RS=0; while(*p>0) LCD_RW=0; { LCD_E=0; WriteDataLCD(*p); delay(2); p++; LCD_Data=udat; } delay(2); } LCD_E=1; void LCDTestWord(bit i,unsigned delay(5); char word) LCD_E=0; {
15
if(i==0) { WriteCommandLCD(word); } else 3.2.2.3 AT24C08数据存储器 void start() {
sda=1; scl=1; delays(); sda=0; delays(); }
void stop() {
sda=0; scl=1; delays(); sda=1; delays(); }
void response() {
uchar i;
while((sda==1)&&i<255)i++; //给应答信号sda=0;错误(while((sda==0)|i<255)i++;)程序进入while 死循环 scl=1; delays();
scl=0; //没有这一步出错,如果sda=0状态,一直处于应答中。程序停止。 delays(); }
void write24c02(uchar date) {
uchar temp,i; temp=date;
for(i=0;i<8;i++) {
scl=0;
sda=temp&0x80;
{ WriteDataLCD(word); } } delays(); scl=1; delays(); temp=temp<<1; }
scl=0; delays(); sda=1; delays(); }
uchar read24c02() {
uchar k,i; scl=0; delays();
sda=1;//仅仅是释放数据线,可有可无
for(i=0;i<8;i++) {
scl=1; delays(); k=k<<1; if(sda) k++; scl=0; delays(); }
return k; } void write_24c02add(uchar address,uchar date) {
start();
write24c02(0xa0); response();
write24c02(address); response();
write24c02(date);
16
response(); stop(); } uchar read_24c02add(uchar address) {
uchar a; start();
write24c02(0xa0); response();
write24c02(address); response(); start();
write24c02(0xa1); response(); a=read24c02(); stop(); return a; }
4 测试方案与测试结果
4.1 各模块调试方案
采用先分别上网查找各芯片的资料,找到经典接法,然后在面包板上连接好电路,调试各单元模块,成功后再进行整个系统连调的方法,方便寻找错误,提高效率。
4.1.1 STC89C52主芯片调试
主要测试STC89C52的内存大小,通过下载器和烧录软件将多功能万年历程序下载到单片机中,看能否装下程序。在通过单片机开发板和其它外围电路及相应程序测试单片机工作是否正常。
17
图4.1 单片机最小系统电路图
4.1.2 DS1302时钟芯片调试
出现问题:
从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)。
18
日期寄存器地址 日期数据寄存器
读出来的日期的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 蜂鸣器电路
19
4.1.4 AT24C08数据存储器调试
出现问题:
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位的地址。 具体如下,首先把要寻址的地址赋给一个无符号整形(unsigned int)变量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.5 12864LCD显示模块调试
编写程序使LCD12864显示多功能电子万年历中要显示的所有汉字和符号,看是否都能正常显示。 问题出现:
通过测试发现本次使用的LCD12864液晶屏不能显示汉字“三”。 问题解决:
方案一:测试看LCD12864能否显示汉字“叁”,若能显示则用汉字“叁”替
20
代汉字“三”。
方案二:使用LCD12864汉字取模软件获取汉字“三”的代码。
4.1.6 总体调试
下载多功能电子万年历程序到单片机中,通电观察万年历是否工作正常,按键是否正常等,如发现问题,根据问题修改程序,反复修改直到电子万年历功能和操作达到最佳。
21
结论
系统功能
大赛要求:
1、基本要求
(1)能显示阳历年、月、日、星期、小时、分、秒 (2)显示模块采用LCD液晶显示,要求能用按键调整时间。 (3)能显示阴历月、日,在显示阴历时间时能标明是否为闰年。 (4)具有定时报警功能,能够进行整点和半点语音报时。 (5)具有闹铃设定功能
2、发挥部分
(1)掉电存储功能,可存储掉电前用户定时设置。
(2)具有日程管理,可以设定指定日期的日程,可以设置日程的提醒时间,并可用语音进行提示。
(3)可以保存30个日程设定,每个日程的提醒采用音乐提醒,至少有5首歌曲进行选择播放,提示音乐具有重复播放功能。 作品功能介绍:
1. 具有6秒开机界面显示,如下图所示:
2. 可以设定两个闹钟,而且具有独自的开关,闹钟响1分钟后停止。 3. 具有半点和整点提示,为了不影响休息,半点和整点提示设置在6:00 – 23:00之间,半点提示蜂鸣器响两声,整点提示响5声。 4. 可显示当年为闰年还是平年。 5. 可显示当年生肖。
22
6. 具有节日和纪念日提醒。 7. 可显示阴历。 8. 具有按键音。
操作说明:
第一个按键为【选择】键;
第二个按键为【确定】键; 第三个按键为【上调】键; 第四个按键为【下调】键。
参赛总结
本文介绍了为大赛而准备的设计方案,该系统以STC89C52单片机作为系统控制处理器,同时集合了DS1302时钟芯片、12864液晶显示、蜂鸣器、AT24C08数据存储器,通过c语言设计程序,最终实现了一个多功能电子万年历。
从一开始的组队,题目的挑选,队员的分工,到后来一个半月的奋战,终于完成了当初预定的目标,在参赛之前对单片机不了解,也没有学习过单片机,制作阶段大部分时间都用在了单片机的学习上了,通过查资料并且通过单片机开发板实践,终于弄懂了单片机的工作原理。多功能电子万年历的设计主要难在程序上,各模块都是一些固定接法。本次设计也使用了很多软件,比如protel 99 SE、proteus、Keil uvsion 4、photoshop CS 6、lcd取模软件等。一些软件之前都没接触过,特别是使用protel作图。最初打算使用proteus仿真的,但最终没有实现,使用protel作电路图简洁明了。
经历了本次设计,队员们掌握了焊接技巧、元件识别、电路设计、相关软件使用、单片机程序设计。更重要的是锻炼了大家的动手能力和协作能力。
23
参考文献
[1] 郭天祥编.新概念51单片机C语言教程.北京:电子工业出版社,2009.
[2] 周兴华编.手把手教你学单片机C程序设计.北京:北京航空航天大学出版社,2008.6. [3] 谭浩强编.C程序设计.北京:清华大学出版社,2008.7.
[4] 张元良编.单片机原理及应用教程北京:清华大学出版社,2011.2
[5] 王连相,赵付青编.C/C++程序设计教程.北京:中国铁道出版社,2011.2
[6] 王雅芳编.Protel 99 SE 电路设计与制版从入门到提高.北京:机械工业出版社,2011.4
24
附录
附录一 系统原理图
25
附录二 原程序代码
#include #define uchar unsigned char #define uint unsigned int unsigned char sec,min,hour,day,month,year,cen,week, next,c1,d1,m1,c2,d2,m2,temp0,LunarMonth, LunarDay,LunarYear; int temp; uchar tt=1; bit c_moon; bit cenbit=1; bit w; sbit LCD_RS=P2^4; sbit LCD_RW=P2^3; sbit LCD_E=P2^2; sbit PSB=P2^1; sbit DS1302_CLK=P3^5; sbit DS1302_IO=P3^6; sbit DS1302_RST=P3^7; sbit speak=P2^7; sbit SetKey=P1^7; //按键功能:设置 sbit SureKey=P1^6; //按键功能:确认 sbit PlusKey=P1^5; //按键功能:加 sbit ReduceKey=P1^4; //按键功能:减 sbit scl=P1^0; sbit sda=P1^1; void DisplayShengXiao(void); /********************************************************/ #define delayNOP(); {_nop_();_nop_();_nop_();_nop_();}; //开机界面图形 uchar code Photo1[] ={ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xBF,0xFF,0xE7,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFC,0x9F,0xFF,0xFF, 0xFF,0xFF,0xF8,0xBF,0xFF,0xE7,0xFF,0xEF, 0xFF,0xFF,0xFE,0x7F,0xF4,0x3F,0xFF,0xFF, 0xFF,0xFF,0xF9,0x3F,0xF6,0x6F,0xF3,0x17, 0xFF,0xFF,0xFE,0x7F,0xF2,0x7F,0xFF,0xFF, 0xFF,0xFF,0xFC,0x3F,0xF7,0x4F,0xF2,0x97, 0xFF,0x1F,0xFE,0x7F,0xF0,0x0F,0xFF,0xFF, 0xFF,0xFF,0xFC,0x1F,0xE7,0x4F,0xFA,0x17, 0xF8,0x1F,0xFE,0x0F,0xE8,0xC7,0xFF,0xFF, 0xFF,0xFF,0xF1,0x7F,0xC4,0x2F,0xE2,0x87, 0xFC,0x7F,0xFE,0x3F,0xC7,0x1F,0xFF,0xFF, 0xFF,0xFF,0xFE,0xFF,0xC4,0xAF,0xC3,0x0F, 0xFE,0x7F,0xF8,0x7F,0xC8,0x3F,0xFF,0xFF, 0xFF,0xFF,0xF8,0x3F,0xE6,0xEF,0xF1,0x9F, 0xFE,0x7F,0xF0,0xFF,0xDE,0x7F,0xFF,0xFF, 0xFF,0xFF,0xF8,0x7F,0xF6,0xEF,0xE3,0x0F, 0xFC,0xEF,0xF9,0xFF,0xDE,0x1F,0xFF,0xFF, 26 0xFF,0xFF,0xFD,0xFF,0xF6,0xEF,0xE7,0x1F, 0xF0,0x03,0xF9,0x1F,0xF8,0x1F,0xFF,0xFF, 0xFF,0xFF,0xF0,0x07,0xEF,0xEF,0xEE,0x07, 0xC3,0xF3,0xF9,0xC7,0xF7,0x3F,0xFF,0xFF, 0xFF,0xFF,0xC3,0xFB,0xFF,0xEF,0xFE,0x7F, 0xFF,0xFF,0xE3,0xE7,0xFF,0x7F,0xFF,0xFF, 0xFF,0xFF,0xCF,0xFF,0xFF,0xEF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFC,0x7F,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFD, 0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC, 0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC, 0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC, 0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDC, 0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9C, 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x1C, 0x00,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,0xF8,0x1C, 0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xBF,0xFF,0xF3,0xFF,0xF8,0x1C, 0x00,0x1F,0xFF,0xE7,0xFF,0xF0,0xFF,0xFF, 0xFF,0xFF,0x3F,0xFF,0xF1,0xFF,0xF8,0x1C, 0x00,0x1F,0xFF,0xF6,0x3F,0xF8,0xFF,0xFF, 0xFF,0xFF,0x7F,0xF9,0xCB,0xFF,0xF8,0x1C, 0x00,0x1F,0xFF,0xF3,0x3F,0xE6,0xFF,0xFF, 0xFF,0xFF,0x0F,0xFC,0xC1,0xFF,0xF8,0x1C, 0x00,0x1F,0xFF,0xE1,0xFF,0xE0,0xFF,0xFF, 0xFF,0xFE,0x1F,0xF9,0x01,0xFF,0xF8,0x1C, 0x00,0x1F,0xFF,0x87,0xFF,0xE2,0xFF,0xFF, 0xFF,0xF4,0x3F,0xFF,0x8B,0xFF,0xF8,0x1C, 0x00,0x1F,0xFF,0x07,0xFF,0xE0,0xFF,0xFF, 0xFF,0xF8,0xDF,0xF3,0xD0,0xFF,0xF8,0x1C, 0x00,0x1F,0xFF,0xAE,0xFF,0xE0,0x3F,0xFF, 0xFF,0xFC,0xEF,0xF9,0x40,0xFF,0xF8,0x1C, 0x00,0x1F,0xFF,0xEE,0xFF,0xC0,0x7F,0xFF, 0xFF,0xFD,0xC7,0xFB,0x03,0xFF,0xF8,0x1C, 0x00,0x1F,0xFE,0x6D,0xFF,0xC1,0x7F,0x 27 FF, 0xFF,0xF8,0x01,0xFD,0x1B,0xFF,0xF8,0x1C, 0x00,0x1F,0xFF,0x4D,0xFF,0x08,0x3F,0xFF, 0xFF,0xF8,0xB0,0x7D,0xDB,0xFF,0xF8,0x1C, 0x00,0x1F,0xFF,0x2C,0x7E,0x58,0x7F,0xFF, 0xFF,0xF1,0x14,0x30,0x53,0xFF,0xF8,0x00, 0x00,0x1F,0xFE,0x2E,0x3F,0x81,0xFF,0xFF, 0xFF,0xEC,0x27,0xFB,0x80,0x3F,0xF8,0x00, 0x00,0x1F,0xFE,0xCD,0xFF,0xB8,0x7F,0xFF, 0xFF,0xFD,0xA7,0xFF,0xF0,0x3F,0xF8,0x00, 0x00,0x1F,0xFF,0xEF,0xFF,0x7E,0x03,0xFF, 0xFF,0xFC,0x0F,0xFF,0xFF,0xFF,0xF8,0x00, 0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0x87,0xFF, 0xFF,0xFE,0xEF,0xFF,0xFF,0xFF,0xF8,0x1C, 0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x1C, 0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x1C, 0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x1C, 0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xF7,0xFB,0xFF,0xFF, 0xFE,0x7F,0xFF,0xFF,0xF7,0x9F,0xFF,0xEF, 0xC0,0x03,0x80,0x03,0xF3,0xFB,0xE0,0x07, 0xFC,0x3F,0x83,0x73,0xE7,0x9F,0xC4,0x6F, 0xCE,0x7B,0x9D,0xFB,0xFB,0xDB,0xEF,0xE7, 0xE3,0xC3,0xFB,0x77,0xE4,0x03,0xD5,0x09, 0xCE,0x7B,0x9C,0xF9,0x80,0x5B,0xE0,0x07, 0x98,0x39,0xFB,0x6F,0xEC,0x03,0xD5,0x29, 0xE8,0x1B,0xE0,0x07,0xFD,0xDB,0xEF,0xE7, 0xE0,0x07,0xFB,0x4F,0xCF,0x9F,0xD5,0x2B, 0xEE,0x7B,0xFB,0xFF,0xDD,0xDB,0xEF,0xE7, 0xFA,0xDF,0x83,0x5F,0x8F,0x9F,0xC4,0x3B, 0xC0,0x0B,0xF6,0x7F,0xED,0xDB,0xE0,0x07, 0xC0,0x03,0x9C,0x01,0xA8,0x01,0xD5,0x33, 0xCF,0xFB,0xEF,0x7F,0xE1,0xDB,0xCF,0x3F, 0xE3,0xCF,0x9F,0x5F,0xAF,0x9F,0xD5,0x3F, 0xC8,0x1B,0xE0,0x07,0xF3,0xDB,0xCF,0x 28 3F, /* 延时函数 0xCC,0xB7,0x83,0x4F,0xEF,0x9F,0x84,0x*/ 01, /* 0xDB,0xDB,0xFF,0x7F,0xF1,0xDB,0xC1,0x*/ 23, /************************************0xA0,0x2D,0xFB,0x6F,0xEC,0x03,0x95,0x*******************************/ 7D, void delayone(int ms) 0xDB,0xDB,0xBF,0x7F,0xF5,0xDB,0xCF,0x{ 0F, while(ms--) 0xF7,0xEF,0xFB,0x6F,0xEF,0x9F,0xB5,0x { 45, uchar i; 0xD8,0x1B,0x80,0x01,0xE6,0xFB,0xCF,0x for(i=0;i<150;i++) 3F, { 0xF7,0x03,0xF3,0x77,0xEF,0x9F,0xB5,0x _nop_(); 3D, _nop_(); 0x9F,0xFB,0xFF,0x7F,0xCE,0xFB,0xC1,0x _nop_(); BD, _nop_(); 0xD5,0x6B,0xF3,0x13,0xEF,0x9F,0xB3,0x } 7D, } 0xBF,0xC3,0xFE,0x7F,0x9F,0xE3,0xC7,0x} 81, /************************************0x80,0x81,0xC6,0x39,0xE8,0x01,0x22,0x*******************************/ 79, /* 0xFF,0xEF,0xFE,0x7F,0xFF,0xF7,0xDF,0x*/ FF, /* 延时函数 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x*/ F3, /* 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x*/ FF, /************************************0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x*******************************/ FF, void delaytwo(int ms) 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x{ FF, while(ms--) 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x { FF, uchar y; 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x for(y=0;y<100;y++) ; FF, } 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x} FF /************************************}; *******************************/ /************************************/* *******************************/ */ /* /*检查LCD忙状态 */ */ 29 /*lcd_busy为1时,忙,等待。lcd-busy*******************************/ 为0时,闲,可写指令与数据。 */ /* /* */ */ /*写显示数据到LCD /*************************************/ *******************************/ /*RS=H,RW=L,E=高脉冲,D0-D7=数据。 bit lcd_busy() */ { /* bit result; */ LCD_RS = 0; /************************************ LCD_RW = 1; *******************************/ LCD_E = 1; void lcd_wdat(uchar dat) delayNOP(); { result = (bit)(P0&0x80); while(lcd_busy()); LCD_E = 0; LCD_RS = 1; return(result); LCD_RW = 0; } LCD_E = 0; /************************************ P0 = dat; *******************************/ delayNOP(); /* LCD_E = 1; */ delayNOP(); /*写指令数据到LCD LCD_E = 0; */ } /*RS=L,RW=L,E=高脉冲,D0-D7=指令码。 /*************************************/ *******************************/ /* /* */ */ /************************************/* LCD初始化设定 *******************************/ */ void lcd_wcmd(uchar cmd) /* { */ while(lcd_busy()); /************************************ LCD_RS = 0; *******************************/ LCD_RW = 0; void lcd_init() LCD_E = 0; { _nop_(); PSB = 1; //并口方式 _nop_(); lcd_wcmd(0x34); //扩充指令操 P0 = cmd; 作 delayNOP(); delayone(5); LCD_E = 1; lcd_wcmd(0x30); //基本指令操 delayNOP(); 作 LCD_E = 0; delayone(5); } lcd_wcmd(0x0C); //显示开,关/************************************光标 30 delayone(5); lcd_wcmd(0x34); //写数据时, lcd_wcmd(0x01); //清除LCD的关闭图形显示 显示内容 delayone(5); for(i=0;i<32;i++) } { /************************************ lcd_wcmd(0x80+i); //先写入水平*********************/ 坐标值 /* lcd_wcmd(0x80); //写入垂直坐*/ 标值 /* 设定显示位置 for(j=0;j<16;j++) //再写入两个8*/ 位元的数据 /* lcd_wdat(*bmp++); */ delaytwo(1); /************************************ } *********************/ void lcd_pos(uchar X,uchar Y) for(i=0;i<32;i++) { { uchar pos; lcd_wcmd(0x80+i); if (X==1) lcd_wcmd(0x88); {X=0x80;} for(j=0;j<16;j++) else if (X==2) lcd_wdat(*bmp++); {X=0x90;} delaytwo(1); else if (X==3) } {X=0x88;} lcd_wcmd(0x36); //写完数据,开 else if (X==4) 图形显示 {X=0x98;} } pos = X+Y ; /************************************ ********************/ lcd_wcmd(pos); //显示地址 void delay1(uint z) } { /************************************ uint x,y; ********************* for(x=z;x>0;x--) * for(y=110;y>0;y--); * } * 图形显示 void delay(unsigned int a)//延时1MS/* 次 * { * unsigned char i; *************************************while(--a) ********************/ { void photodisplay(uchar *bmp) for(i=0;i<125;i++) ; { } uchar i,j; } void delayb(unsigned int count) 31 { while(count--); } void delays() { ; ;} void di()//按键音 { speak=0; delay1(100); speak=1; } void start() { sda=1; scl=1; delays(); sda=0; delays(); } void stop() { sda=0; scl=1; delays(); sda=1; delays(); } void response() { uchar i; while((sda==1)&&i<255)i++; //给应答信号sda=0;错误(while((sda==0)|i<255)i++;)程序进入while 死循环 scl=1; delays(); scl=0; //没有这一步出错,如果sda=0状态,一直处于应答中。程序停止。 delays(); } void write24c02(uchar date) { uchar temp,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(); } uchar read24c02() { uchar k,i; scl=0; delays(); sda=1;//仅仅是释放数据线,可有可无 for(i=0;i<8;i++) { scl=1; delays(); k=k<<1; if(sda) k++; scl=0; delays(); } return k; } void write_24c02add(uchar address,uchar date) { start(); write24c02(0xa0); response(); write24c02(address); response(); write24c02(date); response(); stop(); } uchar read_24c02add(uchar address) 32 { uchar a; start(); write24c02(0xa0); response(); write24c02(address); response(); start(); write24c02(0xa1); response(); a=read24c02(); stop(); return a; } void WriteDs1302Byte(unsigned temp) { unsigned char i; for (i=8;i>0;i--) { DS1302_IO=temp&0x01; DS1302_CLK=0; DS1302_CLK=1; temp>>=1; } } void WriteDs1302( unsigned address,unsigned char dat ) { DS1302_RST=0; DS1302_CLK=0; DS1302_RST=1; delay(1); WriteDs1302Byte(address); WriteDs1302Byte(dat); DS1302_RST=0; } unsigned char read_byte() { unsigned char i; for(i=8;i>0;i--) { if(DS1302_IO) temp0=temp0|0x80; DS1302_CLK=1; DS1302_CLK=0; temp0=temp0>>1; } return temp0; } unsigned char ReadDs1302(unsigned char address) { unsigned char temp; DS1302_RST=0; DS1302_CLK=0; DS1302_RST=1; WriteDs1302Byte(address); temp=read_byte(); char DS1302_RST=0; DS1302_CLK=1; return temp; } /*void InitDS1302()//DS1302初始化函数,第一次下载使用 { unsigned char Second=ReadDs1302(0x80);// if(Second&0x80) { WriteDs1302(0x8e,0x00); char delay(5); WriteDs1302(0x8c,0x10);//写入年份10 年 delay(5); WriteDs1302(0x8a,0x06);//写入星期6 delay(5); WriteDs1302(0x88,0x11);//定入月分11 月 delay(5); WriteDs1302(0x86,0x6);//写入日期6 日 delay(5); WriteDs1302(0x84,0x17);//写入小时17 点 delay(5); WriteDs1302(0x82,0x43); delay(5); WriteDs1302(0x80,0x00);//写入秒30 秒 delay(5); 33 WriteDs1302(0x8e,0x80);//控制命令,WP 为1,禁止写操作 } }*/ /*阳历对应的阴历数据,每年三字节, 格式第一字节BIT7-4 位表示闰月月份, 为0,则无闰月,BIT3-0 对应阴历第1-4 月 的大小, 第二字节BIT7-0 对应阴历第5-12 月大 小,第三字节BIT7 表示阴历第13 月大小 月分对应的位为1,表示农历月大(30 天)为0 表示小(29 天) 第三字节BIT6-5 表示春节的公历月份, BIT4-0 表示春节公历日期 */ code unsigned char YearCode[597]= { 0x04,0xAe,0x53, //1901 0 0x0A,0x57,0x48, //1902 3 0x55,0x26,0xBd, //1903 6 0x0d,0x26,0x50, //1904 9 0x0d,0x95,0x44, //1905 12 0x46,0xAA,0xB9, //1906 15 0x05,0x6A,0x4d, //1907 18 0x09,0xAd,0x42, //1908 21 0x24,0xAe,0xB6, //1909 0x04,0xAe,0x4A, //1910 0x6A,0x4d,0xBe, //1911 0x0A,0x4d,0x52, //1912 0x0d,0x25,0x46, //1913 0x5d,0x52,0xBA, //1914 0x0B,0x54,0x4e, //1915 0x0d,0x6A,0x43, //1916 0x29,0x6d,0x37, //1917 0x09,0x5B,0x4B, //1918 0x74,0x9B,0xC1, //1919 0x04,0x97,0x54, //1920 0x0A,0x4B,0x48, //1921 0x5B,0x25,0xBC, //1922 0x06,0xA5,0x50, //1923 0x06,0xd4,0x45, //1924 0x4A,0xdA,0xB8, //1925 0x02,0xB6,0x4d, //1926 0x09,0x57,0x42, //1927 0x24,0x97,0xB7, //1928 0x04,0x97,0x4A, //1929 0x66,0x4B,0x3e, //1930 0x0d,0x4A,0x51, //1931 0x0e,0xA5,0x46, //1932 0x56,0xd4,0xBA, //1933 0x05,0xAd,0x4e, //1934 0x02,0xB6,0x44, //1935 0x39,0x37,0x38, //1936 0x09,0x2e,0x4B, //1937 0x7C,0x96,0xBf, //1938 0x0C,0x95,0x53, //1939 0x0d,0x4A,0x48, //1940 0x6d,0xA5,0x3B, //1941 0x0B,0x55,0x4f, //1942 0x05,0x6A,0x45, //1943 0x4A,0xAd,0xB9, //1944 0x02,0x5d,0x4d, //1945 0x09,0x2d,0x42, //1946 0x2C,0x95,0xB6, //1947 0x0A,0x95,0x4A, //1948 0x7B,0x4A,0xBd, //1949 0x06,0xCA,0x51, //1950 0x0B,0x55,0x46, //1951 0x55,0x5A,0xBB, //1952 0x04,0xdA,0x4e, //1953 0x0A,0x5B,0x43, //1954 0x35,0x2B,0xB8, //1955 0x05,0x2B,0x4C, //1956 0x8A,0x95,0x3f, //1957 0x0e,0x95,0x52, //1958 0x06,0xAA,0x48, //1959 0x7A,0xd5,0x3C, //1960 0x0A,0xB5,0x4f, //1961 0x04,0xB6,0x45, //1962 0x4A,0x57,0x39, //1963 0x0A,0x57,0x4d, //1964 0x05,0x26,0x42, //1965 0x3e,0x93,0x35, //1966 0x0d,0x95,0x49, //1967 0x75,0xAA,0xBe, //1968 0x05,0x6A,0x51, //1969 0x09,0x6d,0x46, //1970 0x54,0xAe,0xBB, //1971 34 0x04,0xAd,0x4f, //1972 0x0A,0x4d,0x43, //1973 0x4d,0x26,0xB7, //1974 0x0d,0x25,0x4B, //1975 0x8d,0x52,0xBf, //1976 0x0B,0x54,0x52, //1977 0x0B,0x6A,0x47, //1978 0x69,0x6d,0x3C, //1979 0x09,0x5B,0x50, //1980 0x04,0x9B,0x45, //1981 0x4A,0x4B,0xB9, //1982 0x0A,0x4B,0x4d, //1983 0xAB,0x25,0xC2, //1984 0x06,0xA5,0x54, //1985 0x06,0xd4,0x49, //1986 0x6A,0xdA,0x3d, //1987 0x0A,0xB6,0x51, //1988 0x09,0x37,0x46, //1989 0x54,0x97,0xBB, //1990 0x04,0x97,0x4f, //1991 0x06,0x4B,0x44, //1992 0x36,0xA5,0x37, //1993 0x0e,0xA5,0x4A, //1994 0x86,0xB2,0xBf, //1995 0x05,0xAC,0x53, //1996 0x0A,0xB6,0x47, //1997 0x59,0x36,0xBC, //1998 0x09,0x2e,0x50, //1999 294 0x0C,0x96,0x45, //2000 297 0x4d,0x4A,0xB8, //2001 300 0x0d,0x4A,0x4C, //2002 303 0x0d,0xA5,0x41, //2003 306 0x25,0xAA,0xB6, //2004 309 0x05,0x6A,0x49, //2005 312 0x7A,0xAd,0xBd, //2006 315 0x02,0x5d,0x52, //2007 318 0x09,0x2d,0x47, //2008 321 0x5C,0x95,0xBA, //2009 324 0x0A,0x95,0x4e, //2010 327 0x0B,0x4A,0x43, //2011 0x4B,0x55,0x37, //2012 0x0A,0xd5,0x4A, //2013 0x95,0x5A,0xBf, //2014 0x04,0xBA,0x53, //2015 0x0A,0x5B,0x48, //2016 0x65,0x2B,0xBC, //2017 0x05,0x2B,0x50, //2018 0x0A,0x93,0x45, //2019 0x47,0x4A,0xB9, //2020 0x06,0xAA,0x4C, //2021 0x0A,0xd5,0x41, //2022 0x24,0xdA,0xB6, //2023 0x04,0xB6,0x4A, //2024 0x69,0x57,0x3d, //2025 0x0A,0x4e,0x51, //2026 0x0d,0x26,0x46, //2027 0x5e,0x93,0x3A, //2028 0x0d,0x53,0x4d, //2029 0x05,0xAA,0x43, //2030 0x36,0xB5,0x37, //2031 0x09,0x6d,0x4B, //2032 0xB4,0xAe,0xBf, //2033 0x04,0xAd,0x53, //2034 0x0A,0x4d,0x48, //2035 0x6d,0x25,0xBC, //2036 0x0d,0x25,0x4f, //2037 0x0d,0x52,0x44, //2038 0x5d,0xAA,0x38, //2039 0x0B,0x5A,0x4C, //2040 0x05,0x6d,0x41, //2041 0x24,0xAd,0xB6, //2042 0x04,0x9B,0x4A, //2043 0x7A,0x4B,0xBe, //2044 0x0A,0x4B,0x51, //2045 0x0A,0xA5,0x46, //2046 0x5B,0x52,0xBA, //2047 0x06,0xd2,0x4e, //2048 0x0A,0xdA,0x42, //2049 0x35,0x5B,0x37, //2050 0x09,0x37,0x4B, //2051 0x84,0x97,0xC1, //2052 0x04,0x97,0x53, //2053 0x06,0x4B,0x48, //2054 0x66,0xA5,0x3C, //2055 0x0e,0xA5,0x4f, //2056 0x06,0xB2,0x44, //2057 0x4A,0xB6,0x38, //2058 0x0A,0xAe,0x4C, //2059 35 0x09,0x2e,0x42, //2060 0x3C,0x97,0x35, //2061 0x0C,0x96,0x49, //2062 0x7d,0x4A,0xBd, //2063 0x0d,0x4A,0x51, //2064 0x0d,0xA5,0x45, //2065 0x55,0xAA,0xBA, //2066 0x05,0x6A,0x4e, //2067 0x0A,0x6d,0x43, //2068 0x45,0x2e,0xB7, //2069 0x05,0x2d,0x4B, //2070 0x8A,0x95,0xBf, //2071 0x0A,0x95,0x53, //2072 0x0B,0x4A,0x47, //2073 0x6B,0x55,0x3B, //2074 0x0A,0xd5,0x4f, //2075 0x05,0x5A,0x45, //2076 0x4A,0x5d,0x38, //2077 0x0A,0x5B,0x4C, //2078 0x05,0x2B,0x42, //2079 0x3A,0x93,0xB6, //2080 0x06,0x93,0x49, //2081 0x77,0x29,0xBd, //2082 0x06,0xAA,0x51, //2083 0x0A,0xd5,0x46, //2084 0x54,0xdA,0xBA, //2085 0x04,0xB6,0x4e, //2086 0x0A,0x57,0x43, //2087 0x45,0x27,0x38, //2088 0x0d,0x26,0x4A, //2089 0x8e,0x93,0x3e, //2090 0x0d,0x52,0x52, //2091 0x0d,0xAA,0x47, //2092 0x66,0xB5,0x3B, //2093 0x05,0x6d,0x4f, //2094 0x04,0xAe,0x45, //2095 0x4A,0x4e,0xB9, //2096 0x0A,0x4d,0x4C, //2097 0x0d,0x15,0x41, //2098 0x2d,0x92,0xB5, //2099 }; void WriteDataLCD(unsigned char dat) { 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); } void WriteCommandLCD(unsigned char udat) { 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);} void LCDInit(void) { WriteCommandLCD(0x30); WriteCommandLCD(0x01); WriteCommandLCD(0x06); WriteCommandLCD(0x0C); } void LCDClear(void) { WriteCommandLCD(0x01); WriteCommandLCD(0x34); WriteCommandLCD(0x30); } void LCDSendWord(unsigned char *p) { while(*p>0) { WriteDataLCD(*p); p++; } } 36 void LCDTestWord(bit i,unsigned char LCDTestWord(0,0x92); word) { if(i==0) { WriteCommandLCD(word); } else { WriteDataLCD(word); } } void DisplayYear(void) { year=ReadDs1302(0x8d); LCDTestWord(0,0x81); LCDTestWord(1,(year/16)+0x30); LCDTestWord(1,year%16+0x30); LCDTestWord(0,0x82); LCDSendWord(\"年\"); DisplayShengXiao(); } void DisplayMonth(void) { month=ReadDs1302(0x89); LCDTestWord(0,0x83); if(month/16!=0) { LCDTestWord(1,(month/16)+0x30); } else { LCDTestWord(1,0x20); } LCDTestWord(1,month%16+0x30); LCDTestWord(0,0x84); LCDSendWord(\"月\"); DisplayShengXiao(); } void DisplayWeek(void) { week=ReadDs1302(0x8b); LCDTestWord(0,0x90); LCDSendWord(\"星期\"); // LCDTestWord(1,week+0x30); if(week==7) {LCDSendWord(\"日\");} if(week==6) {LCDSendWord(\"六\");} if(week==5) {LCDSendWord(\"五\");} if(week==4) {LCDSendWord(\"四\");} if(week==3) {LCDSendWord(\"叁\");} if(week==2) {LCDSendWord(\"二\");} if(week==1) {LCDSendWord(\"一\");} } void DisplayDay(void) { day=ReadDs1302(0x87); LCDTestWord(0,0x85); if(day/16!=0) { LCDTestWord(1,(day/16)+0x30); } else { LCDTestWord(1,0x20);} LCDTestWord(1,day%16+0x30); LCDTestWord(0,0x86); LCDSendWord(\"日\"); DisplayShengXiao(); } void DisplayHour(void) { hour=ReadDs1302(0x85); LCDTestWord(0,0x88); LCDTestWord(1,(hour/16)+0x30); LCDTestWord(1,hour%16+0x30); } void DisplayMin(void) { min=ReadDs1302(0x83); LCDTestWord(0,0x89); //LCDTestWord(1,0x3a); LCDSendWord(\"点\"); LCDTestWord(1,(min/16)+0x30); LCDTestWord(1,min%16+0x30); LCDSendWord(\"分\"); } void DisplaySec(void) { unsigned char i=0; unsigned int a=0,b=0,c=0; 37 sec=ReadDs1302(0x81); LCDTestWord(0,0x8c); LCDTestWord(1,(sec/16)+0x30); LCDTestWord(1,sec%16+0x30); } void Displayrnorpn(void)//显示闰年或平年 { int y; y=ReadDs1302(0x8d); year=2000+(y/16)*10+y%16; if((year%4==0&&year%100!=0)||(year%400==0)) { LCDTestWord(0,0x8e); LCDSendWord(\"闰年\"); } else { LCDTestWord(0,0x8e); LCDSendWord(\"平年\"); } } code unsigned char DayCode1[9]={0x00,0x1f,0x3b,0x5a,0x78,0x97,0xb5,0xd4,0xf3}; code unsigned int DayCode2[3]={0x111,0x130,0x14e};//计算公历日离当年元旦的天数,为了减少运算,用了两个表 //DayCode1[9],DayCode2[3]//如果公历月在九月或前,天数会少于0xff,用表DayCode1[9],在九月后,天数大于0xff,用表DayCode2[3] //如输入公历日为8 月10 日,则公历日离元旦天数为DayCode1[8-1]+10-1,如输入公历日为11 月10 日,则公历日离元旦天数为DayCode2[11-10]+10-1 /*读取数据表中农历月的大月或小月, 如果该月为大返回1,为小返回0*/ bit GetMoonDay(unsigned char LunarMonth,unsigned int TableAddr) { unsigned char temp; switch (LunarMonth)//LunarMonth 指向农历月份 { case 1: { temp=YearCode[TableAddr]&0x08;//1 月,对应年份表里第一字节的BIT3 位,如果是1,则月大,如果是0,则月小 if (temp==0) return(0);//为0,月小 else return(1);//为1,月大 } case 2: { temp=YearCode[TableAddr]&0x04; //2月,对应年份表里第一字节的BIT2 位,如果是1,则月大,如果是0,则月小 if (temp==0) return(0);//为0,月小 else return(1);//为1,月大 } case 3: { temp=YearCode[TableAddr]&0x02; //3月,对应第一字节的BIT1 位,如果是1,则月大,如果是0,则月小 if (temp==0) return(0);//为0,月小 else return(1);//为1,月大 } case 4: { temp=YearCode[TableAddr]&0x01; //1月,对应第一字节的BIT0 位,如果是1,则月大,如果是0,则月小 if (temp==0) return(0); else return(1); } case 5: { temp=YearCode[TableAddr+1]&0x80; //5月,对应第二字节的BIT7 位,如果是1,则月大,如果是0,则月小 if (temp==0) return(0); else return(1); 38 } case 6: { temp=YearCode[TableAddr+1]&0x40; //6月,对应第二字节的BIT6 位,如果是1,则月大,如果是0,则月小 if (temp==0) return(0); else return(1); } case 7: { temp=YearCode[TableAddr+1]&0x20; //7月,对应第二字节的BIT5 位,如果是1,则月大,如果是0,则月小 if (temp==0) return(0); else return(1); } case 8: { temp=YearCode[TableAddr+1]&0x10; //8月,对应第二字节的BIT4 位,如果是1,则月大,如果是0,则月小 if (temp==0) return(0); else return(1); } case 9: { temp=YearCode[TableAddr+1]&0x08; //9月,对应第二字节的BIT3 位,如果是1,则月大,如果是0,则月小 if (temp==0) return(0); else return(1); } case 10: { temp=YearCode[TableAddr+1]&0x04;//10 月,对应第二字节的BIT2 位,如果是1,则月大,如果是0,则月小 if (temp==0) return(0); else return(1); } case 11: { temp=YearCode[TableAddr+1]&0x02;//11 月,对应第二字节的BIT1 位,如果是1,则月大,如果是0,则月小 if (temp==0) return(0); else return(1); } case 12: { temp=YearCode[TableAddr+1]&0x01;//12 月,对应第二字节的BIT0 位,如果是1,则月大,如果是0,则月小 if (temp==0) return(0); else return(1); } case 13: { temp=YearCode[TableAddr+2]&0x80;//13 月,对应第三字节的BIT7 位,如果是1,则月大,如果是0,则月小 if (temp==0) return(0); else return(1); } } } void Conversion(bit cenbit,unsigned char year,unsigned char month,unsigned char day) { unsigned char temp1,temp2,temp3,MonthP;//temp3,temp4 分别表示春节距元旦的天数,公历日离元旦的天数 unsigned int temp4,TableAddr; bit flag2,flag_y; temp1=year/16;//BCD->hex 先把数据转换为十六进制高位 temp2=year%16; //低位 year=temp1*10+temp2; //把年数据转换成10 进制 temp1=month/16; //月份高位 temp2=month%16; //月份低位 month=temp1*10+temp2; //把月数据转换成10 进制 temp1=day/16; //日期高位 temp2=day%16; //日期低位 39 day=temp1*10+temp2; //把日数据转换成16 进制 //如果是21 世纪 TableAddr=(year+0x64-1)*0x03;//定位数据表地址year 对应的年份表中的地址是(year+99)*3 如2010 年其地址是327 LCDTestWord(0,0x80); LCDSendWord(\"20\"); temp1=YearCode[TableAddr+2]&0x60;//取当年春节所在的公历月份年份表中第三字节BIT6-5 表示春节的公历月份 temp1=_cror_(temp1,5);//循环右移5 位,得到春节所在的公历月份 temp2=YearCode[TableAddr+2]&0x1f;//取当年春节所在的公历日年份表中第三字节BIT4-0 表示当年春节所在的公历日 if(temp1==0x01)// 计算当年春年离当年元旦的天数,春节只会在公历1 月或2 月 temp3=temp2-1;//假如春节在公历1 月,则元旦离春节的天数为temp2-1 天 else temp3=temp2+0x1f-1;//假如春节在公历2 月,则无理离春节的天数为temp2+0x1f-1 天 if (month<10) temp4=DayCode1[month-1]+day-1;//0 到8 月某日距元旦的天数 else temp4=DayCode2[month-10]+day-1;//9 月开始的某一天距元旦的天数 if((month>0x02)&&(year%0x04==0))//如果公历月大于2 月并且该年的2 月为闰月,天数加1 temp4+=1;//计算机出公历日距元旦的天数和春节距元旦的天数,则是为了比较公历日是在春节前还是春节后 //如果temp3>temp4 则公历日在春节之前 if (temp4>=temp3)//公历日在春节后或就是春节当日使用下面代码进行运算 { temp4-=temp3;//公历日离春节的天数因为公历日在春节后所以为temp4-temp3 month=0x01; MonthP=0x01;//LunarMonth 为月份指向,公历日在春节前或就是春节当日LunarMonth 指向首月 flag2=GetMoonDay(MonthP,TableAddr); //检查该农历月为大小还是小月,大月返回1,小月返回0 flag_y=0; if(flag2==0)//GetMoonDay()函数返回的是0 {temp1=0x1d;}//小月29 天 else//GetMoonDay()函数返回的是1 {temp1=0x1e;}//大月30 天 temp2=YearCode[TableAddr]&0xf0;//年份数据表中第1 字节BIT7-4 为闰月,为0 则这年无闰月,如为1,表示有闰月 temp2=_cror_(temp2,4);//从数据表中取该年的闰月月份,如为0,则该年无闰月BIT3-0 表示阴历1 到4 月的大小1 为大0 为小 while(temp4>=temp1) { temp4-=temp1; MonthP+=1; if(month==temp2) { flag_y=~flag_y; if(flag_y==0) {month+=1;} } else { month+=1; } flag2=GetMoonDay(MonthP,TableAddr); if(flag2==0) { temp1=0x1d; } else { temp1=0x1e; } } day=temp4+1; } 40 else { //公历日在春节前使用下面代码进行运算 temp3-=temp4;//公历日离春节的天数因为公历日在春节前所以为temp3-temp4 if(year==0x00){year=0x63;cenbit=1;} else year-=1; TableAddr-=0x03; month=0x0c; temp2=YearCode[TableAddr]&0xf0; //格式第一字节BIT7-4 位表示闰月月份,为0,则无闰月,BIT3-0 对应阴历第1-4 月的大小, temp2=_cror_(temp2,4); if (temp2==0)MonthP=0x0c; else MonthP=0x0d; // /* MonthP 为月份指向,如果 当年有闰月,一年有十三个月,月指向13,无 闰月指向12*/ flag_y=0; flag2=GetMoonDay(MonthP,TableAddr); if(flag2==0)temp1=0x1d; else temp1=0x1e; while(temp3>temp1) { temp3-=temp1; MonthP-=1; if(flag_y==0)month-=1; if(month==temp2)flag_y=~flag_y; flag2=GetMoonDay(MonthP,TableAddr); if(flag2==0)temp1=0x1d; else temp1=0x1e; } day=temp1-temp3+1; } c_moon=cenbit; temp1=year/10; temp1=_crol_(temp1,4); temp2=year%10; LunarYear=temp1|temp2; temp1=month/10; temp1=_crol_(temp1,4); temp2=month%10; LunarMonth=temp1|temp2; temp1=day/10; temp1=_crol_(temp1,4); temp2=day%10; LunarDay=temp1|temp2; } void DisplayShengXiao(void) { unsigned char LunarYearD,ReYear; //农历年份的十进制数和取模后的余数 if(cen==0x19) {cenbit=1;} if(cen==0x20) {cenbit=0;} Conversion(cenbit,year,month,day); //将公历日期转换成农历 LCDTestWord(0,0x94); //显示在LCD 的0X94 位置上 LCDTestWord(1,LunarYear/16+0x30); //农历年十位 LCDTestWord(1,LunarYear%16+0x30); //农历年个位 LCDTestWord(1,'-'); //用-隔开 LCDTestWord(1,LunarMonth/16+0x30); //农历月十位 LCDTestWord(1,LunarMonth%16+0x30); //农历月个位 LCDTestWord(1,'-'); LCDTestWord(1,LunarDay/16+0x30); //农历日十位 LCDTestWord(1,LunarDay%16+0x30); //农历日个位 LunarYearD=(LunarYear/16)*10+LunarYear%16; //农历年转换成10 进制数 ReYear=LunarYearD%12;//农历年模12,取余运算 switch(ReYear) { case 0: LCDTestWord(0,0x93);LCDSendWord(\"龙\");break; //余0 即整除农历龙年 case 1: LCDTestWord(0,0x93);LCDSendWord(\"蛇\");break; //蛇年 case 2: LCDTestWord(0,0x93);LCDSendWord(\"马\");break; case 3: 41 LCDTestWord(0,0x93);LCDSendWord(\"羊\");break; case 4: LCDTestWord(0,0x93);LCDSendWord(\"猴\");break; case 5: LCDTestWord(0,0x93);LCDSendWord(\"鸡\");break; case 6: LCDTestWord(0,0x93);LCDSendWord(\"狗\");break; case 7: LCDTestWord(0,0x93);LCDSendWord(\"猪\");break; case 8: LCDTestWord(0,0x93);LCDSendWord(\"鼠\");break; case 9: LCDTestWord(0,0x93);LCDSendWord(\"牛\");break; case 10:LCDTestWord(0,0x93);LCDSendWord(\"虎\");break; case 11:LCDTestWord(0,0x93);LCDSendWord(\"兔\");break; } } /***************节假日提示 ********************/ void Holidays(void) { LCDTestWord(0,0x98); if(next==0){ if(LunarMonth==0x01&&LunarDay==0x01) {LCDSendWord(\" 春节\");} if(LunarMonth==0x01&&LunarDay==0x15) {LCDSendWord(\" 元宵节\");} if(LunarMonth==0x05&&LunarDay==0x05) {LCDSendWord(\" 端午节\");} if(LunarMonth==0x07&&LunarDay==0x07) {LCDSendWord(\" 七夕节\");} if(LunarMonth==0x08&&LunarDay==0x15) {LCDSendWord(\" 中秋节\");} if(LunarMonth==0x09&&LunarDay==0x09) {LCDSendWord(\" 重阳节\");} if(LunarMonth==0x12&&LunarDay==0x08) {LCDSendWord(\" 腊八节! \");} if(LunarMonth==0x12&&LunarDay==0x15) {LCDSendWord(\" 小年\");} if(LunarMonth==0x12&&LunarDay==0x30) {LCDSendWord(\"新年夜\");} if(month==0x01&&day==0x01) {LCDSendWord(\" 元旦节\");} if(month==0x02&&day==0x14) {LCDSendWord(\" 情人节\");} if(month==0x03&&day==0x12) {LCDSendWord(\" 植树节\");} if(month==0x04&&day==0x01) {LCDSendWord(\" 愚人节\");} if(month==0x04&&day==0x05) {LCDSendWord(\" 清明节\");} if(month==0x05&&day==0x01) {LCDSendWord(\" 劳动节\");} if(month==0x05&&day==0x12) {LCDSendWord(\" 汶川地震纪念日\");} if(month==0x06&&day==0x01) {LCDSendWord(\" 儿童节\");} if(month==0x06&&day==0x26) {LCDSendWord(\" 禁毒日\");} if(month==0x07&&day==0x01) {LCDSendWord(\"香港回归纪念日\");} if(month==0x08&&day==0x01) {LCDSendWord(\" 建军节\");} if(month==0x09&&day==0x10) {LCDSendWord(\" 教师节\");} if(month==0x09&&day==0x18) {LCDSendWord(\" 九一八纪念日\");} if(month==0x10&&day==0x01) {LCDSendWord(\" 国庆节\");} if(month==0x12&&day==0x20) {LCDSendWord(\" 澳门回归纪念日\");} if(month==0x12&&day==0x24) {LCDSendWord(\" 平安夜\");} if(month==0x12&&day==0x25) {LCDSendWord(\" 圣诞节\");} else { 42 if(SetKey==1&&SureKey==1&&PlusKey==1&&ReduceKey==1) { if((hour/16*10+hour%16)>=6&&(hour/16*10+hour%16)<22) { if((hour/16*10+hour%16)>12&&(hour/16*10+hour%16)<14) LCDSendWord(\"午休时间\"); else LCDSendWord(\" 兰州理工大学 \"); } if((hour/16*10+hour%16)>21||(hour/16*10+hour%16)<=5) LCDSendWord(\"注意休息\"); } } } } void UpDate(void) { DisplayYear(); DisplayMonth(); DisplayDay(); DisplayWeek(); DisplayHour(); DisplayMin(); DisplaySec(); DisplayShengXiao(); } void SetTime(unsigned char count) { char address,item; unsigned char max,mini; if(count<8){ LCDTestWord(0,0x98); LCDSendWord(\"调整\"); if(count==7) {LCDSendWord(\"秒钟请按+ - \"); address=0x81; max=59;mini=0;} if(count==2) {LCDSendWord(\"分钟请按+ - \"); address=0x83; max=59;mini=0;} if(count==1) {LCDSendWord(\"小时请按+ - \");address=0x85; max=23;mini=0;} if(count==5) {LCDSendWord(\"星期请按+ - \"); address=0x8b; max=7;mini=1;} if(count==3) {LCDSendWord(\"日期请按+ - \");address=0x87; max=31; mini=1;} if(count==4) {LCDSendWord(\"月份请按+ - \"); address=0x89; max=12;mini=1;} if(count==6) {LCDSendWord(\"年份请按+ - \"); address=0x8d; max=99;mini=0;} item=ReadDs1302(address);//读取DS1302 某地址上的数值赋给item item=(item/16)*10+item%16; if(PlusKey==0) //PlusKey-加 { item++; } //数加1 if(ReduceKey==0)//ReduceKey-减 {item--; } //数减1 if(item>max) item=mini; //查看数值有效范围 if(item WriteDs1302(address-1,item); //将调整好的item 值写入DS1302 UpDate(); } else{ if(count==8){ c1=read_24c02add(30); LCDTestWord(0,0x01); WriteCommandLCD(0x0c); LCDTestWord(0,0x92); if(PlusKey==0) //PlusKey-加 c1++; //数加1 if(ReduceKey==0) //ReduceKey-减 c1--; write_24c02add(30,c1); LCDTestWord(0,0x80); LCDSendWord(\"请设置闹钟1\"); LCDTestWord(0,0x93); LCDSendWord(\"点\"); 43 LCDTestWord(0,0x95); LCDSendWord(\"分\"); LCDTestWord(0,0x92); LCDTestWord(1,c1/10+0x30); LCDTestWord(1,c1%10+0x30); LCDTestWord(0,0x94); LCDTestWord(1,d1/10+0x30); LCDTestWord(1,d1%10+0x30); LCDTestWord(0,0x88); LCDSendWord(\"闹钟:\"); LCDTestWord(0,0x98); LCDSendWord(\"设置闹钟小时位\"); } if(count==9) { d1=read_24c02add(31); if(PlusKey==0) //PlusKey-加 d1++; //数加1 if(ReduceKey==0) //ReduceKey-减 d1--; write_24c02add(31,d1); LCDTestWord(0,0x94); LCDTestWord(1,d1/10+0x30); LCDTestWord(1,d1%10+0x30); LCDTestWord(0,0x98); LCDSendWord(\"设置闹钟分钟位\"); } if(count==10) { LCDTestWord(0,0x98); LCDSendWord(\"设置闹钟状态\"); if(PlusKey==0) //PlusKey- m1=1; if(ReduceKey==0)//ReduceKey-减 m1=0; write_24c02add(32,m1); if(m1==1) {LCDTestWord(0,0x8b);LCDSendWord(\"开\");} if(m1==0) {LCDTestWord(0,0x8b);LCDSendWord(\"关\");} } if(count==11){ c2=read_24c02add(33); LCDTestWord(0,0x01); WriteCommandLCD(0x0c); LCDTestWord(0,0x92); if(PlusKey==0) //PlusKey-加 c2++; //数加1 if(ReduceKey==0) //ReduceKey-减 c2--; write_24c02add(33,c2); LCDTestWord(0,0x80); LCDSendWord(\"请设置闹钟2\"); LCDTestWord(0,0x93); LCDSendWord(\"点\"); LCDTestWord(0,0x95); LCDSendWord(\"分\"); LCDTestWord(0,0x92); LCDTestWord(1,c2/10+0x30); LCDTestWord(1,c2%10+0x30); LCDTestWord(0,0x94); LCDTestWord(1,d2/10+0x30); LCDTestWord(1,d2%10+0x30); LCDTestWord(0,0x88); LCDSendWord(\"闹钟:\"); LCDTestWord(0,0x98); LCDSendWord(\"设置闹钟小时位\"); } if(count==12) { d2=read_24c02add(34); if(PlusKey==0) //PlusKey-加 d2++; //数加1 if(ReduceKey==0) //ReduceKey-减 d2--; write_24c02add(34,d2); LCDTestWord(0,0x94); LCDTestWord(1,d2/10+0x30); LCDTestWord(1,d2%10+0x30); LCDTestWord(0,0x98); LCDSendWord(\"设置闹钟分钟位\"); } if(count==13) { LCDTestWord(0,0x98); 44 LCDSendWord(\"设置闹钟状态\"); if(PlusKey==0) //PlusKey- m2=1; if(ReduceKey==0)//ReduceKey-减 m2=0; write_24c02add(35,m2); if(m2==1) {LCDTestWord(0,0x8b);LCDSendWord(\"开\");} if(m2==0) {LCDTestWord(0,0x8b);LCDSendWord(\"关\");} } } } void Key(void) { if (SetKey==0) //设置间 { delay(10); //按键消抖 if(SetKey==0&&w==0) //当是正常状态时就进入调时状态 { w=1; //进入调时 SetTime(next); //调整 } if(SetKey==0&&w==1) //当是调时状态本键用于调整下一项 { di();next++; if(next==15) {next=0;WriteCommandLCD(0x0c);} SetTime(next); //调整 } while(SetKey==0); //等待键松开 } switch(next) { case 1: WriteCommandLCD(0x0f); LCDTestWord(0,0x88);break; case 2: WriteCommandLCD(0x0f); LCDTestWord(0,0x8a);break; case 3: WriteCommandLCD(0x0f); LCDTestWord(0,0x85);break; case 4: WriteCommandLCD(0x0f); LCDTestWord(0,0x83);break; case 5: WriteCommandLCD(0x0f); LCDTestWord(0,0x92);break; case 6: WriteCommandLCD(0x0f); LCDTestWord(0,0x81);break; case 7: WriteCommandLCD(0x0f); LCDTestWord(0,0x8c);break; case 8: WriteCommandLCD(0x0f); LCDTestWord(0,0x92);break; case 9: WriteCommandLCD(0x0f); LCDTestWord(0,0x94);break; case 10: WriteCommandLCD(0x0f); LCDTestWord(0,0x8b);break; case 11: WriteCommandLCD(0x0f); LCDTestWord(0,0x92);break; case 12: WriteCommandLCD(0x0f); LCDTestWord(0,0x94);break; case 13: WriteCommandLCD(0x0f); LCDTestWord(0,0x8b);break; } if(SureKey==0) // 当在调时状态时就退出调时 { di();delay(10); //按键消抖 if(SureKey==0&&w==1) { w=0; next=0; Holidays(); } while(SureKey==0); //等待键松开 } if (PlusKey==0) //加调整 { di();delay(10); //按键消抖 if(PlusKey==0&&w==1) { SetTime(next); //调整 } while(PlusKey==0); //等待键松开 } if (ReduceKey==0) //减调整 { 45 di();delay(10); //按键消抖 if(ReduceKey==0&&w==1) { SetTime(next); //调整 } while(ReduceKey==0); //等待键松开 } } void beep() { //int i; uchar hour1,min1,hour2,min2;//high,low; hour1=read_24c02add(30); min1=read_24c02add(31); m1=read_24c02add(32); hour2=read_24c02add(33); min2=read_24c02add(34); m2=read_24c02add(35); hour=ReadDs1302(0x85)/16*10+ReadDs1302(0x85)%16; min=ReadDs1302(0x83)/16*10+ReadDs1302(0x83)%16; sec=ReadDs1302(0x81)/16*10+ReadDs1302(0x81)%16; if((m1==1)||(m2==1)) { LCDTestWord(0,0x87);WriteDataLCD(0x0e);WriteDataLCD(0x0e); } if((m1==0)||(m2==0)) {LCDTestWord(0,0x87); WriteDataLCD(0x01);WriteDataLCD(0x01); } if(((hour>=6&&hour<=23)&&min==0)&&sec<=5)//6点到23点整点报时,响5声 { speak=0; delay(20); speak=1; delay(10); } if(((hour>=6&&hour<=23)&&min==30)&&sec<=2)//6点到23点半点报时,响2声 { speak=0; delay(20); speak=1; delay(10); } if(((hour==hour1&&min==min1)&&m1==1)||((hour==hour2&&min==min2)&&m2==1))//闹钟,响1分钟 { speak=0; delay(20); speak=1; delay(10); } } void main() { photodisplay(Photo1); //显示开机界面 delayone(3000); SetKey=1; SureKey=1; PlusKey=1; ReduceKey=1; PSB=1; next=0; delayb(100); LCDInit(); LCDClear(); //InitDS1302();//ds1302初始化,第一次下载使用!!! while(1) { while(!next){ Key(); WriteCommandLCD(0x0c); DisplayYear(); //显示年 DisplayMonth(); //显示月 DisplayDay(); //显示日 DisplayWeek(); //显示星期 DisplayHour(); //显示时 DisplayMin(); //显示分 DisplaySec(); //显示秒 Displayrnorpn();//显示闰年或平年 46 Holidays(); //显示节日 beep(); } Key(); } } 47 因篇幅问题不能全部显示,请点此查看更多更全内容