青草国产精品久久久久久,国产高清一区二区三区视频,免费av一区二区三区,午夜熟女插插XX免费视频

產(chǎn)品
有人云 — 物聯(lián)網(wǎng)云平臺 零編程,組態(tài)拖拽即可實現(xiàn)遠程監(jiān)控。同時支持私有部署,擁有屬于自己的軟硬件一體化方案
200
+
私有云項目
數(shù)據(jù)本地化
業(yè)務個性化
10
+
萬 公有云注冊用戶
80%公有云功能免費
付費VIP享自定義品牌服務
有人云官網(wǎng)
有人智造 — ODM/EMS 依托自動化、智能化、柔性化、透明化的智能工廠,
提供代研、代料、代工一站式OEM/ODM服務
有人智造官網(wǎng)
有人智能 — 解決方案 打包提供云、管、邊、端整體解決方案
從問題診斷、方案設計,到實施落地、系統(tǒng)運維
有人智能官網(wǎng)
新聞資訊
AVR單片機中斷實現(xiàn) ATmega16 INT ISR(INT0_vect)
2010-11-28


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

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

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

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

  1. 非屏蔽中斷。非屏蔽中斷是指MCU對中斷源產(chǎn)生的中斷請求信號是不能屏蔽的,也就是說一旦發(fā)生中斷請求,MCU肯定響應該中斷。在單片機中,外部RESET引腳產(chǎn)生的復位信號,就是一個非屏蔽的中斷。
  2. 可屏蔽中斷??善帘沃袛嗍侵赣脩舫绦蚩梢酝ㄟ^中斷屏蔽控制標志對中斷源產(chǎn)生的中斷請求信號進行控制,既允許或禁止MCU對該中斷的響應。在用 戶程序中,可以預先執(zhí)行一條允許中斷的指令,這樣一旦發(fā)生中斷請求,MCU就能夠響應中斷。反之,用戶程序也可以預先執(zhí)行一條中斷禁止(屏蔽)指令,使 MCU不響應中斷請求。因此,可屏蔽中斷的中斷請求能否可以被MCU響應,最終是由用戶程序來控制的。在單片機中,大多數(shù)的中斷都是可屏蔽的中斷。

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

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

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

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

● ISR(中斷向量名 )   

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

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

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

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

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

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

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

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

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

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

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

}
}

[/code]

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

工作日每天: 14:00~17:00
抖音、天貓 "有人旗艦店"

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