|
小弟最近在做項目的驅動設計時碰到關于外部中斷的一些問題想過來請教一下大神。
1.背景描述:使用INT0檢測紅外信號,測試程序包含了I2C、UART0、定時器0這些外設;
2.處理方法:在INT0中斷處理函數中先關閉EX0避免紅外信號多段下降沿的多次觸發,然后使用定時器結合對引腳高低電平的判斷進行電平計時從而實現解碼,解碼結束后再重新開啟EX0。
3.出現的問題:1、上述的方法還是無法避免多次進入中斷的情況,而且一個紅外信號時間內進入中斷次數沒有明顯規律;
2、如果本次紅外信號中斷僅進一次,還是可以回到主程序繼續執行,但是一旦連續進入大于等于兩次則無法返回主程序,也就是說PC所指向的地址已經不是主程序了,但是下次紅外信號還是可以被接收并觸發中斷的,只不過也回不到主程序而已。
4.下面我貼一下我的部分代碼,煩請各位大神指教
uint8 IrValue[4];//紅外信號緩存數組
uint8 IrFlag = 0;//接收并成功解碼紅外信號標志量
uint32 LowTime, HighTime;//存儲高、低電平的時間長度
…………………………
…………………………
…………………………
/*******************************************************************************
* 函數名 : IrDeCode
* 函數功能 : 4字節紅外碼解碼函數
* 輸入 : void
* 輸出 : bit,解碼正確返回1,否則返回0
*******************************************************************************/
bit IrDeCode(void)
{
uint8 i,j;
uint8 Temp;//存儲解碼出的數據
for(i=0;i<4;i++)//識別4組數據,即4個字節數據
{
for(j=0;j<8;j++)//識別字節中的每一位
{
Temp <<= 1;//因為先讀出的是高位數據,故每一次右移一位,保證8次后得到完整數據
/*檢測每一位的0.56ms低電平*/
Timer0Enable(); //啟動定時器0
while(IRIN == 0); //等每1位0.56ms低電平過去
TR0 = 0; //暫時關閉定時器0
LowTime = TH0*256+TL0; //保存低電平的時間
/*檢測每一位的后續高電平時間*/
Timer0Enable(); //啟動定時器0
while(IRIN == 1); //等每1位后續的高電平過去
TR0 = 0; //暫時關閉定時器0
HighTime = TH0*256+TL0; //保存低電平的時間
/*判斷位1或位0*/
if((LowTime<531)||(LowTime>1531))//超出低電平范圍
return 0;
if((HighTime>732)&&(HighTime<1332))
Temp &= 0xfe;
if((HighTime>2615)&&(HighTime<3415))
Temp |= 0x01;
}
IrValue[i] = Temp;
}
/*校驗*/
if(IrValue[2] != ~IrValue[3])
return 0;//若校驗錯誤,則返回0
return 1;//若通過校驗,則返回1
}
/*******************************************************************************
* 函數名 : IrIRQ
* 函數功能 :外部中斷處理函數
* 輸入 : void
* 輸出 : void
*******************************************************************************/
void IrIRQ(void) interrupt 0 using 0
{
/*只進行一次的下降沿判斷,剩下的全在中斷中完成解碼*/
EX0=0; //關閉外中斷0,不再接收二次紅外信號的中斷,只解碼當前紅外信號
/*低電平段檢測*/
Timer0Enable(); //啟動定時器0
while(IRIN == 0); //等引導段9ms低電平過去
TR0 = 0; //暫時關閉定時器0
LowTime = TH0*256+TL0; //保存低電平的時間
/*高電平段檢測*/
Timer0Enable(); //啟動定時器0
while(IRIN == 1); //等引導段4.5ms高電平過去
TR0 = 0; //暫時關閉定時器0
HighTime = TH0*256+TL0; //保存高電平的時間
if((LowTime>15580)&&(LowTime<17580)&&(HighTime>7290)&&(HighTime<9290))
{
IrFlag = IrDeCode();
}
UARTSendByte(0xDD);//通過串口判斷進入幾次中斷
EX0 = 1;//重新開啟INT0中斷
}
|
|