NEC红外(ir)解码协议

一、时序

一个完整的NEC解码协议,由以下几个部分组成,其中数据位为低位先行
在这里插入图片描述

详细的数据格式如下,其中如果一直按住一个按钮的时候,会隔110ms左右发一次引导码
在这里插入图片描述

二、代码实现

#include <string.h>
#include <stdio.h>

static uint64_t time_100us = 0;
static bool ir_pin_status = false;
static EN_IR__NEC_STATE_T en_ir_state = EN_IR_NEC_STATE_IDLE;
static uint8_t ir_receive_data_count= 0;
static uint32_t ir_receive_data= 0;
static uint8_t ir_key_code= 0;


static void device_ir_NEC_poll(TASK_PARAM)//定时器中断,100us触发一次,根据具体器件实现
{
    time_100us ++;
    if(time_100us >60000){
        time_100us = 0;
    }
}

static void device_ir_external_irq_pressed(void)//外部中断,配置为ir接收引脚,上升沿和下降沿都触发
{
    ir_pin_status = platform_gpio_get_level(IR_PIN);//获取当前ir输入电平,高电平证明是上升沿触发,反之下降沿
    switch(en_ir_state ){
        case EN_IR_NEC_STATE_IDLE ://空闲状态
            if(ir_pin_status ==0){//下降沿触发
                en_ir_state = EN_IR_NEC_STATE_PREAMBLE_START_LOW;//状态改为等待9ms低电平引导码
            }
        break;
        case EN_IR_NEC_STATE_PREAMBLE_START_LOW://9ms低电平引导判断
            if((ir_pin_status ==1)&&(time_100us >=70)&&(time_100us <=110)){//满足9ms电平引导时序
                en_ir_state = EN_IR_NEC_STATE_PREAMBLE_START_HIGH;//状态改为等待高电平引导码
            }else{
                en_ir_state = EN_IR_NEC_STATE_IDLE;//校验失败,返回空闲状态
            }
        break;

        case EN_IR_NEC_STATE_PREAMBLE_START_HIGH://4.5ms高电平引导或repeat
            if(ir_pin_status ==0){//下降沿触发
                if((time_100us >=35)&&(time_100us <=60)){//4.5ms高电平引导
                 	en_ir_state = EN_IR_NEC_STATE_RECEIVE_DECODE;//状态改为接收数据
                 	ir_receive_data_count= 0;//清空接收计次
                	ir_receive_data= 0;//清空接收数据
                } else if ((time_100us >=15)&&(time_100us <35)){//2.25ms高电平repeat
                    en_ir_state = EN_IR_NEC_STATE_RECEIVE_REPEAT;//状态改为repeat
                }else{
                en_ir_state = EN_IR_NEC_STATE_IDLE;//校验失败,返回空闲状态
                }
            }else{
                en_ir_state = EN_IR_NEC_STATE_IDLE;//校验失败,返回空闲状态
            }
        break;
        case EN_IR_NEC_STATE_RECEIVE_DECODE://接收数据
        if(ir_pin_status == 0){//下降沿触发(即只判断高电平持续时间)
                if((time_100us <=8)&&(time_100us >=3)){//满足(1.12-0.56ms)存入低电平
                     ir_receive_data >>= 1;
                }else if((time_100us >=12)&&(time_100us <=20)){//满足(2.25-0.56ms)存入高电平
                    ir_receive_data = ((ir_receive_data >> 1) | 0x80000000);
                }else{//校验失败

                    en_ir_state = EN_IR_NEC_STATE_IDLE;
                }
                if(++ir_receive_data_count >= 32){//接收到4个字节(两个头码和两个数据),后停止接收
                device_ir_NEC_decode(ir_receive_data);//数据解码
                en_ir_state = EN_IR_NEC_STATE_IDLE;//回到空闲状态

                }
        }
        
        break;

        case EN_IR_NEC_STATE_RECEIVE_REPEAT:
				//自由选择是否继续报上一个键值
        break;

    }
    time_100us = 0;//每次判断完数据,需要把计数清空
}



static bool device_ir_NEC_decode(uint32_t code)
{
    uint8_t head_code_low  = code &0x000000FF; //取出低8位数据
    uint8_t head_code_high = (code &0x0000FF00) >> 8; //取出低8-16位数据
    uint8_t key_code       = (code &0x00FF0000) >> 16; //取出低16-24位数据
    uint8_t key_code_minus = (code &0xFF000000) >> 24;  //取出低24-32位数据
    if((head_code_low ==IR_NEC_HEAD_CODE_LOW) && \   //判断是否是头码低位
        (head_code_high ==IR_NEC_HEAD_CODE_HIGH) && \ //判断是否是头码高位
        (key_code ==((~key_code_minus )&0xFF))){ //判断key_code_minus 是否是key的反码
        ir_key_code = key_code;//获取键值

        return true;
    }
       ir_key_code = 0return false;
}

bool device_ir_NEC_get_key(uint8_t *p_key)//用于给其他应用模块取得键值
{
    if(!ir_key_code){
        *p_key = ir_key_code;
        ir_key_code =0;//获取过键值后,清空键值
        return true;
    }

    return false;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值