3

我遇到了 STM32L151 的 RTC 警报中断问题。我希望我的程序每秒都进入 RTC 警报中断,但它不起作用。我的主要功能:

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)
  {

  }
}

函数配置 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);

}

我使用 CubeMX 创建了项目。你对我有什么想法或建议吗?谢谢

4

3 回答 3

8

如果某个字段被屏蔽,则在检查警报日期时不会进行比较。因此,当您屏蔽 SECONDS 时,只会比较 DAY、HOUR 和 MINUTE 字段。使用 RTC 实现 1 秒中断的正确方法是使用所有警报屏蔽,因为这样不会比较任何字段,并且当 RTC 增加 SECOND 字段时,将生成警报中断。

sAlarm.AlarmMask = RTC_ALARMMASK_ALL;

ST 在​​他们的使用硬件实时时钟 (RTC) 在 STM32 F0、F2、F3、F4 和 L1 系列 MCU应用笔记中也描述了所有这些。

在此处输入图像描述

这是一个非常方便的解决方案,因为您不必在所有中断后重置警报。

于 2016-09-18T11:04:17.463 回答
1

正如您所设置的那样,当时间的秒值匹配您的情况sAlarm.AlarmMask = RTC_ALARMMASK_SECONDS时,RTC 将生成中断。因此,如果您将代码保持原样,则每分钟都会有一次中断。sAlarm.AlarmTime.Seconds0

如果您想要每秒中断一次,则必须在中断处理程序中的下一秒再次设置警报。中断处理程序中的代码如下所示:

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);
}

为此,您必须确保已正确设置 RTC 时钟(内部或外部 32K)。

或者您可以使用 RTC 的唤醒功能,我认为这会更合适。或者在您的主​​循环中,您可以使用HAL_GetTick来检查自上次处理以来是否已经过 1 秒,如下所示:

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
   }
}
于 2016-09-07T07:36:51.260 回答
0
  1. 不要__HAL_RTC_ALARM_ENABLE_IT()直接打电话。它被HAL_RTC_SetAlarm_IT().
  2. 启用警报 B。为什么?因为有时,正如我所经历的那样,一个警报不起作用。您“有时”必须启用两个警报。
  3. 对于屏蔽,您必须屏蔽所有位:
    sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY|RTC_ALARMMASK_HOURS|RTC_ALARMMASK_MINUTES|RTC_ALARMMASK_SECONDS;

这样,您要求 ST 只使用秒。您也可以使用RTC_ALARMMASK_ALL.

于 2021-10-30T20:17:16.897 回答