|
小弟最近在做项目的驱动设计时碰到关于外部中断的一些问题想过来请教一下大神。
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中断
}
|
|