【STM32筆記】HAL庫低功耗STOP停止模式的序列槽喚醒(解決進入以後立馬喚醒、序列槽喚醒和回調無法一起使用的問題)
前文:
blog.csdn.net/weixin_53403301/article/details/128216064
【STM32筆記】HAL庫低功耗模式配置(ADC喚醒無法使用、低功耗模式無法燒錄解決方案)
低功耗模式如圖所示
停止模式有三種 分别是0 1 2
其中 0 1可以由序列槽喚醒
2隻能由LPUART喚醒
在手冊裡可以查到
進入也很簡單:
/*!
* @brief 進入低功耗模式
*
* @param [in] mode_flag: 模式标志
* 0/大于4 不進入任何模式,1 進入睡眠,2 進入停止,3 進入待機,4 關機
* [in] WakeUpPinPolarity: 待機模式下WKUP喚醒引腳極性配置,其他模式無用
*
* @return None
*/
void Enter_Low_PWR(uint8_t mode_flag,uint32_t WakeUpPinPolarity)
{
__HAL_RCC_PWR_CLK_ENABLE();
switch(mode_flag)
{
case 0:
{
printf("[INFO] 不進入低功耗模式\n");
break;
}
case 1:
{
printf("[INFO] 進入睡眠模式\n");
delay_ms(10); //消抖
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON,PWR_SLEEPENTRY_WFI);
break;
}
case 2:
{
printf("[INFO] 進入停止模式\n");
delay_ms(10); //消抖
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON,PWR_SLEEPENTRY_WFI);
break;
}
case 3:
{
printf("[INFO] 三秒後進入待機模式\n");
delay_ms(3000);
printf("[INFO] 進入待機模式\n");
HAL_PWR_EnableWakeUpPin(WakeUpPinPolarity);
delay_ms(10); //消抖
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
HAL_PWR_EnterSTANDBYMode();
break;
}
case 4:
{
printf("[INFO] 三秒後進入關機模式\n");
delay_ms(3000);
printf("[INFO] 進入關機模式\n");
HAL_PWR_EnableWakeUpPin(WakeUpPinPolarity);
delay_ms(10); //消抖
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
HAL_PWREx_EnterSHUTDOWNMode();
break;
}
default:
{
printf("[INFO] 不進入低功耗模式\n");
break;
}
}
}
要進入停止2模式則需要在pwr_ex.c中配置
HAL_PWREx_EnterSTOP2Mode();函數
其中
HAL_PWR_EnterSTOPMode中的PWR_MAINREGULATOR_ON、PWR_LOWPOWERREGULATOR_ON分别是開啟穩壓器和關閉穩壓器 分别對應STOP 0和1
在停止模式中,進一步關閉了其它所有的時鐘,于是所有的外設都停止了工作,但由于其 1.8V 區域的部分電源沒有關閉,還保留了核心的寄存器、記憶體的資訊,是以從停止模式喚醒,并重新開啟時鐘後,還可以從上次停止處繼續執行代碼。停止模式可以由任意一個外部中斷(EXTI)喚醒,在停止模式中可以選擇電壓調節器為開模式或低功耗模式。
特性和說明:
調壓器低功耗模式: 在停止模式下調壓器可工作在正常模式或低功耗模式,可進一步降低功耗。
進入方式: 核心寄存器的 SLEEPDEEP=1,PWR_CR 寄存器中的 PDDS=0,然後調用 WFI 或 WFE 指令即可進入停止模式;PWR_CR 寄存器的 LPDS=0 時,調壓器工作在正常模式,LPDS=1 時工作在低功耗模式。
喚醒方式: 如果是使用 WFI 指令睡眠的,可使用任意 EXTI 線的中斷喚醒;如果是使用 WFE 指令睡眠的,可使用任意配置為事件模式的 EXTI 線事件喚醒。
停止時: 核心停止,片上外設也停止。這個狀态會保留停止前的核心寄存器、記憶體的資料。
喚醒延遲: 基礎延遲為 HSI 振蕩器的啟動時間,若調壓器工作在低功耗模式,還需要加上調壓器從低功耗切換至正常模式下的時間。
喚醒後: 若由中斷喚醒,先進入中斷,退出中斷服務程式後,接着執行 WFI 指令後的程式;若由事件喚醒,直接接着執行 WFE 後的程式。喚醒後,STM32 會使用 HSI 作為系統時鐘。
隻能由外部中斷喚醒 喚醒後需要重新使能時鐘(SystemClock_Config();)
建議将一條外部中斷線專門作為喚醒中斷,執行中斷後進入回調進行時鐘使能
停止模式0和1由PWR_MAINREGULATOR_ON和PWR_LOWPOWERREGULATOR_ON兩個變量确定
停止模式0和1可以被序列槽 I2C等裝置喚醒(具體看手冊)
停止模式2則在pwr_ex.c中進入
停止模式2 隻能被特定器件(如LPUART等在内部與EXTI有連結的器件)喚醒
若要配置UART喚醒 則需要:
/*!
* @brief 配置序列槽在停止模式下的喚醒
*
* @param [in] huart: UART_HandleTypeDef類型的器件
* [in] EnableNotDisable: 使能或者關閉
*
* @return None
*/
void Ctrl_UART_StopMode_WakeUp(UART_HandleTypeDef *huart,bool EnableNotDisable)
{
if(EnableNotDisable)
{
__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI); //保留喚醒用的HSI線 序列槽初始化時鐘也必須要配置為HSI
UART_WakeUpTypeDef UART_WakeUpStruct={0};
UART_WakeUpStruct.WakeUpEvent=UART_WAKEUP_ON_READDATA_NONEMPTY; //接收資料不為空時喚醒
HAL_UARTEx_StopModeWakeUpSourceConfig(huart,UART_WakeUpStruct);
__HAL_UART_ENABLE_IT(&huart2,UART_IT_WUF); //開啟喚醒中斷
HAL_UARTEx_EnableStopMode(huart); //開啟模式
}
else
{
__HAL_UART_DISABLE_IT(&huart2,UART_IT_WUF); //關閉喚醒中斷
HAL_UARTEx_DisableStopMode(huart); //關閉模式
}
}
配置為接收資料就喚醒
若要使用 則UART必須為HSI或MSI時鐘 配置太麻煩 是以我建議直接在HAL裡面配置
序列槽回調一般是:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart==&huart2)
{
HAL_UART_Transmit(&huart2,&RxBuffer,1,0xFFFF);
HAL_UART_Receive_IT(&huart2,&RxBuffer,1);
}
if(huart==&huart4)
{
HAL_UART_Transmit(&huart4,&RxBuffer,1,0xFFFF);
HAL_UART_Receive_IT(&huart4,&RxBuffer,1);
}
}
接收資料後發送資料
而喚醒回調則是:
void HAL_UARTEx_WakeupCallback(UART_HandleTypeDef *huart)
{
if(huart==&huart2)
{
__HAL_RCC_PWR_CLK_ENABLE();
SystemClock_Config();
Ctrl_UART_StopMode_WakeUp(huart,false);
}
}
進入以後立馬喚醒
若是序列槽懸空 或硬體設計問題 序列槽資料不定 則可能進入以後立馬被喚醒
在外部硬體上加下拉 或者軟體配置下拉(或上拉)即可 不過下拉更省電
序列槽喚醒和回調無法一起使用的問題
在調試時 發現序列槽喚醒和回調無法一起使用 進入了回調以後就退出了 不會進入序列槽喚醒
其實就是
的問題
若不使用這個語句 雖然序列槽可以用 也能接收資料并傳回 但是進不了喚醒回調
其實就是因為時序被改變了
進入低功耗以後 接收資料喚醒 則先進入接收回調 然後發一次資料 但不會進行喚醒 因為時序有問題 mcu認為接收的資料不正常
保留這個語句以後就好了
另外 每次進入低功耗前 都要先調用
語句 否則無法正常喚醒 也不能再次進入低功耗模式
為了避免出錯 每次喚醒以後都應該清空調喚醒中斷
STOP模式會關閉時鐘 是以建議是回調以後就初始化時鐘一次
Ctrl_UART_StopMode_WakeUp(&huart2,true);
Enter_Low_PWR(2,0);
LPUART的配置同理 完全一模一樣的語句