STM32进入STOP模式并唤醒实验总结

项目需求,需要实现设备低功耗功能,实现过程中遇到几个问题,以此记录总结。(stm32f103ret6)

问题一:执行PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFI);后,程序继续执行,看到的现象像是没有进入休眠。

 

调试步骤:

1.关闭自己的时钟配置,调用启动函数中默认的SystemInit()

2.关闭相关外设初始化,只开启串口一以追踪程序运行流程和一个IO中断以唤醒

         现象:能进入中断并且正常唤醒

3.换为调用自己的时钟,休眠不了,一步步打开相关时钟配置没问题直到开启了

SysTick_Config(SystemCoreClock / 1000 )   //1ms定时器

就休眠失败

源码贴图如下:

 

原因:开始以为把所有的外设中断关闭就没事了,其实系统时钟开了个1Ms的系统定时中断(功能需要)

 

【解决方式】

方式一:.注释SysTick_Config(SystemCoreClock / 1000)

方式二:.在进入休眠之前,关闭系统定时器,清空计数值

        SysTick->CTRL = 0x00;//关闭定时器
        SysTick->VAL = 0x00;//清空val,清空定时器

功能需要不能关闭,选择方式二

【补充说明】:

     SysTick系统定时器是属于CM3内核中的一个外设,内嵌在NVIC中。它是一个24bit的向下递减计数器,每计数一次的时间为1/SYSCLK。当重装载数值寄存器地见到0的时候,系统定时器就产生一次中断,依次循环反复。我的累计值是SystemCoreClock / 1000,所以中断就是1ms一次。

     相比定时器中断,产生之后需要清中断标志位,但是系统时钟中断是没有的,开始怀疑是不是中断产生之后标志位是不会复位的,导致停止模式进入被忽略,程序继续执行。后面找资料发现每次systick溢出后会置位计数标志位和中断标志位,计数标志位在计数器重装载后被清除,而中断标志位也会随着中断服务程序的响应被清除,所以这两个标志位是不需要手动清除的。

     具体为什么开启系统定时器之后不能进入停止模式还需要查找原因,在此也请各位网友赐教。

    【发现应该是系统时钟中断一直是开启的,所以在中断标志位清掉之后,每到1ms就又产生一次中断,标志位重新被置位,导致停止模式进入被忽略,程序继续进行,把这个定时器关掉就好//add 2019.5.9】

 

【回复评论为什么定时中断不是外部中断却能唤醒停止模式的问题//add 20200713】

 

以上信息来自《CM3权威指南》13.2节电源管理

(FCLK是自由运行时钟,因为不来自系统时钟HCLK,所以再系统停止时FCLK也能继续运行)

问题二:成功进入休眠并退出后,串口打印失败

原因:

       退出停止模式后,其他时钟还是保持原来的配置(原来我的配置是以外部高速时钟HSE不分频作为PLL时钟源,再经过9倍频得到,即72MHz,然后PLL作为系统时钟源,系统时钟一分频得到AHB总线时钟,AHB再 一分频作为高速总线时钟PCLK2,也就是72MHz,USART1用的就是高速总线时钟),这些配置是不会变的,但是退出停止模式后,内部高速时钟(HSI)默认变成了系统时钟源,造成时钟紊乱。

【其实不仅仅是串口,其他在进入停止模式之前的外设在退出停止模式之后都会工作不正常,重新配置系统时钟即可】

 

问题三:进入停止模式后整个电流还是很大

1.根据设备原理图查看IO外部引脚连接电路,闲置状态为低电平时,设置为下拉输入;闲置状态为高电平时,设置为上拉输入;闲置状态为悬空时设置为模拟输入;输出引脚根据功能需要设置就行

原因:当IO通过外围电路电阻接地被拉低时,如果设置为上拉输入,则在芯片内部的上拉电阻和外围的下拉电阻构成回路,电流损耗取决于这两个电阻;当IO通过外围电路电阻接电源被拉高时,则在芯片内部的下拉电阻和外围的上拉电阻构成回路,电流损耗也取决于这两个电阻;当悬空时,斯密特触发器是打开的,要判断输入的是高电平还是低电平,需要一点电流损耗,但是设备模拟输入,这个触发器是关闭的

2.排查外围电路,某些驱动、电源转换IC如果是由软件使能,如果进入停止模式之后不需要则关闭,因为本身就有工作电流;如果是由硬件使能,则需要查看芯片手册看静态工作电流是多少,如果比较高,只能修改硬件电路或者用低耗ic代替

3.外围是否有一些闭合回路,比如电压采集,虽然ADC已经关闭,但是这个分压电路还是有损耗的,大小一般取决于电阻和电源电压

4.另外如果在线调试时,进入停止模式后,调试失去作用,看看是不是SWDIO、SWCLK两个引脚也直接设置成了模拟输入,还关闭了调试功能:GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);

5.设备运行时开启的外设功能,视情况关闭,可以依次关闭看电流减小情况,并和数据手册做对比(要先关功能,再失能对应外设时钟,否则会关闭不成功,会有电流损耗,试验图1就是以为关闭了ADC,实际没关闭成功的情况,最后为板子总电流为74uA)

 

RTC唤醒停止模式

外部中断功能已经实现,项目需求中另外还需要定时唤醒,现在选用RTC唤醒

EXTI有20个中断/事件线,每个GPIO都能被设置为输入线,占用EXTI0-EXTI15,有4根用于特定的外设事件触发

所以RTC的闹钟事件就能触发EXTI17中断(这就是为什么进入停止模式设置的是中断唤醒,但还能用RTC闹钟事件唤醒的原因,本质还是被外部中断唤醒)

全功能代码不需要改,在进入停止模式之前配置EXTI17中断,配置闹钟事件

/**************************************1.配置EXTI17中断*********************************/

    EXTI_ClearITPendingBit(EXTI_Line17);                //注意先清掉标志位,要不然可能会出现停止模式被忽略进                                                                                                                //入不了的问题,上面问题一截图有说明
    EXTI_InitStructure.EXTI_Line = EXTI_Line17;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

 

/**************************************2.配置中断控制器闹钟事件优先级*********************************/

    NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn;   //RTC在最开始初始化的时候是秒中断,这里添加闹钟事件

                                                                                                    //中断,此时RTC秒钟秒中断和闹钟事件中断同时开启
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    
    NVIC_Init(&NVIC_InitStructure);

 

/**************************************3.设置闹钟时间,sec即想要唤醒的时间间隔*********************************/

    RTC_SetAlarm(RTC_GetCounter() + sec);     //用RTC_SetAlarm()函数配置闹钟时间,当计数器的值与闹钟寄存器的

                                                                            //值相等时,可产生闹钟事件或中断
    RTC_WaitForLastTask();                                 //等待确保已成功修改RTC寄存器
    RTC_ITConfig(RTC_IT_ALR, ENABLE);        //使能闹钟事件   
    RTC_WaitForLastTask();

以上三步在将要进入停止模式之前执行。

 

/**************************************RTC中断函数*********************************/

void RTC_IRQHandler(void)
{
    if (RTC_GetITStatus(RTC_IT_SEC) != RESET)         //秒钟中断
    {                            
        RTC_GetTime(&SystemTime);                               //更新时间(项目需要)   
        RTC_ClearITPendingBit(RTC_IT_SEC);    
        RTC_WaitForLastTask();
     }
    if(RTC_GetITStatus(RTC_IT_ALR) != RESET)            //闹钟中断    
    {
        RTC_ClearITPendingBit(RTC_IT_ALR);                   //清中断
        RTC_WaitForLastTask();
    }
}

void RTCAlarm_IRQHandler(void)
{
    EXTI_ClearITPendingBit(EXTI_Line17);                      //闹钟事件发生,会产生一个EXTI_17外部中断,此标志位要清除,否                                                                                             //则下次停止模式进入失败,原因见问题一贴图
}

 

【补充】:1.每次进入停止模式之前,都重新执行最开始的三步配置,否则可能出现前几次闹钟事件会触发,后面触发失败的问                       题。

                  2.停止模式唤醒之后,需要重新初始化系统时钟,这时候可以把闹钟中断关闭(因为进入之前会重新开启,避免没有                       进入 停止模式时一直有闹钟事件产生)

 

STM32进入Standby模式请参考:STM32进入Standby模式

 

以上为个人实验总结,不对之处还希望指正

原创文章,转载请注明出处:https://mp.csdn.net/postedit/85785336

 

 

 

 

 

 

  • 45
    点赞
  • 207
    收藏
    觉得还不错? 一键收藏
  • 29
    评论
### 回答1: STM32Stop模式是一种低功耗模式,可以降低芯片的功耗以延长电池寿命。在Stop模式下,芯片的大部分功能都被关闭,只有一些必要的模块继续工作。 在使用HAL库实现Stop模式唤醒时,可以按照以下步骤进行: 1. 配置待唤醒的外设:使用HAL库提供的相应函数对需要唤醒的外设进行配置,如GPIO、外部中断等。确保外设能够唤醒芯片。 2. 配置唤醒源:使用HAL库提供的函数对Stop模式唤醒源进行配置。常见的唤醒源包括外部中断、RTC闹钟、唤醒定时器等。根据实际需求选择相应的唤醒源,并配置相应的参数。 3. 进入Stop模式:调用HAL库提供的函数将芯片进入Stop模式。可以选择进入低功耗或深度睡眠模式。 4. 唤醒处理:当外部事件触发唤醒源后,芯片将会被唤醒并执行唤醒后的处理。可以使用中断的方式处理唤醒事件,或者在主循环中轮询检测唤醒事件。 5. 恢复外设和时钟:在芯片被唤醒后,需要重新配置和使能之前被关闭的外设和时钟。使用HAL库提供的相应函数对外设和时钟进行恢复。 需要注意的是,在Stop模式下芯片的工作频率会降低,因此需要重新校准外部设备(如外部晶振)的时钟。 通过以上步骤,就可以使用HAL库实现STM32Stop模式唤醒。在低功耗要求较高的应用中,采用Stop模式进行合理的功耗管理可以达到较高的电池寿命。 ### 回答2: STM32Stop模式是一种功耗较低的模式,在这种模式下,系统会停止运行,只保留必要的模块以维持一些基本功能。当需要唤醒系统时,HAL库提供了一种方便的方法。 首先,我们需要在使用Stop模式前进行一些初始化设置。我们可以调用HAL_PWR_EnterSTOPMode函数,将系统设置为Stop模式。在进入Stop模式前,我们需要关闭不需要的外设以降低功耗,例如关闭闹钟、定时器、串口等。同时,我们还需要配置唤醒源,以决定何时唤醒系统。 在停止模式下,系统处于低功耗状态,只有唤醒源被触发时,才能唤醒系统。当唤醒源被触发时,系统会从Stop模式中恢复。在STM32中,常见的唤醒源有外部中断、定时器中断、RTC闹钟中断等。我们可以使用HAL库提供的相应函数来配置唤醒源,例如HAL_PWR_EnableWakeUpPin函数用于配置外部中断唤醒。 当唤醒源被触发后,我们需要进行一些必要的操作以恢复系统。例如重新初始化各个外设,开启必要的中断以实现相应功能。然后,我们可以调用HAL_PWR_DisableWakeUpPin函数来关闭唤醒源,并将系统从Stop模式恢复到正常运行模式。 通过调用HAL库提供的相关函数,我们可以很方便地实现STM32Stop模式唤醒功能。这种低功耗模式在一些对功耗有严格要求的应用中非常有用,能够有效地延长系统的电池寿命。 ### 回答3: STM32Stop模式是一种低功耗模式,可以使MCU进入待机状态以减少能耗。HAL库是STM32的一个开发库,使用它可以简化MCU的编程过程。 在使用HAL库实现STM32Stop模式唤醒时,需要以下几个步骤: 1. 配置RCC时钟:首先需要配置RCC (Reset and Clock Control)模块来启用所需的外设时钟。具体配置内容包括使能所需外设时钟,设置系统时钟源等。 2. 配置唤醒源:在进入Stop模式前,需要配置唤醒源以确定如何唤醒MCU。唤醒源可以是外部中断、定时器中断、低功耗定时器中断等。可以使用HAL库提供的相应函数进行配置。 3. 进入Stop模式:调用相应的HAL库函数进入Stop模式。在进入Stop模式前,需要进行一些准备工作,如关闭不需要的外设、保存必要的数据和状态等。然后调用HAL库提供的函数,将MCU设置为Stop模式。 4. 唤醒处理:当满足唤醒条件时,MCU会从Stop模式唤醒唤醒后,需要进行一些处理,如重新使能外设时钟、恢复保存的数据和状态等。可以使用HAL库提供的相应函数完成这些处理。 需要注意的是,在使用HAL库实现Stop模式唤醒时,需要对不同型号的STM32芯片进行不同的配置和操作。具体的配置和操作方法可以参考相关的官方文档和参考资料。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值