个人通用型红外NEC解码思路总结

方法一:采用纯定时器中断扫描

方法简单说明:将解码的过程分解成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;
        }
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值