新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > avr的外部中断

avr的外部中断

作者: 时间:2016-11-20 来源:网络 收藏
关于AVR中断:

系统在正常运行主程序时,如果突然有一个重要的任务要马上处理,那么系统就要保存现在的工作,然后再去处理这个任务,执行这个重要任务完毕以后再返回原来的主程序继续运行,这就是中断。

本文引用地址:https://www.eepw.com.cn/article/201611/318679.htm

主程序一旦进入中断服务程序,那么AVR芯片将自动的关闭全局中断,在这个期间不再执行其它的中断请求,直到中断程序结束以后芯片才自动的重新开放全局中断。(注意,在这个期间某些中断请求可能会被丢弃,某些请求会留下中断请求标致,一旦当前的中断执行完毕,这个有中断标致的请求就有可能马上得到响应,如INT0的下降沿触发就会留下中断请求标致,而低电平触发就不会流下中断请求标致)。如果你想在执行中断服务程序时响应另外一个更重要的中断,那么就要在中断服务程序中加入一条打开全局中断的语句。

我们现在先来讨论外部中断

外部中断要要记得5个寄存器,分别是:

1.status register -SREG状态寄存器。而且外部中断关心的是它的Bit-7-I位,全局中断使能。置位时,使能全局中断。那些单独的中断,就是你要实现的那些中断,他们的使能由其他独立的控制寄存器控制,就比如说下面说的EIMSK等。如果我们对I清0,则全部的中断是不可能发生了,就象一个总的开关一样,即使单独中断标志置位与否。I可以通过SEI和CLI指令来置位和清0。

2.External Interrupt Mask Register -EIMSK外部中断屏蔽寄存器。当INT7–INT0为1’,而且状态寄存器SREG的I标志置位,相应的外部引脚中断就使能了。

3.External Interrupt Control Register A – EICRA外部中断控制寄存器A。Bits 7..0–ISC31, ISC30–ISC00, ISC00:外部中断3 - 0敏感电平控制位。详见datesheet。如果SREG寄存器的I标志和EIMSK寄存器相应的中断屏蔽位置位,那么外部中断3 - 0由引脚INT3~INT0引脚激活。需要注意的是,改变ISCn时,有可能发生中断。因此,建议首先在EIMSK里清除相应的中断使能位INTn,然后再改变ISCn。最后呢,千万不要忘记在重新使能中断之前,通过对EIFR的相应中断标志位INTFn写“1”,使其清0。

4.External Interrupt Control Register B – EICRB外部中断控制寄存器B。Bits 7..0–ISC71, ISC70 - ISC41, ISC40:外部中断7 - 4敏感电平控制位。详见datesheet,它和EICRA可是不同的。检测信号跳变沿之前MCU首先对INT7:4引脚进行采样。如果选择了跳变沿中断或是电平变换中断(上升沿和下降沿都将产生中断),只要信号持续时间大于一个时钟周期,中断就会发生;否则无法保证触发中断。要注意由于XTAL分频器的存在,CPU时钟有可能比XTAL时钟慢。若选择了低电平中断,低电平必须保持到当前指令完成,然后才会产生中断。而且只要将引脚拉低,就会引发中断请求。而且,同样需要象EICRA一样注意:改变ISCn1/ISCn0时一定要先通过清零EIMSK寄存器的中断使能位来禁止中断。否则在改变ISCn1/ISCn0的过程中可能发生中断。

5.External Interrupt Flag Register – EIFR。外部中断标志寄存器。INT7:0引脚电平发生跳变时触发中断请求,并置位相应的中断标志INTF7:0。如果SREG的位I以及EIMSK寄存器相应的中断使能位为’1’,MCU既跳转到中断例程。中断例程执行时标志被硬件清零。此外,标志位也可以通过写入’1’的方式来清零。若INT7:0配置为电平触发,这些标志位总是为0’。在睡眠模式下,如果中断是禁止的,则这些引脚的输入缓冲器也是禁止的。这有可能产生逻辑电平的变化并置位INTF3:0。更多信息请参考手册的“数字输入使能和睡眠模式”。

我们应该清楚的是:外部中断通过引脚INT7:0触发。只要使能了中断,即使引脚INT7:0配置为输出,只要电平发生了合适的变化,中断也会触发。这个特点可以用来产生软件中断。通过设置外部中断控制寄存器–EICRA (INT3:0)和EICRB (INT7:4),中断可以由下降沿、上升沿,或者是低电平触发。当外部中断使能并且配置为电平触发,只要引脚电平为低,中断就会产生。若要求INT7:4在信号下降沿或上升沿触发,I/O时钟必须工作,如数据手册P 33“时钟系统及其分布”说明的那样。INT3:0的中断条件检测则是异步的。也就是说,这些中断可以用来将器件从睡眠模式唤醒。在睡眠过程(除了空闲模式)中I/O时钟是停止的。

上面的多为数据手册里面的内容。也许我们回有几个困惑。

1.为何AVR写“1”也能清0呢,这不是很奇怪嘛。你可以参考下面几个网页

http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=749852

http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=691118&bbs_page_no=1&bbs_id=1000

http://www.c51bbs.com/c51bbs/topic1/c51bbs17322.htm

但最终呢,真正的原因是在AVR-GCC的帮助文档avr-libc本来就有的,FAQ24,Why are (many) interrupt flags cleared by writing a logical 1?当然,你的E文要好地。

参见如下说明:

Why are (many) interrupt flags cleared by writing a logical 1?

Usually, each interrupt has its own interrupt flag bit in some control register, indicating the specified interrupt condition has been met by representing a logical1 inthe respective bit position. When working with interrupt handlers, this interrupt flag bit usually gets cleared automatically in the course of processing the interrupt, sometimes by just calling the handler at all, sometimes (e. g. for the U[S]ART) by reading a particular hardware register that will normally happen anyway when processing the interrupt.

From the hardwares point of view, an interrupt is asserted as long as the respective bit is set, while global interrupts are enabled. Thus, it is essential to have the bit cleared before interrupts get re-enabled again (which usually happens when returning from an interrupt handler).

Only few subsystems require an explicit action to clear the interrupt request when using interrupt handlers. (The notable exception is the TWI interface, where clearing the interrupt indicates to proceed with the TWI bus hardware handshake, so its never done automatically.)

However, if no normal interrupt handlers are to be used, or in order to make extra sure any pending interrupt gets cleared before re-activating global interrupts (e. g. an external edge-triggered one), it can be necessary to explicitly clear the respective hardware interrupt bit by software. This is usually done by writing a logical 1 into this bit position. This seems to be illogical at first, the bit position already carries a logical 1 when reading it,so why does writing a logical 1 to it clear the interrupt bit?

The solution is simple:writing a logical 1 to it requires only a single OUT instruction, and it is clear that only this single interrupt request bit will be cleared. There is no need to perform a read-modify-write cycle (like, an SBI instruction), since all bits in these control registers are interrupt bits, and writing a logical 0 to the remaining bits (as it is done by the simple OUT instruction) will not alter them, so there is no risk of any race condition that might accidentally clear another interrupt request bit. So instead of writing

TIFR |= _BV(TOV0); /* wrong! */

simply use

TIFR = _BV(TOV0);

2.只要使能了中断,即使引脚INT7:0配置为输出,只要电平发生了合适的变化,中断也会触发.这句怎么理解?答:也就是说,你打开了中断int0和int1,同时这两个管脚定义为输出,然后,你使用软件设置这两个管脚的输出电平,当满足中断条件时,中断就发生了。这不就是软件中断吗?

3.在配置了外部中断控制寄存器、屏蔽寄存器、标志寄存器后,是否还需要设置IO口为输入端口呢?答:是的,不过IO口上电时就默认是输入了,可以不写这条指令。补充,设置成输出也照样产生中断。它用PINx读。



关键词: avr外部中

评论


技术专区

关闭