Files
ds18b20-MODBUS/john103C6T6NewVer/john103C8T6_JZ-F407VET6/Core/Src/rtc.c

334 lines
7.8 KiB
C

/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file rtc.c
* @brief This file provides code for the configuration
* of the RTC instances.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "rtc.h"
/* USER CODE BEGIN 0 */
#define RTC_BKP_CONFIGURED_MARKER 0x32A5U
#define RTC_BKP_MARKER_REG RTC_BKP_DR1
#define RTC_BKP_YEAR_MONTH_REG RTC_BKP_DR2
#define RTC_BKP_DATE_WEEKDAY_REG RTC_BKP_DR3
static uint8_t RTC_NormalizeYear(uint16_t year, uint8_t *normalized_year)
{
if (year <= 99U)
{
*normalized_year = (uint8_t)year;
return 1U;
}
if ((year >= 2000U) && (year <= 2099U))
{
*normalized_year = (uint8_t)(year - 2000U);
return 1U;
}
return 0U;
}
static uint8_t RTC_IsLeapYearFull(uint16_t year)
{
return (uint8_t)(((year % 4U) == 0U) && (((year % 100U) != 0U) || ((year % 400U) == 0U)));
}
static uint8_t RTC_DaysInMonth(uint16_t year, uint8_t month)
{
static const uint8_t days_in_month[] = { 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U };
if ((month == 0U) || (month > 12U))
{
return 0U;
}
if ((month == 2U) && RTC_IsLeapYearFull(year))
{
return 29U;
}
return days_in_month[month - 1U];
}
static uint8_t RTC_IsDateValid(uint16_t year, uint8_t month, uint8_t date)
{
uint8_t normalized_year = 0U;
uint16_t full_year = year;
uint8_t max_day = 0U;
if (RTC_NormalizeYear(year, &normalized_year) == 0U)
{
return 0U;
}
if (year <= 99U)
{
full_year = 2000U + year;
}
max_day = RTC_DaysInMonth(full_year, month);
return (uint8_t)((date >= 1U) && (date <= max_day));
}
static void RTC_SaveDateToBackup(const RTC_DateTypeDef *date)
{
uint32_t year_month = (((uint32_t)date->Year) << 8U) | date->Month;
uint32_t date_weekday = (((uint32_t)date->Date) << 8U) | date->WeekDay;
if ((HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_YEAR_MONTH_REG) != year_month) ||
(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DATE_WEEKDAY_REG) != date_weekday))
{
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_YEAR_MONTH_REG, year_month);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DATE_WEEKDAY_REG, date_weekday);
}
if (HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_MARKER_REG) != RTC_BKP_CONFIGURED_MARKER)
{
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_MARKER_REG, RTC_BKP_CONFIGURED_MARKER);
}
}
static uint8_t RTC_RestoreDateFromBackup(void)
{
RTC_DateTypeDef restored_date = {0};
uint32_t year_month = 0U;
uint32_t date_weekday = 0U;
if (HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_MARKER_REG) != RTC_BKP_CONFIGURED_MARKER)
{
return 0U;
}
year_month = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_YEAR_MONTH_REG);
date_weekday = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DATE_WEEKDAY_REG);
restored_date.Year = (uint8_t)((year_month >> 8U) & 0xFFU);
restored_date.Month = (uint8_t)(year_month & 0xFFU);
restored_date.Date = (uint8_t)((date_weekday >> 8U) & 0xFFU);
restored_date.WeekDay = (uint8_t)(date_weekday & 0xFFU);
if (RTC_IsDateValid(restored_date.Year, restored_date.Month, restored_date.Date) == 0U)
{
return 0U;
}
if (restored_date.WeekDay > RTC_WEEKDAY_SATURDAY)
{
restored_date.WeekDay = RTC_WEEKDAY_MONDAY;
}
hrtc.DateToUpdate = restored_date;
return 1U;
}
/* USER CODE END 0 */
RTC_HandleTypeDef hrtc;
/* RTC init function */
void MX_RTC_Init(void)
{
/* USER CODE BEGIN RTC_Init 0 */
/* USER CODE END RTC_Init 0 */
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef DateToUpdate = {0};
/* USER CODE BEGIN RTC_Init 1 */
uint8_t rtc_backup_ready = 0U;
/* USER CODE END RTC_Init 1 */
/** Initialize RTC Only
*/
hrtc.Instance = RTC;
hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
hrtc.Init.OutPut = RTC_OUTPUTSOURCE_SECOND;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN Check_RTC_BKUP */
rtc_backup_ready = RTC_RestoreDateFromBackup();
/* USER CODE END Check_RTC_BKUP */
/** Initialize RTC and set the Time and Date
*/
if (rtc_backup_ready == 0U)
{
sTime.Hours = 0U;
sTime.Minutes = 0U;
sTime.Seconds = 0U;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
{
Error_Handler();
}
DateToUpdate.WeekDay = RTC_WEEKDAY_MONDAY;
DateToUpdate.Month = RTC_MONTH_JANUARY;
DateToUpdate.Date = 1U;
DateToUpdate.Year = 0U;
if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN) != HAL_OK)
{
Error_Handler();
}
RTC_SaveDateToBackup(&DateToUpdate);
}
/* USER CODE BEGIN RTC_Init 2 */
/* USER CODE END RTC_Init 2 */
}
void HAL_RTC_MspInit(RTC_HandleTypeDef* rtcHandle)
{
if(rtcHandle->Instance==RTC)
{
/* USER CODE BEGIN RTC_MspInit 0 */
/* USER CODE END RTC_MspInit 0 */
HAL_PWR_EnableBkUpAccess();
/* Enable BKP CLK enable for backup registers */
__HAL_RCC_BKP_CLK_ENABLE();
/* RTC clock enable */
__HAL_RCC_RTC_ENABLE();
/* RTC interrupt Init */
HAL_NVIC_SetPriority(RTC_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(RTC_IRQn);
/* USER CODE BEGIN RTC_MspInit 1 */
/* USER CODE END RTC_MspInit 1 */
}
}
void HAL_RTC_MspDeInit(RTC_HandleTypeDef* rtcHandle)
{
if(rtcHandle->Instance==RTC)
{
/* USER CODE BEGIN RTC_MspDeInit 0 */
/* USER CODE END RTC_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_RTC_DISABLE();
/* RTC interrupt Deinit */
HAL_NVIC_DisableIRQ(RTC_IRQn);
/* USER CODE BEGIN RTC_MspDeInit 1 */
/* USER CODE END RTC_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
uint8_t RTC_CalendarIsValid(const RTC_CalendarTypeDef *calendar)
{
if (calendar == NULL)
{
return 0U;
}
return (uint8_t)((calendar->hours <= 23U) &&
(calendar->minutes <= 59U) &&
(calendar->seconds <= 59U) &&
RTC_IsDateValid(calendar->year, calendar->month, calendar->date));
}
HAL_StatusTypeDef RTC_CalendarGet(RTC_CalendarTypeDef *calendar)
{
RTC_TimeTypeDef time = {0};
RTC_DateTypeDef date = {0};
if (calendar == NULL)
{
return HAL_ERROR;
}
if (HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN) != HAL_OK)
{
return HAL_ERROR;
}
if (HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN) != HAL_OK)
{
return HAL_ERROR;
}
RTC_SaveDateToBackup(&date);
calendar->hours = time.Hours;
calendar->minutes = time.Minutes;
calendar->seconds = time.Seconds;
calendar->date = date.Date;
calendar->month = date.Month;
calendar->year = 2000U + date.Year;
calendar->weekday = date.WeekDay;
return HAL_OK;
}
HAL_StatusTypeDef RTC_CalendarSet(const RTC_CalendarTypeDef *calendar)
{
RTC_TimeTypeDef time = {0};
RTC_DateTypeDef date = {0};
uint8_t normalized_year = 0U;
if ((calendar == NULL) || (RTC_CalendarIsValid(calendar) == 0U))
{
return HAL_ERROR;
}
if (RTC_NormalizeYear(calendar->year, &normalized_year) == 0U)
{
return HAL_ERROR;
}
time.Hours = (uint8_t)calendar->hours;
time.Minutes = (uint8_t)calendar->minutes;
time.Seconds = (uint8_t)calendar->seconds;
date.Year = normalized_year;
date.Month = (uint8_t)calendar->month;
date.Date = (uint8_t)calendar->date;
date.WeekDay = RTC_WEEKDAY_MONDAY;
if (HAL_RTC_SetTime(&hrtc, &time, RTC_FORMAT_BIN) != HAL_OK)
{
return HAL_ERROR;
}
if (HAL_RTC_SetDate(&hrtc, &date, RTC_FORMAT_BIN) != HAL_OK)
{
return HAL_ERROR;
}
RTC_SaveDateToBackup(&date);
return HAL_OK;
}
/* USER CODE END 1 */