Electronic – STM32 RTC alarm not configuring for the second time

rtcstm32

I am using STM32l151vbt6 MCU and I am trying to configure RTC Alarm for every 15th minute. (That is 0, 15, 30 and 45th minute of the every hour.)

I can configure the alarm and it will work for the first time, if I try to set it again after the alarm occurs, it would set to previous alarm state. If I reset the MCU I can set the alarm and it will wake the controller from the stop mode when the alarm occurs. Please let me know how can I set the next alarm without resetting the MCU.

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    /* 8(hour) and 19(day) are masked and there is no effect on the alarm */
    RTC_AlarmTypeDef    RTC_AlarmStructure =
    {
        0,
        0,
        0,
        RTC_H12_AM,
        (RTC_AlarmMask_DateWeekDay | RTC_AlarmMask_Hours),
        RTC_AlarmDateWeekDaySel_Date,
        19
    };
    const uint8_t       alarm_interval[4] = { 15, 30, 45, 0 };
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/


    RTC_AlarmStructure.RTC_AlarmTime.RTC_Minutes =  alarm_interval[RTC_current_time.minute/15];
/*Alarm A will be configured*/
    RTC_Alarm_Config(&RTC_AlarmStructure);

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void RTC_Alarm_Config(RTC_AlarmTypeDef *RTC_AlarmStructure)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    EXTI_InitTypeDef    EXTI_InitStructure;
    NVIC_InitTypeDef    NVIC_InitStructure;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

    RTC_AlarmCmd(RTC_Alarm_A, DISABLE);
    RTC_AlarmCmd(RTC_Alarm_B, DISABLE);//Not using this


    /* EXTI configuration */
    EXTI_ClearITPendingBit(EXTI_Line17);
    EXTI_InitStructure.EXTI_Line = EXTI_Line17;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);


    /* Enable the RTC Alarm Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = RTC_Alarm_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, RTC_AlarmStructure);


    /* Clear RTC AlarmA Flags */
    RTC_ClearITPendingBit(RTC_IT_ALRA);

    /* Enable AlarmA interrupt */
    RTC_ITConfig(RTC_IT_ALRA, ENABLE);


    /* Enable the alarmA */
    RTC_AlarmCmd(RTC_Alarm_A, ENABLE);
}

Best Answer

We faced the same problem while working with RTC on my STM32F030 Controller. Our alarm interrupt triggered once, but it would never trigger again.

The problem was as follows:

  1. We needed to put the system in low power mode when not in use
  2. To enable the low power mode, we had to call this function RCC_APB1PeriphResetCmd(RCC_APB1Periph_PWR, ENABLE);
  3. This function prevents write access to the DBP bit of register PWR_CR and it makes DBP bit = 0. This bit must be set before we can change any values of RTC registers (as mentioned in reference manual)

Reference manual RM0360 for STM32F030 and STM32F070 states that:

After system reset, the RTC registers are protected against parasitic write access by clearing the DBP bit in the PWR_CR register (refer to the power control section). DBP bit must be set in order to enable RTC registers write access. After RTC domain reset, all the RTC registers are write-protected. Writing to the RTC registers is enabled by writing a key into the Write Protection register, RTC_WPR. The following steps are required to unlock the write protection on all the RTC registers except for RTC_TAFCR and RTC_ISR[13:8].

  1. Write ‘0xCA’ into the RTC_WPR register.

  2. Write ‘0x53’ into the RTC_WPR register. Writing a wrong key reactivates the write protection. The protection mechanism is not affected by system reset.

We solved the problem by making following changes to the IRQ handler of RTC:

void RTC_IRQHandler(void)
{
   /*  Check line 17 has triggered the IT */
   if ((EXTI->PR & 0x20000) != 0)  
   {  
      /* Makes the DBP bit of PWR_CR register write accessible */
      RCC_APB1PeriphResetCmd(RCC_APB1Periph_PWR, DISABLE);

      /* Writes 1 in the DBP bit of PWR_CR register */
      PWR_BackupAccessCmd(ENABLE);



      /* Your code here ... */


      /* RTC registers are made write accessible */
      RTC_WriteProtectionCmd(DISABLE);

      /* Clear the RTC Alarm-A Flag */
      RTC_ClearFlag(RTC_FLAG_ALRAF);


      /* Makes the RTC registers read only */
      RTC_WriteProtectionCmd(ENABLE);

      /* Locks the DBP bit of PWR_CR register again */
      RCC_APB1PeriphResetCmd(RCC_APB1Periph_PWR, ENABLE);

      /* Clear the EXTI Line 17 Pending bit (Connected internally to RTC Alarm) */
      EXTI->PR |= 0x20000;
  }
}