|
改造RTC_HAL库函数,让STM32F1XX也具有完美的日历功能: STM32F103C8T6是大多数初学者的入门首选,CubeMX使得编程更加简单,但它的RTC只有时间可以正常使用,日历功能不完善。具体表现为掉电或重启后日期归0,恢复到2000年1月1日。RTC的秒计数器是32位的,在有后备电池供电情况下,应该可以连续计时136年。 经过分析CubeMX生成的stm32f1xx_rtc.c文件,涉及到日历的主要有下面4个函数: HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format); HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format); HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format); 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的后备存储器保存日期,在适当的时候取出。但这个方法并不适用于那些不定时开关机的场合,比如周五关机,周一再开机,因为日期没有及时更新,而还是两天的日期。 于是本人对这4个函数进行了改写,在不影响其它(如闹钟)功能的前提下,完善日历功能。经试用基本满意,用法及参数规则和原函数一致:在主程序中用HAL_RTC_SetTime和HAL_RTC_SetDate设置时间及日期,用HAL_RTC_GetTime和HAL_RTC_GetDate获取时间及日期。 下面有改造好的stm32f1xx_hal_rtc.c文件,只要在编译器中用本文件的内容替代原stm32f1xx_hal_rtc.c的全部内容即可。也不用担心会出现其它问题,如果不想要,只需在CubeMX里重新“GENERATE CODE”就还原了。另外在rtc初始化MX_RTC_Init()函数里也不需要作任何处理。只保留 hrtc.Instance = RTC; hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND; hrtc.Init.OutPut = RTC_OUTPUTSOURCE_ALARM; if (HAL_RTC_Init(&hrtc) != HAL_OK) { Error_Handler(); } 其它可以删除。 |
微信公众号
手机版
附件:
stm32f1xx_hal_rtc.c.rar
2020-6-2 13:18 上传
点击文件名下载附件
10.66 KB, 下载次数: 196
很感谢楼主的分享,这方法只有楼主作,其他不曾看过。
年份跟4楼一样,HAL_RTC_SetDate(&hrtc, &RTC_Date, RTC_FORMAT_BCD),写0x20读出来会变成0x32;写0x14读出来会变成0x20。
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; //总天数