可能LVD中断确实没有触发或者中断触发了但写操作失败(电压太低导致Flash写入失败)LVD配置可能有问题
改进的检测方法
// 定义检测变量
volatile uint32_t lvd_int_count = 0;
volatile uint32_t lvd_status = 0;
// LVD中断服务函数
void LVD_IRQHandler(void)
{
if(lvd_interrupt_flag_get() != RESET) {
lvd_int_count++; // 中断计数
lvd_status = 0xAA55AA55; // 设置特殊标记
// 不要在这里写Flash,电压可能已经不稳定
// 改为设置标志,在主循环中处理
lvd_interrupt_flag_clear();
}
}
// 主循环中检测
while(1) {
if(lvd_status == 0xAA55AA55) {
// LVD中断已触发
printf("LVD中断已触发,计数: %lu\n", lvd_int_count);
lvd_status = 0; // 清除标志
// 这里可以执行安全操作,如保存关键数据
}
}
完整的LVD配置示例
void lvd_config(void)
{
/* 配置LVD */
// 选择LVD阈值,根据你的需求选择
lvd_deinit();
lvd_select(LVD_SEL_0); // 例如2.6V
/* 使能LVD中断 */
lvd_interrupt_enable();
/* 使能LVD */
lvd_enable();
/* 配置NVIC */
nvic_irq_enable(LVD_IRQn, 0, 0);
printf("LVD配置完成\r\n");
}
实用的仿真调试技巧
方法一:使用备份寄存器
// 在LVD中断中写入备份寄存器
void LVD_IRQHandler(void)
{
if(lvd_interrupt_flag_get() != RESET) {
// 写入备份寄存器,掉电后仍能保持
BKP_DATA0 = 0x3C3C3C3C;
lvd_interrupt_flag_clear();
}
}
// 开机时检查
if(BKP_DATA0 == 0x3C3C3C3C) {
printf("上次发生了LVD中断!\n");
BKP_DATA0 = 0; // 清除标记
}
方法二:使用内部Flash标记
#define LVD_MARK_ADDR 0x0800F000 // Flash最后一页的某个地址
void set_lvd_mark(void)
{
// 在LVD中断中调用此函数
fmc_unlock();
fmc_page_erase(LVD_MARK_ADDR);
fmc_word_program(LVD_MARK_ADDR, 0x12345678);
fmc_lock();
}
uint8_t check_lvd_mark(void)
{
if((*(__IO uint32_t*)LVD_MARK_ADDR) == 0x12345678) {
// 清除标记
fmc_unlock();
fmc_page_erase(LVD_MARK_ADDR);
fmc_lock();
return 1;
}
return 0;
}
硬件调试建议
使用可调电源:缓慢降低电压,观察LVD触发点
添加LED指示:在LVD中断中点亮LED
使用串口输出:在中断中通过串口发送消息(确保串口在低电压下仍能工作)
检查LVD状态寄存器
void check_lvd_status(void)
{
if(lvd_flag_get(LVD_FLAG_OUT) != RESET) {
printf("当前电压低于LVD阈值\n");
} else {
printf("当前电压高于LVD阈值\n");
}
}
|