avr的外部中斷
系統(tǒng)在正常運(yùn)行主程序時(shí),如果突然有一個(gè)重要的任務(wù)要馬上處理,那么系統(tǒng)就要保存現(xiàn)在的工作,然后再去處理這個(gè)任務(wù),執(zhí)行這個(gè)重要任務(wù)完畢以后再返回原來(lái)的主程序繼續(xù)運(yùn)行,這就是中斷。
主程序一旦進(jìn)入中斷服務(wù)程序,那么AVR芯片將自動(dòng)的關(guān)閉全局中斷,在這個(gè)期間不再執(zhí)行其它的中斷請(qǐng)求,直到中斷程序結(jié)束以后芯片才自動(dòng)的重新開(kāi)放全局中斷。(注意,在這個(gè)期間某些中斷請(qǐng)求可能會(huì)被丟棄,某些請(qǐng)求會(huì)留下中斷請(qǐng)求標(biāo)致,一旦當(dāng)前的中斷執(zhí)行完畢,這個(gè)有中斷標(biāo)致的請(qǐng)求就有可能馬上得到響應(yīng),如INT0的下降沿觸發(fā)就會(huì)留下中斷請(qǐng)求標(biāo)致,而低電平觸發(fā)就不會(huì)流下中斷請(qǐng)求標(biāo)致)。如果你想在執(zhí)行中斷服務(wù)程序時(shí)響應(yīng)另外一個(gè)更重要的中斷,那么就要在中斷服務(wù)程序中加入一條打開(kāi)全局中斷的語(yǔ)句。
我們現(xiàn)在先來(lái)討論外部中斷
外部中斷要要記得5個(gè)寄存器,分別是:
1.status register -SREG狀態(tài)寄存器。而且外部中斷關(guān)心的是它的Bit-7-I位,全局中斷使能。置位時(shí),使能全局中斷。那些單獨(dú)的中斷,就是你要實(shí)現(xiàn)的那些中斷,他們的使能由其他獨(dú)立的控制寄存器控制,就比如說(shuō)下面說(shuō)的EIMSK等。如果我們對(duì)I清0,則全部的中斷是不可能發(fā)生了,就象一個(gè)總的開(kāi)關(guān)一樣,即使單獨(dú)中斷標(biāo)志置位與否。I可以通過(guò)SEI和CLI指令來(lái)置位和清0。
2.External Interrupt Mask Register -EIMSK外部中斷屏蔽寄存器。當(dāng)INT7–INT0為
3.External Interrupt Control Register A – EICRA外部中斷控制寄存器A。Bits 7..0–ISC31, ISC30–ISC00, ISC00:外部中斷3 - 0敏感電平控制位。詳見(jiàn)datesheet。如果SREG寄存器的I標(biāo)志和EIMSK寄存器相應(yīng)的中斷屏蔽位置位,那么外部中斷3 - 0由引腳INT3~INT0引腳激活。需要注意的是,改變ISCn時(shí),有可能發(fā)生中斷。因此,建議首先在EIMSK里清除相應(yīng)的中斷使能位INTn,然后再改變ISCn。最后呢,千萬(wàn)不要忘記在重新使能中斷之前,通過(guò)對(duì)EIFR的相應(yīng)中斷標(biāo)志位INTFn寫(xiě)“
4.External Interrupt Control Register B – EICRB外部中斷控制寄存器B。Bits 7..0–ISC71, ISC70 - ISC41, ISC40:外部中斷7 - 4敏感電平控制位。詳見(jiàn)datesheet,它和EICRA可是不同的。檢測(cè)信號(hào)跳變沿之前MCU首先對(duì)INT7:4引腳進(jìn)行采樣。如果選擇了跳變沿中斷或是電平變換中斷(上升沿和下降沿都將產(chǎn)生中斷),只要信號(hào)持續(xù)時(shí)間大于一個(gè)時(shí)鐘周期,中斷就會(huì)發(fā)生;否則無(wú)法保證觸發(fā)中斷。要注意由于XTAL分頻器的存在,CPU時(shí)鐘有可能比XTAL時(shí)鐘慢。若選擇了低電平中斷,低電平必須保持到當(dāng)前指令完成,然后才會(huì)產(chǎn)生中斷。而且只要將引腳拉低,就會(huì)引發(fā)中斷請(qǐng)求。而且,同樣需要象EICRA一樣注意:改變ISCn1/ISCn0時(shí)一定要先通過(guò)清零EIMSK寄存器的中斷使能位來(lái)禁止中斷。否則在改變ISCn1/ISCn0的過(guò)程中可能發(fā)生中斷。
5.External Interrupt Flag Register – EIFR。外部中斷標(biāo)志寄存器。INT7:0引腳電平發(fā)生跳變時(shí)觸發(fā)中斷請(qǐng)求,并置位相應(yīng)的中斷標(biāo)志INTF7:0。如果SREG的位I以及EIMSK寄存器相應(yīng)的中斷使能位為’
我們應(yīng)該清楚的是:外部中斷通過(guò)引腳INT7:0觸發(fā)。只要使能了中斷,即使引腳INT7:0配置為輸出,只要電平發(fā)生了合適的變化,中斷也會(huì)觸發(fā)。這個(gè)特點(diǎn)可以用來(lái)產(chǎn)生軟件中斷。通過(guò)設(shè)置外部中斷控制寄存器–EICRA (INT3:0)和EICRB (INT7:4),中斷可以由下降沿、上升沿,或者是低電平觸發(fā)。當(dāng)外部中斷使能并且配置為電平觸發(fā),只要引腳電平為低,中斷就會(huì)產(chǎn)生。若要求INT7:4在信號(hào)下降沿或上升沿觸發(fā),I/O時(shí)鐘必須工作,如數(shù)據(jù)手冊(cè)P 33“時(shí)鐘系統(tǒng)及其分布”說(shuō)明的那樣。INT3:0的中斷條件檢測(cè)則是異步的。也就是說(shuō),這些中斷可以用來(lái)將器件從睡眠模式喚醒。在睡眠過(guò)程(除了空閑模式)中I/O時(shí)鐘是停止的。
上面的多為數(shù)據(jù)手冊(cè)里面的內(nèi)容。也許我們回有幾個(gè)困惑。
1.為何AVR寫(xiě)“
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本來(lái)就有的,F(xiàn)AQ24,Why are (many) interrupt flags cleared by writing a logical 1?當(dāng)然,你的E文要好地。
參見(jiàn)如下說(shuō)明:
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 logical
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配置為輸出,只要電平發(fā)生了合適的變化,中斷也會(huì)觸發(fā).這句怎么理解?答:也就是說(shuō),你打開(kāi)了中斷int0和int1,同時(shí)這兩個(gè)管腳定義為輸出,然后,你使用軟件設(shè)置這兩個(gè)管腳的輸出電平,當(dāng)滿足中斷條件時(shí),中斷就發(fā)生了。這不就是軟件中斷嗎?
3.在配置了外部中斷控制寄存器、屏蔽寄存器、標(biāo)志寄存器后,是否還需要設(shè)置IO口為輸入端口呢?答:是的,不過(guò)IO口上電時(shí)就默認(rèn)是輸入了,可以不寫(xiě)這條指令。補(bǔ)充,設(shè)置成輸出也照樣產(chǎn)生中斷。它用PINx讀。
評(píng)論