STM32停止模式记录

第一次写博客,感觉我这脑子越来越不好用,怕忘记了,所以以此记录。

1、STM32F10xxx进入和退出停止模式的条件在这里插入图片描述
2、外部中断线描述
共有20个外部中断线,EXTI线0-15对应IO口Px0-Px15,另外四个EXTI线的连接方式如下:
● EXTI线16连接到PVD输出
● EXTI线17连接到RTC闹钟事件
● EXTI线18连接到USB唤醒事件
● EXTI线19连接到以太网唤醒事件(只适用于互联型产品)

3、基于Hal库的外部中断+RTC闹钟中断唤醒停止模式
以下例程实现了,按照工作时间+停止时间周期性的进入和退出停止模式。MCU为STM32F072。

3.1:RTC初始化

void MX_RTC_Init(void)
{
  RTC_TimeTypeDef sTime = {0};
  RTC_DateTypeDef sDate = {0};
  RTC_AlarmTypeDef sAlarm = {0};

  /** Initialize RTC Only 
  */
  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;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }

  /* USER CODE BEGIN Check_RTC_BKUP */
    
  /* USER CODE END Check_RTC_BKUP */

  /** Initialize RTC and set the Time and Date 
  */
  sTime.Hours = 0x0;
  sTime.Minutes = 0x58;
  sTime.Seconds = 0x0;
  sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sTime.StoreOperation = RTC_STOREOPERATION_RESET;
  if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  sDate.WeekDay = RTC_WEEKDAY_MONDAY;
  sDate.Month = RTC_MONTH_JANUARY;
  sDate.Date = 0x1;
  sDate.Year = 0x0;

  if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  /** Enable the Alarm A 
  */
  sAlarm.AlarmTime.Hours = 0x0;
  sAlarm.AlarmTime.Minutes = 0x0;
  sAlarm.AlarmTime.Seconds = 0x20;
  sAlarm.AlarmTime.SubSeconds = 0x0;
  sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
  sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY|RTC_ALARMMASK_HOURS;
  sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
  sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
  sAlarm.AlarmDateWeekDay = 0x1;
  sAlarm.Alarm = RTC_ALARM_A;
  if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }

}

使能RTC闹钟中断,闹钟设置了分秒匹配,不匹配日期星期小时。

3.2:退出和进入停止模式

//系统进入停止模式
void sys_enter_stop_mode(void)
{
    // 使能PWR时钟
    __HAL_RCC_PWR_CLK_ENABLE();

    HAL_SuspendTick();

    // 进入STOP模式
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
}
void SYSCLKConfig_STOP(void)
{
  /* 使能 HSE */
  __HAL_RCC_HSE_CONFIG(RCC_HSE_ON);

  /* 等待 HSE 准备就绪 */
  while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET);
  
  /* 使能 PLL */ 
  __HAL_RCC_PLL_ENABLE();

  /* 等待 PLL 准备就绪 */
  while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET)
  {
  }

  /* 选择PLL作为系统时钟源 */
  __HAL_RCC_SYSCLK_CONFIG(RCC_SYSCLKSOURCE_PLLCLK);

  /* 等待PLL被选择为系统时钟源 */
  while(__HAL_RCC_GET_SYSCLK_SOURCE() != 0x08)
  {
  }
}


//系统从停止模式恢复
void sys_resume(void)
{
    SYSCLKConfig_STOP();
    HAL_ResumeTick();
}

在这里插入图片描述

进入停止模式后,因为晶振关闭程序无法运行,当从停止模式恢复后,需要重新初始化系统时钟。恢复后程序会从停止的位置开始继续运行。
3.3:外部中断函数

void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
    if (RunPara.WorkMode == Stop){
        if (RunPara.LocalConfigFlag == 0){
            sys_resume();
        }
        RunPara.WorkMode = Work;
        RunPara.AlarmIntReason = StopArrive;
    }
    else{
        RunPara.AlarmIntReason = WakeArrive;
    }
}


void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == GPIO_PIN_15){
        RunPara.LocalConfigFlag = 1;
        RunPara.ExitConfigTimes = ExitConfigTime;
        if (RunPara.WorkMode == Stop){
            sys_resume();
        }
    }
}

注意!!!:RTC闹钟中断一定要进入HAL_RTC_AlarmAEventCallback函数才能从低功耗模式唤醒,笔者之前设置了闹钟中断,但是进入的是RTC全局中断函数,在全局中断中判断闹钟中断源,导致死活唤醒不了。

3.4 闹钟设置

            HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);  //hal库读rtc时间,一定要再读日期,不然时间不更新
            HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
            sAlarm.AlarmTime.Hours = sTime.Hours;
            if (sTime.Minutes+TerUser.WorkTime<60){
                sAlarm.AlarmTime.Minutes = sTime.Minutes+TerUser.WorkTime; 
            }
            else{
                sAlarm.AlarmTime.Minutes = sTime.Minutes+TerUser.WorkTime-60;
            }   
            sAlarm.AlarmTime.Seconds = sTime.Seconds;
            HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN); 

不涉及时间进位,闹钟配置只能按分钟进行配置,范围为0-59分钟。

4、对于停止模式下喂狗的看法
独立看门狗使用的是LSI,所以停止模式下独立看门狗是一直运行的。并且独立看门狗,一旦打开,不可以停止,导致停止模式下无法喂狗。网上关于停止模式下独立看门狗喂狗,都是定期唤醒闹钟喂狗,但是不适用于本例程的应用逻辑。所以最后决定放弃独立看门狗,选择窗口看门狗,进入停止模式后,窗口看门狗也会停止,不需要对喂狗做任何额外的处理。不知道大家对低功耗模式下独立看门狗喂狗有什么好的方法,欢迎指教。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值