AVR_Interrupt

#AVR中断系统与基本应用(ATMega16)
##一、中断的基本概念
###1.1 中断的基本概念

  • 中断是指计算机自动响应的一个中断请求信号,暂时停止(中断)当前程序的执行,转而执行为外部设备服务 的型号(中断服务程序),并在执行完服务程序后自动返回原程序的过程。
  • 具有的优势
    • 实现实时处理
    • 实现分时操作,提高MCU的处理效率
    • 进行故障处理
    • 待机状态的唤醒
      ###1.2 中断的处理过程
  • 由于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$000RESET外部引脚电平引发的复位、上电复位、掉电检测复位、看门狗复位和JTAG AVR复位
2$002INT0外部中断请求0SIG_INTERRUPT0
3$004INT1外部中断请求1SIG_INTERRUPT1
4$006TIMER2 COMP定时器/计数器2比较匹配SIG_OUTPUT_COMPARE2
5$008TIMER2 OVF定时器/计数器2溢出SIG_OVERFLOW2
6$00ATIMER1 CAPT定时器/计数器1事件捕捉TIMER1_CAPT_vect
7$00CTIMER1 COMPA定时器/计数器1比较匹配ASIG_OUTPUT_COMPARE1A
8$00ETIMER1 COMPB定时器/计数器1比较匹配BSIG_OUTPUT_COMPARE1B
9$010TIMER1 OVF定时器/计数器1溢出SIG_OVERFLOW1
10$012TIMER0 OVF定时器/计数器0溢出SIG_OVERFLOW0
11$014SPI STCSPI串行输入结束SIG_SPI
12$016USART RXCUSART,接收结束SIG_UART_RECV
13$018USART UDREUSART,数据寄存器空SIG_UART_DATA
14$01AUSART TXCUSART,发送结束SIG_UART_TRANS
15$01CADCA/D转换结束SIG_ADC
16$01EEE RDYEEPROM就绪SIG_EEPROM_READY
17$020ANA_COMP模拟比较器SIG_COMPARATOR
18$022TWI两线串行接口SIG_2WIRE_SERIAL
19$024INT2外部中断请求2SIG_INTERRUPT2
20$026TIMER0 COMP定时/计数器0比较匹配SIG_OUTPUT_COMPARE0
21$028SPM_RDY保存程序寄存器内容就绪SIG_SPM_READY
  • 这21个中断中,包含1个非屏蔽中断(RESET),3个外部中断(INT0,INT1,INT2)和17个内部中断
    ###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 种中断触发方式:
触发方式INT0INT1INT2说明
上升沿触发YesYesYes(异步)
下降沿触发YesYesYes(异步)
任意电平变化触发YesYes——
低电平触发YesYes——无中断标志

###3.2 与外部中断相关的寄存器和标志位

  • 在ATMega16中,除了寄存器SERG的全局中断允许标志位 I 外,与外部中断有关的寄存器有 4 个,其中有 11 个标志位。其作用分别是 3 个外部中断各自的中断标志位,中断允许标志位及用于定义外部中断的触发类型。

  • 1) MCU 控制寄存器 MCUCR

76543210
$35($0055)SM2SESM1SM0ISC11ISC10ISC01ISC00
读/写R/WR/WR/WR/WR/WR/WR/WR/W
初始化值00000000

INT0,INT1中断触发方式:

ISCn1ISCn0中断的触发方式
00INTn的低电平产生一个中断请求
01INTn的下降沿和上升沿都产生一个中断请求
10INTn的下降沿产生一个中断请求
11INTn的上升沿产生一个中断请求
  • 2) MCU 控制和状态寄存器 MCUCSR
76543210
$34($0054)JTDICS2——JTRFWDRFBORFEXDRFPORF
读/写R/WR/WRR/WR/WR/WR/WR/W
初始化值000RESET复位RESET复位RESET复位RESET复位RESET复位

INT2中断触发方式:

ISC2中断的触发方式
0INT2的下降沿产生一个异步中断请求
1INT2的上升沿产生一个异步中断请求
  • 3) 通用中断控制寄存器 GICR
    • 通用中断控制寄存器 GICR 的高 3 位为INT0,INT1,INT2的中断允许控制位,如果SERG寄存器的I为**“1”,而且GICF寄存器中相应的中断允许控制位为“1”,那当 INTn 中断触发时, MCU 就会响应中断。**
76543210
$3B($005B)INT1INT0INT2——————IVSELIVCE
读/写R/WR/WR/WRRRR/WR/W
初始化值00000000
  • 4) 通用中断标志寄存器 GIFR
    • 通用中断标志寄存器 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 ,并不意味着不产生中断请求,而是低电平触发方式是不带中断标志类型的中断触发。
    • 低电平触发时,中断请求将一直保持到引脚的低电平消失为止。
76543210
$3A($005A)INTF1INTF0INTF2——————————
读/写R/WR/WR/WRRRRR
初始化值00000000

##四、外部中断简单实用实例
###4.1 WinAVR平台

  • 代码实例:
/**
*作者: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;
}
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值