zoukankan      html  css  js  c++  java
  • STM32F0的低功耗模式

    STM32的低功耗模式有三种, STOP, SLEEP, STANDBY.

    其中SLEEP没啥用, 好处是一戳就醒.

    最低功耗是STANDBY模式, 据说只有2ua电流, 但是每次醒来, 就相当于重启了, SRAM全重置, 另外一个坏处是需要指定一个PA0脚, 即WAKEUP脚的上升沿唤醒.

    最好用的应该就是这个STOP模式, 寄存器跟SRAM都保存状态, 连IO都保持, 唤醒的方法是外部中断跟通讯, 通讯还没测试, 外部中断是ok了.

    进中断的方法很简单:

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
        PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_SLEEPEntry_WFI);

    但是之前要设置要外部中断, 比如一个按键:

         GPIO_InitTypeDef GPIO_InitStruct; 
         EXTI_InitTypeDef EXTI_InitStruct;
         NVIC_InitTypeDef NVIC_InitStruct;
    
         RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);              
                  
         GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12; 
         GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
         GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_2;
         GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; 
         GPIO_Init(GPIOB, &GPIO_InitStruct);
    
         SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource12);
    
         EXTI_ClearITPendingBit(EXTI_Line12);
                  
         EXTI_InitStruct.EXTI_Line = EXTI_Line12;
         EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
         EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; 
         EXTI_InitStruct.EXTI_LineCmd = ENABLE;
         EXTI_Init(&EXTI_InitStruct); 
    
         NVIC_InitStruct.NVIC_IRQChannel = EXTI4_15_IRQn;
         NVIC_InitStruct.NVIC_IRQChannelPriority = 0x01;
         NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
         NVIC_Init(&NVIC_InitStruct);
    

    为了防止醒来之后时钟的问题:

    void SYSCLKConfig_STOP(void)
    {  
      /* After wake-up from STOP reconfigure the system clock */
      /* Enable HSE */
      RCC_HSEConfig(RCC_HSE_ON);
      
      /* Wait till HSE is ready */
      while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET)
      {}
      
      /* 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)
      {}
    }
    

     结果这里发现一个问题, 我先是需要使用一个TIM来进行定时任务, 我的目标是, 如果系统空闲超过一段时间, 比如20秒, 就进入STOP模式, 结果发现在定时器的irq_hendle函数中, 无法进入低功耗, 没辙, 在main里面增加了一个全局变量, 用TIM将这个变量置, 在main的while循环中去进入STOP模式.

            if(ifGotoStop){
                printf("sleepy
    ");
    
                sysEnterStopMode();
                //System_Init();
                //TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
                SYSCLKConfig_STOP();
                printf("go out
    ");
                ifGotoStop = 0;
            }
    

    唤醒的按键中断(增加了去抖):

    void EXTI4_15_IRQHandler(void)
    { 		
    
        if(EXTI_GetITStatus(EXTI_Line12)!=RESET)  {
           
            while(TEST_KEY == RESET){
                timeCounter++;
            }
            if(timeCounter > 10000){
                printf("wake up! 
    ");
            }
            timeCounter = 0;
            //LED05_OFF;
    
        }  
    	EXTI_ClearITPendingBit(EXTI_Line12); 
    
    } 
    

    剩下的就是检查低功耗时候的电流, 以及增加串口输入的中断作为唤醒条件.

  • 相关阅读:
    codevs 5964 [SDOI2017]序列计数
    codevs 5963 [SDOI2017]树点染色
    【opencv】c++ 读取图片 & 绘制点 & 绘制文字 & 保存图片
    【opencv安裝】opencv2和opencv3共存——安装opencv2和opencv3到指定目录
    【opencv】cv::Mat_ 对单个元素赋值
    【opencv】projectPoints 三维点到二维点 重投影误差计算
    【opencv】cv::Mat转std::vector<cv::Point2d> (注意两容器中数据类型的一致性)
    高斯分布抽样
    射影变换、仿射变换、欧式变换、相似变换、等距变换
    【opencv】 solvepnp 和 solvepnpRansac 求解 【空间三维坐标系 到 图像二维坐标系】的 三维旋转R 和 三维平移 T 【opencv2使用solvepnp求解rt不准的问题】
  • 原文地址:https://www.cnblogs.com/Montauk/p/6889406.html
Copyright © 2011-2022 走看看