2440有60個(gè)中斷源(有的中斷源還有幾個(gè)子中斷源),中斷原理如下圖:
中斷源使中斷源請(qǐng)求寄存器(SRCPND)的相應(yīng)位置一,中斷模式寄存器(INTMOD)選擇是IRQ還是FIQ模式,如果是IRQ,在中斷屏蔽寄存器(INTMSK)不屏蔽的情況下,會(huì)產(chǎn)生中斷,同時(shí)中斷請(qǐng)求寄存器(INTPND)的相應(yīng)位被置一。
2440 外部中斷 編程步驟:
外部中斷初始化()
{
引腳初始化: 設(shè)置相應(yīng)引腳為外部中斷功能 GPxCON
選擇相應(yīng)觸發(fā)模式 EXTINT 中斷初始化: 清除SRCPNF、INTPND中的相應(yīng)中斷標(biāo)志位
中斷例程地址 -> 中斷向量表 pISR_EINTx
使能相應(yīng)中斷 rINTMSK
}
中斷例程() __irq
{
……中斷程序……
清除SRCPNF(先)、INTPND(后)中的相應(yīng)中斷標(biāo)志位
}
這是一個(gè)外部中斷0的實(shí)驗(yàn)程序(GPF0作外部中斷源):
//********************************************************************
void Main(void)
{
int i;
……硬件初始化……
Eint0_init();
while(1); } void Eint0_init(void) //EINT0初始化
{
Uart_Printf("\n外部中斷實(shí)驗(yàn):Eint0\n");
rGPFCON = rGPFCON & ~7 | 2 ; //設(shè)置GPF0 為 外部中斷模式
rEXTINT0 = rEXTINT0 & ~7 | 2 ;//設(shè)置EINT0 為 下降沿觸發(fā) rSRCPND = 1; //SRCPND寫(xiě)1清0
rINTPND = 1; //INTPND寫(xiě)1清0
pISR_EINT0 = (U32)Eint0_ISR; //向向量表申請(qǐng)中斷向量
rINTMSK = rINTMSK & ~(1); //禁止EINT0的屏蔽
}
void Eint0_ISR(void) __irq //EINT0中斷例程
{
Uart_Printf("你按了一次Eint0引腳的按鍵\n");
rSRCPND = 1; //清楚EINT0中斷標(biāo)志
rINTPND = 1;
}
//*******************************************************************
運(yùn)行結(jié)果如圖:
注意中斷標(biāo)志的清除順序:SUBSRCPND(如果有)->SRCPND->INTPND ,如果不這樣做,中斷例程結(jié)束后,還會(huì)再次引起額外的中斷
注意 pISR_EINT0 = (U32)Eint0_ISR;每一個(gè)中斷例程運(yùn)行之前,都要把它的地址交給中斷向量表(此指60個(gè)中斷源的eboot中斷向量表,非地址0處的異常中斷向量表,IRQ發(fā)生時(shí),PC先指向異常中斷向量表的IRQ位置,再跳轉(zhuǎn)到eboot中斷向量表),以在中斷發(fā)生時(shí),正確進(jìn)入相應(yīng)的中斷例程,其實(shí)是把INTOFFSET中的中斷號(hào)轉(zhuǎn)換成(在eboot中斷向量表的)偏移地址。
外部中斷又24個(gè),但不都是一致的,如下圖:

EINT0、EINT1、EINT2、EINT3是四個(gè)獨(dú)立的中斷源,而EINT4~7組成一個(gè)中斷源,EINT8~23組成一個(gè)中斷源。
那么EINT4~7的中斷程序如何寫(xiě),顯然不能用EINT0的方式,不然EINT4~EINT7的四個(gè)源相互之間無(wú)法被區(qū)分開(kāi),EINT8~23也同理。
所以為了區(qū)分它們,要用到EINTMASK和EINTPEND,EINTMASK每一位對(duì)應(yīng)EINT4~EINT23的屏蔽,其他位保留;EINTPEND每一位對(duì)應(yīng)EINT4~EINT23的中斷請(qǐng)求,其他位保留;這樣就可以順利區(qū)分EINT4~EINT23了。
下面是Eint2和Eint11的中斷程序
//********************************************************************
void Main(void)
{
int i;
……硬件初始化……
Uart_Printf("\n外部中斷實(shí)驗(yàn):Eint2 和 Eint8_23\n"); Eint2_init();
Eint8_23_init(); //EINT11初始化
while(1); } void Eint2_init(void) //EINT2初始化
{
rGPFCON = rGPFCON & ~3<<4 | 2<<4 ; //設(shè)置GPF2 為 外部中斷模式
rEXTINT0 = rEXTINT0 & ~7<<8 | 4<<8 ;//設(shè)置EINT2 為 上升沿觸發(fā)
rSRCPND = 1<<2; //SRCPND寫(xiě)1清0
rINTPND = 1<<2; //INTPND寫(xiě)1清0
pISR_EINT2 = (U32)Eint2_ISR; //填入Eint2的中斷向量
rINTMSK = rINTMSK & ~(1<<2); //禁止EINT2的屏蔽
}
void Eint2_ISR(void) __irq //EINT2中斷例程
{
Uart_Printf("你按了一次Eint2引腳的按鍵\n");
rSRCPND = 1<<2; //清楚EINT2中斷標(biāo)志
rINTPND = 1<<2;
}
void Eint8_23_init(void) //Eint8_23初始化
{
rGPGCON = rGPGCON & ~3<<6 | 2<<6 ; //設(shè)置GPG3 為 外部中斷模式
rEXTINT1 = rEXTINT1 & ~7<<12 | 2<<12 ;//設(shè)置EINT11 為 下降沿觸發(fā)
rEINTPEND = 1<<11; //***EINTPEND中的 EINT11位 清0
rSRCPND = 1<<5; //SRCPND中的 Eint8_23位 清0
rINTPND = 1<<5; //INTPND中的 Eint8_23位 清0
pISR_EINT8_23 = (U32)Eint8_23_ISR; //填入Eint8_23的中斷向量
rEINTMASK = rEINTMASK & ~(1<<11); //***禁止EINT11的屏蔽
rINTMSK = rINTMSK & ~(1<<5); //禁止Eint8_23的屏蔽
}
void Eint8_23_ISR(void) __irq //EINT2中斷例程
{
Uart_Printf("你按了一次Eint8_23引腳的按鍵\n");
rEINTPEND = 1<<11; //***EINTPEND中的 EINT11位 清0
rSRCPND = 1<<5; //SRCPND中的 Eint8_23位 清0
rINTPND = 1<<5; //INTPND中的 Eint8_23位 清0
}
//*******************************************************************
結(jié)果如下:

|