一、外部中斷介紹
在前面文章中,我們對中斷的概念進行了介紹。STC89C516單片機內部有6箇中斷源,它們分別爲:
INT0—外部中斷0,由P32端口線引入,低電平或下降沿觸發中斷。
INT1—外部中斷1,由P33端口線引入,低電平或下降沿觸發中斷。
T0—定時器/計數器0中斷,由T0計數器計滿回零引起。
T1—定時器/計數器1中斷,由T1計數器計滿回零引起。
T2—定時器/計數器2中斷,由T2計數器計滿回零引起。
TI/RI—串行口中斷,串行端口完成一幀字符發送/接收後引起。
在定時器實驗中,我們已經對T0、T1、T2中斷進行了學習,本文我們對INT0和INT1這兩個外部中斷進行學習。與這兩個外部中斷有關的寄存器是中斷允許寄存器IE和定時器/計數器控制寄存器TCON。
IE用來設定各個中斷源的打開和關閉,IE在特殊功能寄存器中字節地址爲A8H,位地址(由低位到高位)分別爲A8H~AFH,該寄存器可進行位尋址,即可以對這個寄存器的每一位進行操作。單片機復位時IE寄存器全部被清0,這個寄存器的各位如下表所示。
中斷允許寄存器IE
位序號 |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
位符號 |
EA |
-- |
ET2 |
ES |
ET1 |
EX1 |
ET0 |
EX0 |
位地址 |
AFH |
-- |
ADH |
ACH |
ABH |
AAH |
A9H |
A8H |
EA—全局中斷允許位。
EA=1,打開全局中斷控制,在此條件下,由各個中斷控制位確定相應中斷的打開和關閉。
EA=0,關閉全部中斷。
--—無效位。
ET2—定時器/計數器2中斷允許位。
ET2=1,打開T2中斷。
ET2=0,關閉T2中斷。
ES—串行口中斷允許位。
ES=1,打開串行口中斷。
ES=0,關閉串行口中斷。
ET1—定時器/計數器1中斷允許位。
ET1=1,打開T1中斷。
ET1=0,關閉T1中斷。
EX1—外部中斷1中斷允許位。
EX1=1,打開外部中斷1中斷。
EX1=0,關閉外部中斷1中斷。
ET0—定時器/計數器0中斷允許位。
ET0=1,打開T0中斷。
ET0=0,關閉T0中斷。
EX0—外部中斷0中斷允許位。
EX0=1,打開外部中斷0中斷。
EX0=0,關閉外部中斷0中斷。
TCON在特殊功能寄存器中,字節地址爲88H,位地址(由低位到高位)分別爲88H~8FH,該寄存器可以進行位尋址。TCON寄存器用來控制定時器的啓、停,標誌定時器的溢出和中斷情況。單片機復位時TCON全部清0。這個寄存器的給位定義如下表所示。其中TF1、TR1、TF0和TR0位用於定時器/計數器的設置。IE1、IT1、IE0和IT0位用於外部中斷的設置。
定時器/計數器控制寄存器TCON
位序號 |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
位符號 |
TF1 |
TR1 |
TF0 |
TR0 |
IE1 |
IT1 |
IE0 |
IT0 |
位地址 |
8FH |
8EH |
8DH |
8CH |
8BH |
8AH |
89H |
88H |
TF1—定時器1溢出標誌位。
當定時器1計滿溢出時,由硬件使TF1置1,並且申請中斷。進入中斷服務程序後,由硬件自動清0。需要注意的是,如果使用定時器的中斷,那麼該位完全不用人爲去操作,但是如果使用軟件查詢的方式的話,當查詢到該位置1後,就必須用軟件清0。
TR1—定時器1運行控制位。
由軟件清0關閉定時器1。當GATE=1時,INT1爲高電平且TR1置1啓動定時器1;當GATE=0時,TR1置1啓動定時器1。
TF0—定時器0溢出標誌位。
該位與TF1功能和操作方法相同。
TR0—定時器0運行控制位。
該位與TR1功能和操作方法相同。
IE1—外部中斷1請求標誌。
當IT1=0時,外部中斷INT1爲電平觸發方式,每個機器週期採用INT1引腳,若INT1引腳爲低電平,則置1,否則IE1清0。
當IT1=1時,外部中斷INT1爲邊沿觸發方式,當採集到INT1由高電平向低電平的跳變時則將IE1置1。IE1=1表示外部中斷1正向CPU申請中斷。當CPU響應中斷轉向中斷服務程序時,該位由硬件清0。
IT1—外部中斷1觸發方式選擇位。
IT1=0,電平觸發方式,引腳INT1上低電平觸發中斷。
IT0=1,邊沿觸發方式,引腳INT1上由高電平向低電平的跳變觸發中斷。
IE0—外部中斷0請求標誌。
這一位的用法與IE1相同。
IT0—外部中斷0觸發方式選擇位。
這一位的用法與IT1相同。
二、實驗例程
實驗1:電平觸發外部中斷
在這個實驗中,我們把按鍵F1與外部中斷的0通道連接在一起。用F1作爲外部觸發的信號源。這裏例程的代碼如下所示。
main()
{
LED=0x55;
EA=1; //打開全局中斷
EX0=1; //打開外部中斷0
IT0=0; //外部中斷採用電平觸發
for(;;);
}
void int0_ISR(void) interrupt 0 using 1
{
LED=~LED; //按位取反
}
在主函數中,首先給LED賦初值,然後開啓外部中斷,設置外部中斷爲電平觸發方式,之後for循環使程序處於等待狀態。在外部中斷的處理函數中,將LED的每一位取反。
將程序燒寫之後可以看到實驗現象,發光管中有4個點亮,按下F1按鍵則發光管全部點亮,鬆開F1按鍵,則4個發光管點亮。
INT0和INT1分別與P32和P33口複用,將按鍵接到P32口上後,按下按鍵之後,INT0口輸入低電平。則觸發中斷。在中斷中,對LED按位取反。由於採用電平觸發中斷,因此只要按鍵按下,就會一直進入中斷,對LED一直取反。因此,看到的現象是8個發光管都發光。
實驗2:邊沿觸發外部中斷
這個實驗與上一個實驗不同,這個實驗我們採用邊沿觸發的方式採集外部中斷,並對LED進行控制,實驗代碼如下所示。
main()
{
LED=0;
EA=1; //打開全局中斷
EX0=1; //打開外部中斷0
IT0=1; //外部中斷採用邊沿觸發
for(;;);
}
void int0_ISR(void) interrupt 0 using 1
{
delay1ms(10); //去抖
if(INT0==0)
LED=!LED; //改變燈的狀態
}
這個實驗用外部中斷0的下降沿來觸發中斷。在中斷中進行去抖後,將LED1的狀態改變。將按鍵接到P32口上後,按下按鍵之後,則LED1狀態改變。