STM32L151 RTC Alarm interrupt
Solution 1
If a field is masked, then that won't be compared when checking alarm date. So when you mask SECONDS, then only the DAY, HOUR and MINUTE fields will be compared. The proper way of achieving 1 second interrupts with RTC is to use all alarm mask because this way none of the fields are compared and when the RTC increments the SECOND field an alarm interrupt will be generated.
sAlarm.AlarmMask = RTC_ALARMMASK_ALL;
Also all of this are described by ST in their Using the hardware real-time clock (RTC) in STM32 F0, F2, F3, F4 and L1 series of MCUs application note.
This is a very convenient solution as you do not have to reset the alarm after all interrupts.
Solution 2
As you have set sAlarm.AlarmMask = RTC_ALARMMASK_SECONDS
, the RTC will generate an interrupt when the seconds value of the time will match sAlarm.AlarmTime.Seconds
which is 0
in your case. So you will have an interrupt every minute here if you leave the code as it is.
If you want an interrupt every second, you will have to set the alarm again with the next second in your interrupt handler. The code in your interrupt handler would look like:
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
RTC_TimeTypeDef sTime;
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
uint8_t next_second = sTime.Seconds++;
if (next_second > 59) next_second = 0;
RTC_AlarmTypeDef sAlarm;
sAlarm.AlarmTime.Hours = 0;
sAlarm.AlarmTime.Minutes = 0;
sAlarm.AlarmTime.Seconds = RTC_ByteToBcd2(next_second);
sAlarm.AlarmTime.TimeFormat = RTC_HOURFORMAT12_AM;
sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
sAlarm.AlarmMask = RTC_ALARMMASK_SECONDS;
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
sAlarm.AlarmDateWeekDay = 1;
sAlarm.Alarm = RTC_ALARM_A;
HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, FORMAT_BCD);
}
For this to work, you have to make sure that you have set up properly the RTC clock (internal or external 32K).
Alternatively you could use the wake up function of the RTC, it would be more appropriate I think.
Or in your main loop, you could use the HAL_GetTick
to check that 1 second has elapsed since your last processing, like this:
static uint32_t last_second = 0;
void main(void)
{
uint32_t current_second = HAL_GetTick();
if (current_second - last_second > 1000)
{
last_second = current_second;
//1 second has elapsed, do something
}
}
uv_utna
Updated on June 04, 2022Comments
-
uv_utna almost 2 years
I am having problem with RTC alarm interrupt of STM32L151. I want my program to go to RTC alarm interrupt every second but it does not work. My main funtion:
int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_IWDG_Init(); MX_RTC_Init(); MX_SPI1_Init(); MX_USART1_UART_Init(); __HAL_RTC_ALARM_ENABLE_IT(&hrtc, RTC_IT_ALRA); while (1) { } }
Function configures RTC: MX_RTC_Init():
void MX_RTC_Init(void) { RTC_TimeTypeDef sTime; RTC_DateTypeDef sDate; RTC_AlarmTypeDef sAlarm; 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.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; HAL_RTC_Init(&hrtc); sTime.Hours = 0x14; sTime.Minutes = 0; sTime.Seconds = 0; sTime.TimeFormat = RTC_HOURFORMAT12_AM; sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; sTime.StoreOperation = RTC_STOREOPERATION_RESET; HAL_RTC_SetTime(&hrtc, &sTime, FORMAT_BCD); sDate.WeekDay = RTC_WEEKDAY_WEDNESDAY; sDate.Month = RTC_MONTH_AUGUST; sDate.Date = 0x24; sDate.Year = 0x16; HAL_RTC_SetDate(&hrtc, &sDate, FORMAT_BCD); /**Enable the Alarm A */ sAlarm.AlarmTime.Hours = 0; sAlarm.AlarmTime.Minutes = 0; sAlarm.AlarmTime.Seconds = 0; sAlarm.AlarmTime.TimeFormat = RTC_HOURFORMAT12_AM; sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET; sAlarm.AlarmMask = RTC_ALARMMASK_SECONDS; sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE; sAlarm.AlarmDateWeekDay = 1; sAlarm.Alarm = RTC_ALARM_A; HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, FORMAT_BCD); }
I created project using CubeMX. Do you have any idea or advice for me? Thank you
-
Kennet Celeste about 5 yearsis this a legitimate approach ? or it's a workaround ?
-
Kennet Celeste about 5 yearshow can one make this every 5 seconds for instance?
-
Bence Kaulics about 5 years@KennetCeleste I am afraid to do that you have to mask everything except the seconds field and reconfigure the alarm at every interrupt. Something like in the other answer. What would simplfy it is moving from HAL to bare register approach because HAl has a huge overhead.
-
Mohammad Kholghi over 2 yearsYou MUST use
HAL_RTC_GetDate
afterHAL_RTC_GetTime
. Otherwise, it's locked. -
Mohammad Kholghi over 2 years@KennetCeleste You want a 5 seconds alarm? 1. mask time to every second, then use a variable as 0 and
var++;
tillvar==5
. Now, call whatever function you'd like. (Don't forget to reset the variable to 0). 2. use timers. If you set RTC time to 5 seconds, IT WILL INTERRUPT ATXX:XX:05
, NOT EVERY 5 SECONDS! -
Mohammad Kholghi over 2 years@KennetCeleste it's a workaround. RTC generates an alarm every second automatically.