一、中斷的基本概念
中斷程序一般指中斷服務程序。中斷服務程序,處理器處理“急件”,可理解為是一種服務,是通過執行事先編好的某個特定的程序來完成的,這種處理“急件”的程序被稱為——中斷服務程序。在程序方面來說 當CPU在執行一個程序的時候,突然產生了中斷事件CPU就去執行中斷程序了,當執行完成后CPU又回來執行原先的程序。
當單片機正在執行程序時,出現了某些特殊狀況,例如定時時間到、有鍵盤信號輸入等,此時CPU須要暫時停止當前的程序,而轉去執行處理這些事件的程序,待執行完這些特定的程序之后,再返回到原先的程序去執行,這就形成了一次“中斷”。“中斷”加強了單片機處理突發事件的能力,如果沒有中斷功能,對可能發生的特殊狀況的處理就必須采用定時查詢,這樣就會浪費大量的CPU時間。
因此,中斷是單片機中很重要的一個概念,是提高工作效率的重要功能,中斷系統功能的好壞是衡量單片機功能的重要指標。單片機的“中斷源”與單片機包含的外圍設備有很大的關系,所謂“中斷源”就是引起中斷的原因或根源,就是中斷請求的來源。16F873/876內部集成了12個外圍設備。
外圍設備在工作過程中,都需要CPU參與控制、協調或交換數據等服務,而CPU正是通過中斷技術使得這些外圍設備協調工作的。PIC單片機作一次中斷處理的過程如下,當某一中斷源發出中斷請求時:
①假如CPU正在執行更重要的任務,則可采用屏蔽的方法暫時不響應該中斷請求;
②如果可以響應該中斷請求,則CPU執行完當前指令后,必須把斷點處的程序計數器PC的值(即下一條指令的地址)壓入堆棧保存起來(斷點保護),也可以把一些的重要寄存器內容也保護起來(現場保護)。然后再轉移到相應的中斷服務子程序中執行。
③在中斷服務子程序中,首先必須確定發出中斷請求的中斷源,然后再跳轉到與該中斷源相對應的程序分支中去執行中斷服務程序。
?、墚斨袛喾粘绦驁绦挟吅螅仨毾然謴捅槐Wo的寄存器的值(現場恢復),再將程序計數器PC的值從堆棧中恢復(斷點恢復) ,使CPU返回斷點處繼續執行被中斷的程序。
二、中斷處理過程
(1)保護被中斷進程現場。為了在中斷處理結束后能夠使進程準確地返回到中斷點,系統必須保存當前處理機程序狀態字PSW和程序計數器PC等的值。
?。?)分析中斷原因,轉去執行相應的中斷處理程序。在多個中斷請求同時發生時,處理優先級最高的中斷源發出的中斷請求。
?。?)恢復被中斷進程的現場,CPU繼續執行原來被中斷的進程。
三、中斷的運用
1、設置中斷相關寄存器。這里包含了中斷源的方式(高、低、下降沿、上升沿),優先級等,最后得開啟當前的中斷(可能有多個中斷),開啟總中斷。設置完后,有中斷信號到來后,CPU就會處理了,自動跳轉到中斷里去。
2、中斷服務函數。也就是CPU跳到中斷去,你想讓單片機干什么。比如之前的例子,開門后,看是小廣告,我們不要,那關門。中斷服務函數就這樣,就是單片機跳過去需要處理的事情,一般是要求時效性的,緊急的事。
3、中斷嵌套。等會用一般的中斷后,再理解嵌套就簡單了。
四、PIC16F876的中斷源
PIC16F876單片機具備的中斷源如下表所示:
從上表可看出,各中斷源基本上都與各個外圍設備模塊相對應的:多數的外圍設備對應著一個中斷源(如定時/計數器TMR0),也有的外圍設備對應二個中斷源(如SCI同步/異步接收/發送器USART);有的外圍設備沒有中斷源與之對應(如輸入/輸出端口 RA和RC);也有的中斷源沒有外圍設備與之對應(例如外部中斷源INT)。
每一種中斷源對應了一個中斷標志位,記為XXXF,以及一個中斷屏蔽位或叫中斷使能位,記為XXXE。中斷源產生的中斷信號能否到達CPU,都受控于相應的中斷屏蔽位。 每個中斷源申請中斷時,其中斷標志位會自動置位,中斷標志位的清0是由用戶程序完成的;而每個中斷屏蔽位的置位和清位均由用戶程序完成。
PIC16F876單片機的中斷系統的邏輯電路如圖:
圖中全部的的14個中斷源按兩個梯隊并列排開,第一梯隊中只安排了3個中斷源,其余的中斷源全部安排到第二梯隊中。所有的中斷源都受“全局中斷屏蔽位”(也稱總屏蔽位)GIE的控制;第一梯隊的中斷源不僅受GIE的控制,還要受各自中斷屏蔽位的控制;第二梯隊的中斷源不僅受到GIE和各自中斷屏蔽位的控制,還要受到一個外設中斷屏蔽位PEIE的控制。
五、中斷相關的寄存器
與中斷有關的特殊功能寄存器SFR共有6個,分別是:
選項寄存器OPTION_REG、中斷控制寄存器INTCON、第一外圍設備中斷標志寄存器PIR1、第一外圍設備中斷屏蔽寄存器PIE1(也稱中斷使能寄存器)、第二外圍設備中斷標志寄存器PIR2和第二外圍設備中斷屏蔽寄存器PIE2。
后5個SFR,共有40位,但僅使用了30位來控制中斷,分別與圖中的中斷邏輯電路輸入信號成嚴格的對應關系。
1、選項寄存器OPTION _REG
該寄存器包含了與定時/計數器TMR0、分頻器和端口RB有關的控制位。RB端口引腳RB0和外部中斷INT復用一腳,與該腳有關的一個控制位含義如下:
INTEDG:外部中斷INT觸發信號邊沿選擇位:1=選擇RB0/INT上升沿觸發;0=選擇RB0/INT下降沿觸發。
2、中斷控制寄存器INTCON
它將第一梯隊中的3個中斷源的標志位和屏蔽位,以及PEIE和GIE包含在其中:
RBIF:端口RB的引腳RB4~RB7電平變化中斷標志位。1=RB4~RB7已經發生了電平變化;0=RB4~RB7尚未發生電平變化。
RBIE:端口RB的引腳RB4~RB7電平變化中斷屏蔽位。1=允許RB產生的中斷;0=屏蔽端口RB產生的中斷。
INTF:外部INT引腳中斷標志位。1=外部INT引腳有中斷觸發信號; 0=外部INT引腳無中斷觸發信號。
INTE:外部INT引腳中斷屏蔽位。 l=允許外部INT引腳產生的中斷;0=屏蔽外部INT引腳產生的中斷。
T0IF:TMR0溢出中斷標志位。1=TMR0已經發生了溢出;0=TMR0尚未發生溢出。
T0IE:TMR0溢出中斷屏蔽位。1=允許TMR0溢出后產生的中斷; 0=屏蔽TMR0溢出后產生的中斷。
PEIE:外設中斷屏蔽位。1=允許CPU響應來自第二梯隊中斷請求0=禁止CPU響應來自第二梯隊中斷請求。
GIE:全局中斷屏蔽位(總屏蔽位)。1=允許CPU響應所有中斷源產生的中斷請求;0=禁止CPU響應所有中斷源產生的中斷請求。
3、 第一外圍設備中斷標志寄存器PIR1
該寄存器中各中斷標志位的含義如下:
TMR1IF:定時/計數器TMR1模塊溢出中斷標志位。1=發生了TMR1溢出; 0=未發生TMR1溢出。
TMR2IF:定時/計數器TMR2模塊溢出中斷標志位。1=發生了TMR2溢出; 0=未發生TMR2溢出。
CCP1IF:輸入捕捉/輸出比較/脈寬調制CCP1模塊中斷標志位。 輸入捕捉模式下:1=發生了捕捉中斷請求;0=未發生捕捉中斷請求。輸出比較模式下:1=發生了比較輸出中斷請求;0=未發生比較輸出中斷請求。脈寬調制模式下: 無用。
SSPIF:同步串行端口(SSP)中斷標志位。1=發送/接收完畢產生的中斷請求;0=等待發送/接收。
TXIF:串行通信接口(SCI)發送中斷標志位。1=發送完成,即發送緩沖區空 0=正在發送,即發送緩沖區未空。
RCIF:串行通信接口(SCI)接收中斷標志位。1=接收完成,即接收緩沖區滿0=正在接收,即接收緩沖區空。
ADIF:模擬/數字(A/D)轉換中斷標志位。1=發生了A/D轉換中斷;0=未發生A/D轉換中斷。
PSPIF:并行端口中斷標志位,只有40腳封裝型號具備,對于28腳封裝型號總保持0。1=并行端口發生了讀/寫中斷請求;0=并行端口未發生讀/寫中斷請求。
4、 第一外圍設備中斷屏蔽寄存器PIE1
該寄存器中包含的中斷屏蔽位(使能位)的含義如下:
TMR1IE:定時器/計數器TMRl模塊溢出中斷屏蔽位。l=開放TMRl溢出發生中斷;0=屏蔽TMRl溢出發生中斷。
TMR2IE:定時/計數器TMR2溢出中斷屏蔽位。1=開放TMR2溢出發生的中斷;0=屏蔽TMR2溢出發生的中斷。
CCP1IE:輸入捕捉/輸出比較/脈寬調制CCP1模塊中斷屏蔽位。1=開放CCP1模塊產生的中斷請求;0=屏蔽CCP1模塊產生的中斷請求。
SSPIE:同步串行端口(SSP)中斷屏蔽位。1=開放SSP模塊產生的中斷請求0=屏蔽SSP模塊產生的中斷請求。
TXIE:串行通信接口(SCI)發送中斷屏蔽位。1=開放SCI發送中斷請求;0=屏蔽SCI發送中斷請求。
RCIE:串行通信接口(SCI)接收中斷屏蔽位。1=開放SCI接收中斷請求;0=屏蔽SCI接收中斷請求。
ADIE:模擬/數字(A/D)轉換中斷屏蔽位。1=開放A/D轉換器的中斷請求;0=屏蔽A/D轉換器的中斷請求。
PSPIE:并行端口中斷屏蔽位,只有40腳封裝型號具備,對于28腳封裝型號總保持0。1=開放并行端口讀/寫發生的中斷請求;0=屏蔽并行端口讀/寫發生的中斷請求。
5、 第二外圍設備中斷標志寄存器PIR2
CCP2IF:輸入捕捉/輸出比較/脈寬調制CCP2模塊中斷標志位。輸入捕捉模式下:1=發生了捕捉中斷請求(必須用軟件清0);0=未發生捕捉中斷請求。輸出比較模式下:1=發生了比較輸出中斷請求(必須用軟件清0);0=未發生比較輸出中斷請求。脈寬調制模式下:無用
BCLIF:I2C總線沖突中斷標志。當同步串行端口MSSP被配置成I2C總線的主控器模式時:1=發生了總線沖突;0=未發生總線沖突。
EEIF:EEPROM寫操作中斷標志位。1=寫操作已經完成(必須用軟件清0);0=寫操作未完成或尚未開始進行。
6、 第二外圍設備中斷屏蔽寄存器PIE2
CCP2IE:輸入捕捉/輸出比較/脈寬調制CCP2模塊中斷屏蔽位。1=開放CCP2模塊產生的中斷請求;
0=屏蔽CCP2模塊產生的中斷請求。
EEIE:EEPROM寫操作中斷屏蔽位。1=開放EEPROM寫操作產生的中斷請求;0=屏蔽EEPROM寫操作產生的中斷請求。
六、PIC單片機timer中斷實例
功能描述: Timer0實現1s定時,RD低四位取反控制LED低四位,Timer1實現0.5s定時,RD高四位取反控制LED高四位
維護記錄: 2011-8-22
***************************************************************************************************/
#include 《pic.h》 //頭文件在HI-TECH安裝目錄下\HI-TECH Software\PICC\std\9.60\include
#define uchar unsigned char
#define uint unsigned int
uint temp1,temp2;
//***********************************************************************************
//延時
//***********************************************************************************
void delay(uint time)
{
uint i,j;
for(i = 0;i 《 time; i++)
{
for(j = 0;j 《 30; j++);
}
}
//***********************************************************************************
//IO初始化操作
//***********************************************************************************
void IO_init(void)
{
TRISD=0x00; //RD設置為輸出
PORTD=0xff; //初始化為高
}
//***********************************************************************************
//timer0初始化
//***********************************************************************************
void timer0_init(void) //fosc/4=4M/4所以計數周期為1us
{
T0CS=0; //timer0工作于定時器方式
PSA=1; //timer0不分頻
T0IF=0; //清timer0中斷標志
T0IE=1; //timer0中斷允許
TMR0=0xAA; /*置初值,定時100us。因為寫入TMR0后接著的兩個周期不能增量,
中斷需要3個周期的響應時間,以及C語言自動進行現場保護要消
耗周期,取修正值15,所以只需要定時100-15=85us
初值=255-85=0xaa*/
GIE=1; //開總中斷
}
//***********************************************************************************
//timer1初始化
//***********************************************************************************
void timer1_init(void) //fosc/4=4M/4所以計數周期為1us
{
T1CON=0X01; //16位定時方式
TMR1IF=0; //清timer1中斷標志
TMR1IE=1; //timer1中斷允許
TMR1H=0xFC; /*置初值,TMR1每1ms中斷一次。因為寫入TMR1后接著的兩個周期不能增量,
中斷需要3個周期的響應時間,以及C語言自動進行現場保護要消
耗周期,取修正值15,所以只需要定時1000-15=985us
初值=65535-985=0xFC26*/
TMR1L=0x26;
PEIE=1; //允許外圍中斷
GIE=1; //開總中斷
}
//*************************************************
**********************************
//中斷服務子程序
//***********************************************************************************
void interrupt ISR(void)
{
// Timer0 interrupt service routine
if(TMR0IF==1)
{
TMR0=0xAA; //每100us中斷一次對TMR0寫入一個調整值。
T0IF=0; //清timer0中斷標志
temp1++; //中斷次數加1
if(temp1》9999) //中斷10000次后,為1秒
{
temp1=0; //中斷次數清0
RD0=!RD0;RD1=!RD1; RD2=!RD2; RD3=!RD3;//取反控制RD低4位LED發光或熄滅
}
}
// Timer1 interrupt service routine
if(TMR1IF==1)
{
TMR1H=0XFC; //中斷一次對TMR1寫入一個調整值。
TMR1L=0x26;
TMR1IF=0; //清timer1中斷標志
temp2++; //中斷次數加1
if(temp2》499) //中斷500次后,為0.5秒
{
temp2=0; //中斷次數清0
RD4=!RD4; RD5=!RD5; RD6=!RD6; RD7=!RD7; //取反控制RD高4位LED發光或熄滅
}
}
}
//***********************************************************************************
//主函數
//***********************************************************************************
main()
{
__CONFIG(XT&WDTDIS&LVPDIS); //配置,設置為晶振XT方式振蕩,禁看門狗,禁低電壓編程
IO_init(); //IO初始化
timer0_init(); //定時器0初始化
timer1_init(); //定時器1初始化
while(1); //死循環
}
//******************************************程序結束*****************************************
評論
查看更多