ATMEAGl6L的中断系统什么是“中断”?顾名思义中断就是中断某一工作过程去处理一些与本工作过程无关或间接相关或临时发生的事件,处理完后,则继续原工作过程。比如:你在看书,电话响了,你在书上做个记号后去接电话,接完后在原记号处继续往下看书。如有多个中断发生,依优先法则,中断还具有嵌套特性。又比如:看书时,电话响了,你在书上做个记号后去接电话,你拿起电话和对方通话,这时门铃响了,你让打电话的对方稍等一下,你去开门,并在门旁与来访者交谈,谈话结束,关好门,回到电话机旁,拿起电话,继续通话,通话完毕,挂上电话,从作记号的地方继续往下看书。由于一个人不可能同时完成多项任务,因此只好采用中断方法,一件一件地做。
类似的情况在单片机中也同样存在,通常单片机中只有一个CPU,但却要应付诸如运行程序、数据输入输出以及特殊情况处理等多项任务,为此也只能采用停下一个工作去处理另一个工作的中断方法。在单片机中,“中断”是一个很重要的概念。中断技术的进步使单片机的发展和应用大大地推进了一步。所以,中断功能的强弱已成为衡量单片机功能完善与否的重要指标。中断系统的引入解决了微处理器和外设之间数据传输速率的问题,提高了微处理器的实时性和处理能力。
当微处理器处于中断开放时,才能接受外部的中断申请。一个完整的中断处理过程包括中断请求、中断响应、中断处理和中断返回。
中断请求是中断源向微处理器发出的信号,要求微处理器暂停原来执行的程序并为之服务。中断请求可以是电平信号或者脉冲信号。中断请求信号一般保持到微处理器作出响应为止。微处理器在检测到中断请求信号之后,将中止当前正在执行的程序,并对断点实行保护,即将断点的地址(PC值)推入堆栈保护,以便在中断结束时从堆栈弹出断点地址,以便继续执行中断前的任务。然后,微处理器由中断地址表获取中断入口地址,并将此地址送入程序计数器(PC),从而开始执行中断服务程序。在中断服务程序里一般需要完成现场保护、开关中断、执行中断服务程序、现场恢复和中断返回等工作。
ATMEAG16L具有20个中断源和1个复位中断,在中断源中处于低地址的中断具有高的优先级。所有中断源都有独立的中断使能位,当相应的使能位和全局中断使能位(SREG寄存器的位I)都置1时,中断才可以发生,相应的中断服务程序才会执行。下表为ATMEAGl6L的中断源。
向量号
程序地
中断源
中断足义
1
0x000
RESET
外部引脚电平引发的复位,上电复位,掉电检测复位,看门狗复位,以及JTAGAVR复位
2
0x002
INT0
外部中断请求0
3
0x004
INT1
外部中断请求1
4
0x006
TIMER2COMP
定时器/计数器2比较匹配
5
0x008
TIMER2OVF
定时器/计数器2溢出
6
0x00A
TIMERlCAPT
定时器/计数器1事件捕捉
7
0x00C
TIMERlCOMPA
定时器/计数器1比较匹配A
8
0x00E
TIMER1COMPB
定时器/计数器1比较匹配B
9
0x010
TIMER1OVF
定时器/计数器1溢出
10
0x012
TIMER0OVF
定时器/计数器O溢出,
11
0x014
SPI.STC
SPI串行传输结束
12
0x016
USART.RXC
USART,Rx结束
13
0x018
USART.UDRE
USART数据寄存器空
14
0x01A
USART。TXC
USART,Tx结束
15
0x01C
ADC
ADC转换结束
16
0x01E
EERDY
EEPROM就绪
17
0x020
ANACOMP
模拟比较器
18
0x022
TWI
两线串行接口
19
0x024
INT2
外部中断请求2
20
0x026
TIMER0COMP
定时器/计数器0比较匹配
21
0x028
SPMRDY
保存程序存储器内容就绪
一个中断产生后,SREG寄存器的全局中断使能位I将被清零,后续中断被屏蔽。
用户可以在中断服务程序里对I置位从而再次开放中断。在中断返回后,全局中断位I将重新置位。当程序计数器指向中断向量开始执行相应的串断暇务程序时,对应中断标志位将被硬件清零。当一个符合条件的中断发生后,如果相应的中断使能位为0,中断标志位将挂起并一直保持到中断执行或者被软件清除。如果全局中断标志I被清零,则所有的中断都不会被执行直到I置位。然后,被挂起的各个中断按中断优先级依次被处理。
ATMEAG16L的外部中断编程实践ATMEAG16L具有多达20个中断源,这里我们首先进行外部中断的实验,其它的等到介绍到相关内容时再进行实验。
1.外部中断0外部中断0由引脚INT0(PIND2)触发。如果INT0引脚按照MCUCR寄存器中的ISC01、ISC00设置的方式发生跳变,则不管是否INTO中断使能,INTO中断标志位INTFO都将置位。如果SREG寄存器的全局中断位I和通用中断控制寄存器GICR中的lNT0中断使能位INTO置位,则开始执行中断程序。在进入中断服务程序时,INTF0被硬件清零。必须指出,不管INT0(PIND2)引脚方向位设置如何,只要INT0引脚发生规定的跳变,都会触发中断。中断标志位INTF0只在满足发生中断的条件时置位,一旦条件变化,INTF0被硬件清零。向INTF0位写“1”也会对其清零。
2.外部中断1外部中断1由引脚INTI(PIND3)触发。如果INTl引脚按照MCUCR寄存器中的ISC11、ISC10设置的方式发生跳变,则不管是否INT1中断使能,INT1中断标志位INTF1都将置位。如果SREG寄存器的全局中断位l和通用中断控制寄存器GICR中的INTl中断使能位INT1置位,则开始执行中断程序。在进入中断服务程序时,INTF1被硬件清零。必须指出,不管INT1(PIND3)引脚方向位设置如何,只要INT1引脚发生规定的跳变,都会触发中断。中断标志位INTF1只在满足发生中断的条件时置位,一旦条件变化,INTF1被硬件清零。向INTF1位写“1”,也会对其清零。
3.外部中断2外部中断2由引脚INT2(PINB2)触发。如果INT2引脚按照MCUCR寄存器中的ISC2设置的方式发生跳变,则不管是否INT2中断使能,INT2中断标志位INTF2都将置位。如果SREG寄存器的全局中断位I和通用中断控制寄存器GICR中的INT2中断使能位INT2置位,则开始执行中断程序。在进入中断服务程序时,INTF2被硬件清零。必须指出,不管INT2(PINB2)引脚方向位设置如何,只要INT2引脚发生规定的跳变,都会触发中断。中断标志位INTF2只在满足发生中断的条件时置位,一旦条件变化,INTF2被硬件清零。向INTF1位写“1”,也会对其清零。
INT1中断实验:平时8个LED闪烁,点亮/熄灭时间约500mS。一旦INT1触发中断后,蜂鸣器发出10秒的报警声。
在我的文档中新建一个ac6的文件夹。建立一个ac6.prj的工程项目,最后建立源程序文件ac6.C。输入下面的程序(程序1):
编译通过后,可在AVRStudio集成开发环境中进行INTO、INT1中断嵌套实验:平时8个LED闪烁,点亮/熄灭时间约500ms。INTl触发中断后,蜂鸣器发出1O秒的报警声。在INT1的中断服务子函数中,再置位总中断使能位I,这样INT1中断服务子函数中,即可进行INT0中断嵌套。当INT0触发中断时,进入INT0中断服务子函数,将8个LED的一半熄灭。
在我的文档中新建一个ac7的文件夹。建立一个JTAG在线仿真或进行软件模拟仿真。仿真完成后,将ac6.hex文件下载到AVR单片机综合试验板上。注意,标示“LED”及“INT1”的双排针应插上短路块。我们看到,D1-D8发光管闪亮,间隔约0.5秒。按下INT1键后,单片机进入中断,蜂鸣器发声10秒。
ac7.prj的工程项目,最后建立源程序文件ac7.C。输入下面的程序(程序2):
编译通过后,可在AVRStudio集成开发环境中进行JTAG在线仿真或进行软件模拟仿真。仿真完成后,将ac7.hex文件下载到AVR单片机综合试验板上进行实际的中断操作。注意,标示“LED”、“BEEP”及“INT0”、“INT1”的双排针应插上短路块。
两路防盗报警器实验:平时一个数码管熄灭。当盗情发生时自动显示“1”或“2”,同时一个LED点亮(代表报警)。着两路同时产生盗情,则数码管每隔2秒轮流显示“1”、“2”。直到值班人员按下复位按钮后才解除报警。
在我的文档中新建一个ac8的文件夹。建立一个ac8.pd的工程项目,最后建立源程序文件ac8.C。输入下面的程序(程序3):
程序3)
#include //包含头文件
#define uchar unsigned char ∥变量类型的宏定
义
#define uint unsigned int
uchar const SEG7f [10]={0X3f,0x06.0x5b,∥共阴极数
码管0-9的字形码
0x4f,Ox66;Ox6d,0x7d,Ox07,0x7f,0x6f};
#define ALM_ON(PORTB=PORTB&0xfe)//报警
器启动
uchar aim_flag1,alm_flag2;//第1、2路盗情标志
//**********************************
void delay_ms(uint k)//定义毫秒级的延时子函数
{
uint i,j;
for(=O:i
{
for(j=0;j<1140;j++)
}
}
//========================
void main(void)∥定义主函数
{ ∥主函数开始
DDRA=0xff; ∥将PA端口设为输出
DDRC=0xff; ∥将PC端口设为输出
PORTA=0x00;#PA端口初始化输出00000000
PORTC=0xff; //PC端口初始化输出1 1 11 1 1 1 1
PORTB=0xff; //PB端口初始化输出11 11 1 1 1 1
DDRB=0xff: //将PB端口设为输出
PORTD=0xff; #PD端口初始化输出1 111111 1
DDRD=0xf3; //将PIND2、3设为输入
MCUCR=0x0A;//INT0、1为下降沿触发
GICR:0xC0;//使能INT0、1中断
SREG=0x80;//使能总中断
while(1) //无限循环
{ ∥无限循环语句开始
if(alm_flag1==1)//如果第1路产生盗情
{PORTA=SEG7[1];∥数码管显示为1
PORTC=Oxfe;//点亮最右的数码管
ALM_ON://报警器启动
delay_ms(2000);#延时2秒
}
if(alm_flag2==1)∥如果第2路产生盗情
{PORTA=SEG7[2];∥数码管显示为2
PORTC=0xfe;//点亮最右的数码管
ALM_ON;//报警器启动
delay_ms(2000);//延时2秒
}
} ////无限循环语句结束
} ////主函数结束
∥****************************************
*
#pragma interrupt_handler intO_isr:2#INTO中断服
务子函数
void intO_isr(void)
{
aim_flagl=1: //置第1路盗情标志为
1
#pragma interrupt_handler int1_isr:3//INT1
务子函数
中断服
void int1_isr(void)
{
alm_flag2=1; //置第2路盗情标志为1
}
}
//****************************************
编译通过后,可将ac8.hex文件下载到AVR单片机综合试验板上进行实际的操作演示。注意,标示“LED”、“LEDMOD_DISP”、“LED-MOD_COM”及“INT0”、“INT1”的双排针应插上短路块。