По условию задачи необходимо, чтобы контроллер (STM32F051) находился в режиме STANDBY и периодически просыпался 4 раза в сек. RTC тактируется от LSE. Настройка Alarm происходит после проверки конфигурации RTC по содержимому BACKUP регистра. Конфигурация RTC происходит один раз:
CODE
#define RTC_ASYNCH_PREDIV 0x7F
#define RTC_SYNCH_PREDIV 0x00FF
//---------------------------------------------------------
void MX_RTC_Init(void)
{
/* Configure RTC prescaler and RTC data registers */
/* RTC configured as follows:
- Hour Format = Format 24
- Asynch Prediv = Value according to source clock
- Synch Prediv = Value according to source clock
- OutPut = Output Disable
- OutPutPolarity = High Polarity
- OutPutType = Open Drain */
RTCHandle.Init.HourFormat = RTC_HOURFORMAT_24;
RTCHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
RTCHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV;
RTCHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
RTCHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
RTCHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
RTCHandle.Instance = RTC;
if (HAL_RTC_Init(&RTCHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/*##-2- Check if Data stored in BackUp register0: No Need to reconfigure RTC ##*/
/* Read the Back-Up Register 0 Data */
if (HAL_RTCEx_BKUPRead(&RTCHandle, RTC_BKP_DR0) != CONFIGURATION_DONE)
{BSP_LED_On(LED_GREEN);
/* Configure RTC Calendar */
RTC_CalendarConfig();
}
else
{BSP_LED_On(LED_BLUE);
/* Check and Clear the Wakeup flag */
if (__HAL_PWR_GET_FLAG(PWR_FLAG_WU) != RESET)
{
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
}
/* Check if the system was resumed from StandBy mode */
if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET)
{
/* Clear StandBy flag */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
/* Disable the write protection for RTC registers */
__HAL_RTC_WRITEPROTECTION_DISABLE(&RTCHandle);
/* Wait for RTC APB registers synchronization (needed after start-up from Reset)*/
if (HAL_RTC_WaitForSynchro(&RTCHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/* Enable the write protection for RTC registers */
__HAL_RTC_WRITEPROTECTION_ENABLE(&RTCHandle);
/* No need to configure the RTC as the RTC config(clock source, enable, prescaler, ...)
* are kept after wake-up from STANDBY */
}
/* Check if the Power On Reset flag is set */
if (__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) != RESET)
{
/* Turn on LED2: Power on reset occured */
///BSP_LED_On(LED_RED);
}
/* Check if Pin Reset flag is set */
if (__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST) != RESET)
{
/* Turn on LED4: External reset occured */
//BSP_LED_On(LED_BLUE);
}
/* Clear source Reset Flag */
__HAL_RCC_CLEAR_RESET_FLAGS();
}
RTC_AlarmConfig(); // установить генерацию Alarm A каждые 250+140=390 мсек
}
//--------------------------------------
void RTC_AlarmConfig(void)
{
RTC_AlarmTypeDef RTC_AlarmStructure;
RTC_TimeTypeDef RTC_TimeStructure;
RTC_DateTypeDef RTC_DateStructure;
//HAL_RTC_DeactivateAlarm(&RTCHandle, RTC_ALARM_A);
/* Get Time Stamp of the current time */
HAL_RTC_GetTime(&RTCHandle, &RTC_TimeStructure, FORMAT_BIN);
HAL_RTC_GetDate(&RTCHandle, &RTC_DateStructure, FORMAT_BIN);
/* Set the alarm to current time + 250ms + offset 140ms */
RTC_AlarmStructure.Alarm = RTC_ALARM_A;
RTC_AlarmStructure.AlarmTime.TimeFormat = RTC_TimeStructure.TimeFormat;
RTC_AlarmStructure.AlarmTime.Hours = RTC_TimeStructure.Hours;
RTC_AlarmStructure.AlarmTime.Minutes = RTC_TimeStructure.Minutes;
RTC_AlarmStructure.AlarmTime.Seconds = RTC_TimeStructure.Seconds; //(RTC_TimeStructure.Seconds + 2) % 60; //
RTC_AlarmStructure.AlarmTime.SubSeconds = 255; //(RTC_TimeStructure.SubSeconds + 255) % 256;
RTC_AlarmStructure.AlarmDateWeekDay = RTC_DateStructure.Date;
RTC_AlarmStructure.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
RTC_AlarmStructure.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY | RTC_ALARMMASK_HOURS | RTC_ALARMMASK_MINUTES | RTC_ALARMMASK_SECONDS;
RTC_AlarmStructure.AlarmSubSecondMask =RTC_ALARMSUBSECONDMASK_SS14_6; // RTC_ALARMSUBSECONDMASK_None; //
if (HAL_RTC_SetAlarm_IT(&RTCHandle, &RTC_AlarmStructure, FORMAT_BIN) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
//----------------------
void RTC_CalendarShow(uint8_t *showtime, uint8_t *showdate)
{
RTC_DateTypeDef sdatestructureget;
RTC_TimeTypeDef stimestructureget;
/* Get the RTC current Time */
HAL_RTC_GetTime(&RTCHandle, &stimestructureget, FORMAT_BIN);
/* Get the RTC current Date */
HAL_RTC_GetDate(&RTCHandle, &sdatestructureget, FORMAT_BIN);
/* Display time Format : hh:mm:ss */
sprintf_((char *)showtime, "%02d:%02d:%02d", stimestructureget.Hours, stimestructureget.Minutes, stimestructureget.Seconds);
/* Display date Format : mm-dd-yy */
sprintf_((char *)showdate, "%02d-%02d-%02d", sdatestructureget.Month, sdatestructureget.Date, 2000 + sdatestructureget.Year);
}
Прерывание AlarmA настроено и в обработчике деактивизирую Alarm:
Код
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc){HAL_RTC_DeactivateAlarm(&RTCHandle, RTC_ALARM_A);}
И в главном цикле:
CODE
MX_RTC_Init();
//HAL_Delay(1000);
//while (1)
//{
/* Display the updated Time and Date */
RTC_CalendarShow(aShowTime, aShowDate);
printf_("%s \n\r", aShowTime);
printf_("%s \n\r", aShowDate);
BSP_LED_On(LED_RED); // индикация работы программы
HAL_Delay(10);
//}
/* Request to enter STANDBY mode */
HAL_PWR_EnterSTANDBYMode();
/* Infinite Loop */
while (1);
Пробуждение по Alarm происходит почти как положено. Вместо ожидаемого периода 250 мс реальное значение на 140 мс больше. И эта "надбавка" сохраняется при разных значениях RTC_ALARMSUBSECONDMASK_SS14_X. Но это меня устраивает... Проблема в том, что при вызове RTC_CalendarShow() отображается одно и то же значение времени. Если раскомментировать while (1), в котором вечно отображать время (т.е. в режим STANDBY не входим), то все в порядке - время "тикает". Если закомментировать while (1) (т.е. вход в режим STANDBY), но добавить задержку в 1 сек, то показания часов обновляются. Проблема с обновлением показания часов также имеет место, если сбрасывать контроллер вручную кнопкой RESET чаще, чем 1 сек. Почему так происходит?