AVR单片机外部中断0、1、2 详解中断基本包含:1.中断源2.中断向量(中断入口地址)3.中断优先级4.中断函数除此之外,在单片机中,中断的执行或者中断的触发必须符合以下的规则:中断触发|执行= 全局中断使能位AND 中断源使能位AND 中断源标志位单片机内部中断的触发必须完成,全局中断使能,中断源使能,中断源标志位置一等条件。
除此之外,如果是外部中断0,1,2(INT0,1,2),必须设置引脚触发的规则。
最后呢,就是需要在程序里建立处理中断的中断函数。
在编程的时候的步骤大致如下:(无视INT2)1. 初始化PD2,PD3 为输入状态。
DDRD|=BIT(2)|BIT(3);2. 设置INT0,1 引脚触发的规则,实验中为低电平触发。
MCUCR=0xF0;3. 设置INT0,1 中断源使能位为逻辑1。
GICR|BIT(7)|BIT(6);4. 清除INT0,1 的中断标志位(软件写入,逻辑1 为清除)。
GIFR|=BIT(7);BIT(6);5. 全局中断允许位使能。
SREG|=BIT(7);6. 编辑中断处理函数。
/*ATmega16提供3个外部中断,分别由INT0、INT1和INT2引脚触发。
需要注意的是,如果将ATmega16设置为允许外部中断,则即使把INT0、INT1和INT2引脚设置为输出方式,外部中断仍然会被触发。
外部中断可选择采用上升沿触发、下降沿触发和低电平触发(INT2中断只能采用沿触发方式。
*/#include;#include;#include "smg.h"/*1.状态寄存器SREGbit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0I T H S V N Z CI:全局中断使能位。
在I置位后,单独的中断使能由不同的中断寄存器控制。
若I为0,则禁止中断。
MCU 控制寄存器- MCUCR MCU 控制寄存器包含中断触发控制位与通用 MCU 功能Bit 7 6 5 4 3 2 1 0SM2 SE SM1 SM0 ISC11 ISC10 ISC01 ISC00外部中断 1 由引脚 INT1 激发,如果 SREG 寄存器的 I 标志位和相应的中断屏蔽位置位的话。
在检测边沿前MCU 首先采样 INT1 引脚上的电平。
如果选择了边沿触发方式或电平变化触发方式,那么持续时间大于一个时钟周期的脉冲将触发中断,过短的脉冲则不能保证触发中断。
如果选择低电平触发方式,那么低电平必须保持到当前指令执行完成。
SE:MCU休眠使能位SM1~SM0:MCU休眠模式选择SM2 SM1 SM0 休眠模式0 0 0 空闲0 0 1 ADC 噪声抑制模式0 1 0 掉电模式0 1 1 省电模式1 0 0 保留1 0 1 保留1 1 0 Standby(1) 模式1 1 1 扩展Standby(1) 模式ISC11 ISC10 说明0 0 INT1 为低电平时产生中断请求0 1 INT1 引脚上任意的逻辑电平变化都将引发中断1 0 INT1 的下降沿产生异步中断请求1 1 INT1 的上升沿产生异步中断请求外部中断 0 由引脚 INT0 激发,如果 SREG 寄存器的 I 标志位和相应的中断屏蔽位置位的话。
在检测边沿前MCU 首先采样 INT0 引脚上的电平。
如果选择了边沿触发方式或电平变化触发方式,那么持续时间大于一个时钟周期的脉冲将触发中断,过短的脉冲则不能保证触发中断。
如果选择低电平触发方式,那么低电平必须保持到当前指令执行完成ISC01 ISC00 说明0 0 INT0 为低电平时产生中断请求0 1 INT0 引脚上任意的逻辑电平变化都将引发中断1 0 INT0 的下降沿产生异步中断请求1 1 INT0 的上升沿产生异步中断请求*//*MCU 控制与状态寄存器-MCUCSR-Bit 7 6 5 4 3 2 1 0JTD ISC2 – JTRF WDRF BORF EXTRF PORF * Bit 6 – ISC2: 中断 2 触发方式控制异步外中断 2 由外部引脚 INT2 激活,如果 SREG 寄存器的 I 标志和 GICR 寄存器相应的中断屏蔽位置位的话。
若 ISC2 写 0 , INT2 的下降沿激活中断。
若 ISC2 写 1 , INT2 的上升沿激活中断。
INT2 的边沿触发方式是异步的。
只要 INT2 引脚上产生宽度大于50ns(1s=1000ms,1 ms=1000μs,1μs=1000ns ) 所示数据的脉冲就会引发中断。
若选择了低电平中断,低电平必须保持到当前指令完成,然后才会产生中断。
而且只要将引脚拉低,就会引发中断请求。
改变 ISC2 时有可能发生中断。
因此建议首先在寄存器 GICR 里清除相应的中断使能位 INT2 ,然后再改变ISC2。
最后,不要忘记在重新使能中断之前通过对 GIFR 寄存器的相应中断标志位 INTF2 写 '1’使其清零。
*//*通用中断控制寄存器- GICRBit 7 6 5 4 3 2 1 0INT1 INT0 INT2 – – – IVSEL IVCE* 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 引脚被配置为输出,只要引脚电平发生了相应的变化,中断可将产生*//*通用中断标志寄存器- GIFRBit 7 6 5 4 3 2 1 0INTF1 INTF0 INTF2 – – – – –* Bit 7 – INTF1: 外部中断标志 1INT1引脚电平发生跳变时触发中断请求,并置位相应的中断标志INTF1。
如果SREG 的位I以及GICR寄存器相应的中断使能位INT1为”1” ,MCU即跳转到相应的中断向量。
进入中断服务程序之后该标志自动清零。
此外,标志位也可以通过写入 ”0” 来清零。
* Bit 6 – INTF0: 外部中断标志 0INT0引脚电平发生跳变时触发中断请求,并置位相应的中断标志INTF0。
如果SREG 的位I以及GICR寄存器相应的中断使能位INT0为”1” ,MCU即跳转到相应的中断向量。
进入中断服务程序之后该标志自动清零。
此外,标志位也可以通过写入 ”0” 来清零。
* Bit 5 – INTF2: 外部中断标志 2INT2引脚电平发生跳变时触发中断请求,并置位相应的中断标志INTF2。
如果SREG 的位I以及GICR寄存器相应的中断使能位INT2为”1” ,MCU即跳转到相应的中断向量。
进入中断服务程序之后该标志自动清零。
此外,标志位也可以通过写入 ”0” 来清零。
注意,当INT2中断禁用进入某些休眠模式时,该引脚的输入缓冲将禁用。
这会导致INTF2标志设置信号的逻辑变化*///外部中断0向量端口#pragma interrupt_handler INTER_0:iv_INT0//外部中断1向量端口#pragma interrupt_handler INTER_1:iv_INT1//外部中断2向量端口#pragma interrupt_handler INTER_2:iv_INT2void INTER_init_0(unsigned char a)//a取值0-3 {switch(a){case0:MCUCR&=~(1<<ISC01);MCUCR&=~(1<<ISC00);break;//INT0 为低电平时产生中断请求case1:MCUCR&=~(1<<ISC01);MCUCR|=1<<ISC00;break;//INT0 引脚上任意的逻辑电平变化都将引发中断case2:MCUCR|=1<<ISC01;MCUCR&=~(1<<ISC00);break;//INT0 的下降沿产生异步中断请求case3:MCUCR|=1<<ISC01;MCUCR|=1<<ISC00;break;//INT0 的上升沿产生异步中断请求default :MCUCR|=1<<ISC01;MCUCR&=~(1<<ISC00);break;//设置错误时,下降沿产生异步中断请求}}void INTER_init_1(unsigned char a)//a取值0-3 {switch(a){case0:MCUCR&=~(1<<ISC11);MCUCR&=~(1<<ISC10);break;//I NT1 为低电平时产生中断请求case1:MCUCR&=~(1<<ISC11);MCUCR|=1<<ISC10;break;//INT1 引脚上任意的逻辑电平变化都将引发中断case2:MCUCR|=1<<ISC11;MCUCR&=~(1<<ISC10);break;//INT1 的下降沿产生异步中断请求case 3:MCUCR|=(1<<ISC11)|(1<<ISC10);break;//INT1 的上升沿产生异步中断请求default :MCUCR|=1<<ISC11;MCUCR&=~(1<<ISC10);break;//设置错误时,下降沿产生异步中断请求}}void INTER_init_2(unsigned char a){if(a)MCUCSR|=(1<<ISC2);//上升沿触发;elseMCUCSR&=~(1<<ISC2);//下降沿触发;}void INTER_0(void){show(2,1);//add your code here!}void INTER_1(void){show(1,0);//add your code here!}void INTER_2(void){// show(3,2);//add your code here!}void InterruptInit(void){PORTD |= (1 << PD2)|(1 << PD3); //INT0、INT1端口输出高电平DDRD &= ~(1 << PD2)&~(1 << PD3); //方向:输入PORTB = (1 << PB3); //INT2端口输出高电平DDRB &= ~(1 << PB3); //方向:输入GICR |= (1 << INT0)|(1 << INT1)|(1<<INT2);//使能INT0,INT1GIFR&=~(1<<INTF0)&~(1<<INTF1)&~(1<<INTF2);//清零中断标志SREG|=0x80;//使能全局中断}///////////////////////////////////////////////////////////////////#include "smg.h"#pragma data:code//共阳数码管断码表consttable[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xb6,0xff}; //**********1ms基准延时程序**********************************void delay(uint ms){uint i,j;for(i=0;i<ms;i++){for(j=0;j<1141;j++);}}//***********系统初始化************************* void SmgInit(void){DDRA|=BIT(PA2);//设置PA2为输出DDRB=0XFF;//设置PB口为输出PORTA|=BIT(PA2);//PA2=1,使能控制LED的74HC573 PORTB|=0XFF;//PB口输出1111 1111,使得所有的LED 熄灭PORTA&=~BIT(PA2);//PA2=0,禁止控制LED的573,使控制LED的数据锁存DDRA|=BIT(PA3);//设置PA3(smgd_lk)为输出DDRA|=BIT(PA4);//设置PA4(SMGB_LK)为输出DDRA|=BIT(PA6);//设置蜂鸣器控制口为输出PORTA&=~BIT(PA6);//关闭蜂鸣器}//***********数码管动态扫描程序*************************void show(uchar data,uchar bit){PORTA|=BIT(3);//PA3=1,使能控制数码管数据的74HC573PORTB=table[data];//送数码管断码数据PORTA&=~BIT(3);//关闭控制数码管数据的573,使得数码管数据锁存PORTB=0X00;//PB口输出0000 0000PORTA|=BIT(4);//PA4=1,使能控制数码管数据口的573 PORTB|=BIT(bit);//数码管位选PORTA&=~BIT(4);//数码管位选锁存delay(1);//稍微延时}///////////////////////////////////////////////// //////////////////////////////#include "smg.h"#include "interrupt.h"void main(void){// unsigned char i;SmgInit();InterruptInit();INTER_init_0(2);INTER_init_1(2);INTER_init_2(0);while(1) {;}}。