单片机型号:STM32G473RB
环境:使用HAL库,RTC使用LSE
问题:使用正点原子的RTC例子代码配置RTC,在读取时间的时候发现小时(RTC_TimeTypeDef的Hours)读取来会超过24小时,并且天数不会自动+1
原因分析:调用HAL_RTC_SetTime的时候DayLightSaving 和 StoreOperation被弃用,见函数说明:
This interface is deprecated. To manage Daylight Saving Time, please use HAL_RTC_DST_xxx functions
导致夏令时的管理开启。
解决方法:使用HAL_RTC_DST_ClearStoreOperation函数关闭夏令时管理,附上代码片段:
int DrvRTC::init(void){
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
__HAL_RCC_PWR_CLK_ENABLE();//使能电源时钟PWR
HAL_PWR_EnableBkUpAccess();//取消备份区域写保护
RCC_OscInitStruct.OscillatorType=RCC_OSCILLATORTYPE_LSE;//LSE配置
RCC_OscInitStruct.PLL.PLLState=RCC_PLL_NONE;
RCC_OscInitStruct.LSEState=RCC_LSE_ON; //RTC使用LSE
HAL_RCC_OscConfig(&RCC_OscInitStruct);
PeriphClkInitStruct.PeriphClockSelection=RCC_PERIPHCLK_RTC;//外设为RTC
PeriphClkInitStruct.RTCClockSelection=RCC_RTCCLKSOURCE_LSE;//RTC时钟源为LSE
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
__HAL_RCC_RTC_ENABLE();//RTC时钟使能
memset(&RTC_Handler, 0, sizeof(RTC_Handler));
RTC_Handler.Instance=RTC;
RTC_Handler.Init.HourFormat=RTC_HOURFORMAT_24;//RTC设置为24小时格式
RTC_Handler.Init.AsynchPrediv=0X7F; //RTC异步分频系数(1~0X7F)
RTC_Handler.Init.SynchPrediv=0XFF; //RTC同步分频系数(0~7FFF)
RTC_Handler.Init.OutPut=RTC_OUTPUT_DISABLE;
RTC_Handler.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
RTC_Handler.Init.OutPutPullUp = RTC_OUTPUT_PULLUP_NONE;
if(HAL_RTC_Init(&RTC_Handler)!=HAL_OK)
return 2;
HAL_RTC_DST_ClearStoreOperation(&RTC_Handler);
if(HAL_RTCEx_BKUPRead(&RTC_Handler,RTC_BKP_DR0)!=0X5050)//是否第一次配置
{
RTC_Set_Time(23, 59, 46, RTC_HOURFORMAT12_PM); //设置时间 ,根据实际时间修改
RTC_Set_Date(22, 5, 4, 4); //设置日期
HAL_RTCEx_BKUPWrite(&RTC_Handler, RTC_BKP_DR0, 0X5050);//标记已经初始化过了
}
return 0;
}
int DrvRTC::setTime(uint8_t year, uint8_t mon, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec){
if(RTC_Set_Time(hour, min, sec, RTC_HOURFORMAT12_PM) != HAL_OK)
return -1;
if(RTC_Set_Date(year, mon, day, 4) != HAL_OK)
return -1;
return 0;
}
int DrvRTC::getTime(uint8_t *year, uint8_t *mon, uint8_t *day, uint8_t *hour, uint8_t *min, uint8_t *sec){
RTC_DateTypeDef RTC_DateStructure;
RTC_TimeTypeDef RTC_TimeStructure;
memset(&RTC_DateStructure, 0, sizeof(RTC_DateTypeDef));
memset(&RTC_TimeStructure, 0, sizeof(RTC_TimeTypeDef));
HAL_StatusTypeDef status;
status = HAL_RTC_GetTime(&RTC_Handler, &RTC_TimeStructure, RTC_FORMAT_BIN);
status = HAL_RTC_GetDate(&RTC_Handler, &RTC_DateStructure, RTC_FORMAT_BIN);
if(status != HAL_OK)
return -1;
*year = RTC_DateStructure.Year;
*mon = RTC_DateStructure.Month;
*day = RTC_DateStructure.Date;
*hour = RTC_TimeStructure.Hours;
*min = RTC_TimeStructure.Minutes;
*sec = RTC_TimeStructure.Seconds;
return 0;
}
//RTC时间设置
//hour,min,sec:小时,分钟,秒钟
//ampm:@RTC_AM_PM_Definitions:RTC_HOURFORMAT12_AM/RTC_HOURFORMAT12_PM
//返回值:SUCEE(1),成功
// ERROR(0),进入初始化模式失败
HAL_StatusTypeDef DrvRTC::RTC_Set_Time(u8 hour,u8 min,u8 sec,u8 ampm)
{
RTC_TimeTypeDef RTC_TimeStructure;
RTC_TimeStructure.Hours=hour;
RTC_TimeStructure.Minutes=min;
RTC_TimeStructure.Seconds=sec;
RTC_TimeStructure.TimeFormat=ampm;
RTC_TimeStructure.DayLightSaving=RTC_DAYLIGHTSAVING_NONE;
RTC_TimeStructure.StoreOperation=RTC_STOREOPERATION_RESET;
return HAL_RTC_SetTime(&RTC_Handler, &RTC_TimeStructure, RTC_FORMAT_BIN);
}
//RTC日期设置
//year,month,date:年(0~99),月(1~12),日(0~31)
//week:星期(1~7,0,非法!)
//返回值:SUCEE(1),成功
// ERROR(0),进入初始化模式失败
HAL_StatusTypeDef DrvRTC::RTC_Set_Date(u8 year,u8 month,u8 date,u8 week)
{
RTC_DateTypeDef RTC_DateStructure;
RTC_DateStructure.Date=date;
RTC_DateStructure.Month=month;
RTC_DateStructure.WeekDay=week;
RTC_DateStructure.Year=year;
return HAL_RTC_SetDate(&RTC_Handler, &RTC_DateStructure, RTC_FORMAT_BIN);
}