方法一:采用纯定时器中断扫描
方法简单说明:将解码的过程分解成3个状态:空闲态、引导码、数据;在定时器中断中函数扫码IO电平,先判断引导码的低电平、高电平、然后数据位采用高电平识别。
void IR_Sacn(void) // 50us
{
switch (IR_State)
{
case 0: // 空闲状态高电平、检测引导码L:9ms
if (IR_IO == 0)
{
IR_L_Time++;
PB0 = 1;
}
else
{
PB0 = 0;
if ((IR_L_Time >= 160) && (IR_L_Time <= 200)) // 引导码L:9ms H:4.5ms
{
IR_State = 1;
}
IR_L_Time = 0;
}
break;
case 1: // 检测引导码H:4.5ms 可以加上判断重复码2.25ms
if (IR_IO)
{
IR_H_Time++;
}
else
{
if ((IR_H_Time >= 70) && (IR_H_Time <= 110)) // 引导码L:9ms H:4.5ms
{
IR_State = 2;
IR_Count_bit = 0;
IR_Count1 = 0;
Temp = 0;
}
else
{
IR_State = 0;
}
IR_H_Time = 0;
}
break;
case 2: // 开始解码数据
if (IR_IO)
{
IR_H_Time++;
}
else
{
if (IR_H_Time >= 30 && IR_H_Time <= 36) // 数据1>>L:560us H:2.25ms-560us
{
Temp <<= 1;
Temp |= 0x01;
IR_Count_bit++;
}
else if (IR_H_Time >= 8 && IR_H_Time <= 14) // 数据0>>L:560us H:1.12ms-560us
{
Temp <<= 1;
IR_Count_bit++;
}
if (IR_Count_bit >= 8)
{
IR_Count_bit = 0;
if (Count_10min_En)
{
Study_IR_Code[IR_Count1] = Temp;
}
else
{
IR_Code[IR_Count1] = Temp;
}
Temp = 0;
IR_Count1++;
if (IR_Count1 >= 4) // 解码结束
{
IR_Count1 = 0;
Decode_Flg = 1;//解码成功
if (Count_10min_En) // 学习完毕
{
Count_10min_En = 0;
Count_10min = 0;
LED_IO = 0;
}
IR_State = 0;
}
}
IR_H_Time = 0;
}
break;
default:
break;
}
}
方法二:IO变化中断+定时器计时
方法简单说明:
1、开始关闭定时器;空闲状态:当IO检测到低电平(下降沿),打开定时器;
2、引导码状态:低电平(下降沿)到来,先关闭定时器然后获取定时器时间、判断上一次下降沿到这一次下降沿时间是否符合引导码周期,是则打开定时器继续解码,否则返回空闲状态;
3、数据状态:低电平(下降沿)到来,先关闭定时器然后获取定时器时间、判断上一次下降沿到这一次下降沿时间是否符合数据0或1,如果还没解码完32位,则继续打开定时器。解码完成后返回空闲状态
void IR_Sacn(void)
{
// IO变化中断+定时器计时
switch (IR_State)
{
case 0:
if (IR_IO == 0)
{
TMR1ON = 1; // 打开定时器
IR_State = 1;
}
T1_Time = 0;
break;
case 1:
if (IR_IO == 0)
{
TMR1ON = 0;//关闭定时
// 获取时间 实际是中断溢出时间+计数值
if ((T1_Time >= 240) && (T1_Time <= 300)) // 引导码L:9ms H:4.5ms 可以加上判断重复码L:9ms H:2.25ms
{
IR_State = 2;
IR_Count_bit = 0;
IR_Count1 = 0;
Temp = 0;
TMR1ON = 1;
}
else
{
IR_State = 0;
}
T1_Time = 0;
}
break;
case 2: // 解码数据 判断高低电平完整周期
if (IR_IO == 0)
{
TMR1ON = 0;//关闭定时器
// 获取时间
if (T1_Time >= 40 && T1_Time <= 50) // 数据1>>L:560us H:2.25ms-560us
{
Temp <<= 1;
Temp |= 0x01;
IR_Count_bit++;
}
else if (T1_Time >= 20 && T1_Time <= 26) // 数据0>>L:560us H:1.12ms-560us
{
Temp <<= 1;
IR_Count_bit++;
}
if (IR_Count_bit >= 8)
{
IR_Count_bit = 0;
if (Count_10min_En)
{
Study_IR_Code[IR_Count1] = Temp;
}
else
{
IR_Code[IR_Count1] = Temp;
}
Temp = 0;
IR_Count1++;
}
if (IR_Count1 >= 4) // 解码结束
{
IR_Count1 = 0;
Decode_Flg = 1; // 解码成功
if (Count_10min_En) // 学习完毕
{
Count_10min_En = 0;
Count_10min = 0;
LED_IO = 0;
}
IR_State = 0;
}
else
{
TMR1ON = 1; // 数据为解码完,开启重新计时下一位
}
T1_Time = 0;
}
break;
default:
break;
}
}
方法二的另外一种写法
void IR_Sacn(void)
{
if (IR_IO == 0)
{
switch (IR_State)
{
case 0:
TMR1ON = 1; // 打开定时器
T1_Time = 0;
IR_State = 1;
break;
case 1:
TMR1ON = 0; // 关闭定时
// 获取时间 实际是中断溢出时间+计数值
if ((T1_Time >= 240) && (T1_Time <= 300)) // 引导码L:9ms H:4.5ms 可以加上判断重复码L:9ms H:2.25ms
{
IR_State = 2;
IR_Count_bit = 0;
IR_Count1 = 0;
Temp = 0;
TMR1ON = 1;
}
else
{
IR_State = 0;
}
T1_Time = 0;
break;
case 2: // 解码数据 判断高低电平完整周期
TMR1ON = 0; // 关闭定时器
// 获取时间
if (T1_Time >= 40 && T1_Time <= 50) // 数据1>>L:560us H:2.25ms-560us
{
Temp <<= 1;
Temp |= 0x01;
IR_Count_bit++;
}
else if (T1_Time >= 20 && T1_Time <= 26) // 数据0>>L:560us H:1.12ms-560us
{
Temp <<= 1;
IR_Count_bit++;
}
if (IR_Count_bit >= 8)
{
IR_Count_bit = 0;
if (Count_10min_En)
{
Study_IR_Code[IR_Count1] = Temp;
}
else
{
IR_Code[IR_Count1] = Temp;
}
Temp = 0;
IR_Count1++;
}
if (IR_Count1 >= 4) // 解码结束
{
IR_Count1 = 0;
Decode_Flg = 1; // 解码成功
if (Count_10min_En) // 学习完毕
{
Count_10min_En = 0;
Count_10min = 0;
LED_IO = 0;
}
IR_State = 0;
}
else
{
TMR1ON = 1; // 数据为解码完,开启重新计时下一位
}
T1_Time = 0;
break;
default:
break;
}
}
}