/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2026 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 */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
typedef enum
{
SCREEN_TIME,
SCREEN_DATE,
SCREEN_YEAR,
SCREEN_ALARM
} DisplayScreen_t;
typedef enum
{
MODE_NORMAL,
MODE_SET_HOUR,
MODE_SET_MINUTE,
MODE_SET_WEEKDAY,
MODE_SET_DATE,
MODE_SET_MONTH,
MODE_SET_YEAR,
MODE_SET_ALARM_HOUR,
MODE_SET_ALARM_MINUTE
} WatchMode_t;
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
uint8_t matrix[4][4]; // 2D array for display
uint8_t hour_tens;
uint8_t hour_ones;
uint8_t min_tens;
uint8_t min_ones;
uint8_t day_tens;
uint8_t day_ones;
uint8_t date_tens;
uint8_t date_ones;
uint8_t year_tens;
uint8_t year_ones;
uint8_t month_tens;
uint8_t month_ones;
uint8_t editHour;
uint8_t editMinute;
uint8_t editWeekday;
uint8_t editDate;
uint8_t editMonth;
uint8_t editYear;
uint8_t alarmHour = 0;
uint8_t alarmMinute = 0;
uint8_t editAlarmHour;
uint8_t editAlarmMinute;
uint8_t alarmEnabled = 0;
uint8_t alarmActive = 0; // Alarm currently sounding
uint32_t alarmStartTime = 0; // When the alarm started
uint32_t alarmTimer = 0; // Timing between beeps
uint8_t beepCount = 0; // 0..3 beeps in the current burst
uint8_t buzzerOn = 0; // 0 = OFF, 1 = ON
uint32_t displayTimeout = 0;
uint8_t displayEnabled = 0;
uint32_t buttonPressTime[3] = {0};
uint8_t buttonPressed[3] = {0};
uint32_t lastButtonInterrupt[3] = {0}; // debounce timer
uint8_t settingMode = 0;
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
RTC_HandleTypeDef hrtc;
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim21;
/* USER CODE BEGIN PV */
/* 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_TIM2_Init(void);
static void MX_TIM21_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/*
* Store the pattern in memory matrix
* The digit and the column where to print is sent.
* Then the row is selected by the AND operation and check if the output is true or false (1 or 0)
* digit = 6 = 0110
* 0110 * 1000 = 0 so the 8th bit row will turn off
* 0110 * 0100 = 1 so the 4th bit row will turn on
* 0110 * 0010 = 1 so the 2nd bit row will turn on
* 0110 * 0001 = 0 so the 1st bit row will turn off
*/
void SetColumnMem(uint8_t col, uint8_t digit)
{
matrix[0][col] = (digit & 0x08) ? 1 : 0; // 8
matrix[1][col] = (digit & 0x04) ? 1 : 0; // 4
matrix[2][col] = (digit & 0x02) ? 1 : 0; // 2
matrix[3][col] = (digit & 0x01) ? 1 : 0; // 1
}
// Turn off LEDs before the next pattern
void DisableAllColumns(void)
{
HAL_GPIO_WritePin(GPIOA, COL_1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, COL_2_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, COL_3_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, COL_4_Pin, GPIO_PIN_SET);
}
//------ Convert the patter stored in memory to GPIO ---------
/*
* Check each matrix to see which row is to be set or reset.
* if matrix[0][1] is set then set the row 4 pin
*/
void SetRows(uint8_t col)
{
HAL_GPIO_WritePin(GPIOB, ROW_1_Pin,
matrix[0][col] ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, ROW_2_Pin,
matrix[1][col] ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, ROW_3_Pin,
matrix[2][col] ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, ROW_4_Pin,
matrix[3][col] ? GPIO_PIN_SET : GPIO_PIN_RESET);
}
// Reset the column based on the user column entry
void SetColumn(uint8_t col)
{
switch(col)
{
case 0:
HAL_GPIO_WritePin(GPIOA, COL_1_Pin, GPIO_PIN_RESET);
break;
case 1:
HAL_GPIO_WritePin(GPIOA, COL_2_Pin, GPIO_PIN_RESET);
break;
case 2:
HAL_GPIO_WritePin(GPIOA, COL_3_Pin, GPIO_PIN_RESET);
break;
case 3:
HAL_GPIO_WritePin(GPIOA, COL_4_Pin, GPIO_PIN_RESET);
break;
}
}
void getTime(void)
{
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
/* Get the RTC current Time */
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
/* Get the RTC current Date */
HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
hour_tens = sTime.Hours / 10;
hour_ones = sTime.Hours % 10;
min_tens = sTime.Minutes / 10;
min_ones = sTime.Minutes % 10;
// HH : MM
SetColumnMem(0, hour_tens);
SetColumnMem(1, hour_ones);
SetColumnMem(2, min_tens);
SetColumnMem(3, min_ones);
}
void getDate(void)
{
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
/* Get the RTC current Time */
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
/* Get the RTC current Date */
HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
day_tens = sDate.WeekDay / 10;
day_ones = sDate.WeekDay % 10;
date_tens = sDate.Date / 10;
date_ones = sDate.Date % 10;
// WD : DD
SetColumnMem(0, day_tens);
SetColumnMem(1, day_ones);
SetColumnMem(2, date_tens);
SetColumnMem(3, date_ones);
}
void getYear(void)
{
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
/* Get the RTC current Time */
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
/* Get the RTC current Date */
HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
month_tens = sDate.Month / 10;
month_ones = sDate.Month % 10;
year_tens = sDate.Year / 10;
year_ones = sDate.Year % 10;
// MM : YY
SetColumnMem(0, month_tens);
SetColumnMem(1, month_ones);
SetColumnMem(2, year_tens);
SetColumnMem(3, year_ones);
}
/*
* Initialize the enum with default screen and mode and change the enum to enter the different modes.
* See the functions below for more info
*/
DisplayScreen_t currentScreen = SCREEN_YEAR;
WatchMode_t currentMode = MODE_NORMAL;
/*
* Entering to setting mode based on the screens
* So if the currentScreen is SCREEN_TIME
* then it should go into MODE_SET_HOUR to change the hour.
*/
void EnterSettingMode(void)
{
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
editHour = sTime.Hours;
editMinute = sTime.Minutes;
editWeekday = sDate.WeekDay;
editDate = sDate.Date;
editMonth = sDate.Month;
editYear = sDate.Year;
switch(currentScreen) // Check the currentScreen typedef and enter the appropriate setting modes
{
case SCREEN_TIME:
currentMode = MODE_SET_HOUR; // Change the Hours
break;
case SCREEN_DATE:
currentMode = MODE_SET_WEEKDAY; // Change the Weekday
break;
case SCREEN_YEAR:
currentMode = MODE_SET_MONTH; // Change the month
break;
case SCREEN_ALARM:
editAlarmHour = alarmHour;
editAlarmMinute = alarmMinute;
currentMode = MODE_SET_ALARM_HOUR;
break;
}
}
/*
* Once we are inside setting a particular mode then we need to change the mode
* to set the other field.
* So after setting the hour we need to set the minutes.
*/
void NextField(void)
{
switch(currentMode) // Check the currentMode typedef and go into the next mode to change the num
{
case MODE_SET_HOUR: // is current mode is in setting hour
currentMode = MODE_SET_MINUTE; // then enter setting minute once this function is called
break;
case MODE_SET_MINUTE:
currentMode = MODE_SET_HOUR;
break;
case MODE_SET_WEEKDAY:
currentMode = MODE_SET_DATE;
break;
case MODE_SET_DATE:
currentMode = MODE_SET_WEEKDAY;
break;
case MODE_SET_MONTH:
currentMode = MODE_SET_YEAR;
break;
case MODE_SET_YEAR:
currentMode = MODE_SET_MONTH;
break;
case MODE_SET_ALARM_HOUR:
currentMode = MODE_SET_ALARM_MINUTE;
break;
case MODE_SET_ALARM_MINUTE:
currentMode = MODE_SET_ALARM_HOUR;
break;
default:
currentMode = MODE_NORMAL;
break;
}
}
/*
* This function is to increment the values in each and every mode based on the
* current mode.
*
* SCREEN_TIME:
* MODE_SET_HOUR
* MODE_SET_MINUTE
* SCREEN_DAY:
* MODE_SET_WEEKDAY
* MODE_SET_DAY
* SCREEN_YEAR:
* MODE_SET_MONTH
* MODE_SET_YEAR
*
* All the changes to the time is done to temp variables.
*/
void IncrementCurrentField(void)
{
switch(currentMode)
{
case MODE_SET_HOUR:
editHour++;
if(editHour > 23)
editHour = 0;
break;
case MODE_SET_MINUTE:
editMinute++;
if(editMinute > 59)
editMinute = 0;
break;
case MODE_SET_WEEKDAY:
editWeekday++;
if(editWeekday > 7)
editWeekday = 1;
break;
case MODE_SET_DATE:
editDate++;
if(editDate > 31)
editDate = 1;
break;
case MODE_SET_MONTH:
editMonth++;
if(editMonth > 12)
editMonth = 1;
break;
case MODE_SET_YEAR:
editYear++;
if(editYear > 99)
editYear = 0;
break;
case MODE_SET_ALARM_HOUR:
editAlarmHour++;
if(editAlarmHour > 23)
{
editAlarmHour = 0;
}
break;
case MODE_SET_ALARM_MINUTE:
editAlarmMinute++;
if(editAlarmMinute > 59)
{
editAlarmMinute = 0;
}
break;
default:
break;
}
}
void ShowSettingValue(void)
{
switch(currentScreen)
{
case SCREEN_TIME:
SetColumnMem(0, editHour / 10);
SetColumnMem(1, editHour % 10);
SetColumnMem(2, editMinute / 10);
SetColumnMem(3, editMinute % 10);
break;
case SCREEN_DATE:
SetColumnMem(0, editWeekday / 10);
SetColumnMem(1, editWeekday % 10);
SetColumnMem(2, editDate / 10);
SetColumnMem(3, editDate % 10);
break;
case SCREEN_YEAR:
SetColumnMem(0, editMonth / 10);
SetColumnMem(1, editMonth % 10);
SetColumnMem(2, editYear / 10);
SetColumnMem(3, editYear % 10);
break;
case SCREEN_ALARM:
SetColumnMem(0, editAlarmHour / 10);
SetColumnMem(1, editAlarmHour % 10);
SetColumnMem(2, editAlarmMinute / 10);
SetColumnMem(3, editAlarmMinute % 10);
break;
}
}
void beep()
{
HAL_TIM_PWM_Start(&htim21, TIM_CHANNEL_2);
HAL_Delay(20);
HAL_TIM_PWM_Stop(&htim21, TIM_CHANNEL_2);
}
void getAlarm(void)
{
SetColumnMem(0, alarmHour / 10);
SetColumnMem(1, alarmHour % 10);
SetColumnMem(2, alarmMinute / 10);
SetColumnMem(3, alarmMinute % 10);
if(alarmEnabled)
{
matrix[0][0] = 1;
}
else
{
matrix[0][0] = 0;
}
}
/* 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_TIM2_Init();
MX_TIM21_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim2);
__HAL_TIM_SET_COMPARE(&htim21, TIM_CHANNEL_2, 50);
// read the alarm from eeprom
alarmHour = *(uint8_t *)0x08080000;
alarmMinute = *(uint8_t *)0x08080001;
//beep();
// __HAL_TIM_SET_COMPARE(&htim21, TIM_CHANNEL_2, 250);
// HAL_TIM_PWM_Start(&htim21, TIM_CHANNEL_2);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(alarmActive && buttonPressed[0])
{
alarmActive = 0;
HAL_TIM_PWM_Stop(&htim21, TIM_CHANNEL_2);
buttonPressed[0] = 0;
}
if(alarmActive)
{
uint32_t now = HAL_GetTick();
// Stop after 20 seconds
if((now - alarmStartTime) >= 20000)
{
alarmActive = 0;
HAL_TIM_PWM_Stop(&htim21, TIM_CHANNEL_2);
}
else
{
if(buzzerOn)
{
// ON for 80ms
if((now - alarmTimer) >= 80)
{
HAL_TIM_PWM_Stop(&htim21, TIM_CHANNEL_2);
buzzerOn = 0;
alarmTimer = now;
beepCount++;
}
}
else
{
if(beepCount < 4)
{
// OFF between beeps (80ms)
if((now - alarmTimer) >= 80)
{
HAL_TIM_PWM_Start(&htim21, TIM_CHANNEL_2);
buzzerOn = 1;
alarmTimer = now;
}
}
else
{
// Pause after 4 beeps (250ms)
if((now - alarmTimer) >= 500)
{
beepCount = 0;
HAL_TIM_PWM_Start(&htim21, TIM_CHANNEL_2);
buzzerOn = 1;
alarmTimer = now;
}
}
}
}
}
if(currentMode == MODE_NORMAL)
{
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == GPIO_PIN_RESET)
{
uint32_t now = HAL_GetTick();
if(buttonPressed[2] == 0 &&
(now - lastButtonInterrupt[2]) > 100)
{
if(currentScreen != SCREEN_ALARM)
{
currentScreen = SCREEN_ALARM;
getAlarm();
}
else
{
currentScreen = SCREEN_TIME;
getTime();
}
displayEnabled = 1;
displayTimeout = HAL_GetTick();
beep();
buttonPressed[2] = 1;
lastButtonInterrupt[2] = now;
}
}
else
{
buttonPressed[2] = 0;
}
}
if(currentMode == MODE_NORMAL && currentScreen == SCREEN_ALARM)
{
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET)
{
uint32_t now = HAL_GetTick();
if(buttonPressed[1] == 0 &&
(now - lastButtonInterrupt[1]) > 100)
{
alarmEnabled = !alarmEnabled;
if(alarmEnabled)
{
RTC_AlarmTypeDef sAlarm = {0};
sAlarm.AlarmTime.Hours = alarmHour;
sAlarm.AlarmTime.Minutes = alarmMinute;
sAlarm.AlarmTime.Seconds = 0;
sAlarm.AlarmTime.SubSeconds = 0;
sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY;
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
sAlarm.AlarmDateWeekDay = 1;
sAlarm.Alarm = RTC_ALARM_A;
HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN);
matrix[0][0] = 1;
}
else
{
HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_A);
matrix[0][0] = 0;
}
beep();
buttonPressed[1] = 1;
lastButtonInterrupt[1] = now;
}
}
else
{
buttonPressed[1] = 0;
}
}
if(currentMode != MODE_NORMAL)
{
displayEnabled = 1;
ShowSettingValue();
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET)
{
uint32_t now = HAL_GetTick();
if(buttonPressed[1] == 0 &&
(now - lastButtonInterrupt[1]) > 100)
{
IncrementCurrentField();
buttonPressed[1] = 1;
lastButtonInterrupt[1] = now;
}
}
else
{
buttonPressed[1] = 0;
}
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == GPIO_PIN_RESET)
{
uint32_t now = HAL_GetTick();
if(buttonPressed[2] == 0 &&
(now - lastButtonInterrupt[2]) > 50)
{
NextField();
beep();
buttonPressed[2] = 1;
lastButtonInterrupt[2] = now;
}
}
else
{
buttonPressed[2] = 0;
}
if(buttonPressed[0])
{
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET)
{
if((HAL_GetTick() - buttonPressTime[0]) >= 1000)
{
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
sTime.Hours = editHour;
sTime.Minutes = editMinute;
sDate.WeekDay = editWeekday;
sDate.Date = editDate;
sDate.Month = editMonth;
sDate.Year = editYear;
HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
if(currentScreen == SCREEN_ALARM)
{
alarmHour = editAlarmHour;
alarmMinute = editAlarmMinute;
// save into eeprom so the memory retains even after powerloss
HAL_FLASHEx_DATAEEPROM_Unlock();
HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE,
0x08080000,
alarmHour);
HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE,
0x08080001,
alarmMinute);
HAL_FLASHEx_DATAEEPROM_Lock();
}
currentMode = MODE_NORMAL;
settingMode = 0;
buttonPressed[0] = 0;
buttonPressTime[0] = 0;
displayEnabled = 1;
displayTimeout = HAL_GetTick();
beep();
}
}
}
continue;
}
if(buttonPressed[0])
{
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET)
{
if(displayEnabled){
if((HAL_GetTick() - buttonPressTime[0]) >= 1000)
{
buttonPressed[0] = 0; // prevent repeated entry
settingMode = 1;
beep();
EnterSettingMode();
}
}
}
else
{
displayEnabled = 1;
displayTimeout = HAL_GetTick();
switch(currentScreen)
{
case SCREEN_TIME:
currentScreen = SCREEN_DATE;
getDate();
//beep();
break;
case SCREEN_DATE:
currentScreen = SCREEN_YEAR;
getYear();
//beep();
break;
case SCREEN_YEAR:
currentScreen = SCREEN_TIME;
getTime();
beep();
break;
case SCREEN_ALARM:
// Do nothing.
// PB0 press has no function on the alarm screen.
break;
}
buttonPressed[0] = 0;
}
}
// Sleep timeout only in normal mode, in setting mode disable timeout
if(currentMode == MODE_NORMAL)
{
if(displayEnabled)
{
if((HAL_GetTick() - displayTimeout) >= 5000)
{
displayEnabled = 0;
DisableAllColumns();
currentScreen = SCREEN_YEAR; // SHOW SCREEN_TIME AFTER WAKEUP. SEE EXTI_CALLBACK() FOR MORE INFO
HAL_SuspendTick();
HAL_TIM_Base_Stop_IT(&htim2);
HAL_TIM_PWM_Stop(&htim21, TIM_CHANNEL_2);
__HAL_RCC_TIM2_CLK_DISABLE();
__HAL_RCC_TIM21_CLK_DISABLE();
HAL_PWREx_EnableUltraLowPower();
HAL_PWREx_EnableFastWakeUp();
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON,PWR_STOPENTRY_WFI);
// RESUME CPU
SystemClock_Config();
HAL_ResumeTick();
__HAL_RCC_TIM2_CLK_ENABLE();
__HAL_RCC_TIM21_CLK_ENABLE();
HAL_TIM_Base_Start_IT(&htim2);
}
}
}
/* USER CODE END WHILE */
/* 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};
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Configure LSE Drive Capability
*/
HAL_PWR_EnableBkUpAccess();
__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
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_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
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_LSE;
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 sDate = {0};
RTC_AlarmTypeDef sAlarm = {0};
/* USER CODE BEGIN RTC_Init 1 */
/* USER CODE END RTC_Init 1 */
/** Initialize RTC Only
*/
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
...
This file has been truncated, please download it to see its full contents.
Comments