AVR ATmega32A-PU的INT0中断触发导致MCU复位问题求助
ATmega32A-PU INT0中断触发导致MCU复位问题
问题现象
编程ATmega32A-PU时遇到INT0中断异常:每当PD2引脚的上升沿触发INT0中断时,MCU会复位,程序重新执行main函数开头的代码。TIMER0_COMP_vect中断运行完全正常。
代码片段
#define F_CPU 16000000 // 16 MHz clock speed #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> volatile unsigned int T2StopFlag = 0; volatile unsigned int initialized = 0; volatile unsigned long millis_value = 0; #include "Includes\csrc\u8g2.h" #include "display.h" #include "utility.h" // (utility.h includes:) /* ----------------------------------------------------------------------- */ IRS(INT0_vect) { PORTA &= ~(1<<6); // MotorOFF(); PORTA &= ~(1<<4); // RV1OFF(); PORTA &= ~(1<<5); // RV2OFF(); T2StopFlag = 1; // T2StopFlag setzen } ISR(TIMER0_COMP_vect) // ISR for millis(); { millis_value++; // Increment millisecond every 1ms } unsigned long millis() { unsigned long m; cli(); m = millis_value; sei(); return m; } /* ----------------------------------------------------------------------- */ #include "systemcheck.h" #include "executions.h" #include "states.h" #include "modusoperandi.h" /* ----------------------------------------------------------------------- */ int main(void) { // --- ISR for T2 (INT0) --- // <- Causes program to restart. MCUCR = 0x03; // 0b 0000 0011 -> INT0 rising edge, INT1 not GICR = 0x40; // 0b 0100 0000 -> INT0 set, INT1 set INT2 not // --- ISR for millis(); --- // <- Works just fine. TCCR0 = 0x0B; // Clock source: System Clock // Mode: CTC top=OCR0 TCNT0 = 0x00; // Timer/Counter 0 initialization OCR0 = 0xF9; // Clock value: 250.000 kHz (16MHz/64) TIMSK = 0x02; // Enable compare match interrupt for timer 0 // --- Enable global interrupt --- // sei(); // ---- StartUp Sequence ---- // StartUpSeqDemo(); // Run Start Up Sequence once ServiceModeReq(); // Request Command to enter Service Mode // ---- Loop ---- // while(1) { /* ... */ } // while(1); end } // int main(void); end
已尝试操作
- 将INT0配置为上升沿触发的中断服务程序
- 怀疑millis()函数中的cli()和sei()导致问题,注释后结果无变化
- DMFR
预期结果
- 程序正常运行,INT0中断触发后继续执行当前任务
实际结果
- 程序重启,执行while(1)之前的代码
额外编译警告信息
IRS(INT0_vect)存在如下编译警告,而ISR(TIMER0_COMP_vect)无警告:
Warning type of '__vector_1' defaults to 'int' [-Wimplicit-int] Warning return type defaults to 'int' [-Wimplicit-int] Warning control reaches end of non-void function [-Wreturn-type]
修改为带返回值的int类型IRS(INT0_vect)后,警告减少为:
Warning type of '__vector_1' defaults to 'int' [-Wimplicit-int]
问题根源与解决思路
核心错误:中断宏拼写错误
你把AVR中断服务程序的宏ISR()写成了IRS(),这是导致所有问题的根本原因:
- AVR的
ISR()宏是专门用来定义中断服务函数的,它会自动处理中断上下文的寄存器保存/恢复、设置正确的函数类型(无返回值的void),并将函数地址关联到对应的中断向量表。 - 错误的
IRS()宏不存在,编译器会把它当成普通函数处理,生成的代码不符合中断执行的上下文要求。当INT0中断触发时,程序跳转到这个错误的函数执行,会破坏寄存器状态或程序计数器,最终导致MCU复位。
解决步骤
- 修正宏拼写:把
IRS(INT0_vect)改为ISR(INT0_vect) - 确保函数类型正确:中断服务函数必须是void类型,不需要返回值(删除你尝试添加的int返回值)
- 重新编译:修正后所有编译警告会消失,中断触发时程序能正常执行ISR逻辑,不会复位
额外检查点
- 修正GICR配置的注释:
GICR = 0x40是仅使能INT0(BIT6),注释里写的"INT1 set"是错误的,避免后续混淆 - 检查PD2引脚硬件:如果修正后仍有异常,排查是否有尖峰干扰导致误触发,或者引脚电平是否符合要求
内容的提问来源于stack exchange,提问作者M.Grae
相关产品推荐
相关产品推荐

