STM32F1的RTC调试记录

闲来无事,折腾一个电子手表。

发现需要一个低功耗模式。

查资料发现,有三种低功耗模式,睡眠、停止、待机。其中待机最低功耗。

于是搜索怎么进入。很简单

void Sys_Enter_Standby(void)

{

        __HAL_RCC_APB2_FORCE_RESET(); //复位所有 IO 口

        __HAL_RCC_PWR_CLK_ENABLE(); //使能 PWR 时钟

        __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); //清除 Wake_UP 标志

        HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1); //设置 WKUP 用于唤醒

        HAL_PWR_EnterSTANDBYMode(); //进入待机模式

}

几句话就进入了。问题来了,怎么唤醒。

 

 查到有4步。目前这个板可以试的只有2.3.4。镊子试了一下NRST,不行。

看起来试一下RTC闹钟事件最快。

在RTC的配置里面发现可以配置一个闹钟

    /** Initialize RTC and set the Time and Date
    */
    sTime.Hours = 0x19;
    sTime.Minutes = 0x48;
    sTime.Seconds = 0x0;

    if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK) {
        Error_Handler();
    }
    DateToUpdate.WeekDay = RTC_WEEKDAY_SUNDAY;
    DateToUpdate.Month = RTC_MONTH_MAY;//RTC_MONTH_OCTOBER;
    DateToUpdate.Date = 0x18;
    DateToUpdate.Year = 0x22;

    if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BCD) != HAL_OK) {
        Error_Handler();
    }
    /** Enable the Alarm A
    */
    sAlarm.AlarmTime.Hours = 0x19;
    sAlarm.AlarmTime.Minutes = 0x50;
    sAlarm.AlarmTime.Seconds = 0x30;
    sAlarm.Alarm = RTC_ALARM_A;
    HAL_RTC_SetAlarm(&hrtc, &sAlarm, RTC_FORMAT_BCD);
    if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK) {
        Error_Handler();
    }

但中断函数在哪呢。

在rtc库函数发现这个

/**
  * @brief  This function handles Alarm interrupt request.
  * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
  *                the configuration information for RTC.
  * @retval None
  */
void HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef *hrtc)
{
  if (__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRA))
  {
    /* Get the status of the Interrupt */
    if (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) != (uint32_t)RESET)
    {
      /* AlarmA callback */
#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
      hrtc->AlarmAEventCallback(hrtc);
#else
      HAL_RTC_AlarmAEventCallback(hrtc);
#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */

      /* Clear the Alarm interrupt pending bit */
      __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
    }
  }

  /* Clear the EXTI's line Flag for RTC Alarm */
  __HAL_RTC_ALARM_EXTI_CLEAR_FLAG();

  /* Change RTC state */
  hrtc->State = HAL_RTC_STATE_READY;
}

那中断函数应该是这个

HAL_RTC_AlarmAEventCallback(hrtc);

写了一个指示灯函数在里面,测试发现达到时间后并没有进入。看来是中断没有配置好。又增加这个:
    HAL_NVIC_SetPriority(RTC_Alarm_IRQn, 1, 0);
//    __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
    HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
      HAL_NVIC_SetPriority(RTC_IRQn, 2, 1);
    HAL_NVIC_EnableIRQ(RTC_IRQn);

发现一到时间,程序就死机,中断进不去。判断应该是中断入口不对。

查看启动文件,发现中断函数是     EXPORT  RTC_Alarm_IRQHandler        [WEAK]

搜索整个工程,发现没有这个函数。

果断加入这个函数

void RTC_Alarm_IRQHandler(void)
{
   HAL_RTC_AlarmIRQHandler(&hrtc);

}

这回中断可以进入了。

期间发现两个问题,一是想用cubemx配置闹钟中断,发现rtc配置里面根本就没有闹钟这一项。

 

 以为是版本问题,升级到最新也没有。网上查询发现有些型号有,就F1系列没有。

NVIC栏倒是有一个闹钟中断可以配置优先级。配置之后生成,也没有生成

void RTC_Alarm_IRQHandler(void)函数。这绝对是cube软件问题,坑。
另外发现一个问题,RTCAlarm_IRQn(高优先级)和RTC_IRQn(低优先级)
像这个链接说的事情确实:https://www.86ic.net/ziliao/beidong/255921.html
"发现闹钟中止使能后,假如使能了秒中止,则秒中止标志会置位:"
处理方式是,让
RTCAlarm_IRQn中断优先级比RTC_IRQn高。而且实测发现,RTCAlarm_IRQn响应的时候,RTC_IRQn也会响应;但

RTCAlarm_IRQn不响应,RTC_IRQn秒中断时间到它也不响应。还有一个方式是禁用RTC_IRQn中断。

现在闹钟中断可以进入了,试一下唤醒待机。还是不行。
查询网上说,RTCAlarm_IRQn连接到了EXTILine17,甚至在标准库里面还有这个配置:

 EXTI_InitStructure.EXTI_Line = EXTI_Line17;//LINE17
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能LINE17
  EXTI_Init(&EXTI_InitStructure);//配置[/mw_shl_code]

说是这样配置,才能唤醒。但是在hal库里面,没有找到EXTI_Line17的定义。黑人问号??百思不得其解情况下,查了很久没有HAL库唤醒的代码涉及到EXTI的。

后来查到一个关键信息:

从RTC的定时器特性来说,它是一个32位的计数器,只能向上计数。它使用的时钟源有三种,分别为高速外部时钟的128分频(HSE/128)、低速内部时钟LSI以及低速外部时钟LSE;使HSE分频时钟或LSI的话,在主电源VDD掉电的情况下,这两个时钟来源都会受到影响,因此没法保证RTC正常工作。因此RTC一般使用低速外部时钟LSE,在设计中,频率通常为实时时钟模块中常用的32.768KHz,这是因为32768=2^15,分频容易实现,所以它被广泛应用到RTC模块。在主电源Vpp有效的情况下(待机),RTC还可以配置闹钟事件使STM32退出待机模式。

查了一下,目前程序竟然是用的HSE!但板上没有LSE,只能改成LSI试试。

 

万幸是我的板子待机后,主电源VDD不是掉电的,所以待机后LSI可以工作,但HSE就不行了!应该是待机后切断了。

这样测试可以唤醒后,EXTI_Line17的事就清楚了:HAL根本不需要配置什么EXTI17,只要RTC闹钟可以进中断,并且闹钟时钟源选择LSE或LSI即可。

从停止模式进入闹钟中断,唤醒后从进入中断,然后回到停止地方继续执行;从待机模式进入闹钟中断,唤醒后相当于Reset;reset后没有标志位可以标记是从待机恢复的,需要使用备份寄存器才行。

进入停止模式,是需要配置唤醒方式的,

 HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFE);        // 进入STOP模式

PWR_STOPENTRY_WFE事件唤醒,PWR_STOPENTRY_WFI,引脚唤醒。

 整个调试过程,其实很简单,发现这位写的比较好

https://blog.csdn.net/qq_39061579/article/details/107061185

感谢。https://zhuanlan.zhihu.com/p/515982984

posted @ 2022-05-31 19:56  Zurro  阅读(366)  评论(0编辑  收藏  举报