打印

STM32睡眠模式的唤醒 讨论

[复制链接]
19135|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
手册上说睡眠是可以用任何一个中断唤醒的,那么我想着应该包括ADC和串口,至于timer能不能唤醒,我想是不能的,应为timer是在cpu内部的,进入睡眠之后就会关闭内核,timer肯定也会关闭的。
在工程中加入.c文件,stm32f10x_pwr.c,这里里面包含着关于PWR的各种操作函数,主程序中加入头文件stm32f10x_pwr.h。
main函数中首先开启PWR时钟:RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);   
然后初始化PWR。我调用的语句是:PWR_DeInit();
PWR_BackupAccessCmd(DISABLE);
然后期望进入睡眠状态,语句是:SCB->SCR |= SCB_SCR_SLEEPDEEP;
__WFI();
  SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
(这是在网上搜到的。设置sleepdeep位,然后执行_WFI指令)


现在应该已经进入睡眠状态了吧??我后面定义了ADC的装换结束中断,ADC是以软件方式开启转换,独立非连续转换,所以是转换一次,中断一次,再在主程序中软件出发一次,如此往复。但是进入睡眠之后就一动不动,没法唤醒,请高手帮忙解答一下,我们讨论讨论。谢谢
沙发
香水城| | 2012-2-22 15:28 | 只看该作者
请LZ看看ST的手册和固件库的例程,没有"设置sleepdeep位,然后执行_WFI指令"这个说法。

使用特权

评论回复
板凳
香水城| | 2012-2-22 15:30 | 只看该作者
这是ST手册中的列表,细节你可以自己看看。

STM32_Low_Power_Mode.GIF (27.41 KB )

STM32_Low_Power_Mode.GIF

使用特权

评论回复
地板
wudingzhiying|  楼主 | 2012-2-22 17:43 | 只看该作者

没有"设置sleepdeep位,然后执行_WFI指令"这个说法

2# 香水城
、谢谢你的提醒。这个确实是我自己理解错误了。 这个地方应该是让SLEEPDEEP=0,而不是置位,谢谢。

使用特权

评论回复
5
wudingzhiying|  楼主 | 2012-2-22 17:50 | 只看该作者
3# 香水城
谢谢。
虽然这个表中说执行WFI或者WFE都能进入sleep模式,但是我看在固件库中无论是void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry);还是void PWR_EnterSTANDBYMode(void);里面都有设置SLEEPDEEP位的语句:

那是不是可以说睡眠模式和停止模式,待机模式是不一样的?因为一个是保证SLEEPDEEP位为0,而后面两种是置位这一位?请赐教
谢谢

使用特权

评论回复
6
香水城| | 2012-2-22 18:18 | 只看该作者
参考3楼的表格:

睡眠模式 对应 SLEEP
停止模式 对应 STOP
待机模式 对应 Standby

他们显然是不一样的。

使用特权

评论回复
7
240899105lcq| | 2013-6-4 17:35 | 只看该作者
你好,想问下楼主,你的睡眠可以退出吗?我的也退不出来

使用特权

评论回复
8
zeluo| | 2013-6-4 18:29 | 只看该作者
还是版主给力   不错   顶一个

使用特权

评论回复
9
mingjiezhong| | 2013-10-19 18:03 | 只看该作者
我也正好要搞这个,参考一下,按照BSP库里的写法,在执行WFI 前要开中断,还要允许唤醒

使用特权

评论回复
10
trumpxp| | 2013-10-19 19:58 | 只看该作者
还是不是很熟悉技术手册   将技术手册仔细钻研钻研   应该就出来了  楼主

使用特权

评论回复
11
wilson970| | 2014-5-8 20:05 | 只看该作者
我调了一个RTC ALARM 唤醒,发现简单测试可以运行很好,但当程序开始执行大量的任务就老是不灵了,很奇怪。我用的是每秒中断苏醒一次,感觉STM32用起来没其他芯片顺。

使用特权

评论回复
12
icecut| | 2014-5-9 10:06 | 只看该作者
我怀疑你吧adc时钟之类的搞停了..不在转换,当然没有中断

使用特权

评论回复
13
yu515301489| | 2015-8-17 09:52 | 只看该作者
不要忘记清中断 配置好唤醒的触发

使用特权

评论回复
14
yangchao1117yc| | 2015-12-23 23:17 | 只看该作者
wilson970 发表于 2014-5-8 20:05
我调了一个RTC ALARM 唤醒,发现简单测试可以运行很好,但当程序开始执行大量的任务就老是不灵了,很奇怪。 ...

你好,有例程 stm32 睡眠唤醒 例程么,分享下。

使用特权

评论回复
15
yushan210| | 2016-1-7 13:30 | 只看该作者
加油

使用特权

评论回复
16
jjjkkk00| | 2016-1-7 13:50 | 只看该作者
找了一下,我这边只有以前测试用的《待机模式》 和《停止模式》的代码。
将就的参考下吧,年代比较久远了。呵呵
/**
  ******************************************************************************
  * [url=home.php?mod=space&uid=288409]@file[/url] /PWR_STANDBY.h
  * [url=home.php?mod=space&uid=187600]@author[/url]    xd.wu
  * [url=home.php?mod=space&uid=895143]@version[/url]   V1.0
  * [url=home.php?mod=space&uid=212281]@date[/url]     2012-4-19
  * [url=home.php?mod=space&uid=247401]@brief[/url]    PWR:待机模式
  WFE事件  新来的中断、之前悬起的中断等(比较容易唤醒)
  WFI中断  
  ******************************************************************************
  *用途:
  3.待机模式:可实现系统的最低功耗
    进入:
      设置CM3系中的SLEEPDEEP位 , PWR_CR中设置PDDS位 , CWUF位
      然后执行WFI(等待中断)或WFE(等待事件)指令
    唤醒:WKUP引脚的上升沿、RTC闹钟事件、NRST引脚上的外部复位、IWDG复位
    唤醒延时:复位阶段时电压调节器的启动

  SCB->SCR[4:0] == SEVONPEND,0,SLEEPDEEP,SLEEPONEXIT,0
  */
  /*实例应用步骤:
  //1."main.cpp"调用fmain()
  
  //2."stm32f10x_it.cpp"拷贝
  void SysTick_Handler(void)
  {
    #if defined __PWR_STANDBY
      GPIO_WriteBit(GPIOF, GPIO_Pin_6, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOF, GPIO_Pin_6)));
    #endif
  }
  void EXTI15_10_IRQHandler(void)
  {
    if(EXTI_GetITStatus(EXTI_Line11) != RESET)
    {
      #if defined __PWR_STANDBY
        GPIO_SetBits(GPIOF, GPIO_Pin_6);
        RTC_ClearFlag(RTC_FLAG_SEC);
        while(RTC_GetFlagStatus(RTC_FLAG_SEC) == RESET);// Wait till RTC Second event occurs
        RTC_SetAlarm(RTC_GetCounter()+ 3);// Set the RTC Alarm after 3s
        RTC_WaitForLastTask();
        //PWR_EnterSTANDBYMode();
        SCB->SCR |= 0x00000004;//SLEEPDEEP = 1
        PWR->CR |= 0x006;//PWR_CR中设置PDDS位 , CWUF位
        __WFE();
      #endif
      EXTI_ClearITPendingBit(EXTI_Line11);
    }
  }
  
  //3."stm32f10x_it.h"声明
  #define __PWR_STANDBY
  void EXTI15_10_IRQHandler(void);
  void SysTick_Handler(void);
  
  //4.Watch中观察
  LED绿灯闪烁
  按下Sel后进入待机模式,3s后RTC闹钟唤醒,黄灯点亮
  */

#ifndef __PWR_STANDBY_H
#define __PWR_STANDBY_H
/* Includes ------------------------------------------------------------------*/
#include "std32periph.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
  #define GPIO_LED      GPIOF   
  #define RCC_LED       RCC_APB2Periph_GPIOF
  #define RCC_EXTI      RCC_APB2Periph_GPIOB
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

void RTC_Configuration(void)
{
  if(PWR_GetFlagStatus(PWR_FLAG_SB) != RESET)/* System resumed from STANDBY mode */
  {
   
    GPIO_SetBits(GPIO_LED, GPIO_Pin_7);

    /* Clear StandBy flag */
    PWR_ClearFlag(PWR_FLAG_SB);

    RTC_WaitForSynchro();
  }
  else
  {
    /* StandBy flag is not set */
    /* RTC clock source configuration ----------------------------------------*/
    BKP_DeInit();
  
    RCC_LSEConfig(RCC_LSE_ON);
    while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
    {
    }

    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
    RCC_RTCCLKCmd(ENABLE);

    /* RTC configuration -----------------------------------------------------*/
    RTC_WaitForSynchro();
    /* Set the RTC time base to 1s */
    RTC_SetPrescaler(32767);  
    RTC_WaitForLastTask();
  }
}

void fmain(void)
{
  RCC_HSEConf(9);//72M
  
  RCC_APB2PeriphClockCmd(RCC_EXTI | RCC_LED | RCC_APB2Periph_AFIO, ENABLE);
  
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIO_LED, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOB, &GPIO_InitStructure);  

  GPIO_SetBits(GPIO_LED, GPIO_Pin_6);
  
  
  /* Enable PWR and BKP clock */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
  /* Enable WKUP pin */
  PWR_WakeUpPinCmd(ENABLE);
  /* Allow access to BKP Domain */
  PWR_BackupAccessCmd(ENABLE);

  /* Configure RTC clock source and prescaler */
  RTC_Configuration();

  /* Configure EXTI Line to generate an interrupt on falling edge */
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource11);
  EXTI_InitTypeDef EXTI_InitStructure;
  EXTI_InitStructure.EXTI_Line = EXTI_Line11;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);  

  NVIC_GroupSet(NVIC_PriorityGroup_0, EXTI15_10_IRQn, 1);

  /* Configure SysTick to generate an interrupt each 250ms */
  SysTick->LOAD = 250000*9;
  SysTick->VAL = 0x00;//清空计数器
  /* ---------------------------------------------------------------------
  SysTick 控制与状态寄存器的位
  SysTick->CTRL: CountFlag【16】,CLKSource【2】,TickINT【1】,ENABLE【0】
  --------------------------------------------------------------------- */
  //CLKSource【2】=0  使用外部时钟源HCLK(1:内核时钟HCLK/8)
  //  TickINT【1】=0  向下计数至0,不会挂起Systick(1:至0会挂起Systick)
  //   ENABLE【0】=0  禁止计数器(1:使能,至0将CountFlag置1)
  SysTick->CTRL = 0x00003;
}

#endif
/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/

使用特权

评论回复
17
jjjkkk00| | 2016-1-7 13:51 | 只看该作者
下面这个是STOP模式。
/**
  ******************************************************************************
  * @file /PWR_STOP.h
  * @author    xd.wu
  * @version   V1.0
  * @date     2012-4-19
  * @brief    PWR:停机模式
  WFE事件  新来的中断、之前悬起的中断等(比较容易唤醒)
  WFI中断  
  ******************************************************************************
  *用途:
  2.停机模式
    进入:
      设置CM3中的SLEEPDEEP位 , PWR_CR中清除PDDS位 , 设置LPDS位
      然后执行WFI(等待中断)或WFE(等待事件)指令
    唤醒:任意外部中断可唤醒
    唤醒延时:HSI RC唤醒时间 + 电压调节器从低功耗唤醒的时间

  SCB->SCR[4:0] == SEVONPEND,0,SLEEPDEEP,SLEEPONEXIT,0
  */
  /*实例应用步骤:
  //1."main.cpp"调用fmain()
  
  //2."stm32f10x_it.cpp"拷贝
  #ifdef  __PWR_STOP
  void RTCAlarm_IRQHandler(void)
  {
    if(RTC_GetITStatus(RTC_IT_ALR) != RESET)
    {
      GPIO_WriteBit(GPIOF, GPIO_Pin_8, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOF, GPIO_Pin_8)));
  
      EXTI_ClearITPendingBit(EXTI_Line17);
  
      if(PWR_GetFlagStatus(PWR_FLAG_WU) != RESET)
      {
        PWR_ClearFlag(PWR_FLAG_WU);
      }
  
      RTC_WaitForLastTask();   
  
      RTC_ClearITPendingBit(RTC_IT_ALR);
  
      RTC_WaitForLastTask();
    }
  }
  #endif
  
  //3."stm32f10x_it.h"声明
  #define __PWR_STOP
  void RTCAlarm_IRQHandler(void);
  
  //4.Watch中观察
  LED绿灯变化
  进入停机模式,3s后RTC闹钟唤醒,红灯点亮,循环
  */

#ifndef __PWR_STOP_H
#define __PWR_STOP_H
/* Includes ------------------------------------------------------------------*/
#include "std32periph.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
  #define GPIO_LED      GPIOF   
  #define RCC_LED       RCC_APB2Periph_GPIOF
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

void SYSCLKConfig_STOP(void)
{
  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON);

  /* Wait till HSE is ready */
  ErrorStatus HSEStartUpStatus;
  HSEStartUpStatus = RCC_WaitForHSEStartUp();

  if(HSEStartUpStatus == SUCCESS)
  {
    /* Enable PLL */
    RCC_PLLCmd(ENABLE);

    /* Wait till PLL is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {
    }

    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till PLL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08)
    {
    }
  }
}

void RTC_Configuration(void)
{
  /* RTC clock source configuration ------------------------------------------*/
  /* Reset Backup Domain */
  BKP_DeInit();
  
  /* Enable the LSE OSC */
  RCC_LSEConfig(RCC_LSE_ON);
  /* Wait till LSE is ready */
  while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
  {
  }

  /* Select the RTC Clock Source */
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

  /* Enable the RTC Clock */
  RCC_RTCCLKCmd(ENABLE);

  /* RTC configuration -------------------------------------------------------*/
  /* Wait for RTC APB registers synchronisation */
  RTC_WaitForSynchro();

  /* Set the RTC time base to 1s */
  RTC_SetPrescaler(32767);  
  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();

  /* Enable the RTC Alarm interrupt */
  RTC_ITConfig(RTC_IT_ALR, ENABLE);
  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();
}


void fmain(void)
{
  RCC_HSEConf(9);//72M
  
  RCC_APB2PeriphClockCmd(RCC_LED | RCC_APB2Periph_AFIO, ENABLE);
  
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIO_LED, &GPIO_InitStructure);


  /* Configure EXTI Line17(RTC Alarm) to generate an interrupt on rising edge */
  EXTI_ClearITPendingBit(EXTI_Line17);
  EXTI_InitTypeDef EXTI_InitStructure;
  EXTI_InitStructure.EXTI_Line = EXTI_Line17;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);

  
  /* Enable PWR and BKP clock */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
  /* Allow access to BKP Domain */
  PWR_BackupAccessCmd(ENABLE);
  /* Configure RTC clock source and prescaler */
  RTC_Configuration();


  NVIC_GroupSet(NVIC_PriorityGroup_0, RTCAlarm_IRQn, 0);

  GPIO_SetBits(GPIO_LED, GPIO_Pin_6);
  
  while (1)
  {
    /* Insert 1.5 second delay */
    Delay_us(1.5e6, 72);

   
    RTC_ClearFlag(RTC_FLAG_SEC);
    while(RTC_GetFlagStatus(RTC_FLAG_SEC) == RESET);

    RTC_SetAlarm(RTC_GetCounter()+ 3);
    RTC_WaitForLastTask();


    GPIO_ResetBits(GPIO_LED, GPIO_Pin_6);


    //PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
    RCC->APB1ENR |= 0x10000000;//PWREN:电源接口时钟使能
    SCB->SCR |= 0x00000004;//SLEEPDEEP = 1
    PWR->CR &= 0x1FD;//PWR_CR中清除PDDS位 , 设置LPDS位
    PWR->CR |= 0x001;
    __WFI();
   

    GPIO_SetBits(GPIO_LED, GPIO_Pin_6);

    SYSCLKConfig_STOP();
  }
}

#endif
/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/

使用特权

评论回复
18
jjjkkk00| | 2016-1-7 13:55 | 只看该作者
顺便说下,当时的测试环境是STM32F103E的万利开发板。
测试功能可用。实际应用时建议对代码优化。

使用特权

评论回复
19
小小飞行器| | 2016-1-23 17:37 | 只看该作者
现在有睡眠模式的好东西吗??不妨分享一下

使用特权

评论回复
20
dongnanxibei| | 2016-1-30 11:30 | 只看该作者
睡眠模式 对应 SLEEP
停止模式 对应 STOP
待机模式 对应 Standby

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

10

帖子

0

粉丝