[STM32L0] stm32l051怎样进入停机模式

[复制链接]
7995|9
 楼主| 240011814 发表于 2015-12-24 15:11 | 显示全部楼层 |阅读模式
如题
我用HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
发现程序还在运行
就试了下HAL_PWR_EnterSTANDBYMode();
发现单片机给玩坏了,拉高nrst程序还是不运行,程序也下不进去
zhuotuzi 发表于 2015-12-24 15:46 | 显示全部楼层
折腾了一天,静下来把整个过程理理。

本次软件运行ARM-Context3架构STM32F103XXX

项目需求:系统在某个条件下进入省电模式,可以通过外部信号唤醒:一、外部震动传感器,一、串口

当前也有省电模式,但直接进入了待机省电模式,在该模式下只能通过震动传感器唤醒,无法通过串口唤醒。要同时满足震动传感器以及串口唤醒,在现有方案上有两种方式:

-、将串口的发送信号(ARM的接收)通过电子开关接到外部震动传感器的输入端

-、省电模式改成串口可唤醒的停机模式

第一种方式硬件改动比较大,第二种方式则只需要修改软件。决定:升级软件

停机模式(STOP)

     有两种方式进入STOP,-、中断唤醒方式  -、事件唤醒方式,根据需求采用方式一

     退出STOP时直接从进入STOP的下一条指令开始运行,SRAM中的数据保留

进入STOP

首先需要设置好外部中断,这里有两个外部中断,代码如下:

EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource10);
//PA0配置
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//外部中断0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级为2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //从优先级 为1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);  
//PA10配置
EXTI_InitStructure.EXTI_Line = EXTI_Line10;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;//外部中断0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //从优先级 为2
NVIC_Init(&NVIC_InitStructure);
中断初始化完成后,就需要完成中断服务程序,如下:

void EXTI0_IRQHandler(void){
if(EXTI_GetITStatus(EXTI_Line0) != RESET){
    EXTI_ClearITPendingBit(EXTI_Line0);
    EXTI_ClearFlag(EXTI_Line0);  
}
}
//中断服务程序中似乎什么也没做,但EXTI_GetITStatus这几个接口必须有,否则无法唤醒

完成这些后就可以进入STOP了

PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
至于唤醒后该如何做,是要重新初始化还是干脆重新启动这就由设计人员自行决定了
zhuotuzi 发表于 2015-12-24 15:47 | 显示全部楼层
STOPMODE实验,本实验是正常情况下LED3不断闪烁,当按下按键2时,进入停止模式,LED3停止闪烁,当按下按键3时,退出停止模式,LED3开始不断闪烁。不过有几点值得奇怪,1是我的手还没有触碰到按键2,板子已经有反应了,LED3停止闪烁,按下按键2并退出后,LED3也开始不断闪烁,根本不用按下按键3来退出停止模式。我又做了这个唤醒的实验,采用不同的方式,是按键1来触发LED3,正常下,按下按键1,LED3变化。按下按键2进入停止模式,按下按键3退出停止模式,操作时,触摸程序也在运行,也出现了手还没有触碰到按键,板子就已经有反应了,奇怪了,,当按下按键2后,触屏程序停止运行,不能校准,不能手写,当按下按键3后,退出停止模式,此时能校准或者手写了。
奇了怪了,手还没有触碰到,就有反应了,这个问题要好好考虑考虑。。。。。难道我用的按键是矩形键盘,按键一头不是直接接GND的?还是其他?。。
zhuotuzi 发表于 2015-12-24 15:48 | 显示全部楼层
采用RTC报警功能来触发退出停止模式,LED2闪烁3次,共计3秒后退出停止模式。重复试验。。。。。。。。
  1. //STOPMODE设置初始化
  2. void STOPMODEG_Config(void)
  3. {
  4. EXTI_InitTypeDef EXTI_InitStructure;
  5. GPIO_InitTypeDef GPIO_InitStructure;
  6.    
  7.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
  8.   
  9.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  10.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  11.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  12.   GPIO_Init(GPIOE, &GPIO_InitStructure);


  13.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  14.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  15.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  16.   GPIO_Init(GPIOC, &GPIO_InitStructure);
  17.   GPIO_ResetBits(GPIOE, GPIO_Pin_2);
  18.   GPIO_SetBits(GPIOC, GPIO_Pin_2);

  19.   GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource2);

  20.   EXTI_InitStructure.EXTI_Line = EXTI_Line2;
  21.   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  22.   //EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
  23.   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  24.   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  25.   EXTI_Init(&EXTI_InitStructure);
  26.    
  27.   EXTI_ClearITPendingBit(EXTI_Line17);
  28.   EXTI_InitStructure.EXTI_Line = EXTI_Line17;
  29.   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  30.   EXTI_Init(&EXTI_InitStructure);   
  31.   RTC_Configuration();

  32.   GPIO_SetBits(GPIOD, GPIO_Pin_6);

  33.   GPIO_ResetBits(GPIOD, GPIO_Pin_3);
  34.   GPIO_ResetBits(GPIOB, GPIO_Pin_5);
  35.   GPIO_ResetBits(GPIOD, GPIO_Pin_6);
  36.   GPIO_ResetBits(GPIOD, GPIO_Pin_3);
  37. }

  38. void RTC_Configuration(void)
  39. {


  40.   PWR_BackupAccessCmd(ENABLE);

  41.   BKP_DeInit();


  42.   RCC_LSEConfig(RCC_LSE_ON);

  43.   while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
  44.   {
  45.   }

  46.   RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

  47.   RCC_RTCCLKCmd(ENABLE);


  48.   RTC_WaitForSynchro();

  49.   RTC_SetPrescaler(32767);

  50.   RTC_WaitForLastTask();

  51.   RTC_ITConfig(RTC_IT_ALR, ENABLE);

  52.   RTC_WaitForLastTask();
  53. }

  54. void SYSCLKConfig_STOP(void)
  55. {

  56.   RCC_HSEConfig(RCC_HSE_ON);

  57.   HSEStartUpStatus = RCC_WaitForHSEStartUp();
  58.   if(HSEStartUpStatus == SUCCESS)
  59.   {
  60.    
  61.     RCC_PLLCmd(ENABLE);
  62.    
  63.     while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
  64.     {
  65.     }
  66.    
  67.     RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
  68.    
  69.     while(RCC_GetSYSCLKSource() != 0x08)
  70.     {
  71.     }
  72.   }
  73. }
  74. void TEST_STOPMODE(void)
  75. {
  76.    
  77.     Tic_Delay(1500);
  78.    
  79.     RTC_ClearFlag(RTC_FLAG_SEC);
  80.     while(RTC_GetFlagStatus(RTC_FLAG_SEC) == RESET);
  81.    
  82.     RTC_SetAlarm(RTC_GetCounter()+ 3);
  83.    
  84.     RTC_WaitForLastTask();
  85.    
  86.     GPIO_SetBits(GPIOD, GPIO_Pin_3);
  87.    
  88.     GPIO_ResetBits(GPIOD, GPIO_Pin_6);
  89.    
  90.     PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);
  91.    
  92.    
  93.    
  94.     GPIO_SetBits(GPIOD, GPIO_Pin_6);
  95.    
  96.     SYSCLKConfig_STOP();
  97.    
  98.     GPIO_ResetBits(GPIOD, GPIO_Pin_3);
  99. }

以上为STOP子程序代码。。。。。。。。在主程序中运行TEST_STOPMODE();即可。

 楼主| 240011814 发表于 2015-12-24 17:20 | 显示全部楼层
while(1)
{
   LedOff();
   HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
   SystemClock_Config();
   LedOn();
}
灯一直亮
 楼主| 240011814 发表于 2015-12-24 17:56 | 显示全部楼层
               HAL_Delay(1000);
                LedOff();
        //        HAL_NVIC_DisableIRQ(SysTick_IRQn);
                HAL_SuspendTick();
                HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
                HAL_ResumeTick();
                SystemClock_Config();
                LedOn();
现在可以进入stop模式但醒不来了,用的是外部中断
lwsn 发表于 2015-12-24 21:01 | 显示全部楼层

F0的固件库里有从STOP模式唤醒的例程的吧
mintspring 发表于 2015-12-24 21:11 | 显示全部楼层
  1. //定义IO初始化结构体
  2. GPIO_InitTypeDef GPIO_InitStructure;
  3.    
  4. //设置zigbee模块进入低功耗模式
  5. inf_zigbee_sleep();
  6.    
  7. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
  8.                        RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD ,ENABLE);
  9.    
  10. //管脚初始化  
  11. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
  12. //选择GPIO响应速度
  13. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
  14. //设置为输出           
  15. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  16. //初始化                           
  17. GPIO_Init(GPIOA, &GPIO_InitStructure);  
  18. GPIO_Init(GPIOB, &GPIO_InitStructure);
  19. GPIO_Init(GPIOC, &GPIO_InitStructure);
  20. GPIO_Init(GPIOD, &GPIO_InitStructure);
  21.    
  22. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
  23.                            RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD ,DISABLE);
  24.    
  25. ADC_Cmd(ADC1,DISABLE);
  26. //进入低功耗模式
  27. PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
注意:
1.将IO置为模拟输入
2.关闭ADC
理论功耗:14ua
实测功耗:12ua

 楼主| 240011814 发表于 2015-12-25 17:55 | 显示全部楼层
发现了我中断里用了延时函数,但 HAL_ResumeTick();还没恢复所以造成我以为一直没唤醒
zhuotuzi 发表于 2015-12-25 22:11 | 显示全部楼层
找到了问题,解决就好,下次就知道了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

70

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部