STM32实现万年历
STM32 RTC万年历设计
static uint8_t num; //接收计数 uint8_t temp=0; //查询是否发生了空闲中断 if(__HAL_UART_GET_FLAG(usart->huart,UART_FLAG_IDLE) != RESET && \
注意,这部分代码要写在 用户代码区之间,闹钟初始化的部分可以保留在外面,不需要加 入到条件判断语句里面。 到这里,如果断电,在恢复以后时间就可以正常走下去了吗?当然…… 是不可以的!!! 现象是:重新上电后,时分秒的时间是可以继续延续下去,但是日期变成了 2000-01-01 , 为什么??这就需要去追一下初始化的代码了。
如果在日期更新的时候,我们没有重新备份日期到备份寄存器中,那么我们上电读回来的时 间就是我们第一次备份的时间,例如,今天我们备份了日期,然后把板子停电 3 天,三天后 再开启的话,读回来的时间就是今天备份的日期,并不是三天后的日期。
对于这个问题,我们就需要在日期更新和设置日期的时候,都需要把新的日期备份到寄存器 中,做法是在日期更新函数中增加备份代码:
我们需要去查看一下 HAL_RTC_Init(&hrtc)这个函数的代码是实现了什么功能。
在函数结尾,我们看到了上面这一段代码,当调用这个函数的时候就会把日期设置成 2000-01-01 了,找到了原因,我们要怎么改呢?这一段初始化代码什么是规避不了的,那 么我们可以在他执行之后重新把日期设置一下,思路还是利用备份寄存器。 我们可以在初始化时,把日期写到备份寄存中,完善一下之前写的条件初始化程序的内容, 增加日期备份。在这里我们备份的日期仅仅是初始化当时配置的时间,上电后读回来的也是 这个时间,不一定就是正确的!!
基于STM32的智能万年历课程设计说明书
课程设计说明书设计题目:基于STM32的智能万年历专业:电气工程及其自动化班级:设计人:课程设计任务书学院电气信息系专业电气工程及其自动化一、课程设计题目:基于STM32的智能万年历专题名称:最小应用系统二、课程设计主要参考资料(1)刘火良,杨森.STM32库开发实战指南[M].北京:机械工业出版社.2013.5(2)ADS7943中文参考资料[M/CD].(3)ILI9320控制器中文参考资料[M/CD].三、课程设计应解决主要问题(1)最小应用系统:包括MCU、复位、启动、晶振、电源等。
(2)日历的显示和设置;(3)万年历的算法和实现;(4)定时闹钟功能;(5)无线设置功能。
四、课程设计相关附件(如:图纸、软件等)(1)软件:Keil μVision4(2)开发平台:神州Ⅱ号STM32嵌入式技术开发板五、任务发出日期:课程设计完成日期:指导教师签字:系主任签字:指导教师对课程设计的评语指导教师(签章):日期:摘要单片机应用技术飞速发展,从导弹的导航装置,到飞机上各种仪表的控制,从计算机的网络通讯与数据传输,到工业自动化过程的实时控制和数据处理,以及生活中广泛使用的各种智能IC卡、电子宠物等,从大到国家防卫,小到日常生活,方方面面都离不开单片机。
单片机是集CPU,RAM,ROM,定时,计数和多种接口于一体的微控制器。
它体积小,成本低,功能强,广泛应用于智能产业和工业自动化上。
二十一世纪的今天科技与经济迅速发展,人们的生活节奏变得越来越快,生活水平越来越高,对于生活的品味和质量的要求也更高。
人们不再满足于只能提供简单计时功能的时钟,希望在能保证计时精确的基础上能多添加一些其他功能,诸如日历、定时等。
本文主要介绍了以STM32F103VCT6开发板为核心部件来设计的一款万年历,以其内部的RTC时钟模块作为时钟,用TFTLCD液晶显示器作为显示模块,时钟电路能准确提供24小时制时间、平年闰年的判断以及定时。
(完整word版)基于STM32的万年历设计
基于STM32的万年历设计班级:姓名:学号:成绩:电子通信工程系题目:基于STM32的万年历设计前言:随着科技的快速发展,时间的流逝,至从观太阳、摆钟到现在电子钟,人类不断研究,不断创新纪录。
美国DALLAS公司推出的具有涓细电流充电能的低功耗实时时钟电路DS12C887。
它可以对年、月、日、周日、时、分、秒进行计时,还具有闰年补偿等多种功能,而且DS12C887的使用寿命长,误差小。
对于数字电子万年历采用直观的数字显示,可以同时显示年、月、日、周日、时、分、秒和温度等信息,还具有时间校准等功能。
该电路采用AT89S52单片机作为核心,采用数字式温度传感器DS18B20提取外界温度,功耗小,能在3V的低压工作,电压可选用3~5V电压供电。
进入新世纪LCD显示屏的技术和产业都取得了长足的发展,作为重要的现代信息发布媒体之一,LCD显示屏在证券交易、金融、交通、体育、广告等领域被广泛的应用。
伴随社会信息化进程的推进,LCD显示屏技术也在不断的推陈出新,应用领域愈加广阔。
基于STM32的LCD显示可以更好的满足各种需求,也更便于操作和实现。
现基于STM32在液晶显示屏幕上显示文本及图形。
目前,显示技术和显示工业的发展迅速。
显示技术是传递视觉的信息技术。
液晶显示器件LCD 是当今最有发展前途的一种平板显示器件,它具有很多独到的优异特性。
它具有显示信息多、易于多彩化、体积小、重量轻、功耗低、寿命长、价格低、无辐射、无污染、接口控制方便等优点。
截至目前,我国在液晶显示取得较大进步,我国LCD产业已经走过了近30年的历程.经历几次大的投资浪潮之后,我国内地已经成为世界最大的TN-LCD(扭曲液晶显示器)生产基地和主要的STN-LCD(超扭曲液晶显示器)生产基地,并且从2003年开始,涉足TFT-LCD(薄膜晶体管液晶显示器)领域.本课题设计采用STM32F103VE开发板,实现在LCD显示屏上显示由按键可操控的万年历功能。
基于STM32的智能万年历设计方案
基于STM32的智能万年历设计方案1.课程设计任务1.1 课程设计目的(1)学习万年历的原理,学会定时器、触摸屏在万年历中的应用。
(2)通过万年历的制作使学生熟练掌握所学的相关知识容,并培养学生工程设计的一般方法和技巧。
1.2 设计要求:独立思考、共同合作、保质保量、按时完成。
1.3 技术要求:(1)系统组成系统选用STM32F103单片机为微处理器,使用开发板上具有的按键、指示灯、触摸屏和串口等实现万年历的功能。
(2)实现功能:1)日历、时间的调整,通过按键切换实现对年月日时分秒的调整控制,可以设置每一部分的初始值。
2)具备闰年的自动调整功能3)具有定时闹钟功能:通过按键/触摸屏设置定时时间。
定时时间到,蜂鸣器发出鸣叫声,维持5S。
4)上位机功能:可以把单片机的时间数据通过串口或者USB传送至上位机。
5)无线设置功能:通过远程设置万年历。
(3)模块组成:STM32 单片机最小应用系统;设置显示模块;闹钟模块;时间运行模块等;1.4 解决的主要问题:(1)最小应用系统设计:设计STM32的最小应用系统,包括MCU、复位、启动、晶振、电源等。
(2)日历的显示和设置;(3)万年历的算法和实现;(4)定时闹钟功能;(5)无线设置功能。
1.5 两周时间安排(1)第一周:星期一:布置设计任务,收集相关资料。
星期二:确定设计方案星期三:软、硬件的总体设计星期四、五、六、日:上机调试(2)第二周星期一、二、三:上机调试星期四:完成设计报告。
星期五:17:00之前上交课程设计报告。
2 总体方案设计2.1 整体方案设计2.2 模块工作原理2.2.1 最小应用系统模块最小应用系统包括MCU和电源、复位、晶振、启动等,该系统可以接收数据传给上位机,通过上位机将数据传输到显示屏上显示数据,也可以通过改变数据让其调整显示屏上的数据。
另外它能使蜂鸣器发声。
2.2.2 基础配置模块基础配置模块实现对SysClock、RCC、GPIO、EXTI、NVIC、Timer、USART 等功能模块进行基础配置,设置其输入输出方式、速度及其它专属配置,并使能需要的管脚及外设,设置中断。
STM32实现万年历..
STM32学习笔记一竹天笑实现的功能:1、日历功能。
2、数字和模拟时钟功能。
图1(为LCD截屏保存在SD卡中的图像)最终界面如下,但还存在不少漏洞。
1、没有更改时间的设置;2、只有节气显示没有节假日显示3、背景不是用uCGUI画的,是在PS中画好然后存在SD卡中,然后显示的BMP 格式图像。
要点分析:1、STM32自带了RTC时钟计数器,从0开始计数到232。
每一个计数代表秒计数,每六十个计数代表分计数,以此类推。
24(小时)*60(分钟)*60(秒钟)=86400代表一天的计数时间。
假设当前计数为count,count/86400得到计数的天数,根据这个得到年月日。
Count%86400得到时分秒。
2、一些根据1中得到的年月日时分秒,进行计算的程序有:阳历转阴历,闰年判断,节气判断,星期几计算,当前月有多少天等等。
3、模拟时钟的绘制:时钟指针运动算法、屏幕重绘方法、RTC消息、画笔/画刷等。
指针运动算法和屏幕重绘方法是本程序主要难点所在。
(以下参照百度文库之模拟时钟)不论何种指针,每次转动均以π/30弧度(一秒的角度)为基本单位,且都以表盘中心为转动圆心。
计算指针端点(x, y)的公式如下:x =圆心x坐标+ 指针长度* cos (指针方向角)y =圆心y坐标+ 指针长度* sin (指针方向角)注意,指针长度是指自圆心至指针一个端点的长度(是整个指针的一部分),由于指针可能跨越圆心,因此一个指针需要计算两个端点。
由于屏幕的重绘1秒钟一次,如果采用全屏删除式重绘则闪烁十分明显,显示效果不佳。
本程序采用非删除式重绘,假定指针将要移动一格,则先采用背景色(这里是白色)重绘原来指针以删除原来位置的指针,再采用指针的颜色在当前位置绘制指针(如果指针没有动,则直接绘制指针,此句在程序中被我删除,具体原因,为数据截断导致一些误差)。
另外,秒表为RTC一秒钟定时计数。
程序分析:uCGUI+uCOS,一共三个任务:主处理任务、触摸屏任务、秒更新任务。
基于STM32单片机的万年历设计毕业设计论文
万年历是一种可以显示年、月、日、星期的电子设备,广泛应用于日常生活和办公场所。
本文将介绍一个基于STM32单片机的万年历的设计思路和实现过程。
首先,我们需要明确设计目标。
在这个项目中,我们的目标是使用STM32单片机开发一个功能齐全、易于操作的万年历。
具体地说,这个万年历应该能够显示当前的年、月、日和星期,并且能够进行日期的加减操作,同时应该具备一些辅助功能如闹钟设置、倒计时等。
接下来,我们需要进行硬件设计。
首先需要选择适当的显示屏,比如常见的LCD或OLED屏幕。
然后,我们需要选择合适的按键和外部触发器,用于用户的交互输入。
同时,还需要添加一些必要的接口,如USB接口用于数据传输和维护。
在软件设计方面,我们需要定义合适的数据结构来存储日期、时间、闹钟等信息。
同时,需要编写相应的程序来实现日期的显示和更新、日期的加减、闹钟的设置等功能。
在实现倒计时功能时,我们可以使用定时器中断来实现精确的计时。
此外,为了提高用户体验,我们可以添加一些额外的功能。
比如,我们可以为万年历设计一个简洁美观的用户界面,考虑使用图形库绘制用户界面元素。
同时,可以添加一些实用的功能如温湿度监测、天气预报等。
最后,在整个开发流程结束后,我们需要进行集成测试和调试,确保万年历的各项功能正常运行。
并且,我们还可以考虑为万年历添加一些优化和改进措施,如增加存储容量、优化节能技术等。
综上所述,基于STM32单片机的万年历设计主要涉及硬件设计和软件设计两个方面。
通过精心的设计和合理的实现,我们可以开发出一款功能丰富、易于使用的万年历产品,满足用户的各种需求。
基于STM32单片机的万年历设计毕业设计论文
本科生毕业论文(或设计)(申请学士学位)论文题目基于STM32单片机的万年历设计毕业设计(论文)原创性声明和使用授权说明原创性声明本人郑重承诺:所呈交的毕业设计(论文),是我个人在指导教师的指导下进行的研究工作及取得的成果。
尽我所知,除文中特别加以标注和致谢的地方外,不包含其他人或组织已经发表或公布过的研究成果,也不包含我为获得及其它教育机构的学位或学历而使用过的材料。
对本研究提供过帮助和做出过贡献的个人或集体,均已在文中作了明确的说明并表示了谢意。
作者签名:日期:指导教师签名:日期:使用授权说明本人完全了解大学关于收集、保存、使用毕业设计(论文)的规定,即:按照学校要求提交毕业设计(论文)的印刷本和电子版本;学校有权保存毕业设计(论文)的印刷本和电子版,并提供目录检索与阅览服务;学校可以采用影印、缩印、数字化或其它复制手段保存论文;在不以赢利为目的前提下,学校可以公布论文的部分或全部内容。
作者签名:日期:学位论文原创性声明本人郑重声明:所呈交的论文是本人在导师的指导下独立进行研究所取得的研究成果。
除了文中特别加以标注引用的内容外,本论文不包含任何其他个人或集体已经发表或撰写的成果作品。
对本文的研究做出重要贡献的个人和集体,均已在文中以明确方式标明。
本人完全意识到本声明的法律后果由本人承担。
作者签名:日期:年月日学位论文版权使用授权书本学位论文作者完全了解学校有关保留、使用学位论文的规定,同意学校保留并向国家有关部门或机构送交论文的复印件和电子版,允许论文被查阅和借阅。
本人授权大学可以将本学位论文的全部或部分内容编入有关数据库进行检索,可以采用影印、缩印或扫描等复制手段保存和汇编本学位论文。
涉密论文按学校规定处理。
作者签名:日期:年月日导师签名:日期:年月日注意事项1.设计(论文)的内容包括:1)封面(按教务处制定的标准封面格式制作)2)原创性声明3)中文摘要(300字左右)、关键词4)外文摘要、关键词5)目次页(附件不统一编入)6)论文主体部分:引言(或绪论)、正文、结论7)参考文献8)致谢9)附录(对论文支持必要时)2.论文字数要求:理工类设计(论文)正文字数不少于1万字(不包括图纸、程序清单等),文科类论文正文字数不少于1.2万字。
使用STM32的RTC制作万年历
使用STM32的RTC制作万年历(2013-09-14 16:39:34)转载▼标签:it注意:红色代码部分,如果不加这两句,修改时间一直卡死在RTC_WaitForLastTask()#include "stm32f10x.h"#include "STM32_RTC.h"#define BKP_TIME_FLAG BKP_DR1#define BKP_TIME_YEAR BKP_DR2#define BKP_TIME_MONTH BKP_DR3#define BKP_TIME_DAY BKP_DR4#define BKP_TIME_DATE BKP_DR5u32 Month_Days_Accu_C[13] = {0,31,59,90,120,151,181,212,243,273,304,334,365}; u32 Month_Days_Accu_L[13] = {0,31,60,91,121,152,182,213,244,274,305,335,366}; #define SecsPerDay (3600*24)extern T_STRUCT Real_Time;//实时时间值void RTC_Configuration(void){RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);PWR_BackupAccessCmd(ENABLE);BKP_DeInit();RCC_LSEConfig(RCC_LSE_ON);while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET){}RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);RCC_RTCCLKCmd(ENABLE);RTC_WaitForSynchro();RTC_WaitForLastTask();RTC_ITConfig(RTC_IT_SEC, ENABLE);RTC_WaitForLastTask();RTC_SetPrescaler(32767);RTC_WaitForLastTask();}void RTC_init(void){if(BKP_ReadBackupRegister(BKP_TIME_FLAG) != 0xA5A5){RTC_Configuration();Real_Time.year = 2013;Real_Time.month = 1;Real_Time.day = 1;Real_Time.hour = 12;Real_Time.minute = 0;Real_Time.second = 0;Real_Time.date = 1;SetRTCTime(&Real_Time);BKP_WriteBackupRegister(BKP_TIME_FLAG, 0xA5A5);}else{if(RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET){//电源复位}else if(RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET){//External Reset occurred}RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); PWR_BackupAccessCmd(ENABLE);BKP_TamperPinCmd(DISABLE);BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);RTC2Time();}RTC_WaitForSynchro();RCC_ClearFlag(); //清除RCC重启标志}void GetRTCTime(T_STRUCT* time){RTC_ITConfig(RTC_IT_SEC, DISABLE); //关闭秒中断RTC_WaitForLastTask();time->year=Real_Time.year;time->month=Real_Time.month;time->day=Real_Time.day;time->hour=Real_Time.hour;time->minute=Real_Time.minute;time->second=Real_Time.second;time->date=Real_Time.date;RTC_WaitForLastTask();RTC_ITConfig(RTC_IT_SEC, ENABLE); //打开秒中断}const u8 TAB_DATE[12]={6,2,2,5,0,3,5,1,4,6,2,4,};u8 GetDate(T_STRUCT* time){return( (time->year + time->year/4 - ( (time->month<3)&&(time->year%4==0) ) +TAB_DATE[time->month-1] + time->day )%7);}const u8 Month2Day_Tab[12]={31,28,31,30,31,30,31,31,30,31,30,31} ;void RTC2Time(void){u32 count;u8 tmp,change=0;Real_Time.year=BKP_ReadBackupRegister(BKP_TIME_YEAR);//年值Real_Time.month=BKP_ReadBackupRegister(BKP_TIME_MONTH);//月值Real_Time.day=BKP_ReadBackupRegister(BKP_TIME_DAY);//日值Real_Time.date=BKP_ReadBackupRegister(BKP_TIME_DATE);//星期值RTC_ITConfig(RTC_IT_SEC, DISABLE); //为了避免代码重入引起的问题,这里吧RTC秒中断屏蔽了count=RTC_GetCounter();//计算新的年月日while (count>=0x0001517f) //上次关电到本次跨越了一天以上{change=1;count-=0x0001517f;//星期自加if ((++Real_Time.date)>=8)Real_Time.date=1;//如果是2月,计算闰年(不需要考虑2099以后的400年一非润) if (Real_Time.month==2){if (Real_Time.year%4)tmp=28;elsetmp=29;}else{tmp=Month2Day_Tab[Real_Time.month-1];}if ((++Real_Time.day)>tmp){Real_Time.day=1;if ((++Real_Time.month)>12){Real_Time.month=1;if ((++Real_Time.year)>=100){Real_Time.year=0;}}}//如果跨越了一天,则计算后,要存回寄存器内if (change){RTC_SetCounter(count);BKP_WriteBackupRegister(BKP_TIME_DATE,Real_Time.date);BKP_WriteBackupRegister(BKP_TIME_DAY,Real_Time.day);BKP_WriteBackupRegister(BKP_TIME_MONTH,Real_Time.month); BKP_WriteBackupRegister(BKP_TIME_YEAR,Real_Time.year);}}//计算新的时分秒Real_Time.hour=count/3600;Real_Time.minute=(count600)/60;Real_Time.second=(count600)`;//重新打开RTC中断// Check if the Power On Reset flag is setRCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);PWR_BackupAccessCmd(ENABLE);RTC_WaitForLastTask();RTC_ITConfig(RTC_IT_SEC, ENABLE);}void SetRTCTime(T_STRUCT* time){u32 count;RTC_ITConfig(RTC_IT_SEC, DISABLE); //关闭秒中断RTC_WaitForLastTask();//付时间值到Real_Time上Real_Time.year=time->year;Real_Time.month=time->month;Real_Time.day=time->day;Real_Time.hour=time->hour;Real_Time.minute=time->minute;Real_Time.second=time->second;//计算星期time->date=Real_Time.date=GetDate(time);//把新的年月日存到掉电寄存器上BKP_WriteBackupRegister(BKP_TIME_DATE,Real_Time.date);// RTC_WaitForLastTask();BKP_WriteBackupRegister(BKP_TIME_DAY,Real_Time.day);// RTC_WaitForLastTask();BKP_WriteBackupRegister(BKP_TIME_MONTH,Real_Time.month); // RTC_WaitForLastTask();BKP_WriteBackupRegister(BKP_TIME_YEAR,Real_Time.year);// RTC_WaitForLastTask();//计算新的RTC count值count=Real_Time.hour*3600+Real_Time.minute*60+Real_Time.second; RTC_WaitForLastTask();RTC_SetCounter(count);// Check if the Power On Reset flag is set//注意红色代码部分,如果不加这两句,修改时间一直卡死在 RTC_WaitForLastTask()RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);PWR_BackupAccessCmd(ENABLE);RTC_WaitForLastTask();RTC_ITConfig(RTC_IT_SEC, ENABLE); //打开秒中断}void RTCTick(void){u8 tmp;if ((++Real_Time.second)>59){Real_Time.second=0;if ((++Real_Time.minute)>59){Real_Time.minute=0;if ((++Real_Time.hour)>23){Real_Time.hour=0;//星期自加if ((++Real_Time.date)>=8)Real_Time.date=1;//--存储新的星期BKP_WriteBackupRegister(BKP_DR5,Real_Time.date);//如果是2月,计算闰年(不需要考虑2099以后的400年一非润)if (Real_Time.month==2){if (Real_Time.year%4)tmp=28;elsetmp=29;}else{tmp=Month2Day_Tab[Real_Time.month-1];}if ((++Real_Time.day)>tmp){Real_Time.day=1;if ((++Real_Time.month)>12){Real_Time.month=1;if ((++Real_Time.year)>99){Real_Time.year=0;}//--储存新的年BKP_WriteBackupRegister(BKP_DR2,Real_Time.year); }//--储存新的月BKP_WriteBackupRegister(BKP_DR3,Real_Time.month); }//--储存新的日BKP_WriteBackupRegister(BKP_DR4,Real_Time.day);}}}}。
万年历_ARM课程设计
目录4 (7)5.总结 (8)万年历系统摘要:万年历在日常生活中最常见,应用也最广泛。
本次课程设计主要就是设计一款电子万年历系统,本次嵌入式系统课程设计以STM32F103RB芯片为核心,主要能够实现显示时间、日期、节日、以及24节气和12生肖等功能。
其中时间显示包括时、分、秒,日期显示包括年、月、日,显示部分通过电脑上的超级终端进行显示,当程序编译无误后,将其下载至开发板中,然后通过超级终端进行显示,开始时用户需要自行设置时间和日期,然后万年历系统才会按照用户设计的功能开始工作。
关键字:STM32F103RB 超级终端时间日期显示 24节气显示十二生肖显示1引言STM32系列基于专为要求高性能、低成本、低功耗的嵌入式应用专门设计的ARM 内核。
按性能有不同的系列:STM32F103“增强型”系列和STM32F101“基本型”系列。
此次我们所使用的STM32F103RB芯片就是增强型系列,增强型系列时钟频率达到72MHz,是同类产品中性能最高的产品;基本型时钟频率为36MHz,以16位产品的价格得到比16位产品大幅提升的性能,是16位产品用户的最佳选择。
两个系列都内置32K到128K的闪存,不同的是SRAM的最大容量和外设接口的组合。
时钟频率72MHz时,从闪存执行代码,STM32功耗36mA,是32位市场上功耗最低的产品,相当于MHz。
ARM公司的高性能”Cortex-M3”内核具有一流的外设(1μs的双12位ADC,4兆位/秒的UART,18兆位/秒的SPI,18MHz的I/O翻转速度)、低功耗(在72MHz 时消耗36mA(所有外设处于工作状态),待机时下降到2μA)、最大的集成度(复位电路、低电压检测、调压器、精确的RC振荡器等)\简单的结构和易用的工具,STM32F10x重要参数主要有供电、容忍5V的I/O管脚、优异的安全时钟模式、带唤醒功能的低功耗模式、内部RC振荡器、内嵌复位电路、工作温度范围是-40°C至+85°C或105°C。
嵌入式智能万年历设计
任务要求:用ARM—M3芯片设计一个智能万年历,要求能够正确显示近100 年时间,星期几,时间格式为****年**月**日(星期**) **:**:**(时:分:秒),能够识别出闰年(计时范围能够从1970年1月1日到2100年左右)。
该程序设计工程里包含有main.c(相关配置、和终端联系,提醒输出初始时间、输出实时时间)/date.c(计算实时时间)/stm32f10x_it.c三个文件,各文件内容如下。
Main.c文件:#include "stm32f10x.h"#include "stdio.h"#include "date.h"__IO uint32_t TimeDisplay = 0;void RCC_Configuration(void);void NVIC_Configuration(void);void GPIO_Configuration(void);void USART_Configuration(void);int fputc(int ch, FILE *f);void RTC_Configuration(void);void Time_Regulate(struct rtc_time *tm);void Time_Adjust(void);void Time_Display(uint32_t TimeVar);void Time_Show(void);u8 USART_Scanf(u32 value);#define RTCClockSource_LSEu8 const *WEEK_STR[] = {"日", "一", "二", "三", "四", "五", "六"};struct rtc_time systmtime;int main(){RCC_Configuration();NVIC_Configuration();GPIO_Configuration();USART_Configuration();/*在启动时检查备份寄存器BKP_DR1,如果内容不是0xA5A5,则需重新配置时间并询问用户调整时间*/printf("\r\n\n RTC not yet configured....");RTC_Configuration();printf("\r\n RTC configured....");Time_Adjust();BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);}else{/*启动无需设置新时钟*//*检查是否掉电重启*/if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET){printf("\r\n\n Power On Reset occurred....");}/*检查是否Reset复位*/else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET){printf("\r\n\n External Reset occurred....");}printf("\r\n No need to configure RTC....");/*等待寄存器同步*/RTC_WaitForSynchro();/*允许RTC秒中断*/RTC_ITConfig(RTC_IT_SEC, ENABLE);/*等待上次RTC寄存器写操作完成*/RTC_WaitForLastTask();}#ifdef RTCClockOutput_EnableRCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); PWR_BackupAccessCmd(ENABLE);BKP_TamperPinCmd(DISABLE);BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);RCC_ClearFlag();Time_Show();}void RCC_Configuration(){SystemInit();RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);}void NVIC_Configuration(){NVIC_InitTypeDef NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);}void GPIO_Configuration(){GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);}void USART_Configuration(){USART_InitTypeDef USART_InitStructure;USART_ART_WordLength = USART_WordLength_8b;USART_ART_StopBits = USART_StopBits_1;USART_ART_Parity = USART_Parity_No ;USART_ART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_ART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure);USART_Cmd(USART1, ENABLE);}int fputc(int ch, FILE *f){/* 将Printf内容发往串口 */USART_SendData(USART1, (unsigned char) ch);while (!(USART1->SR & USART_FLAG_TXE));return (ch);}void RTC_Configuration(){/*允许PWR和BKP时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);/*允许访问BKP域*/PWR_BackupAccessCmd(ENABLE);/*复位备份域*/BKP_DeInit();#ifdef RTCClockSource_LSI/*允许LSI*/RCC_LSICmd(ENABLE);/*等待LSI准备好*/while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY)==RESET){}/*选择LSI作为RTC时钟源*/RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);#elif defined RTCClockSource_LSE/*允许LSE*/RCC_LSEConfig(RCC_LSE_ON);/*等待LSE准备好*/while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET){}/*选择LSE作为RTC时钟源*/RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);#endif/* Enable RTC Clock */RCC_RTCCLKCmd(ENABLE);#ifdef RTCClockOutput_Enable/*禁止Tamper引脚*/BKP_TamperPinCmd(DISABLE);/*为了将RTCCLK/64在Tamper引脚输出,Tamper功能必须被禁止*//*允许RTC时钟在Tamper引脚上输出*/BKP_RTCCalibrationClockOutputCmd(ENABLE);#endif/*等待寄存器同步*/RTC_WaitForSynchro();/*等待上次RTC寄存器写操作完成*/RTC_WaitForLastTask();/*允许RTC秒中断*/RTC_ITConfig(RTC_IT_SEC, ENABLE);/*等待上次RTC寄存器写操作完成*/RTC_WaitForLastTask();#ifdef RTCClockSource_LSI/*设置分频系数*/RTC_SetPrescaler(31999); /*RTC周期=RTCCLK/RTC_PR=(32.000kHz/(31999+1))*/#elif defined RTCClockSource_LSERTC_SetPrescaler(32767); /*RTC周期=RTCCLK/RTC_PR=(32.768kHz/(31767+1))*/ #endif/*等待上次RTC寄存器写操作完成*/RTC_WaitForLastTask();}void Time_Regulate(struct rtc_time *tm){u32 Tmp_YY = 0xFF, Tmp_MM = 0xFF, Tmp_DD = 0xFF, Tmp_HH = 0xFF, Tmp_MI = 0xFF, Tmp_SS = 0xFF;printf("\r\n=========================Time Settings==================");printf("\r\n 请输入年份(Please Set Years): 20");while (Tmp_YY == 0xFF){Tmp_YY = USART_Scanf(99);}printf("\n\r 年份被设置为: 20%0.2d\n\r", Tmp_YY);tm->tm_year = Tmp_YY+2000;Tmp_MM = 0xFF;printf("\r\n 请输入月份(Please Set Months): ");while (Tmp_MM == 0xFF){Tmp_MM = USART_Scanf(12);}printf("\n\r 月份被设置为: %d\n\r", Tmp_MM);tm->tm_mon= Tmp_MM;Tmp_DD = 0xFF;printf("\r\n 请输入日期(Please Set Dates): ");while (Tmp_DD == 0xFF){Tmp_DD = USART_Scanf(31);}printf("\n\r 日期被设置为: %d\n\r", Tmp_DD);tm->tm_mday= Tmp_DD;Tmp_HH = 0xFF;printf("\r\n 请输入时钟(Please Set Hours): ");while (Tmp_HH == 0xFF){Tmp_HH = USART_Scanf(23);}printf("\n\r 时钟被设置为: %d\n\r", Tmp_HH );tm->tm_hour= Tmp_HH;Tmp_MI = 0xFF;printf("\r\n 请输入分钟(Please Set Minutes): ");while (Tmp_MI == 0xFF){Tmp_MI = USART_Scanf(59);}printf("\n\r 分钟被设置为: %d\n\r", Tmp_MI);tm->tm_min= Tmp_MI;Tmp_SS = 0xFF;printf("\r\n 请输入秒钟(Please Set Seconds): ");while (Tmp_SS == 0xFF){Tmp_SS = USART_Scanf(59);}printf("\n\r 秒钟被设置为: %d\n\r", Tmp_SS);tm->tm_sec= Tmp_SS;}void Time_Adjust()RTC_WaitForLastTask();Time_Regulate(&systmtime);GregorianDay(&systmtime);RTC_SetCounter(mktimev(&systmtime));RTC_WaitForLastTask();}void Time_Display(uint32_t TimeVar){to_tm(TimeVar, &systmtime);printf("\r 当前时间为: %d年 %d月 %d日 (星期%s) %0.2d:%0.2d:%0.2d", systmtime.tm_year, systmtime.tm_mon, systmtime.tm_mday, WEEK_STR[systmtime.tm_wday], systmtime.tm_hour,systmtime.tm_min, systmtime.tm_sec);}void Time_Show(){printf("\n\r");/* Infinite loop */while (1){/* 每过1s */if (TimeDisplay == 1){Time_Display(RTC_GetCounter());TimeDisplay = 0;}}}u8 USART_Scanf(u32 value){u32 index = 0;u32 tmp[2] = {0, 0};{while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET){}tmp[index++] = (USART_ReceiveData(USART1));if ((tmp[index - 1] < 0x30) || (tmp[index - 1] > 0x39)) /*数字0到9的ASCII 码为0x30至0x39*/{if((index == 2) && (tmp[index - 1] == '\r')){tmp[1] = tmp[0];tmp[0] = 0x30;}else{printf("\n\rPlease enter valid number between 0 and 9 -->: ");index--;}}}/* 计算输入字符的相应ASCII值*/index = (tmp[1] - 0x30) + ((tmp[0] - 0x30) * 10);/* Checks */if (index > value){printf("\n\rPlease enter valid number between 0 and %d", value);return 0xFF;}return index;}Date.c文件内容如下:#include "date.h"#define FEBRUARY 2#define STARTOFTIME 1970#define SECDAY 86400L#define SECYR (SECDAY * 365)#define leapyear(year) ((year) % 4 == 0)#define days_in_month(a) (month_days[(a) - 1])static int month_days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };/*计算公历*/void GregorianDay(struct rtc_time * tm){int leapsToDate;int lastYear;int day;int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };lastYear=tm->tm_year-1;/*计算到计数的前一年之中一共经历了多少个闰年*/leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;/*如若计数的这一年为闰年,且计数的月份在2月之后,则日数加1,否则不加1*/ if((tm->tm_year%4==0) && ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) && (tm->tm_mon>2)){day=1;}else{day=0;}day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday; /*计算从计数元年元旦到计数日期一共有多少天*/tm->tm_wday=day%7;}u32 mktimev(struct rtc_time *tm){if (0 >= (int) (tm->tm_mon -= 2)){tm->tm_mon += 12;tm->tm_year -= 1;}return ((((u32) (tm->tm_year/4 - tm->tm_year/100 + tm->tm_year/400 + 367*tm->tm_mon/12 + tm->tm_mday)}void to_tm(u32 tim, struct rtc_time * tm){register u32 i;register long hms, day;day = tim / SECDAY;hms = tim % SECDAY;tm->tm_hour = hms / 3600;tm->tm_min = (hms % 3600) / 60;tm->tm_sec = (hms % 3600) % 60;/*算出当前年份,起始的计数年份为1970年*/for (i = STARTOFTIME; day >= days_in_year(i); i++) {day -= days_in_year(i);}tm->tm_year = i;/*计算当前的月份*/if (leapyear(tm->tm_year)){days_in_month(FEBRUARY) = 29;}for (i = 1; day >= days_in_month(i); i++){day -= days_in_month(i);}days_in_month(FEBRUARY) = 28;tm->tm_mon = i;/*计算当前日期*/tm->tm_mday = day + 1;GregorianDay(tm);}stm32f10x_it.c文件内容:#include "stm32f10x_it.h"extern uint32_t TimeDisplay;void NMI_Handler(void){}/*** @brief This function handles Hard Fault exception.* @param None* @retval : None*/void HardFault_Handler(void){/* Go to infinite loop when Hard Fault exception occurs */while (1){}}/*** @brief This function handles Memory Manage exception.* @param None* @retval : None*/void MemManage_Handler(void){/* Go to infinite loop when Memory Manage exception occurs */ while (1){}}/*** @brief This function handles Bus Fault exception.* @param None* @retval : None*/void BusFault_Handler(void){/* Go to infinite loop when Bus Fault exception occurs */while (1){}}* @brief This function handles Usage Fault exception.* @param None* @retval : None*/void UsageFault_Handler(void){/* Go to infinite loop when Usage Fault exception occurs */ while (1){}}/*** @brief This function handles SVCall exception.* @param None* @retval : None*/void SVC_Handler(void){}/*** @brief This function handles Debug Monitor exception.* @param None* @retval : None*/void DebugMon_Handler(void){}/*** @brief This function handles PendSVC exception.* @param None* @retval : None*/void PendSV_Handler(void){}/*** @brief This function handles SysTick Handler.* @param None* @retval : None*/}void RTC_IRQHandler(void){if (RTC_GetITStatus(RTC_IT_SEC) != RESET){/* Clear the RTC Second interrupt */RTC_ClearITPendingBit(RTC_IT_SEC);/* Enable time update */TimeDisplay = 1;/* Wait until last write operation on RTC registers has finished */ RTC_WaitForLastTask();/* Reset RTC Counter when Time is 23:59:59 */if (RTC_GetCounter() == 0x00015180){RTC_SetCounter(0x0);/* Wait until last write operation on RTC registers has finished */ RTC_WaitForLastTask();}}}。
STM32实现万年历演示教学
S T M32实现万年历STM32学习笔记一竹天笑实现的功能:1、日历功能。
2、数字和模拟时钟功能。
图1(为LCD截屏保存在SD卡中的图像)最终界面如下,但还存在不少漏洞。
1、没有更改时间的设置;2、只有节气显示没有节假日显示3、背景不是用uCGUI画的,是在PS中画好然后存在SD卡中,然后显示的BMP格式图像。
要点分析:1、STM32自带了RTC时钟计数器,从0开始计数到232。
每一个计数代表秒计数,每六十个计数代表分计数,以此类推。
24(小时)*60(分钟)*60(秒钟)=86400代表一天的计数时间。
假设当前计数为count,count/86400得到计数的天数,根据这个得到年月日。
Count%86400得到时分秒。
2、一些根据1中得到的年月日时分秒,进行计算的程序有:阳历转阴历,闰年判断,节气判断,星期几计算,当前月有多少天等等。
3、模拟时钟的绘制:时钟指针运动算法、屏幕重绘方法、RTC消息、画笔/画刷等。
指针运动算法和屏幕重绘方法是本程序主要难点所在。
(以下参照百度文库之模拟时钟)不论何种指针,每次转动均以π/30弧度(一秒的角度)为基本单位,且都以表盘中心为转动圆心。
计算指针端点(x, y)的公式如下:x =圆心x坐标 + 指针长度 * cos (指针方向角)y =圆心y坐标 + 指针长度 * sin (指针方向角)注意,指针长度是指自圆心至指针一个端点的长度(是整个指针的一部分),由于指针可能跨越圆心,因此一个指针需要计算两个端点。
由于屏幕的重绘1秒钟一次,如果采用全屏删除式重绘则闪烁十分明显,显示效果不佳。
本程序采用非删除式重绘,假定指针将要移动一格,则先采用背景色(这里是白色)重绘原来指针以删除原来位置的指针,再采用指针的颜色在当前位置绘制指针(如果指针没有动,则直接绘制指针,此句在程序中被我删除,具体原因,为数据截断导致一些误差)。
另外,秒表为RTC一秒钟定时计数。
程序分析:uCGUI+uCOS,一共三个任务:主处理任务、触摸屏任务、秒更新任务。
STM32的RTC实现日历功能程序
STM32的RTC实现日历功能程序STM32的RTC实现日历功能程序发布时间:2011-09-30 14:53:05STM32的RTC只有一个32位的计数器用来计时,没有寄存器来存年月日时分秒等。
通过设置可以让这个计数器1秒加1,从0-0XFFFFFFFF大概可以计时136年。
程序要设置一个时间起点表示0,一般设置起始时间为1970-01-01 0:0:0。
这是UNIX时间戳。
如果要设置RTC时间,如2011-9-30 12:00FAMILY: 宋体">到1970-01-01 0:0:0有多少秒,把这个值写到RTC计数器就可以了。
如果要读当前的年月日时分秒,先读出32位RTC计数器值,然后以1970-01-01 0:0:0为时间基点,算出当前时间。
为什么要设置起始时间为1970-01-01 0:0:0,因为有一个TIME.H 文件,里面有写好的设置时间函数,读时间函数,使用的参数就是32位计数器。
不过我没有找到这个文件。
不使用这个文件的函数的话,起始时间可以设为任意值。
直接使用32位计数器来计算时间的优点:1、可以不使用RTC的秒中断,因为在STM32掉电时,只有电池供电,这时RTC在计数,但是STM32的内核中断应该是不能使用的。
2、不用在备份区保存年月日等参数。
下面是网上找的程序,我实际测试过,是正确的。
//时间结构体typedef struct{u8 hour;u8 min;u8 sec;//公历日月年周u16 w_year;u8 w_month;u8 w_date;u8 week;}tm;tm timer;/****/void RTC_Config(void){u16 u16_WaitForOscSource;//我们在BKP的后备寄存器1中,存了一个特殊字符0xA5A5//第一次上电或后备电源掉电后,该寄存器数据丢失,//表明RTC数据丢失,需要重新配置if (BKP_ReadBackupRegister(BKP_DR1) != 0x5A5A){//重新配置RTC/* Enable PWR and BKP clocks */RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);/* Allow access to BKP Domain */PWR_BackupAccessCmd(ENABLE);/* Reset Backup Domain */BKP_DeInit();/* Enable LSE */RCC_LSEConfig(RCC_LSE_ON);for(u16_WaitForOscSource=0;u16_WaitForOscSource<5000;u16_WaitForOscSource++){}/* Wait till LSE is ready */while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);/* Select LSE as RTC Clock Source */RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);/* Enable RTC Clock */RCC_RTCCLKCmd(ENABLE);/* Wait for RTC registers synchronization */RTC_WaitForSynchro();/* Wait until last write operation on RTC registers has finished */RTC_WaitForLastTask();/* Enable the RTC Second */RTC_ITConfig(RTC_IT_SEC, ENABLE);/* Wait until last write operation on RTC registers has finished */RTC_WaitForLastTask();/* Set RTC prescaler: set RTC period to 1sec */RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) *//* Wait until last write operation on RTC registers has finished */RTC_WaitForLastTask();//配置完成后,向后备寄存器中写特殊字符0xA5A5BKP_WriteBackupRegister(BKP_DR1, 0x5A5A);RTC_Set(2011,01,01,0,0,0);//默认时间}else{//若后备寄存器没有掉电,则无需重新配置RTC//这里我们可以利用RCC_GetFlagStatus()函数查看本次复位类型RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);for(u16_WaitForOscSource=0;u16_WaitForOscSource<5000; u16_WaitForOscSource++);if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET){//这是上电复位}else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET){//这是外部RST管脚复位}//清除RCC中复位标志RCC_ClearFlag();//虽然RTC模块不需要重新配置,且掉电后依靠后备电池依然运行//但是每次上电后,还是要使能RTCCLK//RCC_RTCCLKCmd(ENABLE);//等待RTC时钟与APB1时钟同步//RTC_WaitForSynchro();//使能秒中断RTC_ITConfig(RTC_IT_SEC, ENABLE);//等待操作完成RTC_WaitForLastTask();}return;}//判断是否是闰年函数//月份 1 2 3 4 5 6 7 8 9 10 11 12//闰年 31 29 31 30 31 30 31 31 30 31 30 31//非闰年 31 28 31 30 31 30 31 31 30 31 30 31//输入:年份//输出:该年份是不是闰年.1,是.0,不是u8 Is_Leap_Year(u16 year){if(year%4==0) //必须能被4整除{if(year%100==0){if(year%400==0)return 1;//如果以00结尾,还要能被400整除else return 0;}else return 1;}else return 0;}//设置时钟//把输入的时钟转换为秒钟//以1970年1月1日为基准//1970~2099年为合法年份//返回值:0,成功;其他:错误代码.//月份数据表u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表//平年的月份日期表const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec) {u16 t;u32 seccount=0;if(syear<2000||syear>2099)return 1;//syear范围1970-2099,此处设置范围为2000-2099for(t=1970;t<syear;t++) //把所有年份的秒钟相加{if(Is_Leap_Year(t))seccount+=31622400;//闰年的秒钟数else seccount+=31536000; //平年的秒钟数}smon-=1;for(t=0;t<smon;t++) //把前面月份的秒钟数相加{seccount+=(u32)mon_table[t]*86400;//月份秒钟数相加if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//闰年2月份增加一天的秒钟数}seccount+=(u32)(sday-1)*86400;//把前面日期的秒钟数相加seccount+=(u32)hour*3600;//小时秒钟数seccount+=(u32)min*60; //分钟秒钟数seccount+=sec;//最后的秒钟加上去//设置时钟/* RCC->APB1ENR|=1<<28;//使能电源时钟RCC->APB1ENR|=1<<27;//使能备份时钟PWR->CR|=1<<8; //取消备份区写保护//上面三步是必须的!*/PWR_BackupAccessCmd(ENABLE);RTC_WaitForLastTask();RTC_SetCounter(seccount);RTC_WaitForLastTask();return 0;}//得到当前的时间//返回值:0,成功;其他:错误代码.u8 RTC_Get(void){static u16 daycnt=0;u32 timecount=0;u32 temp=0;u16 temp1=0;timecount=RTC_GetCounter();/*timecount=RTC->CNTH;//得到计数器中的值(秒钟数) timecount<<=16;timecount+=RTC->CNTL; */temp=timecount/86400; //得到天数(秒钟数对应的)if(daycnt!=temp)//超过一天了{daycnt=temp;temp1=1970; //从1970年开始while(temp>=365){if(Is_Leap_Year(temp1))//是闰年{if(temp>=366)temp-=366;//闰年的秒钟数else {temp1++;break;}}else temp-=365; //平年temp1++;}timer.w_year=temp1;//得到年份temp1=0;while(temp>=28)//超过了一个月{if(Is_Leap_Year(timer.w_year)&&temp1==1)//当年是不是闰年/2月份{if(temp>=29)temp-=29;//闰年的秒钟数else break;}else{if(temp>=mon_table[temp1])temp-=mon_table[temp1];//平年else break;}temp1++;}timer.w_month=temp1+1;//得到月份timer.w_date=temp+1; //得到日期}temp=timecount%86400; //得到秒钟数timer.hour=temp/3600; //小时timer.min=(temp%3600)/60; //分钟timer.sec=(temp%3600)%60; //秒钟timer.week=RTC_Get_Week(timer.w_year,timer.w_month,tim er.w_date);//获取星期return 0;}//获得现在是星期几//功能描述:输入公历日期得到星期(只允许1901-2099年)//输入参数:公历年月日//返回值:星期号u8 RTC_Get_Week(u16 year,u8 month,u8 day){u16 temp2;u8 yearH,yearL;yearH=year/100; yearL=year%100;// 如果为21世纪,年份数加100if (yearH>19)yearL+=100;// 所过闰年数只算1900年之后的temp2=yearL+yearL/4;temp2=temp2%7;temp2=temp2+day+table_week[month-1]; if (yearL%4==0&&month<3)temp2--; return(temp2%7);}。
基于STM32单片机的万年历设计设计
本科生毕业论文(或设计)(申请学士学位)论文题目基于STM32单片机的万年历设计作者姓名李杨专业名称自动化指导教师王斌2014年5月学生:(签字)学号:2010210328答辩日期:2014年5 月24日指导教师:(签字)目录摘要 (1)Abstract (1)1绪论 (2)1.1 研究背景及意义 (2)1.2 国内外研究现状 (2)1.3 论文主要内容 (2)2系统硬件电路设计 (3)2.1单片机开发板的介绍 (3)2.2硬件电路总体结构设计 (4)2.3 硬件电路各单元电路设计 (4)2.3.1 按键电路的设计 (4)2.3.2 显示电路的设计 (5)3系统软件设计 (6)3.1 RealView MDK3.80简介 (6)3.2 软件总体设计 (6)3.3 TFT-LCD显示程序设计 (7)3.4 时钟程序设计 (8)3.5 汉字显示程序 (10)3.6 图片显示程序 (11)3.7 按键功能程序 (11)4系统调试 (12)结论 (14)参考文献 (14)附录一 (15)程序列表 (15)主程序 (15)TFT-LCD显示程序 (21)时钟程序 (24)汉字显示程序 (29)图片显示程序 (31)按键程序 (36)致谢 (39)基于STM32单片机的万年历设计摘要:随着现代社会生活和工作节奏的加快,及时准确的掌握时间变得越来越重要。
STM32包含Cortex-M3内核,具有低功耗、低成本、丰富的片内外设以及处理速度快等特点。
本文采用STM32F103RBT6作为主控制器,利用其内部的实时时钟(RTC)在相应软件的配置下,设计了具有时间显示功能的电子万年历,可提供24小时制的实时时钟和区分平、闰年的日历。
测试表明该设计计时准确、界面美观、操作简便。
关键词:万年历;STM32F103RBT6;TFTLCD;Cortex-M3;RTCCalendar Design Based On STM32 MicrocontrollerAbstract:With the development of modern society, the accelerated pace of life and work,to grasp time timely and accurately becomes more and more important. STM32 contains the Cortex-M3 kernel, with low power consumption, low cost, rich on-chip and high processing speed. This paper uses STM32F103RBT6 as the main controller, using real time clock the internal (RTC) with the corresponding software configuration, designs electronic calendar with the function of time display, and it can provide 24 hour real-time clock and the calendar which can distinguish the flat year or the leap year. The test shows that the design of accurate timing, beautiful interface, and easy operation.Key words: Calendar; STM32F103RBT6; TFTLCD; Cortex-M3; RTC1 绪论1.1 研究背景及意义对于时间这个概念一开始在长达几千年的时间里,根本就没有任何测定时间的精确方法。
使用STM32的RTC制作万年历
使用STM32的RTC制作万年历(2013-09-14 16:39:34)转载▼标签:it注意:红色代码部分,如果不加这两句,修改时间一直卡死在RTC_WaitForLastTask()#include "stm32f10x.h"#include "STM32_RTC.h"#define BKP_TIME_FLAG BKP_DR1#define BKP_TIME_YEAR BKP_DR2#define BKP_TIME_MONTH BKP_DR3#define BKP_TIME_DAY BKP_DR4#define BKP_TIME_DATE BKP_DR5u32 Month_Days_Accu_C[13] = {0,31,59,90,120,151,181,212,243,273,304,334,365}; u32 Month_Days_Accu_L[13] = {0,31,60,91,121,152,182,213,244,274,305,335,366}; #define SecsPerDay (3600*24)extern T_STRUCT Real_Time;//实时时间值void RTC_Configuration(void){RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);PWR_BackupAccessCmd(ENABLE);BKP_DeInit();RCC_LSEConfig(RCC_LSE_ON);while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET){}RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);RCC_RTCCLKCmd(ENABLE);RTC_WaitForSynchro();RTC_WaitForLastTask();RTC_ITConfig(RTC_IT_SEC, ENABLE);RTC_WaitForLastTask();RTC_SetPrescaler(32767);RTC_WaitForLastTask();}void RTC_init(void){if(BKP_ReadBackupRegister(BKP_TIME_FLAG) != 0xA5A5){RTC_Configuration();Real_Time.year = 2013;Real_Time.month = 1;Real_Time.day = 1;Real_Time.hour = 12;Real_Time.minute = 0;Real_Time.second = 0;Real_Time.date = 1;SetRTCTime(&Real_Time);BKP_WriteBackupRegister(BKP_TIME_FLAG, 0xA5A5);}else{if(RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET){//电源复位}else if(RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET){//External Reset occurred}RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); PWR_BackupAccessCmd(ENABLE);BKP_TamperPinCmd(DISABLE);BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);RTC2Time();}RTC_WaitForSynchro();RCC_ClearFlag(); //清除RCC重启标志}void GetRTCTime(T_STRUCT* time){RTC_ITConfig(RTC_IT_SEC, DISABLE); //关闭秒中断RTC_WaitForLastTask();time->year=Real_Time.year;time->month=Real_Time.month;time->day=Real_Time.day;time->hour=Real_Time.hour;time->minute=Real_Time.minute;time->second=Real_Time.second;time->date=Real_Time.date;RTC_WaitForLastTask();RTC_ITConfig(RTC_IT_SEC, ENABLE); //打开秒中断}const u8 TAB_DATE[12]={6,2,2,5,0,3,5,1,4,6,2,4,};u8 GetDate(T_STRUCT* time){return( (time->year + time->year/4 - ( (time->month<3)&&(time->year%4==0) ) +TAB_DATE[time->month-1] + time->day )%7);}const u8 Month2Day_Tab[12]={31,28,31,30,31,30,31,31,30,31,30,31} ;void RTC2Time(void){u32 count;u8 tmp,change=0;Real_Time.year=BKP_ReadBackupRegister(BKP_TIME_YEAR);//年值Real_Time.month=BKP_ReadBackupRegister(BKP_TIME_MONTH);//月值Real_Time.day=BKP_ReadBackupRegister(BKP_TIME_DAY);//日值Real_Time.date=BKP_ReadBackupRegister(BKP_TIME_DATE);//星期值RTC_ITConfig(RTC_IT_SEC, DISABLE); //为了避免代码重入引起的问题,这里吧RTC秒中断屏蔽了count=RTC_GetCounter();//计算新的年月日while (count>=0x0001517f) //上次关电到本次跨越了一天以上{change=1;count-=0x0001517f;//星期自加if ((++Real_Time.date)>=8)Real_Time.date=1;//如果是2月,计算闰年(不需要考虑2099以后的400年一非润) if (Real_Time.month==2){if (Real_Time.year%4)tmp=28;elsetmp=29;}else{tmp=Month2Day_Tab[Real_Time.month-1];}if ((++Real_Time.day)>tmp){Real_Time.day=1;if ((++Real_Time.month)>12){Real_Time.month=1;if ((++Real_Time.year)>=100){Real_Time.year=0;}}}//如果跨越了一天,则计算后,要存回寄存器内if (change){RTC_SetCounter(count);BKP_WriteBackupRegister(BKP_TIME_DATE,Real_Time.date);BKP_WriteBackupRegister(BKP_TIME_DAY,Real_Time.day);BKP_WriteBackupRegister(BKP_TIME_MONTH,Real_Time.month); BKP_WriteBackupRegister(BKP_TIME_YEAR,Real_Time.year);}}//计算新的时分秒Real_Time.hour=count/3600;Real_Time.minute=(count600)/60;Real_Time.second=(count600)`;//重新打开RTC中断// Check if the Power On Reset flag is setRCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);PWR_BackupAccessCmd(ENABLE);RTC_WaitForLastTask();RTC_ITConfig(RTC_IT_SEC, ENABLE);}void SetRTCTime(T_STRUCT* time){u32 count;RTC_ITConfig(RTC_IT_SEC, DISABLE); //关闭秒中断RTC_WaitForLastTask();//付时间值到Real_Time上Real_Time.year=time->year;Real_Time.month=time->month;Real_Time.day=time->day;Real_Time.hour=time->hour;Real_Time.minute=time->minute;Real_Time.second=time->second;//计算星期time->date=Real_Time.date=GetDate(time);//把新的年月日存到掉电寄存器上BKP_WriteBackupRegister(BKP_TIME_DATE,Real_Time.date);// RTC_WaitForLastTask();BKP_WriteBackupRegister(BKP_TIME_DAY,Real_Time.day);// RTC_WaitForLastTask();BKP_WriteBackupRegister(BKP_TIME_MONTH,Real_Time.month); // RTC_WaitForLastTask();BKP_WriteBackupRegister(BKP_TIME_YEAR,Real_Time.year);// RTC_WaitForLastTask();//计算新的RTC count值count=Real_Time.hour*3600+Real_Time.minute*60+Real_Time.second; RTC_WaitForLastTask();RTC_SetCounter(count);// Check if the Power On Reset flag is set//注意红色代码部分,如果不加这两句,修改时间一直卡死在 RTC_WaitForLastTask()RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);PWR_BackupAccessCmd(ENABLE);RTC_WaitForLastTask();RTC_ITConfig(RTC_IT_SEC, ENABLE); //打开秒中断}void RTCTick(void){u8 tmp;if ((++Real_Time.second)>59){Real_Time.second=0;if ((++Real_Time.minute)>59){Real_Time.minute=0;if ((++Real_Time.hour)>23){Real_Time.hour=0;//星期自加if ((++Real_Time.date)>=8)Real_Time.date=1;//--存储新的星期BKP_WriteBackupRegister(BKP_DR5,Real_Time.date);//如果是2月,计算闰年(不需要考虑2099以后的400年一非润)if (Real_Time.month==2){if (Real_Time.year%4)tmp=28;elsetmp=29;}else{tmp=Month2Day_Tab[Real_Time.month-1];}if ((++Real_Time.day)>tmp){Real_Time.day=1;if ((++Real_Time.month)>12){Real_Time.month=1;if ((++Real_Time.year)>99){Real_Time.year=0;}//--储存新的年BKP_WriteBackupRegister(BKP_DR2,Real_Time.year); }//--储存新的月BKP_WriteBackupRegister(BKP_DR3,Real_Time.month); }//--储存新的日BKP_WriteBackupRegister(BKP_DR4,Real_Time.day);}}}}。
基于STM 的万年历设计
基于STM32的万年历设计班级:姓名:学号:成绩:电子通信工程系题目:基于STM32的万年历设计前言:随着科技的快速发展,时间的流逝,至从观太阳、摆钟到现在电子钟,人类不断研究,不断创新纪录。
美国DALLAS公司推出的具有涓细电流充电能的低功耗实时时钟电路DS12C887。
它可以对年、月、日、周日、时、分、秒进行计时,还具有闰年补偿等多种功能,而且DS12C887的使用寿命长,误差小。
对于数字电子万年历采用直观的数字显示,可以同时显示年、月、日、周日、时、分、秒和温度等信息,还具有时间校准等功能。
该电路采用AT89S52单片机作为核心,采用数字式温度传感器DS18B20提取外界温度,功耗小,能在3V的低压工作,电压可选用3~5V电压供电。
进入新世纪LCD显示屏的技术和产业都取得了长足的发展,作为重要的现代信息发布媒体之一,LCD显示屏在证券交易、金融、交通、体育、广告等领域被广泛的应用。
伴随社会信息化进程的推进,LCD显示屏技术也在不断的推陈出新,应用领域愈加广阔。
基于STM32的LCD显示可以更好的满足各种需求,也更便于操作和实现。
现基于STM32在液晶显示屏幕上显示文本及图形。
目前,显示技术和显示工业的发展迅速。
显示技术是传递视觉的信息技术。
液晶显示器件LCD 是当今最有发展前途的一种平板显示器件,它具有很多独到的优异特性。
它具有显示信息多、易于多彩化、体积小、重量轻、功耗低、寿命长、价格低、无辐射、无污染、接口控制方便等优点。
截至目前,我国在液晶显示取得较大进步,我国LCD产业已经走过了近30年的历程.经历几次大的投资浪潮之后,我国内地已经成为世界最大的TN-LCD(扭曲液晶显示器)生产基地和主要的STN-LCD(超扭曲液晶显示器)生产基地,并且从2003年开始,涉足TFT-LCD(薄膜晶体管液晶显示器)领域.本课题设计采用STM32F103VE开发板,实现在LCD显示屏上显示由按键可操控的万年历功能。
基于STM32的智能万年历设计
基于STM32的智能万年历设计
张路莹;许亚迪;郑文青;周麟坤
【期刊名称】《现代工业经济和信息化》
【年(卷),期】2018(8)13
【摘要】主要设计基于STM32的智能万年历。
该系统实现了通过触摸和按键两种方式对万年历进行实时控制、公农历对照转换等相关功能,用户也可以通过按键切换来实现对万年历初始状态的调整与控制。
【总页数】2页(P40-41)
【关键词】STM32;智能万年历;触摸与按键
【作者】张路莹;许亚迪;郑文青;周麟坤
【作者单位】山东科技大学电气信息系
【正文语种】中文
【中图分类】TH714.51
【相关文献】
1.基于 STM32和 HC-SR501智能家居的智能照明系统设计 [J], 王东;莫先
2.基于STM32和HC-SR501智能家居的智能照明系统设计 [J], 王东;莫先;
3.基于单片机的智能万年历的设计 [J], 王成
4.基于STM32的电子万年历系统设计 [J], 刘磊
5.基于STM32的智能万年历的定时闹钟设计 [J], 杨宸[1];王智超[1];徐浩然[1];李天宇[1];王啸岳[1]
因版权原因,仅展示原文概要,查看原文内容请购买。
基于STM32的万年历设计
基于STM32的万年历设计班级:姓名:学号:题目:基于STM32的万年历设计前言:随着科技的快速发展,时间的流逝,至从观太阳、摆钟到现在电子钟,人类不断研究,不断创新纪录。
美国DALLAS公司推出的具有涓细电流充电能的低功耗实时时钟电路DS12C887。
它可以对年、月、日、周日、时、分、秒进行计时,还具有闰年补偿等多种功能,而且DS12C887的使用寿命长,误差小。
对于数字电子万年历采用直观的数字显示,可以同时显示年、月、日、周日、时、分、一,目前,体经历几次)领域.在液00:00:00。
1.功能描述1.1设计要求1.具有数字时钟功能。
2.具有简单日历功能。
3.具有手动校准时间功能。
4.具有闰年识别功能。
1.2RTC(实时时钟)简介实时时钟是一个独立的定时器。
RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。
修改计数器的值可以重新设置系统当前的时间和日期。
RTC模块和时钟配置系统(RCC_BDCR寄存器)是在后备区域,即在系统复位或从待机模式唤醒后RTC的设置和时间维持不变。
系统复位后,禁止访问后备寄存器和RTC,防止对后备区域(BKP)的意2.需要主电源给得到时4.个小键盘。
方案一:采用89C51芯片采用89C51芯片作为硬件核心,采用FlashROM,内部具有4KBROM存储空间,能于3V的超低压工作,而且与MCS-51系列单片机完全兼容,但是运用于电路设计中时由于不具备ISP在线编程技术,当在对电路进行调试时,由于程序的错误修改或对程序的新增功能需要烧入程序时,对芯片的多次拔插会对芯片造成一定的损坏。
方案二:采用AT89S52芯片片内ROM全都采用FlashROM;能以3V的超底压工作;同时也与MCS-51系列单片机完全该芯片内部存储器为8KBROM存储空间,同样具有89C51的功能,且具有在线编程可擦除技术,当在对电路进行调试时,由于程序的错误修改或对程序的新增功能需要烧入程序时,不需要对芯片多次拔插,所以不会对芯片造成损坏。
STM32实现万年历
STM32学习笔记一竹天笑实现的功能:1、日历功能。
2、数字和模拟时钟功能。
图1(为LCD截屏保存在SD卡中的图像)最终界面如下,但还存在不少漏洞。
1、没有更改时间的设置;2、只有节气显示没有节假日显示3、背景不是用uCGUI画的,是在PS中画好然后存在SD卡中,然后显示的BMP格式图像。
要点分析:1、STM32自带了RTC时钟计数器,从0开始计数到232。
每一个计数代表秒计数,每六十个计数代表分计数,以此类推。
24(小时)*60(分钟)*60(秒钟)=86400代表一天的计数时间。
假设当前计数为count,count/86400得到计数的天数,根据这个得到年月日。
Count%86400得到时分秒。
2、一些根据1中得到的年月日时分秒,进行计算的程序有:阳历转阴历,闰年判断,节气判断,星期几计算,当前月有多少天等等。
3、模拟时钟的绘制:时钟指针运动算法、屏幕重绘方法、RTC消息、画笔/画刷等。
指针运动算法和屏幕重绘方法是本程序主要难点所在。
(以下参照百度文库之模拟时钟)不论何种指针,每次转动均以π/30弧度(一秒的角度)为基本单位,且都以表盘中心为转动圆心。
计算指针端点(x, y)的公式如下:x =圆心x坐标 + 指针长度 * cos (指针方向角)y =圆心y坐标 + 指针长度 * sin (指针方向角)注意,指针长度是指自圆心至指针一个端点的长度(是整个指针的一部分),由于指针可能跨越圆心,因此一个指针需要计算两个端点。
由于屏幕的重绘1秒钟一次,如果采用全屏删除式重绘则闪烁十分明显,显示效果不佳。
本程序采用非删除式重绘,假定指针将要移动一格,则先采用背景色(这里是白色)重绘原来指针以删除原来位置的指针,再采用指针的颜色在当前位置绘制指针(如果指针没有动,则直接绘制指针,此句在程序中被我删除,具体原因,为数据截断导致一些误差)。
另外,秒表为RTC一秒钟定时计数。
程序分析:uCGUI+uCOS,一共三个任务:主处理任务、触摸屏任务、秒更新任务。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
STM32学习笔记一竹天笑
实现的功能:
1、日历功能。
2、数字和模拟时钟功能。
图1(为LCD截屏保存在SD卡中的图像)
最终界面如下,但还存在不少漏洞。
1、没有更改时间的设置;2、只有节气显示没有节假日显示3、背景不是用uCGUI画的,是在PS中画好然后存在SD卡中,然后显示的BMP 格式图像。
要点分析:
1、STM32自带了RTC时钟计数器,从0开始计数到232。
每一个计数代表秒计数,每六十个计数代表分计数,以此类推。
24(小时)*60(分钟)*60(秒钟)=86400代表一天的计数时间。
假设当前计数为count,count/86400得到计数的天数,根据这个得到年月日。
Count%86400得到时分秒。
2、一些根据1中得到的年月日时分秒,进行计算的程序有:阳历转阴历,闰年判断,节气判断,星期几计算,当前月有多少天等等。
3、模拟时钟的绘制:时钟指针运动算法、屏幕重绘方法、RTC消息、画笔/画刷等。
指针运动算法和屏幕重绘方法是本程序主要难点所在。
(以下参照百度文库之模拟时钟)不论何种指针,每次转动均以π/30弧度(一秒的角度)为基本单位,且都以表盘中心为转动圆心。
计算指针端点(x, y)的公式如下:
x =圆心x坐标+ 指针长度* cos (指针方向角)
y =圆心y坐标+ 指针长度* sin (指针方向角)
注意,指针长度是指自圆心至指针一个端点的长度(是整个指针的一部分),由于指针可能跨越圆心,因此一个指针需要计算两个端点。
由于屏幕的重绘1秒钟一次,如果采用全屏删除式重绘则闪烁十分明显,显示效果不佳。
本程序采用非删除式重绘,假定指针将要移动一格,则先采用背景色(这里是白色)重绘原来指针以删除原来位置的指针,再采用指针的颜色在当前位置绘制指针(如果指针没有动,则直接绘制指针,此句在程序中被我删除,具体原因,为数据截断导致一些误差)。
另外,秒表为RTC一秒钟定时计数。
程序分析:
uCGUI+uCOS,一共三个任务:主处理任务、触摸屏任务、秒更新任务。
void App_UCGUI_TaskCreate (void)
{
CPU_INT08U os_err;
os_err = os_err;
Clock_SEM=OSSemCreate(1); /位置设定
GUI_SetFont(&GUI_Font6x8);
3.1415926f=-20*cos(*30+90)*DEG2RAD)+264; =-20*sin(*30+90)*DEG2RAD)+170;
=-2*cos(*30+270)*DEG2RAD)+264; =-2*sin(*30+270)*DEG2RAD)+170; ,m_OldHour[0].y,
m_OldHour[1].x,m_OldHour[1].y);
GUI_SetColor(GUI_RED); ,m_Hour[0].y,
m_Hour[1].x,m_Hour[1].y);
m_Min[0].x=-30*cos(*6+90)*DEG2RAD)+264; =-30*sin(*6+90)*DEG2RAD)+170;
=-4*cos(*6+270)*DEG2RAD)+264; =-4*sin(*6+270)*DEG2RAD)+170; ,m_OldMin[0].y,
m_OldMin[1].x,m_OldMin[1].y);
GUI_SetColor(GUI_BLUE); ,m_Min[0].y, m_Min[1].x,m_Min[1].y);
m_Sec[0].x=-35*cos(*6+90)*DEG2RAD)+264; =-35*sin(*6+90)*DEG2RAD)+170;
=-8*cos(*6+270)*DEG2RAD)+264; =-8*sin(*6+270)*DEG2RAD)+170; ,m_OldSec[0].y,
m_OldSec[1].x,m_OldSec[1].y);
GUI_SetColor(GUI_BLACK);
GUI_DrawLine(m_Sec[0].x,m_Sec[0].y, m_Sec[1].x,m_Sec[1].y);
for(i=0;i<2;i++)
{
m_OldHour[i]=m_Hour[i]; 8 m*/
u8 getDays(u16 y, u8 m)
{
u8 days = 0;
switch(m)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
days = 31; break;
case 4:
case 6:
case 9:
case 11:
days = 30; break;
case 2:
days = isRunNian(y) 29 : 28; break;
default:;
}
return days;
}
子程序4
86400L/#define leapyear(year) ((year) % 4 == 0)
tm->tm_year = i;
/* Number of months in days left */ /*计算当前的月份*/
if (leapyear(tm->tm_year)) *//*计算当前日期*/
tm->tm_mday = day + 1; //剩下的天数加一为日。
/*
* Determine the day of week
*/
GregorianDay(tm);
}
/*得到星期几*/
void GregorianDay(struct rtc_time * tm)
{
int leapsToDate;
int lastYear;
int day;
int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
lastYear=tm->tm_year-1;
/*计算从公元元年到计数的前一年之中一共经历了多少个闰年*/
leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;
/*如若计数的这一年为闰年,且计数的月份在2月之后,则日数加1,否则不加1*/
if((tm->tm_year%4==0) &&((tm->tm_year%100!=0) || (tm->tm_year%400==0)) && (tm->tm_mon>2)) {
day=1;
} else {
day=0;
}
day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday; /*计算从公元元年元旦到计数日期一共有多少天*/
tm->tm_wday=day%7; //得到今天为星期几
}
程序包下载地址(IAR编译环境):file/beo3fygn#。