这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » ATmega8多数的I/O口外部中断问题

共2条 1/1 1 跳转至

ATmega8多数的I/O口外部中断问题

高工
2020-11-06 22:58:41     打赏

但ATmega8多数的I/O口都是复用口,除了作为通用数字I/O使用,还有其第二功能,这里我们学习PD2、PD3两端口的第二功能:外部中断。

1.外部中断的特点:

PD2端口是外部中断源0,PD3端口是外部中断源1。ATmega8的外部中断就是由这两个引脚触发的。

*要注意的是:如果设置允许外部中断产生,即使是INT0和INT1引脚设置为输出方式,外部中断还是会触发的。

外部中断的触发方式有三种可选性:

(1)上升沿触发;

(2)下降沿触发;

(3)低电平触发。

具体方式是由以下三个决定的:

(1)MCU的控制寄存器MCUCR

(2)MCU控制

(3)状态寄存器MCUCSR

*当允许外部中断且设置为低电平触发方式时,只要中断输入引脚保持低电平,就将一直触发产生中断;

*而对于上升沿或者下降沿的中断触发,则需要I/O时钟信号的存在。

要使用外部中断我们首先要了解几个寄存器:

(1)AVR的状态寄存器SREG

(2)MCU控制寄存器MCUCR

(3)通用中断控制寄存器GICR

(4)通用中断标志寄存器GIFR

详细信息有:

(1)AVR的状态寄存器SREG:

SREG的每一位都是一个标志位,位7(全局中断允许位)——I位;

该位为1时全局中断使能允许,单独的中断使能则有对应的中断寄存器控制;

该位为0时则不论单独允许位是否置1,所有中断都被禁止,系统将不响应任何中断。

(2)MCU控制寄存器MCUCR:

位0(ISC00)是外部中断0的中断方式控制位0;

位1(ISC01)是外部中断0的中断方式控制位1;

位2(ISC10)是外部中断1的中断方式控制位0;

位3(ISC11)是外部中断1的中断方式控制位1;

参考表与上图类似。

(3)通用中断控制寄存器GICR:

位6——INT0控制外部中断0的使能;

位7——INT1控制外部中断1的使能。

当状态寄存器SREG的I位(全局中断允许位)置1时,

INT0置1则外部引脚中断0使能;

INT1置1则外部引脚中断1使能。

(4)通用中断标志寄存器GIFR:

位6——INT0是外部中断0的标志位;

位7——INT1是外部中断1的标志位;

当INT0引脚上的有效事件触发一个中断请求后,INTF0位会变成1。

如果全局中断使能且外部中断0使能,则MCU将跳至相应的中断向量处开始执行中断服务程序,同时硬件自动将INTF0标志位清零。

*当外部中断0被设置为低电平触发方式时,标志INTF0位将始终为0。

扩展:

中断向量表:Atmega8共有18个中断源,Flash程序存储器空间的最低位置(0x000—0x012)定义为复位和中断向量空间,也就是说把中断函数的地址保存在这里,当中断发生后就到这里找到对应函数的地址,然后去执行对应的函数。x向量表如下:

在中断向量表中,处于低地址的中断向量对应的中断优先级高,所以系统复位RESET拥有最高优先;

外部中断0高于外部中断1;系统复位REST不是中断。

编程准备:

用ICCAVR的编程,在C中只要用#pragma伪指令和中断向量说明中断服务程序入口地址即可:

#pragmainterrupt_handler《函数名》:《中断向量》

例如要定义使用INT0中断服务程序:

#pragmainterrupt_handlerint0_fun:2

voidint0_fun()

{

。。。。。。

}

2对应INT0的中断服务程序入口地址(由向量表中红色字体可知);

同理,3对应INT1的中断服务程序入口地址。

也可以让多个中断调用同一个函数,如:

#pragmainterrupt_handlerint_fun:2

#praamainterrupt_handlerint_fun:3

表示外部中断0和中断1都调用int_fun函数。

2.应用实例——中断计数器

用两个按键作为两个外部中断的触发源,再接一个LED数码管用来显示两位数的数据,电路图如下:

将外部中断0设置为下降沿触发(MCUCR的位1为1,位0为0),中断1设置为低电平触发(MCUCR的位3为0,位2为0);(MCUCR=0x02)

调用同一个中断函数,在中断中做数值加1,然后在LED数码管中显示。

代码如下:

中断计数器

3.中断触发键盘扫描

按下键盘的任意一个按键就触发一个中断,然后在中断函数中来调用键盘处理函数。

电路图中,比上一讲的实例中多了一个74S10的与非门,作用是任意一个按键按下都可以触发一个INT0中断。

要实现的内容是:

任意一个按键按下触发一个INT0中断,INT0设置为上升沿触发方式(MCUCR=0x03),在中断中做一个标志,表示有按键按下;

然后在主函数中判断该标志位,有按键按下,消除抖动干扰,再做确认哪个按键按下,最后在LED数码管上显示按键




工程师
2020-11-08 22:40:16     打赏
2楼

确实不错


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]