一、AVRmega16中断向量表
向量号程序地址中断源描述IAR AVR中的定义1000RESET外部引脚电平引发的复位,上电复位,掉电检测复位,看门狗复位,以及JTAG AVR 复位RESET_vect2002INT0外部中断请求0INT0_vect3004INT1外部中断请求1INT1_vect4006TIMER2 COMP定时器/计数 2 比较匹配TIMER2_COMP_vect5008TIMER2 OVF定时器/计数 2 溢出TIMER2_OVF_vect600ATIMER1 CAPT定时器/计数 1事件捕捉TIMER_ CAPT_vect700CTIMER1 COMPA定时器/计数 1比较匹配 ATIMER1_COMPA_vect800ETIMER1 COMPB定时器/计数 1比较匹配 BTIMER1_COMPB_vect9010TIMER1 OVF定时器/计数 1 溢出TIMER1_OVF_vect10012TIMER0 OVF定时器/计数 0 溢出TIMER0_OVF_vect11014SPI,STCSPI串行传输结束SPI_STC_vect12016USART,RXCUSART, Rx 结束USART_RXC_vect13018USART,UDREUSART数据寄存器空USART_UDRE_vect1401AUSART,TXCUSART, Tx 结束USART_TXC_vect1501CADCADC转换结束ADC_vect1601EEE_RDYEEPROM 就绪EE_RDY_vect17020ANA_COMP模拟比较器ANA_COMP_vect18022TWI两线串行接口TWI_vect19024INT2外部中断请求2INT2_vect20026TIMER0_COMP定时器/计数 0 比较匹配TIMER0_COMP_vect21028SPM_RDY保存程序存储器内容就绪SPM_RDY_vect
二、AVR 状态寄存器 -SREG
76543210ITHSVNZC初始值00000000
Bit 7 – I: 全局中断使能
I 置位时使能全局中断。单独的中断使能由其他独立的控制寄存器控制。如果 I 清零,则不论单独中断标志置位与否,都不会产生中断。任意一个中断发生后 I 清零,而执行 RETI指令后 I 恢复置位以使能中断。 I 也可以通过 SEI 和 CLI 指令来置位和清零。
三、MCU控制寄存器-MCUCR
76543210SM2SESM1SM0ISC11ISC10ISC01ISC00初始值00000000
Bit 3, 2 – ISC11, ISC10: 中断触发方式控制 1 Bit1 与 Bit 0
外部中断 1 由引脚 INT1 激发,如果 SREG 寄存器的 I 标志位和相应的中断屏蔽位置位的话。触发方式如下表 所示。在检测边沿前 MCU首先采样INT1引脚上的电平。如果选择了边沿触发方式或电平变化触发方式,那么持续时间大于一个时钟周期的脉冲将触发中断,过短的脉冲则不能保证触发中断。如果选择低电平触发方式,那么低电平必须保 持到当前指令执行完成。
ISC11ISC10说明00INT1 为低电平时产生中断请求01INT1 引脚上任意的逻辑电平变化都将引发中断10INT1 的下降沿产生异步中断请求11INT1 的上升沿产生异步中断请求
Bit 1, 0 – ISC01, ISC00: 中断 0 触发方式控制 Bit 1与 Bit 0
外部中断 0 由引脚 INT0 激发,如果 SREG 寄存器的 I 标志位和相应的中断屏蔽位置位的话。触发方式如 Table 35 所示。在检测边沿前 MCU首先采样INT0引脚上的电平。如果选择了边沿触发方式或电平变化触发方式,那么持续时间大于一个时钟周期的脉冲将触发中断,过短的脉冲则不能保证触发中断。如果选择低电平触发方式,那么低电平必须保持到当前指令执行完成。
ISC01ISC00说明00INT0 为低电平时产生中断请求01INT0 引脚上任意的逻辑电平变化都将引发中断10INT0 的下降沿产生异步中断请求11INT0 的上升沿产生异步中断请求
四、MCU控制与状态寄存器-MCUCSR
76543210JTDISC2-JTRFWDRFBORFEXTRFPORF初始值000
Bit 6 – ISC2: 中断 2 触发方式控制
异步外中断 2 由外部引脚 INT2 激活,如果 SREG 寄存器的 I 标志和 GICR 寄存器相应的中断屏蔽位置位的话。若 ISC2 写 0, INT2 的下降沿激活中断。 若 ISC2 写 1,INT2 的上升沿激活中断。 INT2 的边沿触发方式是异步的。只要INT2引脚上产生宽度大于50nS的脉冲就会引发中断。若选择了低电平中断,低电平必须保持到当前指令完成,然后才会产生中断。而且只要将引脚拉低,就会引发中断请求。改变 ISC2 时有可能发生中断。因此建议首先在寄存器 GICR 里清除相应的中断使能位 INT2,然后再改变 ISC2。最后,不要忘记在重新使能中断之前通过对 GIFR 寄存器的相应中断标志位 INTF2 写 '1’使其清零。
五、通用中断控制寄存器-GICR
76543210INT1INT0INT2---IVSELIVCE初始值00000000
Bit 7 – INT1: 使能外部中断请求 1
当 INT1 为 '1’,而且状态寄存器 SREG 的 I 标志置位,相应的外部引脚中断就使能了。MCU通用控制寄存器– MCUCR的中断敏感电平控制1位 1/0(ISC11与ISC10)决定中断是由上升沿、下降沿,还是 INT1 电平触发的。只要使能,即使 INT1 引脚被配置为输出,只要引脚电平发生了相应的变化,中断可将产生。
Bit 6 – INT0: 使能外部中断请求 0
当 INT0 为 '1’,而且状态寄存器 SREG 的 I 标志置位,相应的外部引脚中断就使能了。MCU通用控制寄存器– MCUCR的中断敏感电平控制0位 1/0(ISC01与ISC00)决定中断是由上升沿、下降沿,还是 INT0 电平触发的。只要使能,即使 INT0 引脚被配置为输出,只要引脚电平发生了相应的变化,中断可将产生。
Bit 5 – INT2: 使能外部中断请求 2
当 INT2 为 '1’,而且状态寄存器 SREG 的 I 标志置位,相应的外部引脚中断就使能了。MCU通用控制寄存器– MCUCR的中断敏感电平控制2位 1/0 (ISC2与ISC2)决定中断是由上升沿、下降沿,还是 INT2 电平触发的。只要使能,即使 INT2 引脚被配置为输出,只要引脚电平发生了相应的变化,中断可将产生。
Bit 1 – IVSEL: 中断向量选择
当 IVSEL 为 "0“ 时,中断向量位于 Flash存储器的起始地址;当 IVSEL 为 "1“ 时,中断向量转移到 Boot 区的起始地址。实际的 Boot 区起始地址由熔丝位BOOTSZ确定。在写的同时可以读 (RWW, Read-While-Write) 的自我编程能力 ” 。 为了防止无意识地改变中断向量表,修改 IVSEL 时需要遵照如下过程:
1. 置位中断向量修改使能位 IVCE
2. 在紧接的 4 个时钟周期里将需要的数据写入 IVSEL,同时对 IVCE 写 ”0”
执行上述序列时中断自动被禁止。其实,在置位 IVCE 时中断就被禁止了,并一直保持到写 IVSEL 操作之后的下一条语句。如果没有 IVSEL 写操作,则中断在置位 IVCE 之后的4个时钟周期保持禁止。需要注意的是,虽然中断被自动禁止,但状态寄存器的位I的值并不受此操作的影响。
Note: 若中断向量位于Boot区,且Boot锁定位BLB02被编程,则执行应用区的程序时中断被禁止;若中断向量位于应用区,且 Boot 锁定位 BLB12 被编程, 则执行 Boot 区的程序时中断被禁止。有关 Boot 锁定位的细节请参见 P234“ 支持引导装入程序 – 在写的同时可以读(RWW, Read-While-Write)的自我编程能力 ” 。
Bit 0 – IVCE: 中断向量修改使能
改变 IVSEL 时 IVCE 必须置位。在 IVCE 或 IVSEL 写操作之后 4 个时钟周期, IVCE 被硬件清零。如前面所述,置位 IVCE 将禁止中断。
六、通用中断标志寄存器-GIFR
76543210INTF1INTF0INTF2-----初始值00000000
Bit 7 – INTF1: 外部中断标志 1
INT1引脚电平发生跳变时触发中断请求,并置位相应的中断标志INTF1。如果SREG的位I以及GICR寄存器相应的中断使能位INT1为”1”,MCU即跳转到相应的中断向量。进入中断服务程序之后该标志自动清零。此外,标志位也可以通过写入 ”1” 来清零。
Bit 6 – INTF0: 外部中断标志 0
INT0引脚电平发生跳变时触发中断请求,并置位相应的中断标志INTF0。如果SREG的位I以及GICR寄存器相应的中断使能位INT0为”1”,MCU即跳转到相应的中断向量。进入中断服务程序之后该标志自动清零。此外,标志位也可以通过写入 ”1” 来清零。
Bit 5 – INTF2: 外部中断标志 2
INT2引脚电平发生跳变时触发中断请求,并置位相应的中断标志INTF2。如果SREG的位I以及GICR寄存器相应的中断使能位INT2为”1”,MCU即跳转到相应的中断向量。进入中断服务程序之后该标志自动清零。此外,标志位也可以通过写入 ”1” 来清零。注意,当INT2中断禁用进入某些休眠模式时,该引脚的输入缓冲将禁用。这会导致INTF2标志设置信号的逻辑变化,详见 P52“ 数字输入使能和休眠模式 ” 。
七、IAR AVR中断程序
以TIMER2溢出为例,中断处理程序应该写成入下的样子。其它中断处理程序只需要改变为相应的中断向量即可
#pragma vector=TIMER2_OVF_vect
__interrupt void Timer2(void)
{}