Trong các hệ thống nhúng, việc kiểm soát nguồn điện là yếu tố then chốt để kéo dài tuổi thọ pin và đảm bảo hoạt động ổn định. Module PWR (Power Control) trên STM32 cung cấp khả năng giám sát điện áp và chuyển đổi giữa các chế độ tiêu thụ điện thấp, phù hợp cho thiết bị IoT, đồng hồ thông minh hoặc thiết bị y tế di động.
Chức năng chính của module PWR
- Giám sát điện áp (PVD): Khi điện áp VDD vượt ngưỡng cấu hình, hệ thống kích hoạt ngắt để xử lý sự cố, ví dụ như tắt an toàn khi pin yếu.
- Chế độ ngủ (Sleep): CPU tạm dừng, nhưng ngoại vi và RAM vẫn hoạt động. Thức dậy nhanh qua ngắt.
- Chế độ dừng (Stop): Hầu hết clock bị tắt, chỉ giữ lại LSI/LSE để duy trì RTC và watchdog. Cần bật lại clock sau khi thức dậy.
- Chế độ chờ (Standby): Điện áp lõi 1.8V bị ngắt, RAM và thanh ghi bị xóa. Chỉ có backup domain (RTC, backup registers) còn sống. Thức dậy bằng WKUP hoặc RTC alarm.
Các bit điều khiển quan trọng
PDDS: Quyết định vào Stop (0) hay Standby (1).LPDS: Trong Stop mode, nếu bật thì tắt voltage regulator để tiết kiệm thêm điện.SLEEPDEEP: Cho phép WFI/WFE đưa hệ thống vào sâu hơn (Stop/Standby thay vì Sleep).WFI/WFE: Hai lệnh chờ ngắt/sự kiện để vào chế độ tiết kiệm điện.
Ví dụ 1: Chế độ Sleep với UART
// Khởi tạo UART cơ bản
void setup_uart(void) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef gpio;
gpio.GPIO_Pin = GPIO_Pin_9;
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio);
USART_InitTypeDef usart;
usart.USART_BaudRate = 9600;
usart.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
usart.USART_Parity = USART_Parity_No;
usart.USART_StopBits = USART_StopBits_1;
usart.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1, &usart);
USART_Cmd(USART1, ENABLE);
}
int main(void) {
setup_uart();
while (1) {
// Xử lý dữ liệu nhận được
if (data_received_flag) {
process_data(received_byte);
data_received_flag = 0;
}
__WFI(); // Vào Sleep, chờ ngắt UART
}
}
Ví dụ 2: Chế độ Stop với cảm biến hồng ngoại
void enter_stop_mode(void) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); // Bắt buộc!
EXTI_ClearITPendingBit(EXTI_Line14);
PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);
SystemInit(); // Khôi phục clock sau khi thức dậy
}
void EXTI15_10_IRQHandler(void) {
if (EXTI_GetITStatus(EXTI_Line14)) {
counter++;
EXTI_ClearITPendingBit(EXTI_Line14);
}
}
int main(void) {
init_oled();
init_sensor_interrupt();
while (1) {
display_counter(counter);
toggle_running_indicator();
enter_stop_mode(); // Vào Stop, chờ ngắt từ sensor
}
}
Ví dụ 3: Chế độ Standby với RTC Alarm
void configure_rtc_standby(void) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
if (BKP_ReadBackupRegister(BKP_DR1) != 0x5A5A) {
setup_rtc_with_lse(); // Hoặc LSI nếu không có crystal
set_initial_time();
BKP_WriteBackupRegister(BKP_DR1, 0x5A5A);
}
}
int main(void) {
configure_rtc_standby();
PWR_WakeUpPinCmd(ENABLE); // Cho phép đánh thức bằng PA0
uint32_t wake_time = RTC_GetCounter() + 10;
RTC_SetAlarm(wake_time);
while (1) {
update_display();
simulate_power_down(); // Tắt màn hình, ngoại vi...
PWR_EnterSTANDBYMode(); // Hệ thống reset sau khi thức dậy
// Code sau dòng này sẽ KHÔNG CHẠY — chương trình bắt đầu lại từ main()
}
}
Lưu ý: Sau khi thoát Standby mode, chip khởi động lại từ đầu, nên cần kiểm tra cờ trong backup register để tránh cấu hình lại RTC. Trong Stop mode, chỉ cần gọi SystemInit() để khôi phục clock tree.