改造RTC_HAL库函数,让STM32F1XX也具有完美的日历功能:+ V) `( r( L- s7 L9 W7 v STM32F103C8T6是大多数初学者的入门首选,CubeMX使得编程更加简单,但它的RTC只有时间可以正常使用,日历功能不完善。具体表现为掉电或重启后日期归0,恢复到2000年1月1日。RTC的秒计数器是32位的,在有后备电池供电情况下,应该可以连续计时136年。 经过分析CubeMX生成的stm32f1xx_rtc.c文件,涉及到日历的主要有下面4个函数:$ @% y8 P+ q' s9 z HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format);+ }: l6 M% @' y0 R. m+ O HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format);( n7 _+ b8 T2 `. v% t HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format);4 w# I4 j3 J0 [ T# x HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format); 在其中2条(HAL_RTC_GetTime和HAL_RTC_GetDate)中都有条“counter_time -= ( xxxx * 24U * 3600U);”语句,就是在计数值超过24小时(86400)后将RTC的秒计数器清0,日期只单纯的做加一操作,且只保存在内存中。所以掉电后日期就归0了。虽然有介绍用RTC的后备存储器保存日期,在适当的时候取出。但这个方法并不适用于那些不定时开关机的场合,比如周五关机,周一再开机,因为日期没有及时更新,而还是两天的日期。& e$ Q8 K/ z |5 |, [, ?! w* I 于是本人对这4个函数进行了改写,在不影响其它(如闹钟)功能的前提下,完善日历功能。经试用基本满意,用法及参数规则和原函数一致:在主程序中用HAL_RTC_SetTime和HAL_RTC_SetDate设置时间及日期,用HAL_RTC_GetTime和HAL_RTC_GetDate获取时间及日期。* C7 t# k- Z( d: x+ {% Y/ h) t' G 下面有改造好的stm32f1xx_hal_rtc.c文件,只要在编译器中用本文件的内容替代原stm32f1xx_hal_rtc.c的全部内容即可。也不用担心会出现其它问题,如果不想要,只需在CubeMX里重新“GENERATE CODE”就还原了。另外在rtc初始化MX_RTC_Init()函数里也不需要作任何处理。只保留0 D5 K) w L% D% S hrtc.Instance = RTC;7 w) u1 Q' ^3 O% \* Y; ]% f hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND;6 N0 e- c2 w. H0 e1 h9 J hrtc.Init.OutPut = RTC_OUTPUTSOURCE_ALARM;* h4 B# m: U8 A$ k4 m" ]" S if (HAL_RTC_Init(&hrtc) != HAL_OK) {: @ m, t, T5 T4 q J2 l' x0 o Error_Handler(); } 其它可以删除。 & }" t4 Q e' X+ S / v# E, V# F7 _% F- }' m% v |
小马哥STM32F103开源小四轴RoboFly全部资料大放送
STM32固件库分享,超全系列整理
【MCU实战经验】+STM32F107的USB使用
基于STM32F103两轮平衡小车设计(开源)
STM32F107VCT6官方原理图和PCB
【福利】用STM32库的朋友有福了:STM32F10x_StdPeriph_Lib_V3.5.0chm...
基于STM32F10xx存储器和系统架构经验分享
基于STM32F1的CAN通信之BH1750
基于STM32F1的CAN通信之OLED
基于STM32F1的CAN通信之之串口IAP
附件:4 g6 f9 \6 g, W! V
stm32f1xx_hal_rtc.c.rar
2020-6-2 13:18 上传
点击文件名下载附件
10.66 KB, 下载次数: 181
很感谢楼主的分享,这方法只有楼主作,其他不曾看过。: N2 q9 ~' F, C% f9 X- E) i0 f
年份跟4楼一样,HAL_RTC_SetDate(&hrtc, &RTC_Date, RTC_FORMAT_BCD),写0x20读出来会变成0x32;写0x14读出来会变成0x20。) _# y6 V& d4 t! p! X
7 n, ]2 ^( o6 A9 Q* [
STM32CubeMX 6.1.1 + STM32F1 Serial 1.8.3
HAL_RTC_SetDate()里,要改为以下代码才可以避免日期设定的错误
for(loop = 0; loop DateToUpdate.Year; loop ++) //累计所有年份的天数 { if(RTC_IsLeapYear(loop + 2000))days += 366; //润年366天 else days += 365; //平年365天 } for(loop = 1; loop DateToUpdate.Month; loop ++) //累计今年已过月份的天数 { if((loop == 1)||(loop == 3)||(loop == 5)||(loop == 7) ||(loop == 8)||(loop == 10)) days += 31; //大月31天 else if((loop == 4)||(loop == 6)||(loop == 9)||(loop == 11))days += 30;//小月30天 else if(loop == 2) { if(RTC_IsLeapYear( hrtc->DateToUpdate.Year+2000))days += 29; //闰年二月29天 else days += 28; //平年二月28天 } } days += hrtc->DateToUpdate.Date - 1; //总天数