野外做受三级视频,人妻无码第一区二区三区,精品欧美成人高清在线观看,色屁屁WWW影院免费观看入口

新聞資訊
AVR單片機(jī)中斷實(shí)現(xiàn) ATmega16 INT ISR(INT0_vect)
2010-11-28


2.21 實(shí)例功能
前面例子中分別介紹了按鍵控制發(fā)光二極管的亮滅,但是我們注意到,在程序中需要一直檢測(cè)按鍵的狀態(tài),這樣明顯的浪費(fèi)了單片機(jī)的資源,降低了單片機(jī)的工作效率,。那么有沒(méi)有一種方法可以讓單片機(jī)不用一直檢測(cè)按鍵的狀態(tài),而只在有按鍵動(dòng)作時(shí)才去響應(yīng)呢?
當(dāng)然有!單片機(jī)中除了具有基本輸入輸出功能的作用外,還有專(zhuān)門(mén)檢測(cè)外界信號(hào)并作出響應(yīng)的中斷系統(tǒng)。在本例中,通過(guò)利用外部中斷實(shí)現(xiàn)單片機(jī)對(duì)按鍵事件的響應(yīng)和處理。
本例中三個(gè)功能模塊描述如下:
● 單片機(jī)系統(tǒng):對(duì)按鍵事件產(chǎn)生的中斷時(shí)間作出響應(yīng),并在數(shù)碼管上顯示按鍵按下的次數(shù)。
● 外圍電路:通過(guò)將按鍵連接到單片機(jī)的外部中斷檢測(cè)端口,實(shí)現(xiàn)中斷產(chǎn)生電路,數(shù)碼管顯示電路用于指示按鍵的按下?tīng)顟B(tài)。
● 軟件程序:編寫(xiě)AVR單片機(jī)的外部中斷服務(wù)程序,從而實(shí)現(xiàn)對(duì)中斷事件的響應(yīng)。
2.2.2 器件和原理
1單片機(jī)的中斷系統(tǒng)
關(guān)于中斷的概念可以在一般的教材中找到,本例中只做簡(jiǎn)要敘述,不再詳細(xì)說(shuō)明。
中斷屬于一種對(duì)事件的實(shí)時(shí)處理過(guò)程。中斷源可能隨時(shí)停止單片機(jī)當(dāng)前正在處理的工作,轉(zhuǎn)而去處理中斷事件,待中斷時(shí)間處理完畢之后,再返回原來(lái)工作的斷點(diǎn)處,繼續(xù)原來(lái)的工作。
對(duì)于單片機(jī)的中斷系統(tǒng),需要了解這幾個(gè)概念:中斷源、中斷信號(hào)、中斷向量、中斷優(yōu)先級(jí)、中斷嵌套、中斷控制(屏蔽)、中斷響應(yīng)條件、中斷響應(yīng)過(guò)程(中斷服務(wù)程序)。
●中斷源
中斷源是指能夠向單片機(jī)發(fā)出中斷請(qǐng)求信號(hào)的部件和設(shè)備。對(duì)于單片機(jī)來(lái)講,往往存在多個(gè)中斷源。中斷源一般可分為內(nèi)部中斷源和外部中斷源。
單片機(jī)內(nèi)部集成的許多功能模塊,如定時(shí)器、串行通訊口、模/數(shù)轉(zhuǎn)換器等,它們?cè)谡9ぷ鲿r(shí)往往無(wú)需CPU參與,而當(dāng)處于某種狀態(tài)或達(dá)到某個(gè)規(guī)定值需要程序 控制時(shí),會(huì)通過(guò)發(fā)出中斷請(qǐng)求信號(hào)通知CPU。這一類(lèi)的中斷源位于單片機(jī)內(nèi)部,稱(chēng)作內(nèi)部中斷源。內(nèi)部中斷源在中斷條件成立時(shí),一般通過(guò)片內(nèi)硬件會(huì)自動(dòng)產(chǎn)生中 斷請(qǐng)求信號(hào),無(wú)須用戶(hù)介入,使用方便。內(nèi)部中斷是CPU管理片內(nèi)資源的一種高效的途徑。
系統(tǒng)中的外部設(shè)備也可以用作中斷源,這時(shí)要求它們能夠產(chǎn)生一個(gè)中斷信號(hào)(通常是高(低)電平或者電平跳變的上升(下降)沿),送到單片機(jī)的外部中斷請(qǐng)求引 腳供CPU檢測(cè)。這些中斷源位于單片機(jī)外部,稱(chēng)為外部中斷源。通常用作外部中斷源的有輸入輸出設(shè)備、控制對(duì)象、以及故障源等。
● 中斷信號(hào)
中斷信號(hào)是指內(nèi)部或外部中斷源產(chǎn)生的中斷申請(qǐng)信號(hào),這個(gè)中斷信號(hào)往往是電信號(hào)的某種變化形式,通常有以下幾種類(lèi)型:
  1. 脈沖的上跳沿或下降沿(上升沿觸發(fā)型或下降沿觸發(fā)型)
  2. 高電平或低電平(電平觸發(fā)型)
  3. 電平的變化(狀態(tài)變化觸發(fā)型)

對(duì)于單片機(jī)來(lái)講,不同的中斷源,產(chǎn)生什么類(lèi)型的中斷信號(hào)能夠觸發(fā)申請(qǐng)中斷,取決于芯片內(nèi)部的硬件結(jié)構(gòu),而且通常也可以通過(guò)用戶(hù)的軟件來(lái)設(shè)定。
單片機(jī)的硬件系統(tǒng)會(huì)自動(dòng)對(duì)這些中斷信號(hào)進(jìn)行檢測(cè)。一旦檢測(cè)到規(guī)定的信號(hào)出現(xiàn),將會(huì)把相應(yīng)的中斷標(biāo)志位置“1”(在I/O空間的控制或狀態(tài)寄存器中),通知CPU進(jìn)行處理。
● 中斷向量
中斷源發(fā)出的請(qǐng)求信號(hào)被CPU檢測(cè)到之后,如果單片機(jī)的中斷控制系統(tǒng)允許響應(yīng)中斷,CPU會(huì)自動(dòng)轉(zhuǎn)移,執(zhí)行一個(gè)固定的程序空間地址中的指令。這個(gè)固定的地址稱(chēng)作中斷入口地址,也叫做中斷向量。中斷入口地址往往是由單片機(jī)內(nèi)部硬件決定的。
一個(gè)單片機(jī)有若干個(gè)中斷源,每個(gè)中斷源都有著自己的中斷向量。這些中斷向量一般在程序存儲(chǔ)空間中占用一個(gè)連續(xù)的地址空間段,稱(chēng)為中斷向量區(qū)。由于一個(gè)中斷 向量通常僅占幾個(gè)字節(jié)或一條指令的長(zhǎng)度,所以在中斷向量區(qū)一般不放置中斷服務(wù)程序的。中斷服務(wù)程序一般放置在程序存儲(chǔ)器的其它地方,而在中斷向量處放置一 條跳轉(zhuǎn)到中斷服務(wù)程序的指令。這樣,CPU響應(yīng)中斷后,首先自動(dòng)轉(zhuǎn)向執(zhí)行中斷向量中的轉(zhuǎn)移指令,再跳轉(zhuǎn)執(zhí)行中斷服務(wù)程序。
● 中斷優(yōu)先級(jí)
單片機(jī)系統(tǒng)一般有多個(gè)中斷源,當(dāng)某一時(shí)刻同時(shí)有多個(gè)中斷產(chǎn)生時(shí),單片機(jī)該如何處理呢?這就有了中斷優(yōu)先級(jí)的概念。
通常,單片機(jī)可以接收若干個(gè)中斷源發(fā)出的中斷請(qǐng)求。但在同一時(shí)刻,MCU只能響應(yīng)這些中斷請(qǐng)求中的其中一個(gè)。為了避免MCU同時(shí)響應(yīng)多個(gè)中斷請(qǐng)求帶來(lái)的混 亂,在單片機(jī)中為每一個(gè)中斷源賦予一個(gè)特定的中斷優(yōu)先級(jí)。一旦有多個(gè)中斷請(qǐng)求信號(hào),MCU先響應(yīng)中斷優(yōu)先級(jí)高的中斷請(qǐng)求,然后再逐次響應(yīng)優(yōu)先級(jí)次一級(jí)的中 斷。中斷優(yōu)先級(jí)也反映了各個(gè)中斷源的重要程度,同時(shí)也是分析中斷嵌套的基礎(chǔ)。
對(duì)于中斷優(yōu)先級(jí)的確定,通常是由單片機(jī)的硬件結(jié)構(gòu)規(guī)定的。一般的確定規(guī)則方式為兩種:

  1. 某中斷對(duì)應(yīng)的中斷向量地址越小,其中斷優(yōu)先級(jí)越高(硬件確定方式)。
  2. 通過(guò)軟件對(duì)中斷控制寄存器的設(shè)定,改變中斷的優(yōu)先級(jí)(用戶(hù)軟件可設(shè)置方式,注意:AVR不支持)。

實(shí)際上,MCU在兩種情況下需要對(duì)中斷的優(yōu)先級(jí)進(jìn)行判斷:
第一種情況為同時(shí)有兩(多)個(gè)中斷源申請(qǐng)中斷。在這種情況下,MCU首先響應(yīng)中斷優(yōu)先級(jí)最高的那個(gè)中斷,而將其它的中斷掛起。待優(yōu)先級(jí)最高的中斷服務(wù)程序執(zhí)行完成返回后,再順序響應(yīng)優(yōu)先級(jí)較低的中斷。
第二種情況是當(dāng)MCU正處于響應(yīng)一個(gè)中斷的過(guò)程中。如已經(jīng)響應(yīng)了某個(gè)中斷,正在執(zhí)行為其服務(wù)的中斷程序時(shí),此時(shí)又產(chǎn)生一個(gè)其它的中斷申請(qǐng),這種情況也稱(chēng)作中斷嵌套。
● 中斷嵌套
對(duì)于中斷嵌套的處理,不同的單片機(jī)處理的方式是不同的,應(yīng)根據(jù)所使用單片機(jī)的特點(diǎn)正確實(shí)現(xiàn)中斷嵌套的處理。
按照通常的規(guī)則,當(dāng)MCU正在響應(yīng)一個(gè)中斷B的過(guò)程中,又產(chǎn)生一個(gè)其它的中斷A申請(qǐng)時(shí),如果這個(gè)新產(chǎn)生中斷A的優(yōu)先級(jí)比正在響應(yīng)的中斷B優(yōu)先級(jí)高的話(huà),就 應(yīng)該暫停當(dāng)前的中斷B的處理,轉(zhuǎn)入響應(yīng)高優(yōu)先級(jí)的中斷A,待高優(yōu)先級(jí)中斷A處理完成后,再返回原來(lái)的中斷B的處理過(guò)程。如果新產(chǎn)生中斷A的優(yōu)先級(jí)比正在處 理中斷B的優(yōu)先級(jí)低(或相同),則應(yīng)在處理完當(dāng)前的中斷B后,再響應(yīng)那個(gè)后產(chǎn)生的中斷A申請(qǐng)(如果中斷A條件還成立的話(huà))。
一些單片機(jī)(如8051結(jié)構(gòu))的硬件能夠自動(dòng)實(shí)現(xiàn)中斷嵌套的處理,既單片機(jī)內(nèi)部的硬件電路能夠識(shí)別中斷的優(yōu)先級(jí),并根據(jù)優(yōu)先級(jí)的高低,自動(dòng)完成對(duì)高優(yōu)先級(jí)中斷的優(yōu)先響應(yīng),實(shí)現(xiàn)中斷的嵌套處理。
而另一類(lèi)的單片機(jī),如我們正在學(xué)習(xí)的AVR單片機(jī),其硬件系統(tǒng)不支持自動(dòng)實(shí)現(xiàn)中斷嵌套的處理。如果在系統(tǒng)設(shè)計(jì)中,必須使用中斷嵌套處理,則需要由用戶(hù)編寫(xiě)相應(yīng)的程序,通過(guò)軟件設(shè)置來(lái)實(shí)現(xiàn)中斷嵌套的功能。
● 中斷控制(屏蔽)
單片機(jī)擁有眾多中斷源,但在某一具體設(shè)計(jì)中通常并不需要使用所有的中斷源,或者在系統(tǒng)軟件運(yùn)行的某些關(guān)鍵階段不允許中斷打斷現(xiàn)行程序的運(yùn)行,這就需要一套 軟件可控制的中斷屏蔽/允許系統(tǒng)。在單片機(jī)的I/O寄存器中,通常存在一些特殊的標(biāo)志位用于控制開(kāi)放或關(guān)閉(屏蔽)MCU對(duì)中斷響應(yīng)處理,這些標(biāo)志稱(chēng)為中 斷屏蔽標(biāo)志位或中斷允許控制位。用戶(hù)程序可以改變這些標(biāo)志位的設(shè)置,在需要的時(shí)候允許MCU響應(yīng)中斷,而在不需要的時(shí)候則將中斷請(qǐng)求信號(hào)屏蔽(注意:不是 取消),此時(shí)盡管產(chǎn)生了中斷請(qǐng)求信號(hào),MCU也不會(huì)響應(yīng)中斷請(qǐng)求。
從對(duì)中斷源的控制角度講,中斷源還可分成2類(lèi):

  1. 非屏蔽中斷。非屏蔽中斷是指MCU對(duì)中斷源產(chǎn)生的中斷請(qǐng)求信號(hào)是不能屏蔽的,也就是說(shuō)一旦發(fā)生中斷請(qǐng)求,MCU肯定響應(yīng)該中斷。在單片機(jī)中,外部RESET引腳產(chǎn)生的復(fù)位信號(hào),就是一個(gè)非屏蔽的中斷。
  2. 可屏蔽中斷??善帘沃袛嗍侵赣脩?hù)程序可以通過(guò)中斷屏蔽控制標(biāo)志對(duì)中斷源產(chǎn)生的中斷請(qǐng)求信號(hào)進(jìn)行控制,既允許或禁止MCU對(duì)該中斷的響應(yīng)。在用 戶(hù)程序中,可以預(yù)先執(zhí)行一條允許中斷的指令,這樣一旦發(fā)生中斷請(qǐng)求,MCU就能夠響應(yīng)中斷。反之,用戶(hù)程序也可以預(yù)先執(zhí)行一條中斷禁止(屏蔽)指令,使 MCU不響應(yīng)中斷請(qǐng)求。因此,可屏蔽中斷的中斷請(qǐng)求能否可以被MCU響應(yīng),最終是由用戶(hù)程序來(lái)控制的。在單片機(jī)中,大多數(shù)的中斷都是可屏蔽的中斷。

● 中斷響應(yīng)條件
單片機(jī)在工作時(shí),在每個(gè)機(jī)器周期都會(huì)查詢(xún)一下各個(gè)中斷源的中斷標(biāo)記,從而判斷是否有中斷申請(qǐng),如果中斷標(biāo)志為1,說(shuō)明有中斷請(qǐng)求發(fā)生。
綜合前面的介紹,我們可以知道,在單片機(jī)中,對(duì)應(yīng)每一個(gè)中斷源都有一個(gè)相應(yīng)的中斷標(biāo)志位該中斷標(biāo)志位將占據(jù)中斷控制寄存器中的一位。當(dāng)單片機(jī)檢測(cè)到某一中斷源產(chǎn)生符合條件的中斷信號(hào)時(shí),其硬件會(huì)自動(dòng)將該中斷源對(duì)應(yīng)的中斷標(biāo)志位置“1”,這就意味著有中斷信號(hào)產(chǎn)生了,向MCU申請(qǐng)中斷。
但中斷標(biāo)志位的置“1”,并不代表MCU一定響應(yīng)該中斷。為了合理控制中斷響應(yīng),在單片機(jī)內(nèi)部還有相關(guān)的用于中斷控制的中斷允許標(biāo)志位。最重要的一個(gè)中斷允許標(biāo)志位是全局中斷允許標(biāo)志位。當(dāng)該標(biāo)志位為“0”,表示禁止MCU響應(yīng)所有的可屏蔽中斷的響應(yīng)。此時(shí)不管有否中斷產(chǎn)生,MCU不會(huì)響應(yīng)任何的中斷請(qǐng)求。只有全局中斷允許標(biāo)志位為“1”,才允許單片機(jī)響應(yīng)中斷。
MCU響應(yīng)中斷請(qǐng)求的第二個(gè)條件是每個(gè)中斷源所具有的各自獨(dú)立的中斷允許標(biāo)志位。當(dāng)某個(gè)中斷允許標(biāo)志位為“0”時(shí),表示MCU不響應(yīng)該中斷的中斷申請(qǐng)。
從上面的中斷響應(yīng)條件看出,只有當(dāng)全局中斷允許標(biāo)志位為“1”(由用戶(hù)軟件設(shè)置),中斷A允許標(biāo)志位為“1”(由用戶(hù)軟件設(shè)置),中斷A標(biāo)志位為“1” (符合中斷條件時(shí)由硬件自動(dòng)設(shè)置或由用戶(hù)軟件設(shè)置)時(shí),MCU才會(huì)響應(yīng)中斷A的請(qǐng)求信號(hào)(如果有多個(gè)中斷請(qǐng)求信號(hào)同時(shí)存在的情況下,還要根據(jù)中斷A的優(yōu)先 級(jí)來(lái)確定)。
用戶(hù)程序?qū)善帘沃袛嗟目刂?,一般是通過(guò)設(shè)置相應(yīng)的中斷控制寄存器來(lái)實(shí)現(xiàn)的。除了設(shè)置中斷的響應(yīng)條件,用戶(hù)程序還需要通過(guò)中斷控制器來(lái)設(shè)置中斷的其他特性,如:中斷觸發(fā)信號(hào)的類(lèi)型、中斷的優(yōu)先級(jí)、中斷信號(hào)產(chǎn)生的條件等等。
●中斷響應(yīng)過(guò)程(中斷服務(wù)程序)
當(dāng)所有的中斷響應(yīng)條件都滿(mǎn)足了之后,就要進(jìn)入中斷響應(yīng)過(guò)程進(jìn)行相應(yīng)處理了。單片機(jī)響應(yīng)中斷后,首先要把當(dāng)前指令的下一條指令的地址送入堆棧(保護(hù)斷點(diǎn)), 然后根據(jù)中斷標(biāo)記,將相應(yīng)的中斷入口地址送入程序指針,程序轉(zhuǎn)到中斷入口處繼續(xù)執(zhí)行(中斷服務(wù)程序),中斷程序執(zhí)行完后,單片機(jī)再把堆棧中保存的地址取 出,程序從剛才的中斷處繼續(xù)向下執(zhí)行。
需要注意的是,單片機(jī)硬件所做的保護(hù)工作只是保護(hù)了程序的一個(gè)指令地址,如果中斷響應(yīng)過(guò)程中修改了一些寄存器和變量的值,就需要在中斷響應(yīng)程序里面自己加以保護(hù)。
2、AVR單片機(jī)的外部中斷
AVR單片機(jī)有很多中斷,在后面的實(shí)例中我們會(huì)逐一介紹。本例中只介紹AVR單片機(jī)的外部中斷,
ATmega16有INT0、INT1和INT23個(gè)外部中斷源,分別由芯片外部引腳PD2、PD3、PB2上的電平的變化或狀態(tài)作為中斷觸發(fā)信號(hào)。
●外部中斷觸發(fā)方式和特點(diǎn)
INT0、INT1、INT2的中斷觸發(fā)方式取決于用戶(hù)程序?qū)CU控制寄存器MCUCR以及MCU控制與狀態(tài)寄存器MCUCSR的設(shè)定。其中,INT0和INT1支持4種中斷觸發(fā)方式:上升沿觸發(fā)、下降沿觸發(fā)、任意電平變化觸發(fā)、低電平觸發(fā)。
INT2支持上升沿觸發(fā)和下降沿觸發(fā)。
任意電平變化觸發(fā)表示只要引腳上有邏輯電平的變化就會(huì)產(chǎn)生中斷申請(qǐng)(不管是上升沿還是下降沿都引起中斷觸發(fā))。在這4種觸發(fā)方式中,還有以下的一些不同的特點(diǎn):
●低電平觸發(fā)是不帶中斷標(biāo)志類(lèi)型的,即只要中斷輸入引腳PD2或PD3保持低電平,那
么將一直會(huì)產(chǎn)生中斷申請(qǐng)。
●MCU對(duì)INT0和INT1的引腳上的上升沿或下降沿變化的識(shí)別(觸發(fā)),需要I/O時(shí)鐘信號(hào)的存在(由I/O時(shí)鐘同步檢測(cè)),屬于同步邊沿觸發(fā)的中斷類(lèi)型。
●MCU對(duì)INT2的引腳上的上升沿或下降沿變化的識(shí)別(觸發(fā)),以及低電平的識(shí)別(觸發(fā))是通過(guò)異步方式檢測(cè)的,不需要I/O時(shí)鐘信號(hào)的存在。因此,這 類(lèi)觸發(fā)類(lèi)型的中斷經(jīng)常作為外部喚醒源,用于將處在Idle休眠模式,以及處在各種其它休眠模式的MCU喚醒。這是由于除了在空閑(Idel)模式 時(shí),I/O時(shí)鐘信號(hào)還保持繼續(xù)工作,在其它各種休眠模式下,I/O時(shí)鐘信號(hào)均是處在暫停狀態(tài)的。
●如果使用低電平觸發(fā)方式的中斷作為喚醒源,將MCU從掉電模式(Power-down)中喚醒時(shí),電平拉低后仍需要維持一段時(shí)間才能將MCU喚醒,這是 為了提高了MCU的抗噪性能。拉低的觸發(fā)電平將由看門(mén)狗的時(shí)鐘信號(hào)采樣兩次(在通常的5V電源和25℃時(shí),看門(mén)狗的時(shí)鐘周期為1μs)。如果電平拉低保持 2次采樣周期的時(shí)間,或者一直保持到MCU啟動(dòng)延時(shí)(start-up time)過(guò)程之后,MCU將被喚醒并進(jìn)入中斷服務(wù)。如果該電平的保持時(shí)間能夠滿(mǎn)足看門(mén)狗時(shí)鐘的兩次采樣,但在啟動(dòng)延時(shí)(start-up time)過(guò)程完成之前就消失了,那么MCU仍將被喚醒,但不會(huì)觸發(fā)中斷進(jìn)入中斷服務(wù)程序。所以,為了保證既能將MCU喚醒,又能觸發(fā)中斷,中斷觸發(fā)電平 必須維持足夠長(zhǎng)的時(shí)間。
●如果設(shè)置了允許響應(yīng)外部中斷的請(qǐng)求,那么即便是引腳PD2、PD3、PB2設(shè)置為輸出方式工作,引腳上的電平變化也會(huì)產(chǎn)生外部中斷觸發(fā)請(qǐng)求。這一特性為用戶(hù)提供了使用軟件產(chǎn)生中斷的途徑。
(3)與外部中斷相關(guān)的寄存器和標(biāo)志位

在ATmega16中,除了寄存器SREG中的全局中斷允許標(biāo)志位I外,與外部中斷有關(guān)的寄存器有4個(gè),共有11個(gè)標(biāo)志位。分別是:MCU控制寄存器—MCUCR、MCU控制和狀態(tài)寄存器—MCUCSR、通用中斷控制寄存器—GICR、通用中斷標(biāo)志寄存器—GIFR。其作用分別是3個(gè)外部中斷各自的中斷標(biāo)志位、中斷允許控制位和用于定義外部中斷的觸發(fā)類(lèi)型。

     具體寄存器各個(gè)標(biāo)志位的意義和如何設(shè)置,請(qǐng)查閱相關(guān)ATmega16的數(shù)據(jù)手冊(cè),在此不做過(guò)多描述。
需要注意的是:在系統(tǒng)程序的初始化部分中對(duì)外部中斷進(jìn)行設(shè)置時(shí)(定義或改變觸發(fā)方式),應(yīng)先將GICR寄存器中該中斷的中斷允許位清零,禁止MCU響應(yīng)該中斷后再設(shè)置ISCn位。
而在開(kāi)放中斷允許前,一般應(yīng)通過(guò)向GIFR寄存器中的中斷標(biāo)志位INTFn寫(xiě)入邏輯“1”,將該中斷的中斷標(biāo)志位清除,然后開(kāi)放中斷。這樣可以防止在改變ISCn的過(guò)程中誤觸發(fā)中斷。
3、按鍵電路
按鍵電路與上一實(shí)例相同,在此略去。
4、外部中斷程序的編寫(xiě)
我們已經(jīng)知道,要實(shí)現(xiàn)中斷程序,首先要在主程序里面對(duì)相關(guān)中斷寄存器進(jìn)行中斷產(chǎn)生條件的設(shè)置。然后就是編寫(xiě)中斷服務(wù)程序。
本例中中斷寄存器的設(shè)置如下:
MCUCR |= (1 << ISC11) | (1 << ISC01) | (1 << ISC00);  
//INT0設(shè)置為上升沿中斷,INT1為下降沿中斷請(qǐng)求
GICR |= (1 << INT0) | (1 << INT1);      //允許INT0、INT1中斷
GIFR |= (1 << INTF1) | (1 << INTF0);    //清除INT0、INT1中斷標(biāo)志位
sei();          //使能全局中斷 

中斷服務(wù)程序的編寫(xiě)具有一定的格式,在不同編譯環(huán)境下各不相同,在WINAVR(GCC)環(huán)境下有兩種方式,分別是:
● SIGNAL(中斷向量名)
{
  …     //中斷服務(wù)程序內(nèi)容 
} 

● ISR(中斷向量名 )   

{
  …     //中斷服務(wù)程序內(nèi)容 
} 

在這兩種方式中,需要分別添加頭文件:#include <avr/signal.h>和#include <avr/interrupt.h>。
宏INTERRUPT 的用法與SIGNAL 類(lèi)似,區(qū)別在于SIGNAL 執(zhí)行時(shí)全局中斷觸發(fā)位被清除、其他中斷被禁止;INTERRUPT 執(zhí)行時(shí)全局中斷觸發(fā)位被置位、其他中斷可嵌套執(zhí)行。
另外avr-libc 提供兩個(gè)API 函數(shù)用于置位和清零全局中斷觸發(fā)位,它們是經(jīng)常用到的,
分別是:void sei(void) 和void cli(void) 由interrupt.h定義
在本實(shí)例中,我們采用包含頭文件#include <avr/interrupt.h>,的方式,使用ISR(中斷向量名 ){…}來(lái)編寫(xiě)中斷函數(shù)。
2.2.3 電路
本實(shí)例的按鍵電路如圖2.2.1所示,數(shù)碼管接口電路與實(shí)例1.3中的電路相同,在此不再給出。
圖2.2.1 按鍵電路
1、電路原理
本實(shí)例用K1、K2兩個(gè)按鍵分別連接到單片機(jī)的PD2、PD3端口,PD2、PD3同時(shí)也是單片機(jī)的外部中斷INT0、INT1的兩個(gè)引腳。當(dāng)按鍵按下時(shí),外部中斷INT0、INT1的兩個(gè)引腳的電平發(fā)生變化,從而產(chǎn)生外部中斷。
2、元器件選擇
在這里列出和本例相關(guān)的、關(guān)鍵部分的器件名稱(chēng)及其在電路中的作用。
● ATmega16:?jiǎn)纹瑱C(jī),檢測(cè)按鍵按下情況并控制數(shù)碼管顯示數(shù)字。
●數(shù)碼管:顯示按鍵狀態(tài)。
● R10:阻值為10K的電阻,下拉限流電阻。
● K1、K2:按鍵,當(dāng)按鍵按下時(shí),與按鍵連接的單片機(jī)端口的電平發(fā)生變化,產(chǎn)生外部中斷。
3、管腳連接
在這里列出和本例相關(guān)的、關(guān)鍵部分的單片機(jī)端口與外圍電路的連接。
● PB0-PB7:連接數(shù)碼管的8個(gè)段,控制數(shù)碼管的顯示。
● PD2、PD3:連接按鍵K1、K2,檢測(cè)兩個(gè)按鍵的狀態(tài)。
●PC6:數(shù)碼管選通端口,該端口通過(guò)三極管9013控制數(shù)碼管的選通,當(dāng)PC6輸出高電平時(shí),數(shù)碼管選通。
2.1.4 程序設(shè)計(jì)
1、程序功能
程序的功能是控制一個(gè)8段數(shù)碼管顯示“0”-“F”16個(gè)十六進(jìn)制的數(shù)字。當(dāng)系統(tǒng)上電時(shí),顯示“0”。K1鍵的作用是加“1”控制鍵:按1次K1鍵,顯示 數(shù)字加1,依次類(lèi)推。當(dāng)?shù)?5次按K1鍵時(shí),顯示“F”,第16次按K1鍵,顯示又從“0”開(kāi)始。K2鍵的作用是減1控制鍵:按1次K1鍵,顯示數(shù)字減 1,減到“0”后,再?gòu)摹癋”開(kāi)始。
● 按鍵開(kāi)關(guān)的軟件去抖和釋放
上一個(gè)實(shí)例已經(jīng)講過(guò)這種方法,本例不再重復(fù)。
● 單片機(jī)外部中斷的編程
在本例中,需要使用單片機(jī)的INT0、INT1,所以在程序中需要對(duì)相應(yīng)的寄存器進(jìn)行設(shè)置,并且編寫(xiě)中斷服務(wù)程序。
● 控制1位數(shù)碼管的顯示
在INT0中斷服務(wù)程序中,當(dāng)按鍵K1按下一次,數(shù)碼管顯示的數(shù)字加1;在INT1的中斷服務(wù)程序中,當(dāng)按鍵K2按下一次,數(shù)碼管顯示的數(shù)字減1。
2、主要變量和函數(shù)說(shuō)明
本例中需要編寫(xiě)中斷函數(shù),函數(shù)的功能是:當(dāng)有外部中斷發(fā)生時(shí),程序跳轉(zhuǎn)到中斷函數(shù)執(zhí)行數(shù)碼管顯示的程序,處理完后跳回主程序繼續(xù)執(zhí)行。
程序中用到變量Counter和 Disp_Buff[16] 。變量Counter用于指示按鍵按下的次數(shù),數(shù)組 Disp_Buff[16]存放數(shù)碼管顯示的字形編碼。
3、使用WINAVR開(kāi)發(fā)環(huán)境,makefile文件同前面的例子,直接復(fù)制到本實(shí)例程序的文件夾中即可。
4、程序代碼
[code="c"] #include <avr/io.h>       
#include <util/delay.h>
#include <avr/interrupt.h>   //中斷函數(shù)頭文件

unsigned char Disp_Buff[16] = {0xaf,0xa0,0xc7,0xe6,0xe8,0x6e,0x6f,0xa2,
0xef,0xee,0xeb,0x6d,0x0f,0xe5,0x4f,0x4b};
//數(shù)碼管字型碼表顯示:0,1,2,3,4,5,6,7,8,9,A,b,C,d,E,F
volatile unsigned char Counter;  //按鍵按下次數(shù)變量,如果在中斷中調(diào)用全局變量,必須加
//volatile來(lái)定義,否則變量不會(huì)變化
int main(void)           
{

PORTB = 0X00;      //
DDRB = 0Xff;      //

PORTC &= ~(1 << PC6);  //配置數(shù)碼管0的位選通口為低電平,不導(dǎo)通數(shù)碼管
DDRC |= (1 << PC6);    ///配置數(shù)碼管0的位選通口為輸出,選通數(shù)碼管0

PORTD = 0X08;     //一定要使能K2的上拉電阻,否則會(huì)有干擾
DDRD = 0XF3;      //K1、K2按鍵(PD2、PD3)設(shè)置為輸入端口

MCUCR |= (1 << ISC11) | (1 << ISC01) | (1 << ISC00);  
//INT0設(shè)置為上升沿中斷,INT1為下降沿中斷請(qǐng)求
GICR |= (1 << INT0) | (1 << INT1);      //允許INT0、INT1中斷
GIFR |= (1 << INTF1) | (1 << INTF0);    //清除INT0、INT1中斷標(biāo)志位

Counter = 0;                //按鍵按下次數(shù)變量清零
PORTC |= (1 << PC6);       //選通數(shù)碼管0

    sei();          //使能全局中斷 

while(1)
{
PORTB = Disp_Buff[Counter];            //數(shù)碼管顯示按鍵按下次數(shù)
}
}

//外部中斷0函數(shù),當(dāng)按鍵K1按下后,進(jìn)入此中斷
ISR(INT0_vect )           
{           
_delay_ms(20);         //按鍵按下,延時(shí)一會(huì)再判斷是否按下, 以消除干擾
if((PIND & (1 <<  PD2)))    // 按鍵真正按下后,進(jìn)行相應(yīng)處理
{
if(++Counter >= 16) Counter = 0; //次數(shù)大于15,清零
while((PIND & (1 <<  PD2)));//等待按鍵釋放                     
}           
}
//外部中斷1函數(shù),當(dāng)按鍵K2按下后,進(jìn)入此中斷
ISR(INT1_vect)
{           
_delay_ms(20);         //判斷按鍵按下,延時(shí)一會(huì)再判斷是否按下, 以消除干擾
if(!(PIND & (1 <<  PD3)))    // 按鍵真正按下后,進(jìn)行相應(yīng)處理
{
if(Counter) --Counter;     // 次數(shù)減1
else Counter = 15;   //   次數(shù)為零則改成15

while(!(PIND & (1 <<  PD3)));  //

}
}

[/code]

在語(yǔ)言C語(yǔ)言編寫(xiě)單片機(jī)程序過(guò)程,如果要使用外部中斷服務(wù)程序時(shí),要盡量減少中斷服務(wù)程序的內(nèi)容和長(zhǎng)度。因?yàn)樵谥鞒绦蛑锌赡苓€要相應(yīng)別的中斷,如果一個(gè)中斷服務(wù)程序過(guò)長(zhǎng),很可能會(huì)影響到主程序?qū)ζ渌袛嗟捻憫?yīng)。
常用的處理方法是:在中斷服務(wù)程序中只改變變量的值,或者設(shè)置各種標(biāo)志,在主程序里面對(duì)變量或標(biāo)志進(jìn)行判斷和處理。本實(shí)例為了演示的方便,在中斷程序中進(jìn) 行了所有的操作。應(yīng)該說(shuō)明的是,這種方法是極不可取的。更為合理的方法是:在中斷服務(wù)程序里面只改變Counter的值。其余部分都放到主程序里面進(jìn)行處 理。
另外需要特別強(qiáng)調(diào)的一點(diǎn)是,在用WINAVR編寫(xiě)中斷服務(wù)程序時(shí),如果中斷服務(wù)程序中用到了全局變量,則在定義全局變量時(shí),必須在變量的數(shù)據(jù)類(lèi)型前加 volatile來(lái)定義,否則該變量在中斷服務(wù)程序中不會(huì)變化。這是因?yàn)樵谟肅語(yǔ)言編寫(xiě)單片機(jī)程序時(shí),都會(huì)用到編譯器的“優(yōu)化”代碼功能,以使程序更加簡(jiǎn) 潔、緊湊。但是畢竟編譯器的優(yōu)化是很死板的,他會(huì)把一些對(duì)變量的讀操作優(yōu)化掉。這樣就導(dǎo)致在全局中斷中使用的變量被優(yōu)化成一個(gè)靜止變量,即該變量的值不再 改變。所以我們要把這些變量定義為volatile,意思是提示編譯器:該變量是很容易變化的,不準(zhǔn)對(duì)該變量的讀取進(jìn)行優(yōu)化。這樣在中斷中每次對(duì)變量的讀 寫(xiě)就都可以正確的執(zhí)行了。


關(guān)注有人微信公眾號(hào)
了解更多信息