/ USER CODE BEGIN Header / /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2024 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 "main.h" /* Private includes ----------------------------------------------------------*/ / USER CODE BEGIN Includes / #include #include / USER CODE END Includes / /* Private typedef -----------------------------------------------------------*/ / USER CODE BEGIN PTD / / USER CODE END PTD / /* Private define ------------------------------------------------------------*/ / USER CODE BEGIN PD / / USER CODE END PD / /* Private macro -------------------------------------------------------------*/ / USER CODE BEGIN PM / / USER CODE END PM / /* Private variables ---------------------------------------------------------*/ RTC_HandleTypeDef hrtc; UART_HandleTypeDef huart3; char time[10]; char date[10]; RTC_TimeTypeDef RtcTime; RTC_DateTypeDef RtcDate; uint8_t CompareSeconds; uint8_t CompareDate; uint8_t Message[64]; uint8_t MessageLen; uint8_t Messagexyz[64]; uint8_t MessageLenxyz; / USER CODE BEGIN PV / void SetRTC(void); void BackupDateToBR(void); / USER CODE END PV / /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_RTC_Init(void); static void MX_USART3_UART_Init(void); / USER CODE BEGIN PFP / extern uint32_t CalculateDayNumber(uint8_t Date, uint8_t Month, uint8_t Year); // DD.MM.YY extern void CalculateDateFromDayNumber(uint32_t DayNumber, uint8_t Date, uint8_t Month, uint8_t *Year); / USER CODE END PFP / /* Private user code ---------------------------------------------------------*/ / USER CODE BEGIN 0 / / USER CODE BEGIN 1 / uint32_t CalculateDayNumber(uint8_t Date, uint8_t Month, uint8_t Year) { // Format: // DD.MM.YY uint32_t _Year = Year + 20; Month = (Month + 9) % 12; Year = Year - (Month / 10); return ((365 Year) + (Year / 4) - (Year / 100) + (Year / 400) + (((Month 306) + 5) / 10) + (Date - 1)); } void CalculateDateFromDayNumber(uint32_t DayNumber, uint8_t Date, uint8_t Month, uint8_t *Year) { uint32_t Date, Month, _Year; _Year = ((10000 * DayNumber) + 14780) / 3652425; int32_t ddd = DayNumber - ((365 * Year) + (Year / 4) - (Year / 100) + (Year / 400)); if (ddd < 0) { _Year -= 1; ddd = DayNumber - ((365 * Year) + (Year / 4) - (Year / 100) + (Year / 400)); } int32_t mi = ((100 * ddd) + 52) / 3060; _Month = (mi + 2) % 12 + 1; Year = Year + (mi + 2)/12; _Date = ddd - ((mi * 306) + 5)/10 + 1; *Date = _Date; *Month = _Month; *Year = _Year - 20; } / USER CODE END 0 / /** * @brief The application entry point. * @retval int */ int main(void) { / USER CODE BEGIN 1 / / USER CODE END 1 / /* MCU Configuration--------------------------------------------------------*/ / Reset of all peripherals, Initializes the Flash interface and the Systick. / HAL_Init(); / USER CODE BEGIN Init / / USER CODE END Init / / Configure the system clock / SystemClock_Config(); / USER CODE BEGIN SysInit / / USER CODE END SysInit / / Initialize all configured peripherals / MX_GPIO_Init(); MX_RTC_Init(); MX_USART3_UART_Init(); / USER CODE BEGIN 2 / / USER CODE END 2 / / Infinite loop / / USER CODE BEGIN WHILE / HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET); HAL_Delay(200); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET); HAL_Delay(200); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET); HAL_Delay(2000); while (1) { / USER CODE END WHILE / HAL_RTC_GetTime(&hrtc, &RtcTime, RTC_FORMAT_BIN); HAL_RTC_GetDate(&hrtc, &RtcDate, RTC_FORMAT_BIN); HAL_UART_Transmit(&huart3, Messagexyz, MessageLenxyz, 100); if(RtcTime.Seconds != CompareSeconds) { MessageLen = sprintf((char*)Message, "Date: %02d.%02d.20%02d Time: %02d:%02d:%02d\n\r", RtcDate.Date, RtcDate.Month, RtcDate.Year, RtcTime.Hours, RtcTime.Minutes, RtcTime.Seconds); HAL_UART_Transmit(&huart3, Message, MessageLen, 100); CompareSeconds = RtcTime.Seconds; } if(RtcDate.Date != CompareDate) { BackupDateToBR(); CompareDate = RtcDate.Date; } // if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(TEST_GPIO_Port, TEST_Pin)) // { // while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(TEST_GPIO_Port, TEST_Pin)) // {} // SetRTC(); // } HAL_Delay(1000); / USER CODE BEGIN 3 / } / USER CODE END 3 / } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_LSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.LSIState = RCC_LSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL2; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC; PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } } /** * @brief RTC Initialization Function * @param None * @retval None */ // static 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 / // / USER CODE END RTC_Init 1 / // /** Initialize RTC Only // */ // 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(); // } // / USER CODE BEGIN Check_RTC_BKUP / // / USER CODE END Check_RTC_BKUP / // /** Initialize RTC and set the Time and Date // */ // sTime.Hours = 0x03; // sTime.Minutes = 0x10; // sTime.Seconds = 0x30; // if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK) // { // Error_Handler(); // } // DateToUpdate.WeekDay = RTC_WEEKDAY_SATURDAY; // DateToUpdate.Month = RTC_MONTH_JULY; // DateToUpdate.Date = 0x27; // DateToUpdate.Year = 0x24; // if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BCD) != HAL_OK) // { // Error_Handler(); // } // / USER CODE BEGIN RTC_Init 2 / // / USER CODE END RTC_Init 2 / // } void MX_RTC_Init(void) { RTC_TimeTypeDef sTime = {0}; RTC_DateTypeDef DateToUpdate = {0}; /** Initialize RTC Only */ 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(); } / USER CODE BEGIN Check_RTC_BKUP / RTC_DateTypeDef BackupDate; RtcDate.Date = (HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2) >> 8); RtcDate.Month = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2); RtcDate.Year = (HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR3) >> 8); RtcDate.WeekDay = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR3); MessageLenxyz = sprintf((char*)Messagexyz, "Backup Date Value: %d, Month: %d, Year: %d, Weekday: %d\n\r", RtcDate.Date, RtcDate.Month, RtcDate.Year, RtcDate.WeekDay); HAL_RTC_GetTime(&hrtc, &RtcTime, RTC_FORMAT_BIN); // There is also an internal date update based on HW RTC time elapsed!! HAL_RTC_GetDate(&hrtc, &BackupDate, RTC_FORMAT_BIN); // Days elapsed since MCU power down uint32_t BackupDateDays = CalculateDayNumber(BackupDate.Date, BackupDate.Month, BackupDate.Year); uint32_t RtcDateDays = CalculateDayNumber(RtcDate.Date, RtcDate.Month, RtcDate.Year); // MessageLenxyz = sprintf((char*)Messagexyz, "BackupDateDays : %d RtcDateDays: %d\n\r", BackupDateDays,RtcDateDays); RtcDateDays += (BackupDateDays - CalculateDayNumber(1, 1, 0)); CalculateDateFromDayNumber(RtcDateDays, &RtcDate.Date, &RtcDate.Month, &RtcDate.Year); HAL_RTC_SetDate(&hrtc, &RtcDate, RTC_FORMAT_BIN); // // You have to do not let Init code to reinitialize Time and Date in RTC. // It's "a bug" in HAL widely described and complain on forums. // That causes every MCU restart the time and date will be same as you configured in CubeMX. // All you have to do is just return before init time/date in this user section. // return; / USER CODE END Check_RTC_BKUP / /** Initialize RTC and set the Time and Date */ sTime.Hours = 23; sTime.Minutes = 59; sTime.Seconds = 55; if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK) { Error_Handler(); } DateToUpdate.WeekDay = RTC_WEEKDAY_SATURDAY; DateToUpdate.Month = RTC_MONTH_FEBRUARY; DateToUpdate.Date = 3; DateToUpdate.Year = 20; if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN) != HAL_OK) { Error_Handler(); } } /** * @brief USART3 Initialization Function * @param None * @retval None */ static void MX_USART3_UART_Init(void) { / USER CODE BEGIN USART3_Init 0 / / USER CODE END USART3_Init 0 / / USER CODE BEGIN USART3_Init 1 / / USER CODE END USART3_Init 1 / huart3.Instance = USART3; huart3.Init.BaudRate = 115200; huart3.Init.WordLength = UART_WORDLENGTH_8B; huart3.Init.StopBits = UART_STOPBITS_1; huart3.Init.Parity = UART_PARITY_NONE; huart3.Init.Mode = UART_MODE_TX_RX; huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart3.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart3) != HAL_OK) { Error_Handler(); } / USER CODE BEGIN USART3_Init 2 / / USER CODE END USART3_Init 2 / } /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; / GPIO Ports Clock Enable / __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET); /*Configure GPIO pin : PA15 */ GPIO_InitStruct.Pin = GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pin : PB13 */ GPIO_InitStruct.Pin = GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); } / USER CODE BEGIN 4 / void BackupDateToBR(void) { HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, ((RtcDate.Date << 8) | (RtcDate.Month))); HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR3, ((RtcDate.Year << 8) | (RtcDate.WeekDay))); } void SetRTC(void) { RTC_TimeTypeDef sTime = {0}; RTC_DateTypeDef DateToUpdate = {0}; /** Initialize RTC and set the Time and Date */ sTime.Hours = 23; sTime.Minutes = 59; sTime.Seconds = 56; if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK) { Error_Handler(); } DateToUpdate.WeekDay = RTC_WEEKDAY_SATURDAY; DateToUpdate.Month = RTC_MONTH_FEBRUARY; DateToUpdate.Date = 3; DateToUpdate.Year = 20; if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN) != HAL_OK) { Error_Handler(); } BackupDateToBR(); } / USER CODE END 4 / /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { __disable_irq(); while (1) { } } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { / USER CODE BEGIN 6 / /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ / USER CODE END 6 / } #endif / USE_FULL_ASSERT /