簡體   English   中英

STM32L151 RTC鬧鍾中斷

[英]STM32L151 RTC Alarm interrupt

我遇到了 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 創建了項目。 你對我有什么想法或建議嗎? 謝謝

如果某個字段被屏蔽,則在檢查警報日期時將不進行比較。 因此,當您屏蔽SECONDS時,將僅比較DAY,HOUR和MINUTE字段。 使用RTC實現1秒中斷的正確方法是使用所有警報掩碼,因為這種方式不會比較任何字段,並且當RTC遞增SECOND字段時,將生成警報中斷。

sAlarm.AlarmMask = RTC_ALARMMASK_ALL;

ST還在《 STM32 F0,F2,F3,F4和L1系列MCU應用筆記》中的“ 使用硬件實時時鍾(RTC)”中對此進行了描述。

在此處輸入圖片說明

這是一個非常方便的解決方案,因為您不必在所有中斷后都重置警報。

設置sAlarm.AlarmMask = RTC_ALARMMASK_SECONDS ,當時間的秒數與sAlarm.AlarmTime.Seconds相匹配(在您的情況下為0時,RTC將生成中斷。 因此,如果您將代碼保持原樣,那么您每分鍾都會有一個中斷。

如果您想每秒中斷一次,則必須在中斷處理程序中再次設置警報,並在下一秒再次設置警報。 您的中斷處理程序中的代碼如下所示:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM