1、中斷的概念
對于單片機中斷的概念,我們可以這樣理解:單片機處理某一事件A時,發生了另一事件B請求(中斷請求);單片機暫時中斷當前工作,轉去處理事件B(中斷響應和中斷服務);待單片機將事件B處理完畢,再回到原來事件A被中斷的地方繼續處理事件A(中斷返回),這一過程稱為中斷。 引起單片機中斷的根源或原因: 中斷源向單片機提出中斷請求。
2、中斷優先級 單片機的中斷系統一般允許多個中斷源,當幾個中斷源同時向單片機請求中斷,要求為它服務的時候,這就存在單片機優先響應哪一個中斷源請求的問題。通常根據中斷源的輕重緩急排隊,優先處理最緊急事件的中斷請求源,即規定每一個中斷源有一個優先級別。單片機總是先響應優先級別最高的中斷請求。 中斷優先級的三條原則: a:單片機同時接收到幾個中斷時,響應優先級別最高的中斷請求。 b:正在進行的中斷過程不能被新同級或低優先級的中斷請求所中斷。 c:正在進行的低優先級中斷服務,能被高優先級中斷請求所中斷。
3、中斷嵌套
當單片機正在處理一個中斷請求源的時候(執行相應的中斷服務程序),發生了另外一個優先級比它還高的中斷源請求。單片機暫停對原來中斷源的服務程序,轉而去處理優先級更高的中斷請求源,處理完以后,再回到原低級中斷服務程序,這樣的過程稱為中斷嵌套。 4、單片機內部中斷電路和寄存器
我們以STC單片機為例進行介紹: 上圖是單片機內部和中斷有關的電路,從圖中我們知道單片機可以有5個中斷源,分別是/INT0,T0,/INT1,T1,RX和TX。/INT0和/INT1為外部中斷源;T0和T1為定時器/計數器中斷;RX和TX為串口收發中斷。 相關寄存器有TCON,IE,IP,這些寄存器又是起什么作用的呢: TF1是定時器1的溢出標志位,當定時器1發生溢出時,此位變成1,同時提出中斷請求,一直保持到CPU響應中斷時,才由硬件清0。如果程序不是采用中斷的方式,而是采用查詢的方式,那么這位需要軟件清0。 TR1是定時器1的運行控制位,當它為1時允許定時器1開始計數,為0時禁止定時器1計數。 TF0和TR0的功能分別與TF1和TR1類似,它們對應的是定時器0。 對于IE1,IT1,IEO,IT0的功能在上圖中有描述了,就不多說了。

IE寄存器是中斷允許寄存器,只有相應的位置為1了,相關的中斷才能被允許哦。 IP寄存器是中斷優先級控制寄存器,當某位被設成1了,那么對應的中斷源就是高優先級了哦,就可以中斷低優先級中斷源的處理函數了哦。
好了,今天給大家介紹了單片機內部中斷電路和相關的寄存器,明天給結合程序給大家講述如何實現單片機中斷功能。
上一條分享我們提到單片機一般有5個中斷源,在這條分享中我們看看如何通過編程實現這些中斷功能。
1、外部中斷
外部中斷源有:INT0和INT1,可由外部信號引發單片機的中斷,我們需要將信號引到單片機的INT0和INT1管腳上。外部中斷INTO和INT1即可底電平觸發,也可下降沿觸發。相關的寄存器有TCON,IE,IP。
下面我們通過一段例程序理解下,怎樣編寫代碼:
#include “reg51.h”
void init_int0(void) //中斷功能的初始化函數,只有對相關的寄存器進行了正確的
配置,采用運用單片機的中斷功能哦。
{
IT0=1; //IT0是寄存器TCON的最低位,在這里設成1,單片機管腳INT0上的信號低跳變(下降沿)引發中斷。
EX0=1; //EX0是寄存器IE的最低位,在這里設成1,允許發生INT0中斷。
EA=1; //EA是寄存器IE的最高位,在這里設成1,相當于開啟了允許中斷的總開關。只有EA和EX0都設成1了, 才開啟了INTO中斷功能哦。
}
void main(void)
{
init_int0(); //需要在主函數中,對INT0的相關寄存器進行初始化配置的。
while(1);
}
Void exint0() interrupt 0 //中斷函數,把我們希望實現的功能加進入,這里面的代碼應該盡量簡潔,短 小,以免占用太多的時間哦。
{
加上你希望實現的功能。
}
在看懂上面這段代碼的基礎上大家在想想如果希望是低電平引發中斷,程序該怎么寫呢?
外部中斷INT1的初始化函數和中斷處理函數該怎么寫呢?
2、定時中斷
與定時器/計數器T0,定時器/計數器T1中斷相關的寄存器主要有TMOD,THX,TLX,TCON,IE。下面我們通過一段例程看看怎樣實現定時器/計數器的中斷功能(以定時器/計數器0為例)。
#include “reg51.h”
void timer0_init(void)//定時器0中斷初始化函數
{
TMOD=0x80; //將定時器/計數器0當成13位定時器/計數器,TL0只用低5位參與分頻,TH0整個8位全用。
TH0=0xXX; //設定定時器0初始計數值的高8位
TL0=0xXX; //設定定時器0初始計數值的低8位
TR0=1; //定時器0開始計數
ET0=1; //開定時器0中斷允許
EA= 1; //開總中斷允許
}
void main(void)
{
timer0_init();
while(1);
}
void timer0int interrupt 1
{
TH0=0xXX; //在中斷處理函數里面記得給TH0重新賦初值哦
TL0=0xXX; //在中斷處理函數里面記得給TL0重新賦初值哦
加上你希望實現的功能哦。
}
這樣在單片機工作頻率固定的前提下,我們可以通過調節TH0和TL0的初值來改變定時0的定時時長,從而改變定時中斷發生的時間間隔。這樣就以我們希望的時間間隔執行中斷處理函數中的指令。
定時器1的中斷的初始化和定時器0的中斷初始化類似。
需要指出的是定時器0和定時器1有4中不同的工作方式,不同的工作方式的選擇可以通過設置寄存器TMOD來實現。
3、串口收發中斷
#include
//FOSC = 11.0592MHz,12T模式,SMOD=0
#define reload_count_1200bps 0xe8
#define reload_count_2400bps 0xf4
#define reload_count_4800bps 0xfa
#define reload_count_9600bps 0xfd
void serial_port_initial(char TH,char TL)
{
SCON=SCON|0x50; //確定串口工作方式,8位可變波特率,無奇偶校驗位
TMOD=TMOD|0x20; //設置定時器1為8位自動重裝記數器
PCON=PCON|0x00; //這個寄存器里有一位SMOD,它和波特率的確定有關。
TH1 = TH; //設置定時器1自動重裝數TH1,它和波特率的確定有關。
TL1 = TL; //設置定時器1自動重裝數TL1,它和波特率的確定有關。
ES=1; //允許串口中斷
EA=1; //開總中斷
TR1=1; //開定時器1
}
波特率=(2SMOD/32)x(定時器1的溢出率) 定時器1的溢出率 = SYSclk/12(256-TH1)
char UARTReceive(void) //串口數據接收函數
{
char ch;
ch=SBUF;
return (ch); // 暫存接收到的數據
}
void main(void)
{
serial_port_initial(reload_count_2400bps,reload_count_2400bps);
//初始化串口參數
while(1);
}
void UART_Interrupr_Receive(void) interrupt 4 //串口接收中斷處理函數
{
ES = 0;
RI = 0; //當串口接收到數據時,RI回被置1,同時引發中斷,在中斷處理函數中將其清零。
buf = UARTReceive();
ES = 1;
}
好了,今天簡單地和大家分享了一下單片機中斷的一些基本知識,在這里只是簡單地具了幾個例,中斷的用法很有技巧,這需要大家在項目的實踐中去掌握,吃透。
|