修改主頻我們直接在cubeMx上面修改就行了,很方便
睡眠,停止,待機模式是通過對電源的控制來進行的,相關代碼在PWR文件里面
SEV(Send Event)
void HAL_PWR_EnterSLEEPMode(uint32_t Regulator, uint8_t SLEEPEntry)
void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry)
void HAL_PWR_EnterSTANDBYMode(void)
當調用HAL_PWR_EnableSleepOnExit()
后,處理器在中斷服務程序結束返回時,會自動進入睡眠模式,除非有其他中斷發生或者手動禁止該功能。
參數Regulator為調節器,PWR_MAINREGULATOR_ON主調節器,PWR_LOWPOWERREGULATOR_ON低功耗調節器
進入睡眠模式后的程序下載
按住復位鍵不松手,點擊下載然后松手
我們把進入睡眠模式的代碼寫入主循環中,能一直觀察到running,也就是沒有成功進入睡眠模式,這是因為hal庫的底層代碼,systick會每隔一段時間刷新并觸發一次中斷,這個中斷會使我們退出睡眠模式。
所以我們得在進入睡眠模式前面關閉tick時鐘,在從睡眠模式恢復的時候再開啟tick時鐘
hal庫睡眠模式串口收發
uint8_t RxData;
uint8_t Serial_RxFlag;
uint8_t Serial_GetRxFlag(void)
{if (Serial_RxFlag == 1) //如果標志位為1{Serial_RxFlag = 0;return 1; //則返回1,并自動清零標志位}return 0; //如果標志位為0,則返回0
}int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_USART1_UART_Init();OLED_Init();OLED_ShowString(1, 1, "RxData:");HAL_UART_Receive_IT(&huart1,&RxData,1);while (1){if (Serial_GetRxFlag() == 1) //檢查串口接收數據的標志位{Serial_SendByte(RxData); //串口將收到的數據回傳回去,用于測試,hal庫我們使用的是中斷接收,所以就不需要和江科大一樣把變量先讀取再發送,直接發送就行了OLED_ShowHexNum(1, 8, RxData, 2); //顯示串口接收的數據}OLED_ShowString(2, 1, "Running"); //OLED閃爍Running,指示當前主循環正在運行HAL_Delay(100);OLED_ShowString(2, 1, " ");HAL_Delay(100);HAL_SuspendTick();HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON,PWR_SLEEPENTRY_WFI);HAL_ResumeTick(); }
}void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){if(huart == &huart1){Serial_RxFlag = 1;HAL_UART_Receive_IT(&huart1,&RxData,1);}
}
hal庫停止模式紅外對射接收器計次
while (1){/* USER CODE END WHILE */OLED_ShowNum(1, 7, CountSensor_Get(), 5); //OLED不斷刷新顯示CountSensor_Get的返回值OLED_ShowString(2, 1, "Running"); //OLED閃爍Running,指示當前主循環正在運行HAL_Delay(100);OLED_ShowString(2, 1, " ");HAL_Delay(100);/* USER CODE BEGIN 3 */HAL_SuspendTick();HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON,PWR_STOPENTRY_WFI);HAL_ResumeTick();SystemClock_Config();}
停止模式結束后得重新對系統的時鐘進行配置,所以我們在停止模式的后面加上cubeMx給我們生成的時鐘配置函數即可。
hal庫待機模式實時時鐘
RTC_ReadTimeCounter()是hal庫的獲取時間戳的函數,這個函數在rtc文件里面是靜態的,要獲取時間戳的話得把他的前綴static刪掉,并在.h文件里面進行聲明。
標準庫的鬧鐘設置是直接通過時間戳來設置的,而hal庫的需要定義一個時間結構體作為鬧鐘結構體的成員,再初始化鬧鐘,對于相差10s的鬧鐘這類應用很差,不如標準庫,但是對于定時時鐘的鬧鐘效果比標準庫的更直白。
鬧鐘配置函數
HAL_StatusTypeDef RTC_SetAlarmTenSecondsLater(RTC_HandleTypeDef *hrtc)
{RTC_TimeTypeDef sTime = {0};RTC_AlarmTypeDef sAlarm = {0};HAL_StatusTypeDef status = HAL_ERROR;/* 檢查參數 */if (hrtc == NULL){return HAL_ERROR;}/* 獲取當前時間 */if (HAL_RTC_GetTime(hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK){return HAL_ERROR;}/* 計算十秒后的時間 */sTime.Seconds += 10;/* 處理秒數進位 */if (sTime.Seconds >= 60){sTime.Seconds -= 60;sTime.Minutes++;if (sTime.Minutes >= 60){sTime.Minutes -= 60;sTime.Hours++;if (sTime.Hours >= 24){sTime.Hours -= 24;/* 注意:這里沒有處理日期進位,因為RTC_DateTypeDef未獲取 */}}}/* 配置鬧鐘結構體 */sAlarm.AlarmTime = sTime;sAlarm.Alarm = 0x00;//鬧鐘成員編號,單個鬧鐘無用/* 設置鬧鐘 */status = HAL_RTC_SetAlarm_IT(hrtc, &sAlarm, RTC_FORMAT_BIN);/* 配置鬧鐘中斷 (可選,如需要中斷處理) */if (status == HAL_OK){HAL_NVIC_SetPriority(RTC_Alarm_IRQn, 0, 0);HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);}return status;
}
相比于標準庫的直接寫入時間戳,hal庫的這類鬧鐘配置比較復雜
RTC_DateTypeDef GetData; //獲取日期結構體RTC_TimeTypeDef GetTime; //獲取時間結構體HAL_StatusTypeDef RTC_SetAlarmTenSecondsLater(RTC_HandleTypeDef *hrtc);
uint32_t Alarm;
int main(void)
{HAL_Init();SystemClock_Config();OLED_Init();MX_GPIO_Init();MX_RTC_Init();/*顯示靜態字符串*/OLED_ShowString(1, 1, "CNT :");OLED_ShowString(2, 1, "ALR :");OLED_ShowString(3, 1, "ALRF:");HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);//wake up標志位得手動清除,不然會一直存在導致程序一直處于喚醒Alarm = RTC_ReadTimeCounter(&hrtc) + 10; //鬧鐘為喚醒后當前時間的后10sOLED_ShowNum(2, 6, Alarm, 10); //顯示鬧鐘值RTC_SetAlarmTenSecondsLater(&hrtc);while (1){OLED_ShowNum(1, 6, RTC_ReadTimeCounter(&hrtc), 10); //顯示32位的秒計數器OLED_ShowNum(3, 6, __HAL_RTC_ALARM_EXTI_GET_FLAG(), 1); //顯示鬧鐘標志位OLED_ShowString(4, 1, "Running"); //OLED閃爍Running,指示當前主循環正在運行HAL_Delay(100);OLED_ShowString(4, 1, " ");HAL_Delay(100);OLED_ShowString(4, 9, "STANDBY"); //OLED閃爍STANDBY,指示即將進入待機模式HAL_Delay(1000);OLED_ShowString(4, 9, " ");HAL_Delay(100);OLED_Clear(); //OLED清屏,模擬關閉外部所有的耗電設備,以達到極度省電HAL_SuspendTick();HAL_PWR_EnterSTANDBYMode(); //STM32進入停止模式,并等待指定的喚醒事件(WKUP上升沿或RTC鬧鐘)HAL_ResumeTick();}
}