對(duì)s3c2440的硬件操作無非就是配置寄存器,中斷也不例外:
需要設(shè)置的寄存器:
GPGCON :引腳配置寄存器,設(shè)置為第二功能,中斷引腳;
EINTPEND:中斷掛起寄存器,當(dāng)有中斷發(fā)生且沒有被屏蔽,相應(yīng)位會(huì)自動(dòng)置1,在進(jìn)入中斷服務(wù)程序后必須用軟件將其相應(yīng)位清0以免發(fā)生錯(cuò)誤中斷;
SRCPND:源掛起寄存器由32位組成,其每一位都涉及一個(gè)中斷源。如果中斷源產(chǎn)生了中斷則相應(yīng)的位被置1并且等待中斷服務(wù)。此寄存器指示出是哪個(gè)中斷源正在等待請(qǐng)求服務(wù)。
注意:此寄存器不顧INTMAST的屏蔽位,由硬件自動(dòng)將相應(yīng)中斷位置1,在進(jìn)入中斷服務(wù)程序后必須通過寫1清除相應(yīng)位,以防發(fā)生錯(cuò)誤中斷。
EINTMASK:外部中斷屏蔽寄存器,若相應(yīng)位置1;則相應(yīng)中斷被屏蔽不會(huì)產(chǎn)生下一級(jí)請(qǐng)求;
INTPND:中斷掛起寄存器中32位的每一位都表明了是否相應(yīng)位未被屏蔽并且正在等待中斷服務(wù)的中斷請(qǐng)求具有最高的優(yōu)先級(jí)。
注意:在多個(gè)中斷共用一個(gè)中斷服務(wù)程序時(shí)可能通過判斷INPND的相應(yīng)位知道是哪個(gè)中斷發(fā)生(比如本次實(shí)驗(yàn)),但確定相應(yīng)位以后必須對(duì)其寫1防止引發(fā)錯(cuò)誤中斷。
下圖將說明中斷如何被通知到CPU:
如果中斷源產(chǎn)生了中斷則SRCPND和INTPND相應(yīng)的位被置1,前提是SUBMASK和MASK相應(yīng)位不使能(即中斷開啟),MODE決定是IRQ還是FIQ,PRIORITY決定中斷優(yōu)先級(jí)
具體編程流程如下:
要想正確地執(zhí)行2440的外部中斷,一般需要完成兩個(gè)部分內(nèi)容:中斷初始化和中斷處理函數(shù)。
1,具體執(zhí)行中斷之前,要初始化好要用的中斷。2440的外部中斷引腳EINT與通用IO引腳F和G復(fù)用,要想使用中斷功能,就要把相應(yīng)的引腳配置成中斷模式。
- rGPGCONrGPGCON = rGPGCON & (~((3<<22)|(3<<6)|(3<<0)|(3<<10)|(3<<12)|(3<<14))) | //相應(yīng)位清零
- ((2<<22)|(2<<6)|(2<<0)|(2<<10)|(2<<12)|(2<<14)) ; //GPG11,3,0,5,6,7set EINT第二功能
配置完引腳后,還需要配置具體的中斷功能。我們要打開某一中斷的屏蔽,這樣才能響應(yīng)該中斷,相對(duì)應(yīng)的寄存器為INTMSK;如:
- rEINTMASK &= ~((1<<8)|(1<<11)|(1<<13)|(1<<14)|(1<<15)|(1<<19)); //enable eint8, 11,13,14,15,19
還要設(shè)置外部中斷的觸發(fā)方式,如低電平、高電平、上升沿、下降沿等,相對(duì)應(yīng)的寄存器為EXTINTn。如:
- rEXTINT1 &= ~(7|(7<<0));//clear 3 bits
- rEXTINT1 |= (0|(0<<0)); //set eint8 low level int
另外由于EINT4到EINT7共用一個(gè)中斷向量,EINT8到EINT23也共用一個(gè)中斷向量,而INTMSK只負(fù)責(zé)總的中斷向量的屏蔽,要具體打開某一具體的中斷屏蔽,還需要設(shè)置EINTMASK。如:
- rEINTMASK &= ~((1<<8)|(1<<11)|(1<<13)|(1<<14)|(1<<15)|(1<<19)); //enable eint8, 11,13,14,15,19
上面介紹的是最基本的初始化,當(dāng)然還有一些其他的配置,如當(dāng)需要用到快速中斷時(shí),要使用INTMOD,當(dāng)需要配置中斷優(yōu)先級(jí)時(shí),要使用PRIORITY等。
2. 中斷處理函數(shù)負(fù)責(zé)執(zhí)行具體的中斷指令,除此以外還需要把SRCPND和INTPND中的相應(yīng)的位清零(通過置1來清零),因?yàn)楫?dāng)中斷發(fā)生時(shí),2440會(huì)自動(dòng)把這兩個(gè)寄存器中相對(duì)應(yīng)的位置1,以表示某一中斷發(fā)生,如果不在中斷處理函數(shù)內(nèi)把它們清零,系統(tǒng)會(huì)一直執(zhí)行該中斷函數(shù)。如:
- <span style="font-family:SimSun;">#define BIT_EINT0 (0x1)
- #define BIT_EINT2 (0x1<<2)
- #define BIT_EINT8_23 (0x1<<5)
- ClearPending(BIT_EINT0|BIT_EINT2|BIT_EINT8_23); //SRCPND和INTPND中的相應(yīng)的位清零(通過置1來清零)
- __inline void ClearPending(int bit)
- {
- register i;
- rSRCPND = bit;
- rINTPND = bit;
- i = rINTPND;
- }</span>
另外還是由于前面介紹過的,有一些中斷是共用一個(gè)中斷向量的,而一個(gè)中斷向量只能有一個(gè)中斷執(zhí)行函數(shù),因此具體是哪個(gè)外部中斷,還需要EINTPEND來判斷,并同樣還要通過置1的方式把相應(yīng)的位清零。
- rEINTPEND |= (1<<8)|(1<<11)|(1<<13)|(1<<14)|(1<<15)|(1<<19); //clear eint8, 11,13,14,15,19
keysan.c源碼:
- /**************************************************************
- 4*4 Key Scan
- **************************************************************/
-
- #include "def.h"
- #include "option.h"
- #include "2440addr.h"
- #include "2440lib.h"
- #include "2440slib.h"
-
- /******************************************************************************
- 1X6 矩陣鍵盤
- 六個(gè)輸入引腳: EINT8 -----( GPG0 )
- EINT11 -----( GPG3 )
- EINT13-----( GPG5 )
- EINT14-----( GPG6 )
- EINT15-----( GPG7 )
- EINT19-----( GPG11 )
-
-
- ******************************************************************************/
- U8 Key_Scan( void )
- {
- Delay( 80 ) ;
-
- if( (rGPGDAT&(1<< 0)) == 0 ) //按下后IO口為低電平
- return 1 ;
- else if( (rGPGDAT&(1<< 3)) == 0 )
- return 2;
- else if( (rGPGDAT&(1<< 5)) == 0 )
- return 3 ;
- else if( (rGPGDAT&(1<< 6)) == 0 )
- return 4 ;
- else if( (rGPGDAT&(1<< 7)) == 0 )
- return 5 ;
- else if( (rGPGDAT&(1<<11)) == 0 )
- return 6 ;
- else
- return 0xff;
-
- }
-
- static void __irq Key_ISR(void)
- {
- U8 key;
- U32 r;
-
- EnterCritical(&r); //設(shè)置相應(yīng)cpsr的值
- if(rINTPND==BIT_EINT8_23) { //為1表示8~23號(hào)中有中斷
- ClearPending(BIT_EINT8_23);//清除INTPND中斷標(biāo)志位
- if(rEINTPEND&(1<<8)) { //通過EINTPEND查看具體是哪一個(gè)中斷源
- //eint8 occur!
- rEINTPEND |= 1<< 8;
- }
- if(rEINTPEND&(1<<11)) {
- //eint11 occur!
- rEINTPEND |= 1<< 11;
- }
- if(rEINTPEND&(1<<13)) {
- //eint13 occur!
- rEINTPEND |= 1<< 13;
- }
- if(rEINTPEND&(1<<14)) {
- //eint14 occur!
- rEINTPEND |= 1<< 14;
- }
- if(rEINTPEND&(1<<15)) {
- //eint15 occur!
- rEINTPEND |= 1<< 15;
- }
- if(rEINTPEND&(1<<19)) {
- //eint19 occur!
- rEINTPEND |= 1<< 19;
- }
- }
-
- key=Key_Scan();//按鍵掃描,讀取按鍵鍵值
- if( key == 0xff )
- Uart_Printf( "Interrupt occur... Key is released!\n") ;
- else
- Uart_Printf( "Interrupt occur... K%d is pressed!\n", key) ;//打印信息
-
- ExitCritical(&r);//恢復(fù)相應(yīng)的cpsr位
- }
-
- void KeyScan_Test(void)
- {
- Uart_Printf("\nKey Scan Test, press ESC key to exit !\n"); //串口打印
-
-
- rGPGCONrGPGCON = rGPGCON & (~((3<<22)|(3<<6)|(3<<0)|(3<<10)|(3<<12)|(3<<14))) | //相應(yīng)位清零
- ((2<<22)|(2<<6)|(2<<0)|(2<<10)|(2<<12)|(2<<14)) ; //GPG11,3,0,5,6,7set EINT第二功能
-
- rEXTINT1 &= ~(7|(7<<0));//clear 3 bits
- rEXTINT1 |= (0|(0<<0)); //set eint8 low level int
-
- rEXTINT1 &= ~(7<<12);
- rEXTINT1 |= (0<<12); //set eint11 low level int
-
- rEXTINT1 &= ~(7<<20);
- rEXTINT1 |= (0<<20); //set eint13 low level int
-
- rEXTINT1 &= ~(7<<24);
- rEXTINT1 |= (0<<24); //set eint14 low level int
-
- rEXTINT1 &= ~(7<<28);
- rEXTINT1 |= (0<<28); //set eint15 low level int
-
- rEXTINT2 &= ~(0xf<<12);
- rEXTINT2 |= (0<<12); //set eint19 low level int
-
-
- rEINTPEND |= (1<<8)|(1<<11)|(1<<13)|(1<<14)|(1<<15)|(1<<19); //clear eint8, 11,13,14,15,19
- rEINTMASK &= ~((1<<8)|(1<<11)|(1<<13)|(1<<14)|(1<<15)|(1<<19)); //enable eint8, 11,13,14,15,19
- ClearPending(BIT_EINT0|BIT_EINT2|BIT_EINT8_23); //清除相應(yīng)中斷源的位
- pISR_EINT0 = pISR_EINT2 = pISR_EINT8_23 = (U32)Key_ISR;//得到相應(yīng)中斷信息
- EnableIrq(BIT_EINT0|BIT_EINT2|BIT_EINT8_23); //打開相應(yīng)中斷源eint0,2,8~23
-
- while( Uart_GetKey() != ESC_KEY ) ;//使能中斷后在此等待,直到按鍵中斷產(chǎn)生,跳到Key_ISR();
- DisableIrq(BIT_EINT0|BIT_EINT2|BIT_EINT8_23);//關(guān)閉相應(yīng)中斷源eint0,2,8~23,中斷已發(fā)生,禁止再次中斷
- }
效果圖:
|