硬核保命:PVD掉电中断------让单片机"咽气前"写完遗书

很多工程师只知看门狗(WWDG/IWDG)能防死机,却不知ARM32内置的PVD(可编程电压检测器)才是处理供电异常的最后防线 。书稿1.10节揭示:PVD能在VCC跌至设定阈值(如2.5V)时触发中断,抢在单片机彻底掉电前执行紧急代码------保存关键数据、关断高危执行器、发送"我快死了"的告警帧。这好比飞机失事前飞行员必须完成的30秒检查单,错过窗口期,一切归零。
1. PVD触发:仅2μs的"黄金抢救时间"
书稿1.10节配置PWR_CR寄存器的PLS位段(011=2.5V阈值)和PVDE使能位,但未算时间账:ARM32内部掉电检测电路的响应时间典型值约2μs,而VCC从2.5V跌至1.8V(POR复位电压)的时长取决于电源电容容量。若系统采用10μF陶瓷电容+100mA负载电流,跌落斜率为 dV/dt = I/C = 100mA/10μF = 10V/ms,则2.5V→1.8V仅70μs。扣除中断响应和现场压栈(约2μs),留给用户代码的净执行时间最多60μs------写一个字节到EEPROM(I²C约需100μs)都来不及,只能先存到SRAM(几μs即可),等上电恢复后再搬运。

2. 缓降存数 vs 陡降保命(我的补充)
PVD的真正精髓在于分级策略:
- 第一级(VCC跌至2.8V):触发PVD中断,执行轻量级任务------停止PWM输出(防止MOS管在欠压下直通)、锁存当前ADC采样值、将关键运行参数(PID系数、累计里程)压入后备寄存器(BKP,书稿1.9节提到的0x40006C00地址区域)。
- 第二级(VCC跌至2.5V):再次触发PVD(需软件重设阈值),此时只做一件事------将SRAM中已打包的"临终数据"通过USART以最高波特率(如921600bps)盲发出去,不求应答,只求"洒出"尽可能多的信息。
- 终极防线(VCC < 1.8V):POR硬件接管,强制复位。但PVD已为复活后的系统留下了"我在哪里、我干了什么、我死在哪一步"的恢复线索。
3. 实验验证的"自杀式测试"
书稿1.10节末尾提到用可调电源降低VCC验证PVDO位,但未提示实验风险:反复触发PVD可能导致Flash擦写中断而损坏扇区 (因掉电时Flash编程电压不足)。正确做法是:中断服务程序中仅操作RAM和寄存器,绝不写Flash(除非外接超级电容保证足够掉电保持时间)。我的补充实测数据:用1000μF电解电容+10mA负载,2.8V→2.0V跌落时间约40ms,此时足以通过USART发送256字节的"遗书"数据。
4. 实战代码骨架(基于书稿1.10节的寄存器操作)
void PVD_IRQHandler(void) {
if (PWR->CSR & PWR_CSR_PVDO) { // 书稿1.10节:PVDO=1表示VCC低于阈值
// 第一优先级:关断执行器(GPIO置低)
GPIOA->BRR = GPIO_PIN_8; // 书稿3.14节的BRR寄存器操作
// 第二优先级:保存现场(SRAM)
memcpy((void*)BACKUP_ADDR, (void*)CRITICAL_VAR, 64);
// 第三优先级:发送告警(如果还有电)
if (PWR->CSR & PWR_CSR_PVDO) { // 再次确认未掉到底
USART1_Send_String("POWER_DYING\r\n");
}
// 清除PVD标志(写1清零)
PWR->CR |= PWR_CR_CWUF;
}
}
结语 :PVD不是用来防止掉电的,而是用来**通知单片机准备"死得体面"**的。用好这2μs~60μs的窗口期,你的产品就能在断电后优雅地留下"临终遗言",而不是突然暴毙、死无对证。
