经过分析,将题目大致分为四大块:
1、提供北京时间以及与时间相关(包括是否为闰年,闹钟判断等)的部分
2、串口显示和液晶显示部分
3、温度采集模块部分
4、拓展部分(开机密码、整点报时等)
将程序按照四大块处理,通过分析,我们发现模块一最适合使用RTC实时时钟外设来处理,利用它提供的时间戳,可通过程序转换输出实时时钟和日历的功能,修改计数器的值则可以重新设置系统当前的时间和日期。再将时间戳转化为生活中可用的日期格式,即可方便的对日期进行新历农历以及闹钟等处理。
模块二部分我们决定液晶串口二者都使用。首先调用USART串口通讯程序,来通过上位机与单片机取得联系。至于液晶采用ILI9341进行数据显示,调用ILI9341的初始化程序,并通过显示程序每1s向液晶传送当前的时间。
模块三我们使用ds18b20来进行温度采集,通过配置引脚,加入其初始化程序以及调用SysTick定时器,便于更精准的按时采集温度。
在模块四拓展部分,首先,我们决定加入一个开机密码,用串口方式登录。如果无法正确的输入密码,则不能进入万年历。第二,我们加入了一个整点报时功能,在离整点差两秒的时候会发出三声滴滴的响声,提醒已到整点。在此处调用蜂鸣器模块,通过蜂鸣器来发出响声。
上述分为四个模块的外设选择如下:
模块一:RTC实时时钟,按键,蜂鸣器等
模块二:USART串口通讯,ILI9341液晶模块
模块三:ds18b20温度采集模块,SysTick定时器
模块四:USART串口通讯,蜂鸣器模块
且每个模块都有使用GPIO
将公历日期转换为自1970-01-01 00:00:00起的秒数。
通过串口采集到的信息,计算出到现在经历了多少个星期,即可判断今天是周几。
通过调用此函数,将定时器内的值,转换成北京时间,便可轻松计算出当前年月日以及时分秒。
当今年为闰年的时候,令变量m=1,并在主函数中判断,当m=1的时候,显示今年为闰年,否则显示不是闰年。
通过GetChinaCalendar(uint16_t year,uint8_t month,uint8_t day,uint8_t *p)函数,将公历转化为农历。
通过函数GetSkyEarth()输入公历日期得到一个甲子年(只允许1901-2099年)。
通过函数GetChinaCalendarStr()输入公历日期得到农历字符串。
如:GetChinaCalendarStr(2007,02,06,str) 返回str=“丙戌年腊月十九”。
通过此函数进行节气的判断,在之前已用一个叔祖定义好了节气,只需得出当前时间对应的序号,即可在数组中找到相应的节气。
设置变量TimeAlarm,当检测到clocktime等于当前时间时,令TimeAlarm=1
在主函数while()语句中,一旦检测到变量TimeAlarm=1,闹铃即开启。
当检测到按键按下时,蜂鸣器停止工作,即闹铃停止。
图为部分截图,只包含了修改年份。
通过该指令保存用户使用串口设置的时间,以便后面转化成时间戳存储到RTC 计数寄存器中。可以通过此函数,实现可以从串口改变时间的功能。
对液晶初始化以及清屏处理。
通过调用此程序,来在液晶上显示日期生肖等信息。
DS18B20_ReadId ( ucDs18b20Id ); // 读取 DS18B20 的序列号
printf("\r\nDS18B20的序列号是: 0x");
for ( uc = 0; uc < 8; uc ++ ) // 打印 DS18B20 的序列号
printf ( “%.2x”, ucDs18b20Id [ uc ] );
对ds18b20进行初始化,每隔1s进行一次温度采集,并将其通过串口,发送到上位机上。
本模块为拓展模块,共包含了密码模块和整点报时功能。
此为密码模块全部内容,如果不输入正确密码,将一直处于死循环状态,无法执行下面程序。当检测到预定按键按下后,进入密码输入阶段。如果输入正确,则会显示“密码正确”将继续执行主程序内容,即万年历开始工作;如果输入错误,则会显示“您输入的密码错误,请重新输入”,并且无法继续执行主程序,直到密码输入正确。
当分钟等于59时,秒钟等于58时,蜂鸣器工作三次,提醒进入整点。
烧录入程序后,会提示输入密码
输入密码错误时,会发出提示:
当输入密码正确后,会进入主程序,即万年历开始工作:
按下按键K1,进入修改时间模式;
将日期更新后的显示如下:
在上位机的接收区可以观察到新历农历等显示,已经当前节气,鼠年显示,时间戳大小以及温度显示。
在液晶工作区可以看到时间每1s刷新一次