本文以smt32L4R5ZIT6單片機為例,編寫代碼。本文隻講代碼,不說廢話。
單片機進入低功耗前,都應該關閉中斷。同時在低功耗前加上如下代碼功耗更低
__HAL_RCC_PWR_CLK_ENABLE();//使能電源時鐘
HAL_PWR_EnableBkUpAccess();//使能LSE/RTC控制的備份域
LSE_OFF_Config();//關閉LSE時鐘,確定RTC關閉
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);//配置内部調節器輸出電壓(預設為Range1)
__HAL_RCC_PWR_CLK_DISABLE();//關閉電源時鐘
在進入低功耗前,都要求設定GPIO為模拟輸入模式,代碼如下
void GPIO_AnalogState_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Pin = GPIO_PIN_All;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
__HAL_RCC_GPIOA_CLK_DISABLE();
__HAL_RCC_GPIOB_CLK_DISABLE();
__HAL_RCC_GPIOC_CLK_DISABLE();
__HAL_RCC_GPIOD_CLK_DISABLE();
__HAL_RCC_GPIOE_CLK_DISABLE();
__HAL_RCC_GPIOF_CLK_DISABLE();
__HAL_RCC_GPIOG_CLK_DISABLE();
__HAL_RCC_GPIOH_CLK_DISABLE();
}
void RTC_Config()函數
void RTC_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
__HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE);
__HAL_RCC_RTC_ENABLE();
}
1關斷模式SHUTDOWN
關斷模式
void test_shutdown(void)
{
GPIO_AnalogState_Config();//設定GPIO為模拟輸入
__HAL_RCC_PWR_CLK_ENABLE();//使能電源時鐘
HAL_PWREx_EnterSHUTDOWNMode();//進入shutdown模式
}
2待機模式standby
待機模式
void test_standby_rtc(void)
{
/* set RTC clock */
//說明:這裡可以設定RTC時鐘喚醒待機模式,但是本文未設定RTC中斷,是以此處代碼省略.如果想要喚醒,應該在此處開啟rtc喚醒
RTC_Config();//配置RTC,因為前文介紹低功耗前關閉RTC,此處相當于重新打開
GPIO_AnalogState_Config();//設定GPIO為低功耗模式
__HAL_RCC_PWR_CLK_ENABLE();//使能電源時鐘
HAL_PWR_EnterSTANDBYMode();//進入STANDBY模式
}
3待機模式+RTC
待機模式+RTC并保留sram2中資料
void test_standby_rtc_sram2(void)
{
/* set RTC clock */
/*這裡可以設定RTC喚醒待機模式,但本文未設定,是以此處代碼省略*/
MX_RTC_Init();//初始化RTC
GPIO_AnalogState_Config();//設定GPIO低功耗模式
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);//清除電源标志
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF);//清除RTC喚醒定時器标志
__HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG();//清除睡眠外部中斷喚醒标志
__HAL_RTC_TIMESTAMP_CLEAR_FLAG(&hrtc, RTC_FLAG_TSF);
__HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG();
__HAL_RCC_PWR_CLK_ENABLE();//使能電源時鐘
/* Request to enter STANDBY mode with SRAM2 active */
HAL_PWREx_EnableSRAM2ContentRetention();//激活待機模式中SRAM2備份域
// HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 5, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);//此代碼是設定RTC定時器喚醒中斷,5秒喚醒.此處作為示例代碼,暫不使用
HAL_PWR_EnterSTANDBYMode();//進入待機模式
}
4停止模式stop2
停止模式2
void test_stop2(void)
{
GPIO_AnalogState_Config();
__HAL_RCC_PWR_CLK_ENABLE();
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);//進入停止模式2
}
5停止模式2+RTC
void test_stop2_rtc(void)
{
GPIO_AnalogState_Config();
MX_RTC_Init();//配置RTC
/* Enable Power Clock */
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
/* Clear RTC Wake Up timer Flag */
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF);
__HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG();
__HAL_RTC_TIMESTAMP_CLEAR_FLAG(&hrtc, RTC_FLAG_TSF);
__HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG();
HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 5, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);//設定RTC定時器喚醒,定時5s
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);//進入停止2模式
SystemClock_80MHz(); //RTC定時5秒後喚醒,必須重新配置時鐘
}
6停止模式1
停止模式1
void test_stop1_mroff(void)
{
GPIO_AnalogState_Config();
__HAL_RCC_PWR_CLK_ENABLE();
/*進入停止模式1,主調節器關,低功耗調節器開*/
HAL_PWREx_EnterSTOP1Mode(PWR_STOPENTRY_WFI);
}
7停止模式1+RTC
停止模式1+RTC
void test_stop1_mroff_rtc(void)
{
/* set RTC clock */
/*這裡可以設定RTC時鐘喚醒*/
RTC_Config();//配置RTC
GPIO_AnalogState_Config();
__HAL_RCC_PWR_CLK_ENABLE();
/* Enter STOP 1 mode (Main Regulator OFF and Low Power Regulator On) */
HAL_PWREx_EnterSTOP1Mode(PWR_STOPENTRY_WFI);
}
8低功耗睡眠模式2MHz
lpsleep_2mhz
void SystemClock_2MHz(void)//配置運作時鐘為2MHz
{
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
/* MSI is enabled after System reset, update MSI to 2Mhz (RCC_MSIRANGE_5) */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_5;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/* Select MSI as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
void test_lpsleep_2mhz(void)//睡眠模式配置
{
GPIO_AnalogState_Config();
__HAL_FLASH_SLEEP_POWERDOWN_ENABLE(); //在睡眠模式下啟用flash power down,如果在低功耗下不需要flash進入待機模式,需要屏蔽這行代碼
SystemClock_2MHz();//配置2MHz(MSI)單片機運作時鐘頻率
HAL_SuspendTick();//暫停時間增量防止系統中斷喚醒,否則Systick中斷在1ms内會喚醒裝置
/* 關閉所有時鐘使能*/
RCC->AHB1SMENR = 0x0;
RCC->AHB2SMENR = 0x0;
RCC->AHB3SMENR = 0x0;
RCC->APB1SMENR1 = 0x0;
RCC->APB1SMENR2 = 0x0;
RCC->APB2SMENR = 0x0;
__HAL_RCC_PWR_CLK_ENABLE();
/*進入睡眠模式,主調節器關閉*/
HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);
}
9運作模式2MHz
2MHz的運作模式
void SystemClock_2MHz(void)//配置運作時鐘為2MHz
{
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
/* MSI is enabled after System reset, update MSI to 2Mhz (RCC_MSIRANGE_5) */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_5;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/* Select MSI as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
void test_lprun_2mhz(void)//配置2MHz的低功耗運作模式
{
GPIO_AnalogState_Config();
SystemClock_2MHz();//配置系統時鐘2 MHz (MSI)
HAL_SuspendTick();//暫停時間增量以防止系統中斷喚醒。
__HAL_RCC_LPUART1_CLK_DISABLE();//失能低功耗序列槽時鐘
__HAL_RCC_PWR_CLK_ENABLE();//開啟電源時鐘
HAL_PWREx_EnableLowPowerRunMode();//低功耗運作模式2MHz
__HAL_RCC_PWR_CLK_DISABLE();//失能電源時鐘
}
10睡眠模式range2(24MHz)
void SystemClock_24MHz(void)//配置24MHz時鐘
{
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
/* MSI is enabled after System reset, update MSI to 24Mhz (RCC_MSIRANGE_9) */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_9;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_OFF;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/* Select MSI as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
{
Error_Handler();
}
}
void test_sleep_range2_24mhz(void)//設定睡眠模式
{
GPIO_AnalogState_Config();
SystemClock_24MHz();//配置系統時鐘24 MHz (MSI)
__HAL_RCC_PWR_CLK_ENABLE();
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2);//配置内部主調節器輸出電壓
HAL_SuspendTick();//暫停Systick中斷
RCC->AHB1SMENR = 0x0; //關閉所有時鐘使能
RCC->AHB2SMENR = 0x0;
RCC->AHB3SMENR = 0x0;
RCC->APB1SMENR1 = 0x0;
RCC->APB1SMENR2 = 0x0;
RCC->APB2SMENR = 0x0;
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);//進入睡眠模式,主調節器開
}
11睡眠模式range1(80MHz)
sleep_range1_80mhz
void SystemClock_80MHz(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
/* MSI is enabled after System reset, activate PLL with MSI as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
RCC_OscInitStruct.PLL.PLLM = 1;
RCC_OscInitStruct.PLL.PLLN = 40;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLP = 7;
RCC_OscInitStruct.PLL.PLLQ = 4;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
}
void test_sleep_range1_80mhz(void)
{
GPIO_AnalogState_Config();
SystemClock_80MHz();//配置系統頻率80 MHz (MSI)
HAL_SuspendTick();
RCC->AHB1SMENR = 0x0;
RCC->AHB2SMENR = 0x0;
RCC->AHB3SMENR = 0x0;
RCC->APB1SMENR1 = 0x0;
RCC->APB1SMENR2 = 0x0;
RCC->APB2SMENR = 0x0;
__HAL_RCC_PWR_CLK_ENABLE();
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);//睡眠模式主調節器開
}
12運作模式range2(24MHz)
void SystemClock_24MHz(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
/* MSI is enabled after System reset, update MSI to 24Mhz (RCC_MSIRANGE_9) */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_9;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_OFF;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/* Select MSI as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
{
Error_Handler();
}
}
void test_run_range2_24mhz(void)
{
SystemClock_24MHz();//設定系統時鐘為24 MHz
__HAL_RCC_PWR_CLK_ENABLE();
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2);//設定内部主調節器輸出電壓
__HAL_RCC_PWR_CLK_DISABLE();
GPIO_AnalogState_Config();
__HAL_RCC_LPUART1_CLK_DISABLE();//關閉低功耗序列槽
HAL_SuspendTick();
}
13運作模式range1(80MHz)
void SystemClock_80MHz(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
/* MSI is enabled after System reset, activate PLL with MSI as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
RCC_OscInitStruct.PLL.PLLM = 1;
RCC_OscInitStruct.PLL.PLLN = 40;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLP = 7;
RCC_OscInitStruct.PLL.PLLQ = 4;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
}
void test_run_range1_80mhz(void)
{
GPIO_AnalogState_Config();
__HAL_RCC_LPUART1_CLK_DISABLE();
SystemClock_80MHz();//配置系統時鐘80 MHz (MSI)
HAL_SuspendTick();
}
至此,低功耗模式的代碼呈現完畢。