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