4、电源监测与欠压保护:MCU内置POR/PDR/BOR原理,外部电源监测芯片(如TPS3803)应用,欠压时的安全状态机
电源,是嵌入式系统的命脉。这话听起来像废话,但我在项目中见过太多「莫名其妙死机」的案例,最后查出来都是电源问题。你想想看,MCU在电压不稳的时候,行为是完全不可预测的——可能跑飞,可能写坏Flash,甚至可能锁死。
所以这一章,咱们就聊聊怎么让MCU在电源出问题时,能体面地「倒下」,而不是「暴毙」。
4.1 MCU内置的POR/PDR/BOR:芯片自带的「保安」
大部分工业级MCU,内部都集成了电源监测电路。说白了,就是芯片自己给自己配了个保安。这三个缩写你得记住:
- POR(Power-On Reset):上电复位。芯片刚通电时,电压还没稳定,POR会强制MCU保持在复位状态,直到电压升到安全阈值以上。
- PDR(Power-Down Reset):掉电复位。电压掉到某个阈值以下,PDR立刻把MCU拉回复位状态。
- BOR(Brown-Out Reset):欠压复位。这个比PDR更精细,可以设置多个阈值。电压跌到某个设定值,BOR就触发复位。
我个人习惯,在选型时一定会看BOR的阈值档位。比如STM32的BOR,有2.0V、2.2V、2.5V等几个档位。你选哪个?这取决于你的系统工作电压和外部电路。
关键点:BOR不是万能的。它只能保证MCU内核复位,但无法保护外设。比如你正在写EEPROM,电压突然掉到BOR阈值以下,MCU复位了,但EEPROM可能已经写了一半——数据就坏了。
4.2 外部电源监测芯片:为什么需要「外援」?
内置的POR/PDR/BOR够用吗?说实话,在工业现场,我建议你还是加一颗外部电源监测芯片。为什么?
- 精度更高:内置电路的阈值精度一般在±5%左右,外部芯片可以做到±1.5%甚至更高。
- 响应更快:外部芯片的检测延迟通常在微秒级,内置电路可能到毫秒级。
- 可配置性更强:你可以自己设定阈值、复位延迟时间。
我常用的芯片是TPS3803(TI出品)。它体积小、功耗低,非常适合工业场景。来看一个典型电路:
// TPS3803典型应用电路
// VDD ——[R1]——+——[R2]—— GND
// |
// SENSE (TPS3803 Pin 3)
//
// 复位输出:RESET (Pin 2) —— MCU的NRST引脚
//
// 阈值计算公式:
// Vth = 1.24V * (R1 + R2) / R2
//
// 例如:R1=100kΩ, R2=47kΩ
// Vth = 1.24 * (100+47)/47 ≈ 3.88V
// 当VDD低于3.88V时,RESET输出低电平
我的经验:R1和R2一定要用1%精度的电阻。我曾经图省事用了5%的,结果阈值偏差了0.3V,差点把一批产品搞废。嗯,从那以后我再也不敢在分压电阻上省钱。
4.3 欠压时的安全状态机:让系统「优雅地倒下」
检测到欠压之后怎么办?直接复位?不一定。有些场景下,你需要先保存关键数据,再复位。这就需要一个安全状态机。
我设计过这样一个状态机,用在工业控制器上:
// 欠压安全状态机(伪代码)
enum PowerState {
POWER_GOOD, // 正常
POWER_WARNING, // 欠压预警
POWER_CRITICAL, // 临界欠压
POWER_FAIL // 掉电
};
void PowerMonitor_Task(void) {
switch(currentState) {
case POWER_GOOD:
if (Voltage < V_WARNING_THRESHOLD) {
// 进入预警状态
currentState = POWER_WARNING;
// 启动定时器,开始计时
StartTimer(T_WARNING_TIMEOUT);
// 通知应用层:准备保存数据
NotifyApp("Save your data!");
}
break;
case POWER_WARNING:
if (Voltage < V_CRITICAL_THRESHOLD) {
// 电压继续下降,进入临界状态
currentState = POWER_CRITICAL;
// 强制保存关键参数到EEPROM
SaveCriticalParams();
// 关闭非必要外设(如LED、通信模块)
DisableNonCriticalPeripherals();
} else if (Voltage > V_WARNING_THRESHOLD + V_HYSTERESIS) {
// 电压恢复,回到正常状态
currentState = POWER_GOOD;
CancelTimer();
}
break;
case POWER_CRITICAL:
if (Voltage < V_FAIL_THRESHOLD) {
// 电压太低,直接复位
currentState = POWER_FAIL;
// 设置复位原因标志
SetResetCause(RESET_CAUSE_BROWNOUT);
// 执行系统复位
NVIC_SystemReset();
}
break;
case POWER_FAIL:
// 等待外部复位或POR
break;
}
}
避坑指南:我曾经在预警状态下直接写EEPROM,结果电压掉得太快,写到一半就复位了,EEPROM里的数据全乱套。后来我改成:先判断电压是否稳定,再决定是否写。如果电压已经低于临界值,那就只写最关键的几个字节,其他的放弃。
4.4 实际项目中的几个「坑」
讲几个我踩过的坑,你遇到了可以少走弯路:
- 迟滞电压:电源监测一定要加迟滞。否则电压在阈值附近抖动时,MCU会反复复位。TPS3803内部有20mV的迟滞,够用。如果自己用比较器搭,记得加正反馈。
- 复位时间:外部复位芯片的复位脉冲宽度要够长。我见过有人用100μs的,结果MCU还没完全复位,脉冲就结束了。STM32要求至少1.5μs,但保险起见,我一般选100ms以上的。
- 去耦电容:电源监测芯片的供电引脚,一定要加0.1μF的陶瓷电容。不加的话,高频噪声可能导致误触发。嗯,这个坑我踩过两次才长记性。
4.5 总结一下
电源监测这事儿,说简单也简单,说复杂也复杂。我的建议是:
- 优先用MCU内置的BOR,省成本。
- 关键系统加外部监测芯片,保可靠性。
- 设计好安全状态机,别让数据丢了。
- 别忘了迟滞、复位时间、去耦这些小细节。
你想想看,一个电源监测电路,成本可能就几毛钱,但能避免的故障可能是几万块的损失。这笔账,怎么算都划算。