嵌入式系統低功耗設計完全指南
物聯網裝置通常需要電池供電,如何讓裝置運作數月甚至數年是核心挑戰。本文將從晶片選型、電路設計、韌體優化三個層面,分享低功耗設計的實戰經驗。
功耗基礎概念
電池壽命計算
電池壽命的基本公式:
電池壽命 (小時) = 電池容量 (mAh) / 平均電流 (mA)
但實際情況更複雜,需要考慮:
- 工作模式週期性切換
- 電池自放電(約 1-3% / 月)
- 溫度影響
- 電池老化
功耗來源分析
典型物聯網裝置的功耗分布:
| 模組 | 工作電流 | 佔比 |
|---|---|---|
| MCU 運算 | 5-50 mA | 20% |
| 無線通訊 | 10-100 mA | 50% |
| 感測器 | 1-10 mA | 15% |
| 電源轉換 | 損耗 5-15% | 15% |
晶片選型
超低功耗 MCU 比較
| 晶片 | 待機電流 | 工作電流 | 喚醒時間 |
|---|---|---|---|
| STM32L4 | 30 nA | 28 μA/MHz | 5 μs |
| nRF52840 | 0.4 μA | 51 μA/MHz | 3 μs |
| ESP32-S3 | 7 μA | 240 μA/MHz | 250 μs |
| MSP430FR | 350 nA | 100 μA/MHz | 3.5 μs |
選型建議
- 需要 BLE:Nordic nRF52 系列
- 需要 WiFi:ESP32-C6(低功耗 WiFi)
- 純感測應用:STM32L0/L4 系列
- 極低功耗:MSP430FR 系列
電路設計技巧
1. 電源開關
使用 MOSFET 或負載開關 IC 控制周邊電源:
┌─────────────────┐
VCC ──────┬───────┤ LDO 3.3V │
│ └────────┬────────┘
│ │
│ ┌────────┴────────┐
│ │ MCU (Always ON) │
│ └────────┬────────┘
│ │ GPIO
│ ▼
│ ┌────────────────┐
└───────┤ 負載開關 IC │
│ (TPS22860) │
└────────┬───────┘
│
┌────────┴────────┐
│ 感測器/模組 │
│ (關閉時 0 電流) │
└─────────────────┘
2. 上拉電阻優化
I2C 上拉電阻選擇影響功耗:
- 10kΩ:標準選擇,平衡功耗與訊號品質
- 4.7kΩ:高速傳輸,功耗較高
- 內建上拉:功耗最低,但可能訊號不佳
3. 去耦電容
使用適當的去耦電容減少高頻雜訊:
// 典型配置
// - 100nF:每個 VCC 腳位
// - 10μF:電源輸入
// - 1μF:敏感類比電路
韌體優化
1. 睡眠模式選擇
以 STM32L4 為例,有多種低功耗模式:
// STM32L4 低功耗模式選擇
void enter_low_power_mode(LowPowerMode mode) {
switch (mode) {
case LP_SLEEP:
// 僅停止 CPU,周邊持續運作
// 電流:約 200 μA
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON,
PWR_SLEEPENTRY_WFI);
break;
case LP_STOP0:
// 停止 CPU 和大部分時鐘
// 電流:約 12 μA
HAL_PWREx_EnterSTOP0Mode(PWR_STOPENTRY_WFI);
break;
case LP_STOP1:
// 更低功耗 STOP 模式
// 電流:約 5 μA
HAL_PWREx_EnterSTOP1Mode(PWR_STOPENTRY_WFI);
break;
case LP_STOP2:
// 最低功耗 STOP 模式
// 電流:約 1.5 μA
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
break;
case LP_STANDBY:
// 僅保留 RTC 和少量暫存器
// 電流:約 280 nA
HAL_PWR_EnterSTANDBYMode();
break;
case LP_SHUTDOWN:
// 最低功耗,需外部喚醒
// 電流:約 30 nA
HAL_PWREx_EnterSHUTDOWNMode();
break;
}
}
2. 時鐘管理
動態調整時鐘頻率:
// 降低時鐘頻率以節省功耗
void reduce_clock_speed(void) {
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
// 切換到 MSI 4MHz(低功耗時鐘源)
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6; // 4 MHz
HAL_RCC_OscConfig(&RCC_OscInitStruct);
// 配置系統時鐘
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
// 關閉不需要的高速時鐘
__HAL_RCC_PLL_DISABLE();
__HAL_RCC_HSE_CONFIG(RCC_HSE_OFF);
}
3. 週邊電源管理
只在需要時啟用周邊:
// 感測器量測週期
void sensor_measure_cycle(void) {
// 1. 開啟感測器電源
HAL_GPIO_WritePin(SENSOR_PWR_GPIO, SENSOR_PWR_PIN, GPIO_PIN_SET);
// 2. 等待穩定(查閱 datasheet)
HAL_Delay(10);
// 3. 啟用 ADC
__HAL_RCC_ADC_CLK_ENABLE();
HAL_ADC_Init(&hadc1);
// 4. 讀取資料
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
uint16_t value = HAL_ADC_GetValue(&hadc1);
// 5. 關閉 ADC
HAL_ADC_DeInit(&hadc1);
__HAL_RCC_ADC_CLK_DISABLE();
// 6. 關閉感測器電源
HAL_GPIO_WritePin(SENSOR_PWR_GPIO, SENSOR_PWR_PIN, GPIO_PIN_RESET);
}
實戰範例:3 年電池壽命設計
設計目標:CR2450 電池(620mAh),運作 3 年以上。
功耗預算
目標壽命:3 年 = 26,280 小時
電池容量:620 mAh(考慮 80% 可用)= 496 mAh
平均電流上限:496 / 26,280 = 18.9 μA
工作週期設計
| 狀態 | 電流 | 時間 | 週期 |
|---|---|---|---|
| 深度睡眠 | 1 μA | 59 秒 | 每分鐘 |
| 感測器量測 | 500 μA | 100 ms | 每分鐘 |
| BLE 廣播 | 8 mA | 3 ms | 每 10 分鐘 |
平均電流計算
感測器:(500 μA × 0.1s) / 60s = 0.83 μA
BLE:(8 mA × 0.003s) / 600s = 0.04 μA
睡眠:1 μA × (59.9/60) = 0.998 μA
總計:0.83 + 0.04 + 1.0 ≈ 1.87 μA
預估壽命:496 mAh / 0.00187 mA = 265,240 小時 = 30 年
(實際會因電池自放電而縮短至 3-5 年)
常見問題排查
功耗異常高?
- 檢查浮空腳位:未使用的 GPIO 設為輸入下拉
- 檢查 debug 介面:SWD 可能持續供電
- 檢查 LED:確認關閉狀態指示燈
- 檢查 LDO 靜態電流:選用超低靜態電流 LDO
睡眠後無法喚醒?
- 確認 RTC 時鐘源配置正確
- 確認喚醒源(GPIO、RTC、UART)設定
- 檢查中斷優先級
低功耗設計是一門需要軟硬體配合的技術。如果你有電池供電的產品需求,歡迎聯繫我們討論。