AVR_Interrupt
2017-01-31 14:31
113 查看
AVR中断系统与基本应用(ATMega16)
一、中断的基本概念
1.1 中断的基本概念
中断是指计算机自动响应的一个中断请求信号,暂时停止(中断)当前程序的执行,转而执行为外部设备服务 的型号(中断服务程序),并在执行完服务程序后自动返回原程序的过程。具有的优势
实现实时处理
实现分时操作,提高MCU的处理效率
进行故障处理
待机状态的唤醒
1.2 中断的处理过程
![](http://i.imgur.com/c06w3jq.jpg)
由于MCU处理完中断之后需要返回原程序,因此,要在执行中断之前,要将主程序中断处的地址,即断点处(实际上是程序计数器PC的当前地址值——即即将执行的主程序的下一条指令,即图中的k + 1处)保护起来,称为保护断点
除了保护断点,在程序执行之前,还要把有关的数据保护起来,称为中断现场保护,方便在返回主程序的时候继续执行,这一过程称为恢复现场和恢复断点
简单说,在响应中断的时候,MCU的硬件系统会将断点地址压进系统的堆栈保护,而在执行中断返回指令时,硬件系统又会自动将断点地址弹出到程序计数器PC中。
1.3 中断源、中断信号和中断向量
中断源一般可分为内部中断和外部中断
典型的中断有定时器溢出中断,ADC完成中断等
系统中的外部设备也可以作为中断源,这些中断源位于单片机外部,所以称之为外部中断源
中断信号
中断信号是指内部或者外部中断源产生的中断申请信号。这个中断信号往往是电信号的某种变化形式,通常有几种类型
脉冲的上升沿或者是下降沿(上升沿触发型或者是下降沿触发型)
高电平或者是低电平(电平触发型)
电平的变化(状态变化触发型)
单片机硬件系统会对这些触发源自动检测,一旦检测到信号,就会将相应的中断标志位置位 1 (在I/O空间的控制或状态寄存器中),通知CPU进行处理。
中断向量
中断源发出的请求信号被CPU检测到之后,如果单片机的中断控制系统允许中断响应,则CPU会自动转移,执行一个固定的程序空间地址中的指令。这个固定的地址叫做中断的入口地址,也叫做中断向量
一般,一个单片机有若干个中断源,而每个中断源都有自己相应的中断向量
1.4 中断的优先级和中断嵌套
中断的优先级,一般由单片机的硬件结构所决定,决定方式一般有两种:某个中断的中断向量越小,其中断的优先级越高
通过软件对中断寄存器进行设置,改变优先级
注意:AVR不支持用户改变中断的优先级,C51单片机可以
MCU只能同时响应一个中断,假如有多个中断同时申请时MCU已经在执行中断,MCU会暂停该中断的执行,执行优先级更高的那个中断,完成后进而执行未完成的中断,再响应其他较低优先级的中断,这就有导致中断嵌套
但是需要注意,一些单片机(如8051结构)的硬件能够自动处理中断嵌套,但是另一些单片机(如AVR ATMega16)却不可以自动处理中断嵌套,这需要通过软件实现中断嵌套的处理
1.5 中断的响应条件和中断的控制
在有些设计中不允许打断现有程序的运行,因此单片机就需要单片机有一套中断屏蔽/允许的系统。在单片机的I/O寄存器中,通常存在一些特殊的标志位用于控制使能和禁止(屏蔽)MCU对中断的响应,这些标志称之为中断屏蔽标志位或者是中断允许标志位
从中断控制的角度来讲,中断源还可以分为三类:
非屏蔽中断:也就是MCU对中断的请求是不可以屏蔽的,比如外部 (RESET)’ 引脚产生的复位信号,就是一个非屏蔽中断。
可屏蔽中断:可以通过用户设置使能或者禁止MCU响应中断,一旦发生中断请求,则MCU只能在中断使能的条件下响应中断。
软件中断:是指具有响应的软件中断指令,当MCU执行执行这条指令时,就可以进入软件中断服务,完成特定的功能,一般用于调试。一般单片机中都没有软件中断的指令,因此,在单片机系统中,如果必须使用软件中断的功能,则一般需要通过间接的方式来实现。
MCU中断响应一个可屏蔽中断源(假定是 A 中断)中断请求的条件是:
响应 A 中断 = 全局中断允许标志 + 中断 A 允许标志 + 中断 A 标志
全局中断允许标志位为“ 1 ”(用户软件设置)
中断 A 允许标志位为“ 1 ”(用户软件设置)
中断 A 标志为“ 1 ”(符合中断条件时,由硬件自动设置或者由用户设置)
三者缺一不可!!!
二、ATMega16的中断系统
2.1 ATMega16的中断源和中断向量
AVR 一般具有数十个中断源,每个中断源都有自己的中断向量。默认情况下,AVR的程序存储器的最低端,即从Flash存储器地址0x0000开始存储中断向量,称之为中断向量区。AVR中断向量区的大小是不同的,由下式决定:
中断向量区大小 = 中断源个数 x 每个中断向量占据字数
ATMega16中断向量区表:
向量号 | Flash空间地址(中断向量) | 中断源 | 中断定义说明 | 在GCC中的中断名SIG_NAME |
---|---|---|---|---|
1 | $000 | RESET | 外部引脚电平引发的复位、上电复位、掉电检测复位、看门狗复位和JTAG AVR复位 | |
2 | $002 | INT0 | 外部中断请求0 | SIG_INTERRUPT0 |
3 | $004 | INT1 | 外部中断请求1 | SIG_INTERRUPT1 |
4 | $006 | TIMER2 COMP | 定时器/计数器2比较匹配 | SIG_OUTPUT_COMPARE2 |
5 | $008 | TIMER2 OVF | 定时器/计数器2溢出 | SIG_OVERFLOW2 |
6 | $00A | TIMER1 CAPT | 定时器/计数器1事件捕捉 | |
7 | $00C | TIMER1 COMPA | 定时器/计数器1比较匹配A | SIG_OUTPUT_COMPARE1A |
8 | $00E | TIMER1 COMPB | 定时器/计数器1比较匹配B | SIG_OUTPUT_COMPARE1B |
9 | $010 | TIMER1 OVF | 定时器/计数器1溢出 | SIG_OVERFLOW1 |
10 | $012 | TIMER0 OVF | 定时器/计数器0溢出 | SIG_OVERFLOW0 |
11 | $014 | SPI STC | SPI串行输入结束 | SIG_SPI |
12 | $016 | USART RXC | USART,接收结束 | SIG_UART_RECV |
13 | $018 | USART UDRE | USART,数据寄存器空 | SIG_UART_DATA |
14 | $01A | USART TXC | USART,发送结束 | SIG_UART_TRANS c6f5 |
15 | $01C | ADC | A/D转换结束 | SIG_ADC |
16 | $01E | EE RDY | EEPROM就绪 | SIG_EEPROM_READY |
17 | $020 | ANA_COMP | 模拟比较器 | SIG_COMPARATOR |
18 | $022 | TWI | 两线串行接口 | SIG_2WIRE_SERIAL |
19 | $024 | INT2 | 外部中断请求2 | SIG_INTERRUPT2 |
20 | $026 | TIMER0 COMP | 定时/计数器0比较匹配 | SIG_OUTPUT_COMPARE0 |
21 | $028 | SPM_RDY | 保存程序寄存器内容就绪 | SIG_SPM_READY |
2.2 中断优先级的确定
在AVR单片机中,一个中断在中断向量区的位置决定了他的优先级。位于低地址的中断优先级高于位于高地址的中断。2.3 中断标志
AVR具有两种不同机制的中断:带有中断标志的中断(可挂起)
不带有中断标志的中断(不可挂起)
这里的挂起是指在中断嵌套的时候,能否等待 MCU 对齐响应
中断标志位一般在 MCU 响应之后会自动清除,或者在中断服务程序中通过读写专门数据寄存器的方式自动清除。
若用软件的方法清除,清除的方法是对其写 1 !!!
在 AVR 中,还有个别不带(不设置)中断标志,例如配置为低电平触发的外部中断即为此类型的中断。该中断只要满足外部输入低电平,就会一直向 MCU 发出中断申请,这种外部低电平中断有其特殊性,他不会产生中断标志,因此不能挂起。如果等待时间过长而得不到响应,则可能因为中断条件结束而失去一次服务的机会。
在退出中断后, AVR 至少要在执行一条指令才能去响应其他被挂起的中断!!!
2.4 中断屏蔽与管理
winAVR 平台中:asm("sei"); //全局中断使能 asm("cli"); //全局中断禁止
ICCAVR 平台中:
#asm("sei"); //全局中断使能 #asm("cli"); //全局中断禁止
注意两个平台上使用的区别!
三、ATMega16的外部中断
ATMega16有 INT0 , INT1 , INT2 这三个外部中断源,分别由芯片外部引脚PD2,PD3,PB2上的电平变化或状态作为中断触发源信号3.1 外部中断的触发方式和特点
INT0,INT1,INT2的中断触发方式取决于用户程序对 MCU 控制寄存器 MCUCR 和 MCU 控制与状态寄存器 MCUCSR 的设定。外部中断的 4 种中断触发方式:
触发方式 | INT0 | INT1 | INT2 | 说明 |
---|---|---|---|---|
上升沿触发 | Yes | Yes | Yes(异步) | |
下降沿触发 | Yes | Yes | Yes(异步) | |
任意电平变化触发 | Yes | Yes | —— | |
低电平触发 | Yes | Yes | —— | 无中断标志 |
3.2 与外部中断相关的寄存器和标志位
在ATMega16中,除了寄存器SERG的全局中断允许标志位 I 外,与外部中断有关的寄存器有 4 个,其中有 11 个标志位。其作用分别是 3 个外部中断各自的中断标志位,中断允许标志位及用于定义外部中断的触发类型。1) MCU 控制寄存器 MCUCR
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
$35($0055) | SM2 | SE | SM1 | SM0 | ISC11 | ISC10 | ISC01 | ISC00 |
读/写 | R/W | R/W | R/W | R/W | R/W | R/W | R/W | R/W |
初始化值 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
ISCn1 | ISCn0 | 中断的触发方式 |
---|---|---|
0 | 0 | INTn的低电平产生一个中断请求 |
0 | 1 | INTn的下降沿和上升沿都产生一个中断请求 |
1 | 0 | INTn的下降沿产生一个中断请求 |
1 | 1 | INTn的上升沿产生一个中断请求 |
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
$34($0054) | JTD | ICS2 | —— | JTRF | WDRF | BORF | EXDRF | PORF |
读/写 | R/W | R/W | R | R/W | R/W | R/W | R/W | R/W |
初始化值 | 0 | 0 | 0 | RESET复位 | RESET复位 | RESET复位 | RESET复位 | RESET复位 |
ISC2 | 中断的触发方式 |
---|---|
0 | INT2的下降沿产生一个异步中断请求 |
1 | INT2的上升沿产生一个异步中断请求 |
* 通用中断控制寄存器 GICR 的高 3 位为INT0,INT1,INT2的中断允许控制位,如果SERG寄存器的I为“1”,而且GICF寄存器中相应的中断允许控制位为“1”,那当 INTn 中断触发时, MCU 就会响应中断。
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
$3B($005B) | INT1 | INT0 | INT2 | —— | —— | —— | IVSEL | IVCE |
读/写 | R/W | R/W | R/W | R | R | R | R/W | R/W |
初始化值 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
* 通用中断标志寄存器 GIFR 的高 3 位为INT0,INT1,INT2的中断标志位。
* 当INT0,INT1,INT2引脚上的有效事件满足中断触发条件之后,INT0,INTF1,INTF2位会变为 1 。假如 MCU 响应中断服务,硬件会自动将 INTFn 位置位“0”
* 用户可以使用指令将 INTFn清 0 ,清除的方式是 INTFn 置位 “1”,将标志清 0
* 当INTF0(INTF1)设置为低电平触发时,标志位INTF0(INTF1)始终未 0 ,并不意味着不产生中断请求,而是低电平触发方式是不带中断标志类型的中断触发。
* 低电平触发时,中断请求将一直保持到引脚的低电平消失为止。
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
$3A($005A) | INTF1 | INTF0 | INTF2 | —— | —— | —— | —— | —— |
读/写 | R/W | R/W | R/W | R | R | R | R | R |
初始化值 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
四、外部中断简单实用实例
4.1 WinAVR平台
![](http://i.imgur.com/dstgaHK.jpg)
代码实例:
/** *作者:Dandri *时间:2017/01/31 *MCU:ATMega16 *频率:8MHz *功能:按下两次按键,LED灯亮一次 */ #include <avr/io.h> #include <avr/interrupt.h> unsigned char count = 0;//用于计数按下按键的次数 unsigned char flag = 0; //用于启动点灯的标志 //中断向量地址里的程序 #pragma interrupt_handler int0_isr:2 //首先使用#pragma interrupt_handler int0_isr:2声明中断,2表示中断向量号 void int0_isr(void) { count++; if (count >= 2) { flag = 1; count = 0; //计数器清0 } } //外部中断相关的寄存器初始化,因为接的是PD2,使用的是INT0 void int0_init() { GIFR = 0x40; //INTF0 标志位清零 MCUCR = 0X02; //INT0下降沿触发 GICR = 0X40; //INT0触发允许 } //引脚初始化 void port_init() { DDRC = 0X01; PORTC = 0X00; } //亮灯程序 void led() { if (flag == 1) { PORTC = 0X01; flag = 0; } else PORTC = 0X00; } int main() { port_init(); int0_init(); asm("sei"); //启用全局中断 while(1) { led(); } return 0; }
相关文章推荐
- Linux中断(interrupt)子系统之三:中断流控处理层
- AVR Programming Methods
- 关于java线程的interrupt方法的使用总结
- 51、AVR、PIC、MSP430、ARM五大单片机全解析
- AVRmega16通过一个定时器实现多路IO口输出多路可调的PWM
- 把arduino当AVRISP烧写器Arduino给Arduino烧boot
- Linux中断(interrupt)子系统之三:中断流控处理层
- Java Thread.interrupt interrupted
- Java中的线程的唤醒Thread.interrupt()
- JAVA——如何停止线程呢?(interrupt)
- 对Thread.interrupt()方法很详细的介绍
- How /proc/interrupts gets updated?
- 【java】Thread 常搞混的几个概念sleep、wait、yield、interrupt
- 停止Java线程,小心interrupt()方法
- Java Thread.interrupt方法
- AVR单片机驱动LCD1602
- linux dts interrupt
- stm8s_STVD生成interrupt_vector.c问题
- Java线程的终止——interrupt
- AVR USART接收中断程序