前言

本節(jié)我們開始,我們學習51單片機的中斷系統(tǒng),51單片機有5個中斷源,我們首先學習外部中斷,并通過中斷方式檢測P3^2接口是否有低電平產(chǎn)生。

一、基礎(chǔ)知識

1.中斷簡介

中斷是指CPU在執(zhí)行A事件的時候,突然收到B事件發(fā)出的(中斷)請求,CPU停止手中的事情,轉(zhuǎn)而去執(zhí)行B事件,B事件執(zhí)行完畢后,又回到原來A事件被打斷的地方,繼續(xù)執(zhí)行程序的過程,示意圖如下所示:

51單片機玩轉(zhuǎn)物聯(lián)網(wǎng)基礎(chǔ)篇07-外部中斷

51單片機共有5個中斷源,分別是外部中斷0、外部中斷1、定時器中斷0、定時器中斷1和串口中斷,這5個中斷源有二個中斷優(yōu)先級,每個中斷源可以編程為高優(yōu)先級和低優(yōu)先級中斷,可實現(xiàn)二級中斷服務(wù)程序嵌套。

51單片機玩轉(zhuǎn)物聯(lián)網(wǎng)基礎(chǔ)篇07-外部中斷

2.中斷寄存器

(1) 中斷允許寄存器TCON(88H)

TCON為定時器/計數(shù)器T0、T1的控制器,同時也鎖存了T0、T1的溢出中斷源和外部中斷源

51單片機玩轉(zhuǎn)物聯(lián)網(wǎng)基礎(chǔ)篇07-外部中斷

各個控制位功能如下表

51單片機玩轉(zhuǎn)物聯(lián)網(wǎng)基礎(chǔ)篇07-外部中斷

(2) 中斷允許寄存器IE(A8H)

寄存器IE為特殊功能寄存器,控制CPU對中斷源的開放或者屏蔽,以及每個中斷源是否允許中斷

51單片機玩轉(zhuǎn)物聯(lián)網(wǎng)基礎(chǔ)篇07-外部中斷

各個控制位功能如下表

51單片機玩轉(zhuǎn)物聯(lián)網(wǎng)基礎(chǔ)篇07-外部中斷

(3) 中斷優(yōu)先級寄存器IP(B8H)

特殊功能寄存器IP為中斷優(yōu)先級寄存器,保存各種中斷源優(yōu)先級控制位,用戶可以通過軟件控制

51單片機玩轉(zhuǎn)物聯(lián)網(wǎng)基礎(chǔ)篇07-外部中斷

各個控制位功能如下表

51單片機玩轉(zhuǎn)物聯(lián)網(wǎng)基礎(chǔ)篇07-外部中斷

當系統(tǒng)復位后,IP各位均為0,所有中斷處于低優(yōu)先級狀態(tài),低優(yōu)先級中斷可以被高優(yōu)先級中斷打斷,反之則不行,一種中斷一旦得到相應,與他同級的中斷不能再中斷打斷,中斷優(yōu)先級默認如下

51單片機玩轉(zhuǎn)物聯(lián)網(wǎng)基礎(chǔ)篇07-外部中斷

3.中斷處理流程

系統(tǒng)啟動后需要使用軟件設(shè)置中斷類型以及中斷觸發(fā)方式,并打開中斷

void interrupt_init(void) 
{ 
    EA=1;  // 打開總中斷 
    IT0=1;  // 外部中斷0, P3.2引腳 下降沿觸發(fā) 
    EX0=1 
} 
 

當中斷源發(fā)出中斷請求時候,CPU停止手頭的工作,進入中斷服務(wù)程序運行,中斷服務(wù)程序按照如下流程處理

51單片機玩轉(zhuǎn)物聯(lián)網(wǎng)基礎(chǔ)篇07-外部中斷

中斷處理過程主要包括三個階段,分別是:中斷響應、中斷處理、中斷返回

4.硬件連接

硬件連接如下所示,通過杜邦線連接P32和GND,控制杜邦線插拔和GND連接一端,控制P32中斷源輸入的電平

51單片機玩轉(zhuǎn)物聯(lián)網(wǎng)基礎(chǔ)篇07-外部中斷

二、示例程序

1.創(chuàng)建工程

將上一節(jié)工程復制出來,并修改名字為06-interrupt

51單片機玩轉(zhuǎn)物聯(lián)網(wǎng)基礎(chǔ)篇07-外部中斷

2.修改程序

/*------------------------------------------------------  
*店鋪網(wǎng)址:https://shop321633213.taobao.com/?spm=a1z10.3-c.0.0.33816af5iLgN2F  
*適用于A08開發(fā)板  
*實驗現(xiàn)象:驅(qū)動LCD1602  
*QQ群:906015840  
-------------------------------------------------------*/  
 
#include<reg51.h> //頭文件  
#include <intrins.h>  
 
#define uchar unsigned char  
#define uint unsigned int  
 
uchar code table_xiaoyi[]="XIAOYI IOT";         //  
uchar code table_xiaoyi_welcome[]="Welcome!";                                    
uchar code table_xiaoyi_interrupt[]="INT0!";                                    
 
 
sbit LCD_EN=P3^7;   //液晶使能信號  
sbit LCD_RS=P3^5;   //數(shù)據(jù)/命令選擇端  
sbit LCD_WR=P3^6;  
int interrupt_flag = 0;  
 
void delay_ms(uint ms)  
{  
  uint x,y;  
  for(x=ms;x>0;x--)  
    for(y=110;y>0;y--);  
}  
 
void write_com(uchar com)          //命令  
{  
   LCD_RS=0;        //選擇寫命令  
   P0=com;  
   delay_ms(5);  
   LCD_EN=1;        //使能信號  
   LCD_EN=0;         //關(guān)閉使能  
}  
 
void write_data(uchar date)          //數(shù)據(jù)  
{  
  LCD_RS=1;        //選擇寫數(shù)據(jù)  
  P0=date;  
  delay_ms(5);  
  LCD_EN=1;  
  LCD_EN=0;  
}  
 
void init()  
{  
  LCD_EN=0;  
  write_com(0x38);         //00111000        設(shè)置16*2顯示,5*7點陣 8為數(shù)據(jù)接口  
        write_com(0x0c);   //00001100        設(shè)置開顯示,不顯示光標  
        write_com(0x06);         // 00000110        寫一個字符后地址指針加 1  
        write_com(0x01);         //00000001        顯示清0,數(shù)據(jù)指針清零         /*   */  
}  
 
void interrupt_init(void)  
{  
    EA=1;  // 打開總中斷  
    IT0=1;  // 外部中斷0, P3.2引腳 下降沿觸發(fā)  
    EX0=1;  
}  
 
void main(void) //主函數(shù)  
{  
        uchar i;  
        LCD_WR=0;  
 
        interrupt_init();  
        init();  
        // 寫第一行數(shù)據(jù)  
        write_com(0x80);   
        for(i=0;i<10;i++)  
        {  
                write_data(table_xiaoyi[i]);  
                delay_ms(5);  
        }  
        // 寫第二行數(shù)據(jù)  
        write_com(0x80+0x40);          
        for(i=0;i<8;i++)  
        {  
                write_data(table_xiaoyi_welcome[i]);  
                delay_ms(5);  
        }  
 
        while(1)  
        {  
                if (interrupt_flag == 1)  
                {  
                         // 第二行顯示清空  
                        write_com(0x80+0x40);          
                        for(i=0;i<8;i++)  
                        {  
                                write_data(0x20);  
                                delay_ms(5);  
                        }  
                        // 寫第二行數(shù)據(jù)  

程序中interrupt_init()函數(shù)初始化外部中斷0,中斷處理函數(shù)int0_func()中先關(guān)閉總中斷,防止被高優(yōu)先級中斷打斷,然后賦值標志位,最后開啟總中斷

三、運行

將上述程序生成的hex文件燒錄到板子中,使用杜邦線將P32引腳接地,可以看到LCD1602第二行顯示INT0!,說明進入中斷成功。

51單片機玩轉(zhuǎn)物聯(lián)網(wǎng)基礎(chǔ)篇07-外部中斷

注意:

不建議直接在中斷處理函數(shù)中處理數(shù)據(jù),本文是中斷處理函數(shù)中設(shè)置interrupt_flag標志位,然后主程序中查詢標志位進行數(shù)據(jù)處理。