STM32學習心得二十二:低功耗待機喚醒實驗

記錄一下,方便以後翻閱~
主要內容:
1) STM32低功耗模式講解;
2) 寄存器和庫函數配置;
3) 實驗代碼解讀。
實驗功能:針對GPIOA,引腳0,啓動後系統進入待機模式,長按3秒待機喚醒,LED0和LED1閃爍,長按3秒進入待機模式,LED0和LED1滅。
官方資料:《STM32中文參考手冊V10》第4章——低功耗模式
1. 待機喚醒
很多單片機有低功耗模式,STM32也不例外。在系統或者電源復位後,微控制器處於運行狀態之下,HCLK爲CPU提供時鐘,內核執行代碼。當CPU不需要繼續運行時,可以利用多種低功耗模式來節省功耗,例如等待某個事件觸發。
2. 低功耗模式:
2.1 睡眠模式:內核停止,外設如NVIC,系統時鐘Systick仍運行;
2.2 停止模式:所有時鐘都已停止。1.8V內核電源工作。PLL,HIS和HSE RC振盪器功能禁止。寄存器和SRAM內容保留;
2.3 待機模式:1.8V內核電源關閉。只有備份寄存器和待機電路維持供電。寄存器和SRAM內容全部丟失。實現最低功耗。
功耗消耗排序:睡眠模式>停止模式>待機模式(功耗消耗最低)
2.4 運行模式下降低功耗的辦法:
2.4.1 降低系統時鐘;
2.4.2 關閉APB和AHB總線上未被使用的外設時鐘。
在這裏插入圖片描述用戶可根據電源消耗,最快啓動時間和可用的喚醒源等條件,選擇一種最佳的低功耗模式。
3. STM32的待機模式
在這裏插入圖片描述
待機模式理想狀態下,只需要2uA電流。停機模式下典型電流爲20uA。
4. 相關寄存器
4.1 PWR_CR電源控制寄存器:
在這裏插入圖片描述
4.1.1 設置PDDS位進入深度睡眠時進入待機模式;
4.1.2 設置CWUF位,清除之前的WUF喚醒位。
4.2 PWR_CSR電源控制/狀態寄存器:
在這裏插入圖片描述
4.1.1 設置EWUP,使能WKUP引腳用於待機模式喚醒;
4.1.2 WUF喚醒標誌,用來判斷是否發生喚醒事件。
5. 相關庫函數
5.1 官方文件爲stm32f10x_pwr.c / stm32f10x_pwr.h;
5.2 主要庫函數:

voidPWR_EnterSTOPMode();                           //進入停機模式
voidPWR_EnterSTANDBYMode(void);                    //進入待機模式
void PWR_WakeUpPinCmd(FunctionalState NewState);   //使能Wakeup引腳喚醒
FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG);
void PWR_ClearFlag(uint32_t PWR_FLAG);

6. 待機喚醒配置步驟:
6.1 使能電源時鐘。因爲要配置電源控制寄存器,所以必須先使能電源時鐘:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

6.2 設置WK_UP引腳作爲喚醒源。設置PWR_CSR的EWUP位,使能WK_UP用於將CPU從待機模式喚醒:

PWR_WakeUpPinCmd(ENABLE);  //使能喚醒管腳功能

6.3 設置SLEEPDEEP位,設置PDDS位,執行WFI指令,進入待機模式:

void PWR_EnterSTANDBYMode(void)

7. 程序思路
7.1 在待機模式下,WKUP用來喚醒。按下WKUP,就會從待機模式喚醒;
7.2 正常情況下(沒有進入低功耗模式),WKUP是可以作爲正常的輸入口,或者中斷觸發引腳來使用。
8. 相關實驗代碼解讀
8.1 wkup.h頭文件代碼

#ifndef __WKUP_H
#define __WKUP_H  
#include "sys.h"         
#define WKUP_KD PAin(0)        //位帶操作,WKUP_KD對應GPIOA_IDR的0位//
//三個函數//
u8 Check_WKUP(void);           //檢測WKUP腳的信號,返回u8格式數據//
void WKUP_Init(void);          //PA0 WKUP喚醒初始化//
void Sys_Enter_Standby(void);  //系統進入待機模式//
#endif

8.2 wkup.c文件代碼解讀

#include "wkup.h"
#include "led.h"
#include "delay.h"
//待機喚醒配置函數//  
void Sys_Standby(void)
{  
 //第一步,使能PWR外設時鐘//
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); 
 //第二步,設置PWR_CSR的EWUP位,使能WK_UP用於將CPU從待機模式喚醒//
 PWR_WakeUpPinCmd(ENABLE);  
 //第三步,進入待機模式//
 PWR_EnterSTANDBYMode();      
}
//系統進入待機模式//
void Sys_Enter_Standby(void)
{    
 RCC_APB2PeriphResetCmd(0X01FC,DISABLE);    //復位所有IO口
 Sys_Standby();
}
//檢測WKUP腳的信號,純C語言//
//返回值1:連續按下3s以上;0:錯誤的觸發// 
u8 Check_WKUP(void) 
{
 u8 t=0;                                    //記錄按下的時間//
 LED0=1;                                    //LED0滅// 
 LED1=1;                                    //LED1滅//
 while(1)
 {
  if(WKUP_KD)                               //WK_UP按鍵對應PA0,即按下時爲高電平//
  {
   t++;                                     //已經按下了// 
   LED0=!LED0;
   LED1=!LED1;
   delay_ms(30);   
   if(t>=100)                               //按下超過3秒鐘//
   {
    LED0=0;                                 //LED0亮// 
    LED1=0;                      
    return 1;                               //按下3s以上了//
   }
  }else 
  { 
   LED0=1;                                  //LED0滅//
   LED1=1;                                  //LED0滅//
   return 0;                                //按下不足3秒//
  }
 }
} 
//編寫外部中斷服務函數//
void EXTI0_IRQHandler(void)                 //因爲檢測PA0,所以用EXTI0//
{                            
 EXTI_ClearITPendingBit(EXTI_Line0);        //清除LINE0上的中斷標誌位//    
 if(Check_WKUP())                           //檢查WK_UP是否按下3s以上//
 {    
  Sys_Enter_Standby();                      //按下3s以上,系統進入待機模式//
 }
} 
//編寫WK_UP初始化函數//
void WKUP_Init(void)
{ 
 GPIO_InitTypeDef  GPIO_InitStructure;      
 NVIC_InitTypeDef  NVIC_InitStructure;
 EXTI_InitTypeDef  EXTI_InitStructure;
 //使能GPIOA和複用功能時鐘//
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
 //GPIOA,引腳0配置//
 GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0;                     //GPIOA,引腳0//
 GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPD;                 //上拉輸入//
 GPIO_Init(GPIOA, &GPIO_InitStructure);      
 //使用外部中斷方式//
 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);  //中斷線0連接GPIOA.0//
 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;             //使能按鍵所在的外部中斷通道//
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;    //先佔優先級2級//
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;           //從優先級2級//
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;              //使能外部中斷通道//
 NVIC_Init(&NVIC_InitStructure); 
 if(Check_WKUP()==0) Sys_Standby();                         //不是開機,進入待機模式// 
}

8.3 main.c文件代碼

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"  
#include "wkup.h"
int main(void)
 {  
 delay_init();                                   //延時函數初始化   
 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設置中斷優先級分組爲組2//
 uart_init(115200);                              //串口初始化爲115200
 LED_Init();                                     //LED端口初始化 
 LED0=0;
 LED1=0; 
 delay_ms(500);  
 WKUP_Init();                                    //待機喚醒初始化  
 while(1)
 {
  LED0=!LED0;
  LED1=!LED1;
  delay_ms(1000);
 }
 }

9. 舊知識點
1)複習如何新建工程模板,可參考STM32學習心得二:新建工程模板
2)複習基於庫函數的初始化函數的一般格式,可參考STM32學習心得三:GPIO實驗-基於庫函數
3)複習寄存器地址,可參考STM32學習心得四:GPIO實驗-基於寄存器
4)複習位操作,可參考STM32學習心得五:GPIO實驗-基於位操作
5)複習寄存器地址名稱映射,可參考STM32學習心得六:相關C語言學習及寄存器地址名稱映射解讀
6)複習時鐘系統框圖,可參考STM32學習心得七:STM32時鐘系統框圖解讀及相關函數
7)複習延遲函數,可參考STM32學習心得九:Systick滴答定時器和延時函數解讀
8)複習ST-LINK仿真器的參數配置,可參考STM32學習心得十:在Keil MDK軟件中配置ST-LINK仿真器
9)複習ST-LINK調試方法,可參考STM32學習心得十一:ST-LINK調試原理+軟硬件仿真調試方法
10)複習如何對GPIO進行復用,可參考STM32學習心得十二:端口複用和重映射
11)複習中斷相關知識,可參考STM32學習心得十三:NVIC中斷優先級管理
12)複習串口通信相關知識,可參考STM32學習心得十四:串口通信相關知識及配置方法
13)複習通用定時器基本原理,可參考STM32學習心得十八:通用定時器基本原理及相關實驗代碼解讀
14)複習USMART調試工具,可參考STM32學習心得二十:USMART調試組件實驗

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章