2
\$\begingroup\$

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);
}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ This problem has been solved by calling reset function from the RTC alarm ISR. But i am not sure whether it is the right way or wrong way of doing this. \$\endgroup\$
    – Myanju
    Commented Jun 27, 2014 at 5:07

2 Answers 2

6
\$\begingroup\$

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;
  }
}
\$\endgroup\$
1
\$\begingroup\$

Have you verified that your alarm mask is actually set correctly? Even with an incorrect alarm mask, you might get the first alarm because the default settings will cause the alarm to trigger (year=0, month=0, day=0, day_of_week_=0, hours=0, minutes=0, seconds=0, mask=all_must_match) because the RTC happens to start with that exact date/time.

You need to enable write access to RTC registers before you can modify them. Some of the STM32 Peripheral Library RTC functions conveniently re-enables write protection behind the scenes; you need to check each function's source code.

You don't show your interrupt routine. You must clear both RTC and EXTI interrupt flags there.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.