ATTiny85进入INT0中断向量的周期数及响应延迟问题
ATtiny85 INT0中断响应20us延迟的问题分析
我编写了一段ATtiny85的代码,可正常运行,但发现其中断响应延迟达20us。该MCU运行在8MHz,我预期响应仅需数微秒。想了解该延迟的来源、是否确实存在如此慢的情况,以及PCIE中断是否会比INT0更慢(我的项目使用PB1比PB2更简便,尚未测试PCIE)。
// Status Register #define SREG (*(volatile uint8_t*)0x5F) // SRAM address (I/O 0x3F + 0x20) #define I_BIT 7 // Global Interrupt Enable // General Interrupt Mask Register #define GIMSK (*(volatile uint8_t*)0x5B) // SRAM address (I/O 0x3B + 0x20) #define INT0 6 // External Interrupt Request 0 Enable #define PCIE 5 // Pin Change Interrupt Enable // MCU Control Register #define MCUCR (*(volatile uint8_t*)0x55) // SRAM address (I/O 0x35 + 0x20) #define ISC01 1 // Interrupt Sense Control 0 Bit 1 #define ISC00 0 // Interrupt Sense Control 0 Bit 0 // External Interrupt 0 ISR (fires on PB2, pin 7) ISR (INT0_vect) { PORTB = (1 << PB4); // Toggle PB4 (pin 3) each time INT0 triggers PORTB = 0; // Toggle PB4 (pin 3) each time INT0 triggers } int main() { DDRB |= (1 << PB4); // Set PB4 (pin 3) as output (LED) GIMSK |= (1 << INT0); // Enable external interrupt INT0 MCUCR |= (1 << ISC01); // Configure INT0 to trigger on falling edge (ISC01=1, ISC00=0) MCUCR &= ~(0 << ISC00); // Configure INT0 to trigger on falling edge (ISC01=1, ISC00=0) SREG |= (1 << I_BIT); // Enable global interrupts while (1) { // main loop does nothing, work is done in ISR } }

延迟来源拆解
1. 中断响应的固有开销
ATtiny85的INT0中断响应本身存在固定周期:
- 中断请求检测需要1-2个时钟周期
- 完成当前正在执行的指令(最长为4周期指令,如
CALL) - 保存寄存器状态、跳转到中断向量:约4-6个时钟周期
8MHz下每个周期是0.125us,理论固有延迟约1-2us,实际延迟远超这个值,肯定还有其他因素。
2. 代码与硬件的额外影响
- 无效代码:
MCUCR &= ~(0 << ISC00);这行是无效操作,0 << ISC00结果还是0,对寄存器无影响,但编译后可能生成冗余指令(影响极小)。 - 时钟精度问题:如果使用内部RC振荡器,默认可能未校准,实际主频低于8MHz,会直接拉长所有操作的时间。
- 硬件延迟:示波器探头的固有延迟、PCB走线的寄生参数、引脚负载过大,都可能贡献几微秒的延迟。
3. 其他潜在因素
如果MCU开启了其他未察觉的中断(如ADC、定时器),会抢占INT0的响应,但你的代码中未启用这类模块,可能性极低。
INT0与PCIE的速度对比
PCIE(引脚变化中断)确实比INT0慢,原因如下:
- INT0是专用硬件中断,有独立的触发检测逻辑,触发后直接跳转到专属中断向量。
- PCIE需要MCU周期性扫描所有启用的引脚,触发后进入通用的PCINT0向量,ISR内还需自行判断触发引脚(即使只启用了PB1),这部分额外判断会增加延迟。
如果项目必须用PB1,PCIE是唯一选择,但要接受额外的几微秒延迟。
优化建议
- 校准内部时钟:通过
OSCCAL寄存器调整内部RC振荡器,确保MCU精准运行在8MHz。 - 简化ISR逻辑:将测试代码改为
PORTB ^= (1 << PB4);减少寄存器写入次数(虽不是延迟主要来源,但能优化波形)。 - 排查硬件:使用短探头线、降低引脚负载、确保电源稳定,减少硬件层面的延迟。
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

