本节描述ATmega32的中断处理。更一般的AVR中断处理请参见P11“复位与中断处理” 。
(点击图片放大)
Notes:
1. 熔丝位BOOTRST被编程时,MCU复位后程序跳转到Boot Loader。请参见 P228 “支
持引导装入程序 – 在写的同时可以读(RWW, Read-While-Write)的自我编程能力 ” 。
2. 当寄存器GICR的IVSEL置位时,中断向量转移到Boot区的起始地址。此时各个中断向
量的实际地址为表中地址与Boot 区起始地址之和。
Table 19给出了不同的BOOTRST/IVSEL设置下的复位和中断向量的位置。如果程序永远不使能中断,中断向量就没有意义。用户可以在此直接写程序。同样,如果复位向量位于应用区,而其他中断向量位于Boot 区,则复位向量之后可以直接写程序。反过来亦是如此。
ATmega32 典型的复位和中断设置如下:
地址 符号代码说明
$000 jmp RESET ; 复位中断向量
$002 jmp EXT_INT0 ; IRQ0 中断向量
$004 jmp EXT_INT1 ; IRQ1 中断向量
$006 jmp TIM2_COMP ; Timer2 比较中断向量
$008 jmp TIM2_OVF ; Timer2 溢出中断向量
$00A jmp TIM1_CAPT ; Timer1 捕捉中断向量
$00C jmp TIM1_COMPA ; Timer1 比较A 中断向量
$00E jmp TIM1_COMPB ; Timer1 比较B 中断向量
$010 jmp TIM1_OVF ; Timer1 溢出中断向量
$012 jmp TIM0_OVF ; Timer0 溢出中断向量
$014 jmp SPI_STC ; SPI 传输结束中断向量
$016 jmp USART_RXC ; USART RX 结束中断向量
$018 jmp USART_UDRE ; UDR 空中断向量
$01A jmp USART_TXC ; USART TX 结束中断向量
$01C jmp ADC ; ADC 转换结束中断向量
$01E jmp EE_RDY ; EEPROM 就绪中断向量
$020 jmp ANA_COMP ; 模拟比较器中断向量
$022 jmp TWSI ; 两线串行接口中断向量
$024 jmp EXT_INT2 ; IRQ2 中断向量
$026 jmp TIM0_COMP ; 定时器0 比较中断向量
$028 jmp SPM_RDY ; SPM 就绪中断向量
;
$02A RESET: ldi r16,high(RAMEND) ; 主程序
$02B out SPH,r16 ; 设置堆栈指针为RAM 的顶部
$02C ldi r16,low(RAMEND)
$02D out SPL,r16
$02E sei ; 使能中断
$02F <instr> xxx
... ... ...
当熔丝位BOOTRST 未编程,Boot 区为 4K 字节,且寄存器GICR 的IVSEL 置位时,典
型的复位和中断设置如下:
地址符号代码说明
$000 RESET: ldi r16,high(RAMEND) ; 主程序
$001 out SPH,r16 ; 设置堆栈指针为RAM 的顶部
$002 ldi r16,low(RAMEND)
$003 out SPL,r16
$004 sei ; 使能中断
$005 <instr> xxx
;
.org $3802
$3802 jmp EXT_INT0 ; IRQ0 中断向量
$3804 jmp EXT_INT1 ; IRQ1 中断向量
... .... .. ;
$3828 jmp SPM_RDY ; SPM 就绪中断向量
当熔丝位BOOTRST 已编程,且Boot 区为 4K 字节时,典型的复位和中断设置如下:
地址符号代码说明
.org $002
$002 jmp EXT_INT0 ; IRQ0 中断向量
$004 jmp EXT_INT1 ; IRQ1 中断向量
... .... .. ;
$028 jmp SPM_RDY ; SPM 就绪中断向量
;
.org $3800
$3800 RESET: ldi r16,high(RAMEND) ; 主程序
$3801 out SPH,r16 ; 设置堆栈指针为RAM 的顶部
$3802 ldi r16,low(RAMEND)
$3803 out SPL,r16
$3804 sei ; 使能中断
$3805 <instr> xxx
当熔丝位BOOTRST 已编程,Boot 区为4K 字节,且寄存器GICR 的IVSEL 置位时,典
型的复位和中断设置如下:
地址符号代码说明
.org $3800
$3800 jmp RESET ; Reset 中断向量
$3802 jmp EXT_INT0 ; IRQ0 中断向量
$3804 jmp EXT_INT1 ; IRQ1 中断向量
... .... .. ;
$3828 jmp SPM_RDY ; SPM 就绪中断向量
;
$382A RESET: ldi r16,high(RAMEND) ; 主程序
$382B out SPH,r16 ; 设置堆栈指针为RAM 的顶部
$382C ldi r16,low(RAMEND)
$382D out SPL,r16
$382E sei ; 使能中断
$382F <instr> xxx
在应用区和Boot 区之间移动中断向量
通用中断控制寄存器决定中断向量表的放置地址
通用中断控制寄存器- GICR
· Bit 1 – IVSEL: 中断向量选择
当IVSEL 为"0" 时,中断向量位于Flash 存储器的起始地址;当IVSEL 为"1" 时,中断向量转移到Boot 区的起始地址。实际的Boot 区起始地址由熔丝位BOOTSZ 确定。具体请参考P234“ 支持引导装入程序 – 在写的同时可以读(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 锁定位的细节请参见P228“ 支持引导装入程序 – 在写的同时可以读
(RWW, Read-While-Write) 的自我编程能力” 。
· Bit 0 – IVCE: 中断向量修改使能
改变IVSEL 时IVCE 必须置位。在IVCE 或IVSEL 写操作之后4 个时钟周期, IVCE 被硬件清零。如前面所述,置位IVCE 将禁止中断。代码如下:
汇编代码例程:
Move_interrupts:
; 使能中断向量的修改
ldi r16, (1<<IVCE)
out GICR, r16
; 将中断向量转移到boot Flash区
ldi r16, (1<<IVSEL)
out GICR, r16
ret
C 代码例程
void Move_interrupts(void)
{
/* 使能中断向量的修改*/
GICR = (1<<IVCE);
/* 将中断向量转移到boot Flash区 */
GICR = (1<<IVSEL);
}