|
外部中断应用注意事项(原创)
这篇文章是以实际的例子为主(实验工具网站套餐C)。
ATMEGA16的外部有三个中端源,分别由PD2,PD3,PB2上的电平变化或状态作为中断触发信号。具体怎么设置大家可以参考网站内的相关文章(请版主此处加入链接)。
先来看看初学中断的一个例子(注意下面两个实验外部中断0都没有外接上拉电阻):
AVRVI.COM (ICC AVR)
例1:
/************************************************
文 件:main.c
用 途:演示外部中断的工作过程
Target : M16
Crystal: 1.0000Mhz
注 意:
创 建:2008.1.25
修 改:2008.1.25
Copy Right (c) www.avrvi.com AVR与虚拟仪器
************************************************/
#include
#include
//iom16v.h中定义 #define iv_INT0 2
//int0_isr:iv_INT0 也可以写成 int0_isr:2
//中断函数完成操作
#pragma interrupt_handler int0_isr:iv_INT0
void int0_isr(void)
{
//按键后INT0触发
PORTA ^= (1<
}
void main(void)
{
DDRA |= (1<
GICR = 0x40; //允许INT0中断
SEI(); //开全局中断
while(1)
{ //空操作
;
}
}
因为要更好的看到仿真结果,我将例子1略加修改,我用的是ICC+AVR
例2:
/************************************************
文 件:main.c
用 途:演示外部中断的工作过程
Target : M16
Crystal: 1.0000Mhz
注 意:
创 建:2008.1.25
修 改:2008.1.25
Copy Right (c) www.avrvi.com AVR与虚拟仪器
************************************************/
#include
#include
unsigned char i;
const unsigned char Seg7_Data[]={0x3F,0x06,0x5B,0x4F,0x66, //0,1,2,3,4
0x6D,0x7D,0x07,0x7F,0x6F, //5,6,7,8,9
0x77,0x7C,0x39,0x5E,0x79,0x71,0x00}; //a,b,c,d,e,f
//iom16v.h中定义 #define iv_INT0 2
//int0_isr:iv_INT0 也可以写成 int0_isr:2
//中断函数完成操作
#pragma interrupt_handler int0_isr:iv_INT0
void int0_isr(void)
{
//按键后INT0触发
if(++i>=16)
{
i=0;
}
}
void main(void)
{
//PORTD = 0Xff;
//DDRD = 0Xff; //输出
//DDRD = 0X00; //输入
PORTA=0Xff;
DDRA = 0xff; //输出
GICR|= 0x40; //允许INT0中断
MCUCR=0X00; //ISC01:ISC00 00 低电平产生中断;01 下降沿和上升沿都
产生中断;10下降沿产生中断;11 上升沿中断,先做00实验
GIFR=0X40;
i=0;
SEI(); //开全局中断
while(1)
{ //空操作
PORTA = Seg7_Data;
}
}
以例2来仿真,单步仿真实验时,按键还起做用,在全速度运行时(仿真),外部中断不起做用了,数码管显示很容易受到干扰,用手在按键上方晃动,竟然都可以产生了中断,数码管的数值在改变!(当时,我是在例1的基础上做的实验,十分不解,然后才改成例2进行实验),不用仿真直接裸奔下(断开了仿真器与主板的连接),此时发现数码管以“8”在不停的闪烁,按键中断无效!(实际上是起作用的,但看起来好象没有产生),这就使我非常困惑了,这个小问题被折磨了3天!
下面就一步一步来做实验,来验证数据手册中所讲的:
实验一:也就是例2,为什么会出现这样的情况呢?
1、 在全速度运行时(仿真),中断不起作用(是观察不到)
2、 自己裸奔,出现“8”不停的闪烁;且易受到干扰(随便晃下手都可以改变中断),
3、 单步仿真时,中断基本上是无效的,时有时无
等会我们再来作结论为什么,先做第2个实验
实验二:给PORTTD设置为全1,即PORTD = 0XFF;给PD口一确定的电平(主要是PD2),其它的不用改变(例2),实验结果
1、 在全速度运行时(仿真),中断能起作用了,但按一次键并不是递增的;
2、 自己裸奔,也不出现“8”不停的闪烁;
3、 也不受到干扰了
该实验验证了数据册中描述的只要使能了外部中断,那么即使引脚设置为输出,引脚上的电平变化也可产生中断。难道该实验就只能说明这一点吗?NO!
4、 单步执行看看,又会出现什么情况呢?先复位下(为了好仿真,找问题,不复位也没有关系),打开“i”的观察窗口,按住键不放,单步执行,直到中断5次(次数多点容易发现问题,次数少不容易发现),此时“i”为5,数码管显示“8”(初始值),松开按键,数码管显示“3”(也有可能是其它的值),竟然不是5?再执行一循环,就显示5了。
5、 将“i”定意为:volatile unsigned char i;效果没有什么改变!
实验三:将PD2设置为输出状态,即DDRD = 0XFF;其它的不用改变(例2),实验结果
1、 不停地中断,一个中断接一个中断,呵呵!
2、 如果给PD2一个确定的值1,再加一句PORTD=0XFF;此时却不中断了,一次都没有
实验四:将PD2设置为输入状态,即DDRD = 0X00;其它的不用改变(例2),实验结果
1、 不发生中断
2、 在(1)的基础上,设置PD2弱上拉,即PORTD = 0XFF;DDRD = 0X00;此时结果同实验二
上面四个实验,中断的触发方式是低电平触发,下面改变为边沿触发方式,在例2中修改,MCUCR = 0X02;即下降沿触发中断(上升沿雷同),重复上面四个实验
实验五:仿真结果:
1、 同实验1,无多大变化
实验六:设置方式同实验二,仿真过程
1、 在全速度运行时(仿真),中断能起作用了,但按一次键基本是递增的;比实验二效果好
2、 己裸奔,也不出现“8”不停的闪烁;
3、 也不受到干扰了
4、 单步执行看看,又会出现什么情况呢?先复位下(为了好仿真,找问题,不复位也没有关系),打开“i”的观察窗口,在执行到开全局中断处按下键,执行一条语句(按住键不放,在这里就合适了)后放开,在进入中断后,在退出中断前按住键,使中断退出后又马上进入中断,单步执行,直到中断5次(次数多点容易发现问题,次数少不容易发现),此时的结果同实验二
实验7:设置方式同实验三,仿真过程
1、 根本就不中断,同实验三完全相反,呵呵!
2、 如果给PD2一个确定的值1,即加一句PORTD=0XFF;此时却不中断了,一次都没有
实验八:设置方式同实验四,
1、 只有1次中断,再不中断了
2、 在(1)的基础上,设置PD2弱上拉,即PORTD = 0XFF;DDRD = 0X00;此时结果同实验六
真没有想到一个简单的中断口竟然有如此之多的学问,是不是把你吓一跳啊!呵呵,其实这些书上讲的都有,只知所以然,不知其所以然,只有通过实验才能对对讲到的要点理解啊!小结一下:
1、 养成良好的编程习惯,一定要记得初始化端口
2、 在使用中断0时,若外部没有上拉电阻,一定记得将PD2置1,不论该端口是输入还是输出
3、 在使用中断0时,最好定义端口为输入状态,可试情况是否上拉
4、 低电平触发中断,若外部没有上拉电阻,内部也不上拉,若端口是输出状态则会不停的中断的,若是输入状态则不发生中断,若对端口不初始化,则现象非常的古怪
5、 下降沿触发若外部没有上拉电阻,内部也不上拉,若端口是输出状态则不中断,若是输入状态则只发生中断一次,若对端口不初始化,则现象非常的古怪
但还存在个问题没有搞清楚:那就是在中断中改变的“i”却不能一一对应起来(实验二)就算将“i”定义为volatile unsigned char I也没有解决掉问题,希望高手指点下!
PS:感谢小可歌的指点!花了一星期了才搞明白中断这点知识,惭愧!希望初学者别再走我的老路了,呵呵!
|
|