前言
本節(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單片機共有5個中斷源,分別是外部中斷0、外部中斷1、定時器中斷0、定時器中斷1和串口中斷,這5個中斷源有二個中斷優(yōu)先級,每個中斷源可以編程為高優(yōu)先級和低優(yōu)先級中斷,可實現(xiàn)二級中斷服務(wù)程序嵌套。
2.中斷寄存器
(1) 中斷允許寄存器TCON(88H)
TCON為定時器/計數(shù)器T0、T1的控制器,同時也鎖存了T0、T1的溢出中斷源和外部中斷源
各個控制位功能如下表
(2) 中斷允許寄存器IE(A8H)
寄存器IE為特殊功能寄存器,控制CPU對中斷源的開放或者屏蔽,以及每個中斷源是否允許中斷
各個控制位功能如下表
(3) 中斷優(yōu)先級寄存器IP(B8H)
特殊功能寄存器IP為中斷優(yōu)先級寄存器,保存各種中斷源優(yōu)先級控制位,用戶可以通過軟件控制
各個控制位功能如下表
當系統(tǒng)復位后,IP各位均為0,所有中斷處于低優(yōu)先級狀態(tài),低優(yōu)先級中斷可以被高優(yōu)先級中斷打斷,反之則不行,一種中斷一旦得到相應,與他同級的中斷不能再中斷打斷,中斷優(yōu)先級默認如下
3.中斷處理流程
系統(tǒng)啟動后需要使用軟件設(shè)置中斷類型以及中斷觸發(fā)方式,并打開中斷
void interrupt_init(void)
{
EA=1; // 打開總中斷
IT0=1; // 外部中斷0, P3.2引腳 下降沿觸發(fā)
EX0=1
}
當中斷源發(fā)出中斷請求時候,CPU停止手頭的工作,進入中斷服務(wù)程序運行,中斷服務(wù)程序按照如下流程處理
中斷處理過程主要包括三個階段,分別是:中斷響應、中斷處理、中斷返回
4.硬件連接
硬件連接如下所示,通過杜邦線連接P32和GND,控制杜邦線插拔和GND連接一端,控制P32中斷源輸入的電平
二、示例程序
1.創(chuàng)建工程
將上一節(jié)工程復制出來,并修改名字為06-interrupt
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!,說明進入中斷成功。
注意:
不建議直接在中斷處理函數(shù)中處理數(shù)據(jù),本文是中斷處理函數(shù)中設(shè)置interrupt_flag標志位,然后主程序中查詢標志位進行數(shù)據(jù)處理。