打印
[STM32L0]

stm32l051怎样进入停机模式

[复制链接]
7445|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秒后退出停止模式。重复试验。。。。。。。。
//STOPMODE设置初始化
void STOPMODEG_Config(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
   
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOE, &GPIO_InitStructure);


  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
  GPIO_ResetBits(GPIOE, GPIO_Pin_2);
  GPIO_SetBits(GPIOC, GPIO_Pin_2);

  GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource2);

  EXTI_InitStructure.EXTI_Line = EXTI_Line2;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  //EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
   
  EXTI_ClearITPendingBit(EXTI_Line17);
  EXTI_InitStructure.EXTI_Line = EXTI_Line17;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  EXTI_Init(&EXTI_InitStructure);   
  RTC_Configuration();

  GPIO_SetBits(GPIOD, GPIO_Pin_6);

  GPIO_ResetBits(GPIOD, GPIO_Pin_3);
  GPIO_ResetBits(GPIOB, GPIO_Pin_5);
  GPIO_ResetBits(GPIOD, GPIO_Pin_6);
  GPIO_ResetBits(GPIOD, GPIO_Pin_3);
}

void RTC_Configuration(void)
{


  PWR_BackupAccessCmd(ENABLE);

  BKP_DeInit();


  RCC_LSEConfig(RCC_LSE_ON);

  while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
  {
  }

  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

  RCC_RTCCLKCmd(ENABLE);


  RTC_WaitForSynchro();

  RTC_SetPrescaler(32767);

  RTC_WaitForLastTask();

  RTC_ITConfig(RTC_IT_ALR, ENABLE);

  RTC_WaitForLastTask();
}

void SYSCLKConfig_STOP(void)
{

  RCC_HSEConfig(RCC_HSE_ON);

  HSEStartUpStatus = RCC_WaitForHSEStartUp();
  if(HSEStartUpStatus == SUCCESS)
  {
   
    RCC_PLLCmd(ENABLE);
   
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {
    }
   
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
   
    while(RCC_GetSYSCLKSource() != 0x08)
    {
    }
  }
}
void TEST_STOPMODE(void)
{
   
    Tic_Delay(1500);
   
    RTC_ClearFlag(RTC_FLAG_SEC);
    while(RTC_GetFlagStatus(RTC_FLAG_SEC) == RESET);
   
    RTC_SetAlarm(RTC_GetCounter()+ 3);
   
    RTC_WaitForLastTask();
   
    GPIO_SetBits(GPIOD, GPIO_Pin_3);
   
    GPIO_ResetBits(GPIOD, GPIO_Pin_6);
   
    PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);
   
   
   
    GPIO_SetBits(GPIOD, GPIO_Pin_6);
   
    SYSCLKConfig_STOP();
   
    GPIO_ResetBits(GPIOD, GPIO_Pin_3);
}

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

使用特权

评论回复
5
240011814|  楼主 | 2015-12-24 17:20 | 只看该作者
while(1)
{
   LedOff();
   HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
   SystemClock_Config();
   LedOn();
}
灯一直亮

使用特权

评论回复
6
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模式但醒不来了,用的是外部中断

使用特权

评论回复
7
lwsn| | 2015-12-24 21:01 | 只看该作者

F0的固件库里有从STOP模式唤醒的例程的吧

使用特权

评论回复
8
mintspring| | 2015-12-24 21:11 | 只看该作者
//定义IO初始化结构体
GPIO_InitTypeDef GPIO_InitStructure;
   
//设置zigbee模块进入低功耗模式
inf_zigbee_sleep();
   
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
                       RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD ,ENABLE);
   
//管脚初始化  
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
//选择GPIO响应速度
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
//设置为输出           
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
//初始化                           
GPIO_Init(GPIOA, &GPIO_InitStructure);  
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_Init(GPIOD, &GPIO_InitStructure);
   
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
                           RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD ,DISABLE);
   
ADC_Cmd(ADC1,DISABLE);
//进入低功耗模式
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
注意:
1.将IO置为模拟输入
2.关闭ADC
理论功耗:14ua
实测功耗:12ua

使用特权

评论回复
9
240011814|  楼主 | 2015-12-25 17:55 | 只看该作者
发现了我中断里用了延时函数,但 HAL_ResumeTick();还没恢复所以造成我以为一直没唤醒

使用特权

评论回复
10
zhuotuzi| | 2015-12-25 22:11 | 只看该作者
找到了问题,解决就好,下次就知道了。

使用特权

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

本版积分规则

17

主题

70

帖子

3

粉丝