多功能电子万年历设计论文_第1页
多功能电子万年历设计论文_第2页
多功能电子万年历设计论文_第3页
多功能电子万年历设计论文_第4页
多功能电子万年历设计论文_第5页
已阅读5页,还剩71页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、江苏大学第六届电子设计竞赛多功能电子万年历作品论文参赛队员:胡建冬(电信科技1302)二零一四年四月【摘要】 该电子万年历实现了阳历年、月、日、星期、时、分、秒、闰平年的显示,以及对应阴历的日期和闰平年的显示,同时实现了定时报警、日程提醒和语音报时功能,并可用按键选择菜单以实现对时间和语音报时模式进行调整。电子万年历的硬件部分采用STC89C52RC为主控芯片,时钟芯片DS1302、液晶LCD1602、语音芯片NY3P065A、5个轻触开关等组成外围电路。软件部分是基于51单片机的C语言程序, 编译环境是Keil。【关键词】 多功能电子万年历 单片机 时钟芯片 液晶 语音芯片 目 录1、 设计

2、任务与要求41.1 设计任务41.2 要求4(1) 基本要求4(2) 选做部分41.3 完成功能4(1) 基本要求4(2) 选做部分41.4 未完成功能42、 方案比较与选择42.1 主控模块42.2 时钟模块52.3 显示模块52.4 语音报时模块62.5 按键模块62.6 存储模块73、 硬件电路的设计与仿真73.1 硬件电路设计7(1) 主控模块7(2) 时钟模块8(3) 显示模块9(4) 语音报时模块9(5) 按键模块103.2 硬件电路仿真104、 万年历软件设计114.1 阳历转阴历程序114.2 main函数244.3 时钟模块554.4 显示模块604.5 语音报时模块654.

3、6 存储模块704.7 液晶显示汉字程序734.8 延时子函数模块74作者简介751、 设计任务与要求1.1 设计任务用实验室提供的或自主购买的MSP430开发装置,设计一个具有多种功能的电子万年历。1.2 要求(1) 基本要求a) 能显示阳历年、月、日、星期、小时、分、秒b) 显示模块采用LCD液晶显示,要求能用按键调整时间。c) 能显示阴历月、日,在显示阴历时间时能标明是否为闰年。d) 具有定时报警功能,能够进行整点和半点语音报时。(2) 选做部分a) 掉电存储功能,可存储掉电前用户定时设置。b) 具有日程管理,可以设定指定日期的日程,可以设置日程的提醒时间,并可用语音进行提示。c) 可以

4、保存30个日程设定,每个日程的提醒采用音乐提醒,至少有5首歌曲进行选择播放,提示音乐具有重复播放功能。1.3 完成功能(1) 基本要求a) 能显示阳历年、月、日、星期、小时、分、秒b) 显示模块采用LCD液晶显示,能用按键调整时间。c) 能显示阴历月、日,在显示阴历时间时能标明是否为闰年。d) 具有定时报警功能,能够进行整点和半点语音报时。(2) 选做部分a) 掉电存储功能,可存储掉电前用户定时设置。b) 具有日程管理,可以设定指定日期的日程,可以设置日程的提醒时间,并用语音进行提示。1.4 未完成功能可以保存30个日程设定,每个日程的提醒采用音乐提醒,至少有5首歌曲进行选择播放,提示音乐具有

5、重复播放功能。2、 方案比较与选择2.1 主控模块方案一:采用MSP430为主控芯片。MSP430系列单片机是美国德州仪器(TI)1996年开始推向市场的一种16位超低功耗、具有精简指令集(RISC)的混合信号处理器。MSP430处理能力强、运算速度快、片内资源丰富,它们分别是看门狗(WTD)、模拟比较器A、定时器A0(Timer_A0)、定时器A1(Timer_A1)、定时器B0(Timer_B0)、UART、SPI、I2C、硬件乘法器、液晶驱动器、10位/12位ADC、16位- ADC、DMA、I/O端口、基本定时器(Basic Timer)、实时时钟(RTC)和USB控制器等若干外围模块

6、的不同组合。方案二:采用STC89C52RC为主控芯片。STC89C52RC是STC公司生产的一种低功耗、高性能CMOS8位微控制器,具有 8K 在系统可编程Flash存储器。 具有以下标准功能: 8k字节Flash,512字节RAM, 32 位I/O 口线,看门狗定时器,内置4KB EEPROM,MAX810复位电路,3个16 位定时器/计数器,4个外部中断,一个7向量4级中断结构(兼容传统51的5向量2级中断结构)。相比较而言,MSP430虽然片内资源丰富,但价格较高,且电子万年历只需单片机的少部分资源,如果选用MSP430会造成资源浪费;而STC89C52RC价格相对较低,且内部资源已能

7、满足电子万年历的需要,所以选择方案二。2.2 时钟模块方案一:采用DS12C887为时钟芯片。DS12C887可计算到2100年前的秒、分、小时、星期、日期、月、年七种日历信息并带闰年补偿;自带晶体振荡器和锂电池,在没有外部电源的情况下可工作10年,对于一天内的时间记录,有12小时制和24小时制两种模式;在12小时制模式中,用AM和PM区分上午和下午,可选用夏令时模式,时间表示方法有两种:一种用二进制数表示,一种用BCD码表示。方案二:采用DS1302为时钟芯片。DS1302可提供年、月、日、星期、时、分、秒,一个月小与31天时可以自动调整,且具有闰年补偿功能,即每月的天数和闰年的天数可自动调

8、整;时钟操作可通过AM/PM指示决定采用24或12小时格式。工作电压宽达2.55.5V。采用双电源供电(主电源和备用电源),可设置备用电源充电方式,提供了对后背电源进行涓细电流充电的能力。相比较而言,DS12C887虽然功能齐全,但价格较高,约是DS1302的20倍;而如果给DS1302配上晶振与备用电源也能达到与DS12C887相同的效果,且DS1302的价格较低。所以选择方案二。2.3 显示模块方案一:选用LCD12864作为显示模块。LCD12864是一种具有4 位/8 位并行、2 线或3 线串行多种接口方式,内部含有国标一级、二级简体 中文字库的点阵图形液晶显示模块;其显示分辨率为12

9、8×64,内置8192 个16*16 点汉字,和128 个16*8 点ASCII 字符 集。利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。可以显示8×4 行16×16 点 阵的汉字。也可完成图形显示.低电压低功耗是其又一显著特点。方案二:选用LCD1602作为显示模块。1602液晶也叫1602字符型液晶,它是一种专门用来显示字母、数字、符号等的点阵型液晶模块。它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔。用户可以自定义CGRAM,显示8个自定义字符。160

10、2LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。相比较而言,LCD12864的显示功能强大,可以显示汉字,做出良好的人机界面,缺点是价格较高;LCD1602虽不能显示汉字,但用来显示万年历已够用,并且价格只有LCD12864的1/3左右。所以选择方案二。2.4 语音报时模块语音报时模块选用NY3P065A芯片。NY3P065A是一次性烧录的语音OTP芯片,具有体积小巧、质量稳定、价格低廉等优点。可以串行控制、并行控制、按键控制等。是一种理想的语音OTP。NY3P065A还可以直接驱动喇叭(PWM)。该电子万年历采用的就是直接驱动喇叭(8欧姆,0.25

11、瓦)。下图就是该语音芯片所能报的内容:图1 语音芯片内容2.5 按键模块按键模块采用5个轻触开关。其中4个分别为K1、K2、K3、K4用作万年历的调整。K1用来在时间显示与菜单选择之间进行切换:K2是选择/确定键;K3与K4分别用作所调整的地方减1、加1。剩余的1个作为万年历的复位开关,用来处理系统故障。选择轻触开关作为按键模块,既能实现所需功能,又可以节省成本。2.6 存储模块存储部分用的是STC89C52RC内部的EEPROM。STC89C52RC内带2K字节EEPROM存储空间,(其实是采用ISP/IAP 技术读写内部FLASH 来实现EEPROM),这样就节省了片外资源,使用起来也更加

12、方便。3、 硬件电路的设计与仿真该电子万年历采用单片机STC89C52RC作为主控模块,由时钟芯片DS1302、液晶LCD1602、语音芯片NY3P065A,5个轻触开关等组成外围电路。3.1 硬件电路设计原理图如下:(1) 主控模块单片机最小系统电路图如下:图2 单片机最小系统该电路时单片机最小系统。其中电容C1、C2、晶振Y1 构成振荡电路为单片机时钟信号,电容C8与电阻R3构成上电复位电路;按键K0与VCC相连构成手动复位电路。复位后单片机各部件恢复为初始状态。STC8952RC的I/O口分配如下:3个I/O口用于控制时钟芯片,16个I/O口用于液晶显示,3个I/O口用于语音芯片,5个I

13、/O口用于按键模块。电源部分采用3节1.5V干电池串联的方式,形成4.5V的电压给万年历各个部件供电 。(2) 时钟模块图3 时钟电路上图是时钟模块的电路图。X1、X2脚外接32768Hz的晶振Y2,为芯片提供计时脉冲。BATTERY为后备电池,VCC2为主电源;VCC1为备份电源。当VCC1>VCC2+0.2V时,由VCC1向DS1302供电,当VCC1< VCC2时,由VCC2向DS1302供电。DS1302的SCLK、I/O、RST三个管脚分别连接单片机的3个I/O口,单片机通过控制这3I/O口来读取DS1302里的时间,然后通过LCD1602来显示时间。(3) 显示模块图4

14、 液晶电路上图是显示模块的LCD1602的连接电路。P0P7为数据口,连接到单片机的P0口;电容C7用来滤波(接其它电源);VO连接电位器,用来调节液晶的对比度;RS、RW、E分别连接到单片机的3个I/O口,控制液晶的显示;15 、16脚是液晶的背光电源端与接地端。(4) 语音报时模块图5 语音芯片电路上图是语音报时模块的电路图。与VL连接的电路作用是去耦;电容C5的作用是滤波;PWM-1、PWM-2直接驱动喇叭(8欧姆,0.25瓦);IO2、OKY1、IO1接到单片机的3个I/O口,用来控制语音芯片。(5) 按键模块 图6 按键模块电路该电路是万年历的按键模块。K1K4连接单片机的4个I/O

15、口用来调整万年历,复位电路见主控模块。3.2 硬件电路仿真图7 Proteus仿真图注:由于Proteus提供的液晶中的点阵是5*7,而LCD1602中的点阵是5*8,所以仿真图中的汉字少了最下面一行。下图是实际的显示:图8 实际显示图第一行:左半部分是阳历日期的显示;右边的英文字母是星期的缩写;最右边的汉字表示2014年是阳历闰年。第二行:左半部分是时间的显示:右边的“03-08”表示阴历三月初八;最右边的汉字表示2014年是阴历闰年。4、 万年历软件设计源程序:#include <reg52.h>#include "lcd1602.h"#include &q

16、uot;delay.h"#include "ds1302.h"#include "character.h"#include "eeprom.h"#include "NY3P065A.h"4.1 阳历转阴历程序 #define uchar unsigned char #define uint unsigned int #include <intrins.h> /* 公历年对应的农历数据,每年三字节, 格式第一字节BIT7-4 位表示闰月月份,值为0 为无闰月,BIT3-0 对应农历第1-4 月的

17、大小 第二字节BIT7-0 对应农历第5-12 月大小,第三字节BIT7 表示农历第13 个月大小 月份对应的位为1 表示本农历月大(30 天),为0 表示小(29 天) 第三字节BIT6-5 表示春节的公历月份,BIT4-0 表示春节的公历日期 */ code uchar year_code597 = 0x04,0xAe,0x53,0x0A,0x57,0x48,0x55,0x26,0xBd,0x0d,0x26,0x50,0x0d,0x95,0x44,0x46,0xAA,0xB9,0x05,0x6A,0x4d,0x09,0xAd,0x42,0x24,0xAe,0xB6,0x04,0xAe,0x

18、4A,0x6A,0x4d,0xBe,0x0A,0x4d,0x52,0x0d,0x25,0x46,0x5d,0x52,0xBA,0x0B,0x54,0x4e,0x0d,0x6A,0x43,0x29,0x6d,0x37,0x09,0x5B,0x4B,0x74,0x9B,0xC1,0x04,0x97,0x54,0x0A,0x4B,0x48,0x5B,0x25,0xBC,0x06,0xA5,0x50,0x06,0xd4,0x45,0x4A,0xdA,0xB8,0x02,0xB6,0x4d,0x09,0x57,0x42,0x24,0x97,0xB7,0x04,0x97,0x4A,0x66,0x4B,0x

19、3e,0x0d,0x4A,0x51,0x0e,0xA5,0x46,0x56,0xd4,0xBA,0x05,0xAd,0x4e,0x02,0xB6,0x44,0x39,0x37,0x38,0x09,0x2e,0x4B,0x7C,0x96,0xBf,0x0C,0x95,0x53,0x0d,0x4A,0x48,0x6d,0xA5,0x3B,0x0B,0x55,0x4f,0x05,0x6A,0x45,0x4A,0xAd,0xB9,0x02,0x5d,0x4d,0x09,0x2d,0x42,0x2C,0x95,0xB6,0x0A,0x95,0x4A,0x7B,0x4A,0xBd,0x06,0xCA,0x

20、51,0x0B,0x55,0x46,0x55,0x5A,0xBB,0x04,0xdA,0x4e,0x0A,0x5B,0x43,0x35,0x2B,0xB8,0x05,0x2B,0x4C,0x8A,0x95,0x3f,0x0e,0x95,0x52,0x06,0xAA,0x48,0x7A,0xd5,0x3C,0x0A,0xB5,0x4f,0x04,0xB6,0x45,0x4A,0x57,0x39, 0x0A,0x57,0x4d,0x05,0x26,0x42,0x3e,0x93,0x35,0x0d,0x95,0x49,0x75,0xAA,0xBe,0x05,0x6A,0x51,0x09,0x6d,0

21、x46,0x54,0xAe,0xBB,0x04,0xAd,0x4f,0x0A,0x4d,0x43,0x4d,0x26,0xB7,0x0d,0x25,0x4B,0x8d,0x52,0xBf,0x0B,0x54,0x52,0x0B,0x6A,0x47,0x69,0x6d,0x3C,0x09,0x5B,0x50,0x04,0x9B,0x45,0x4A,0x4B,0xB9,0x0A,0x4B,0x4d,0xAB,0x25,0xC2,0x06,0xA5,0x54,0x06,0xd4,0x49,0x6A,0xdA,0x3d,0x0A,0xB6,0x51,0x09,0x37,0x46,0x54,0x97,0

22、xBB,0x04,0x97,0x4f,0x06,0x4B,0x44,0x36,0xA5,0x37,0x0e,0xA5,0x4A,0x86,0xB2,0xBf,0x05,0xAC,0x53,0x0A,0xB6,0x47,0x59,0x36,0xBC,0x09,0x2e,0x50,0x0C,0x96,0x45,0x4d,0x4A,0xB8,0x0d,0x4A,0x4C,0x0d,0xA5,0x41,0x25,0xAA,0xB6,0x05,0x6A,0x49,0x7A,0xAd,0xBd,0x02,0x5d,0x52,0x09,0x2d,0x47,0x5C,0x95,0xBA,0x0A,0x95,0

23、x4e,0x0B,0x4A,0x43,0x4B,0x55,0x37,0x0A,0xd5,0x4A,0x95,0x5A,0xBf,0x04,0xBA,0x53,0x0A,0x5B,0x48,0x65,0x2B,0xBC,0x05,0x2B,0x50,0x0A,0x93,0x45,0x47,0x4A,0xB9,0x06,0xAA,0x4C,0x0A,0xd5,0x41,0x24,0xdA,0xB6,0x04,0xB6,0x4A,0x69,0x57,0x3d,0x0A,0x4e,0x51,0x0d,0x26,0x46,0x5e,0x93,0x3A,0x0d,0x53,0x4d,0x05,0xAA,0

24、x43,0x36,0xB5,0x37,0x09,0x6d,0x4B, 0xB4,0xAe,0xBf,0x04,0xAd,0x53,0x0A,0x4d,0x48,0x6d,0x25,0xBC,0x0d,0x25,0x4f,0x0d,0x52,0x44,0x5d,0xAA,0x38,0x0B,0x5A,0x4C,0x05,0x6d,0x41,0x24,0xAd,0xB6,0x04,0x9B,0x4A,0x7A,0x4B,0xBe,0x0A,0x4B,0x51,0x0A,0xA5,0x46,0x5B,0x52,0xBA,0x06,0xd2,0x4e,0x0A,0xdA,0x42,0x35,0x5B,

25、0x37,0x09,0x37,0x4B,0x84,0x97,0xC1,0x04,0x97,0x53,0x06,0x4B,0x48,0x66,0xA5,0x3C,0x0e,0xA5,0x4f,0x06,0xB2,0x44,0x4A,0xB6,0x38,0x0A,0xAe,0x4C,0x09,0x2e,0x42,0x3C,0x97,0x35,0x0C,0x96,0x49,0x7d,0x4A,0xBd,0x0d,0x4A,0x51,0x0d,0xA5,0x45,0x55,0xAA,0xBA,0x05,0x6A,0x4e,0x0A,0x6d,0x43, 0x45,0x2e,0xB7,0x05,0x2d

26、,0x4B,0x8A,0x95,0xBf,0x0A,0x95,0x53,0x0B,0x4A,0x47,0x6B,0x55,0x3B,0x0A,0xd5,0x4f,0x05,0x5A,0x45,0x4A,0x5d,0x38,0x0A,0x5B,0x4C,0x05,0x2B,0x42,0x3A,0x93,0xB6, 0x06,0x93,0x49,0x77,0x29,0xBd,0x06,0xAA,0x51,0x0A,0xd5,0x46,0x54,0xdA,0xBA,0x04,0xB6,0x4e,0x0A,0x57,0x43,0x45,0x27,0x38,0x0d,0x26,0x4A,0x8e,0x9

27、3,0x3e,0x0d,0x52,0x52,0x0d,0xAA,0x47,0x66,0xB5,0x3B,0x05,0x6d,0x4f,0x04,0xAe,0x45,0x4A,0x4e,0xB9,0x0A,0x4d,0x4C,0x0d,0x15,0x41,0x2d,0x92,0xB5, ; /月份数据表 code uchar day_code19=0x0,0x1f,0x3b,0x5a,0x78,0x97,0xb5,0xd4,0xf3; code uint day_code23=0x111,0x130,0x14e; /* 函数功能:输入BCD阳历数据,输出BCD阴历数据(只允许1901-2099年

28、) 调用函数示例:Conversion(c_sun,year_sun,month_sun,day_sun) 如:计算2004年10月16日Conversion(0,0x4,0x10,0x16); c_sun,year_sun,month_sun,day_sun均为BCD数据,c_sun为世纪标志位,c_sun=0为21世 纪,c_sun=1为19世纪 调用函数后,原有数据不变,读c_moon,year_moon,month_moon,day_moon得出阴历BCD数据 */ bit c_moon; data uchar year_moon,month_moon,day_moon,week; /

29、*子函数,用于读取数据表中农历月的大月或小月,如果该月为大返回1,为小返回0*/ bit get_moon_day(uchar month_p,uint table_addr) uchar temp; switch (month_p) case 1:temp=year_codetable_addr&0x08; if (temp=0)return(0);else return(1); case 2:temp=year_codetable_addr&0x04; if (temp=0)return(0);else return(1); case 3:temp=year_codetab

30、le_addr&0x02; if (temp=0)return(0);else return(1); case 4:temp=year_codetable_addr&0x01; if (temp=0)return(0);else return(1); case 5:temp=year_codetable_addr+1&0x80; if (temp=0) return(0);else return(1); case 6:temp=year_codetable_addr+1&0x40; if (temp=0)return(0);else return(1); cas

31、e 7:temp=year_codetable_addr+1&0x20; if (temp=0)return(0);else return(1); case 8:temp=year_codetable_addr+1&0x10; if (temp=0)return(0);else return(1); case 9:temp=year_codetable_addr+1&0x08; if (temp=0)return(0);else return(1); case 10:temp=year_codetable_addr+1&0x04; if (temp=0)retu

32、rn(0);else return(1); case 11:temp=year_codetable_addr+1&0x02; if (temp=0)return(0);else return(1); case 12:temp=year_codetable_addr+1&0x01; if (temp=0)return(0);else return(1); case 13:temp=year_codetable_addr+2&0x80; if (temp=0)return(0);else return(1); /* 函数功能:输入BCD阳历数据,输出BCD阴历数据(只允许1

33、901-2099年) 调用函数示例:Conversion(c_sun,year_sun,month_sun,day_sun) 如:计算2004年10月16日Conversion(0,0x4,0x10,0x16); c_sun,year_sun,month_sun,day_sun均为BCD数据,c_sun为世纪标志位,c_sun=0为21世 纪,c_sun=1为19世纪 调用函数后,原有数据不变,读c_moon,year_moon,month_moon,day_moon得出阴历BCD数据 */ void Conversion(bit c,uchar year,uchar month,uchar

34、day) /c=0 为21世纪,c=1 为19世纪 输入输出数据均为BCD数据 uchar temp1,temp2,temp3,month_p; uint temp4,table_addr; bit flag2,flag_y; temp1=year/16; /BCD->hex 先把数据转换为十六进制 temp2=year%16; year=temp1*10+temp2; temp1=month/16; temp2=month%16; month=temp1*10+temp2; temp1=day/16; temp2=day%16; day=temp1*10+temp2; /定位数据表地址

35、 if(c=0) table_addr=(year+0x64-1)*0x3; else table_addr=(year-1)*0x3; /定位数据表地址完成 /取当年春节所在的公历月份 temp1=year_codetable_addr+2&0x60; temp1=_cror_(temp1,5); /取当年春节所在的公历月份完成 /取当年春节所在的公历日 temp2=year_codetable_addr+2&0x1f; /取当年春节所在的公历日完成 / 计算当年春年离当年元旦的天数,春节只会在公历1月或2月 if(temp1=0x1) temp3=temp2-1; else

36、 temp3=temp2+0x1f-1; / 计算当年春年离当年元旦的天数完成 /计算公历日离当年元旦的天数,为了减少运算,用了两个表 /day_code19,day_code23 /如果公历月在九月或前,天数会少于0xff,用表day_code19, /在九月后,天数大于0xff,用表day_code23 /如输入公历日为8月10日,则公历日离元旦天数为day_code18-1+10-1 /如输入公历日为11月10日,则公历日离元旦天数为day_code211-10+10-1 if (month<10) temp4=day_code1month-1+day-1; else temp4=

37、day_code2month-10+day-1; if (month>0x2)&&(year%0x4=0) temp4+=1; /如果公历月大于2月并且该年的2月为闰月,天数加1/计算公历日离当年元旦的天数完成 /判断公历日在春节前还是春节后 if (temp4>=temp3) /公历日在春节后或就是春节当日使用下面代码进行运算 temp4-=temp3; month=0x1; month_p=0x1; /month_p为月份指向,公历日在春节前或就是春节当日month_p指向首月 flag2=get_moon_day(month_p,table_addr); /检

38、查该农历月为大小还是小月,大月返回1,小月返回0 flag_y=0; if(flag2=0)temp1=0x1d; /小月29天 else temp1=0x1e; /大小30天 temp2=year_codetable_addr&0xf0; temp2=_cror_(temp2,4); /从数据表中取该年的闰月月份,如为0则该年无闰月 while(temp4>=temp1) temp4-=temp1; month_p+=1; if(month=temp2) flag_y=flag_y; if(flag_y=0) month+=1; else month+=1; flag2=get

39、_moon_day(month_p,table_addr); if(flag2=0)temp1=0x1d; else temp1=0x1e; day=temp4+1; else /公历日在春节前使用下面代码进行运算 temp3-=temp4; if (year=0x0) year=0x63;c=1; else year-=1; table_addr-=0x3; month=0xc; temp2=year_codetable_addr&0xf0; temp2=_cror_(temp2,4); if (temp2=0) month_p=0xc; else month_p=0xd; /*mo

40、nth_p为月份指向,如果当年有闰月,一年有十三个月,月指向13,无闰月指向12*/ flag_y=0; flag2=get_moon_day(month_p,table_addr); if(flag2=0)temp1=0x1d; elsetemp1=0x1e; while(temp3>temp1) temp3-=temp1; month_p-=1; if(flag_y=0)month-=1; if(month=temp2)flag_y=flag_y; flag2=get_moon_day(month_p,table_addr); if(flag2=0)temp1=0x1d; elset

41、emp1=0x1e; day=temp1-temp3+1; c_moon=c; /HEX->BCD ,运算结束后,把数据转换为BCD数据 temp1=year/10; temp1=_crol_(temp1,4); temp2=year%10; year_moon=temp1|temp2; temp1=month/10; temp1=_crol_(temp1,4); temp2=month%10; month_moon=temp1|temp2; temp1=day/10; temp1=_crol_(temp1,4); temp2=day%10; day_moon=temp1|temp2;

42、/*函数功能:输入BCD阳历数据,输出BCD星期数据(只允许1901-2099年) 调用函数示例:Conver_week(c_sun,year_sun,month_sun,day_sun) 如:计算2004年10月16日Conversion(0,0x4,0x10,0x16); c_sun,year_sun,month_sun,day_sun均为BCD数据,c_sun为世纪标志位,c_sun=0为21世 纪,c_sun=1为19世纪 调用函数后,原有数据不变,读week得出阴历BCD数据 */ code uchar table_week12=0,3,3,6,1,4,6,2,5,0,3,5; /月

43、修正数据表 /* 算法:日期+年份+所过闰年数+月较正数之和除7 的余数就是星期但如果是在 闰年又不到3 月份上述之和要减一天再除7 星期数为0 */ void Conver_week(bit c,uchar year,uchar month,uchar day) /c=0 为21世纪,c=1 为19世纪 输入输出数据均为BCD数据 uchar temp1,temp2; temp1=year/16; /BCD->hex 先把数据转换为十六进制 temp2=year%16; year=temp1*10+temp2; temp1=month/16; temp2=month%16; month

44、=temp1*10+temp2; temp1=day/16; temp2=day%16; day=temp1*10+temp2; if (c=0)year+=0x64; /如果为21世纪,年份数加100 temp1=year/0x4; /所过闰年数只算1900年之后的 temp2=year+temp1; temp2=temp2%0x7; /为节省资源,先进行一次取余,避免数大于0xff,避免使用整型数据 temp2=temp2+day+table_weekmonth-1; if (year%0x4=0&&month<3)temp2-=1; week=temp2%0x7;

45、sbit K1 = P32;/定义按键K1:时钟显示与菜单切换sbit K2 = P33;/定义按键K2:选择/确认sbit K3 = P34;/定义按键K3:数字减1sbit K4 = P35;/定义按键K4:数字加1bit m0 = 0;unsigned char m1, m2, m3, m4, SoundMode, t;/分别对应:m0时钟显示与菜单切换、m1菜单1选项、m2菜单2选项、m3菜单3选项、m4菜单4选项、语音报时模式选择、t菜单选项unsigned char i = 0, j = 0;/用于按键的延时消抖以及循环unsigned char t0 = 0;/菜单返回计数uns

46、igned char MonthsDays13 = 0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31; /1-12月每月的天数unsigned char code runnian37 = 0x01, 0x04, 0x06, 0x09, 0x12, 0x14, 0x17,0x20, 0x23, /2000-2099年阴历闰年数据0x25, 0x28, 0x31, 0x33, 0x36, 0x39, 0x42, 0x44, 0x47, 0x50, 0x52, 0x55, 0x58, 0x61, 0x63, 0x66, 0x69, 0x71,0x74,

47、 0x77, 0x80, 0x82, 0x85, 0x88, 0x90, 0x93, 0x96, 0x99;4.2 main函数/*下面为调用的子函数声明*/*下面为调用的子函数声明*/*一上电就读取单片机内部EEPROM中的闹钟、日程数据*/void ReadData ();/*函数功能:显示时钟界面*/void TimeDisplay ();/*函数功能:判断是否为阳历闰年*/unsigned char LeapYear (unsigned char year);/*函数功能:闹钟程序*/void AlarmClock ();/*函数功能:日程程序*/void ScheduleAlarm

48、();/*函数功能:语音报时*/void TimeSound();/*函数功能:按键, 按K3数字减1, 按K4数字加1*/void K3K4Down (unsigned char j, unsigned char min, unsigned char max);/*函数功能:在调时界面,按下K2将时钟数据写入DS1302*/void K2WriteTime ();/*函数功能:在调时界面,按下K2将闹钟数据写入单片机内部EEPROM保存*/void K2WriteAlarmTime ();/*函数功能:在调时界面,按下K2将日程数据写入单片机内部EEPROM保存*/void K2WriteS

49、cheduleTime ();/*函数功能:在语音报时模式显示界面下,将语音报时模式数据写入STC内部EEPROM保存*/void K2WriteSoundMode();/*函数功能:外部中断1初始化*/void Int1Init();/*函数功能:中断日程响应*/void AlarmScheduleInterrupt();/一上电会给语音芯片一个脉冲,使语音芯片发出语音:“0”void main ()Lcd1602Init (); /LCD1602初始化Int1Init();/外部中断1初始化WriteCharacter (); /将汉字“年”、“月”、“日”、“闰”、“平”、“开”、“关”

50、写进LCD1602Lcd1602WriteString (0x80, " Welcome!");/欢迎界面Lcd1602WriteString (0xc0, " Welcome!");Ds1302ReadTime(); /一上电就读取DS1302中的时钟数据ReadData (); /读取存放在STC内部EEPROM中的数据Delay10ms (250);/欢迎界面保持3秒左右Write1602Cmd (0x01); /清屏while (1)if (K1 = 0)/按一下,在时钟显示与菜单显示之间转换Delay10ms (1);/延时消抖if (K1 =

51、 0)t = 1;/初始化状态m1 = 0; /在回到时钟显示时若之前的操作未保存则回到初始状态m2 = 0;m3 = 0;m4 = 0;Time7 = AlarmTime0; /将闹钟数据送到LCD显示Time8 = AlarmTime1;Time9 = AlarmTime2;Time13 = ScheduleTime0; /将日程数据送到LCD显示Time14 = ScheduleTime1;Time15 = ScheduleTime2;Time16 = ScheduleTime3;Time17 = ScheduleTime4;Time18 = ScheduleTime5;Time19 = SoundMode;Write1602Cmd (0x01);/清屏m0 = m0;/m0只能是0、1while (i < 20) && (K1 = 0) /松手检测,防止因硬件问题导致死循环Delay1ms (2);i+;i = 0;if (m0 = 0)TimeSound ();/只报一次AlarmClock ();/不断检测是否为闹钟时间,按下K2后闹钟停止,并且闹钟为OFF状态ScheduleAlarm (); /不断检测是否为日

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论