s3c2440外部中斷操作
在具體執(zhí)行中斷之前,要初始化好要用的中斷。2440的外部中斷引腳EINT與通用IO引腳F和G復(fù)用,要想使用中斷功能,就要把相應(yīng)的引腳配置成中斷模式,如我們想把端口F0設(shè)置成外部中斷,而其他引腳功能不變,則GPFCON=(GPFCON & ~0x3) | 0x2。配置完引腳后,還需要配置具體的中斷功能。我們要打開某一中斷的屏蔽,這樣才能響應(yīng)該中斷,相對應(yīng)的寄存器為INTMSK;還要設(shè)置外部中斷的觸發(fā)方式,如低電平、高電平、上升沿、下降沿等,相對應(yīng)的寄存器為EXTINTn。另外由于EINT4到EINT7共用一個中斷向量,EINT8到EINT23也共用一個中斷向量,而INTMSK只負(fù)責(zé)總的中斷向量的屏蔽,要具體打開某一具體的中斷屏蔽,還需要設(shè)置EINTMASK。上面介紹的是最基本的初始化,當(dāng)然還有一些其他的配置,如當(dāng)需要用到快速中斷時,要使用INTMOD,當(dāng)需要配置中斷優(yōu)先級時,要使用PRIORITY等。
中斷處理函數(shù)負(fù)責(zé)執(zhí)行具體的中斷指令,除此以外還需要把SRCPND和INTPND中的相應(yīng)的位清零(通過置1來清零),因?yàn)楫?dāng)中斷發(fā)生時,2440會自動把這兩個寄存器中相對應(yīng)的位置1,以表示某一中斷發(fā)生,如果不在中斷處理函數(shù)內(nèi)把它們清零,系統(tǒng)會一直執(zhí)行該中斷函數(shù)。另外還是由于前面介紹過的,有一些中斷是共用一個中斷向量的,而一個中斷向量只能有一個中斷執(zhí)行函數(shù),因此具體是哪個外部中斷,還需要EINTPEND來判斷,并同樣還要通過置1的方式把相應(yīng)的位清零。一般來說,使用__irq這個關(guān)鍵詞來定義中斷處理函數(shù),這樣系統(tǒng)會為我們自動保存一些必要的變量,并能夠在中斷處理函數(shù)執(zhí)行完后正確地返回。還需要注意的是,中斷處理函數(shù)不能有返回值,也不能傳遞任何參數(shù)。
為了把這個中斷處理函數(shù)與在2440啟動文件中定義的中斷向量表相對應(yīng)上,需要先定義中斷入口地址變量,該中斷入口地址必須與中斷向量表中的地址一致,然后把該中斷處理函數(shù)的首地址傳遞給該變量,即中斷入口地址。
下面就是一個外部中斷的實(shí)例。開發(fā)板上一共有四個按鍵,分別連到了EINT0,EINT1,EINT2和EINT4,我們讓這四個按鍵分別控制連接在B5~B8引腳上的四個LED:按一下鍵則LED亮,再按一下則滅:
#define _ISR_STARTADDRESS 0x33ffff00
#define U32 unsigned int
#define pISR_EINT0(*(unsigned *)(_ISR_STARTADDRESS+0x20))
#define pISR_EINT1(*(unsigned *)(_ISR_STARTADDRESS+0x24))
#define pISR_EINT2(*(unsigned *)(_ISR_STARTADDRESS+0x28))
#define pISR_EINT4_7(*(unsigned *)(_ISR_STARTADDRESS+0x30))
#define rSRCPND(*(volatile unsigned *)0x4a000000)//Interrupt request status
#define rINTMSK(*(volatile unsigned *)0x4a000008)//Interrupt mask control
#define rINTPND(*(volatile unsigned *)0x4a000010)//Interrupt request status
#define rGPBCON(*(volatile unsigned *)0x56000010)//Port B control
#define rGPBDAT(*(volatile unsigned *)0x56000014)//Port B data
#define rGPBUP(*(volatile unsigned *)0x56000018)//Pull-up control B
#define rGPFCON(*(volatile unsigned *)0x56000050)//Port F control
#define rEXTINT0(*(volatile unsigned *)0x56000088)//External interrupt control register 0
#define rEINTMASK(*(volatile unsigned *)0x560000a4)//External interrupt mask
#define rEINTPEND(*(volatile unsigned *)0x560000a8)//External interrupt pending
static void __irq Key1_ISR(void) //EINT1
{
int led;
rSRCPND = rSRCPND | (0x1<<1);
rINTPND = rINTPND | (0x1<<1);
led = rGPBDAT & (0x1<<5);
if (led ==0)
rGPBDAT = rGPBDAT | (0x1<<5);
else
rGPBDAT = rGPBDAT & ~(0x1<<5);
}
static void __irq Key2_ISR(void) //EINT4
{
int led;
rSRCPND = rSRCPND | (0x1<<4);
rINTPND = rINTPND | (0x1<<4);
if(rEINTPEND&(1<<4))
{
rEINTPEND = rEINTPEND | (0x1<<4);
led = rGPBDAT & (0x1<<6);
if (led ==0)
rGPBDAT = rGPBDAT | (0x1<<6);
else
rGPBDAT = rGPBDAT & ~(0x1<<6);
}
}
static void __irq Key3_ISR(void) //EINT2
{
int led;
rSRCPND = rSRCPND | (0x1<<2);
rINTPND = rINTPND | (0x1<<2);
led = rGPBDAT & (0x1<<7);
if (led ==0)
rGPBDAT = rGPBDAT | (0x1<<7);
else
rGPBDAT = rGPBDAT & ~(0x1<<7);
}
void __irq Key4_ISR(void) //EINT0
{
int led;
rSRCPND = rSRCPND | 0x1;
rINTPND = rINTPND | 0x1;
led = rGPBDAT & (0x1<<8);
if (led ==0)
rGPBDAT = rGPBDAT | (0x1<<8);
else
rGPBDAT = rGPBDAT & ~(0x1<<8);
}
void Main(void)
{
int light;
rGPBCON = 0x015550;
rGPBUP = 0x7ff;
rGPFCON = 0xaaaa;
rSRCPND = 0x17;
rINTMSK = ~0x17;
rINTPND =0x17;
rEINTPEND = (1<<4);
rEINTMASK = ~(1<<4);
rEXTINT0 = 0x20222;
light = 0x0;
rGPBDAT = ~light;
pISR_EINT0 = (U32)Key4_ISR;
pISR_EINT1 = (U32)Key1_ISR;
pISR_EINT2 = (U32)Key3_ISR;
pISR_EINT4_7 = (U32)Key2_ISR;
while(1)
;
}
評論