• “龙江二号”微卫星传回地月合影 2019-04-18
  • 中国驻泰国大使考察合艾国光中学孔子课堂 2019-04-18
  • 【清园20年】感恩大回馈!半价!半价! 2019-04-18
  • 中央纪委紧盯节点 4年来通报曝光问题近4000起 2019-04-13
  • 2013环球企业领袖宁夏圆桌会议嘉宾云集 2019-04-13
  • 《魔兽世界》未解之谜 那些仍不能被玩家们踏足的领地 2019-04-11
  • 钱江潮评 让高质量发展插上人才的翅膀 2019-04-10
  • 习近平两会期间谈社会主义核心价值观 2019-04-02
  • 文脉颂中华——黄河新闻网 2019-04-02
  • 陈小林的专栏作者中国国家地理网 2019-03-29
  • 中英航母大战谁能赢歼151枚炸弹就能炸瘫女王 2019-03-22
  • 独特“光捕捉器”可控制分子生化性质 2019-03-22
  • 女性之声——全国妇联 2019-03-19
  • 【理上网来·辉煌十九大】德国北威州经济部长:十九大报告表明中国有能力为世界做出更多贡献 2019-03-11
  • 全国小麦收获进度过八成 2019-03-07
  • 打印

    360粤11选五走势图: [8/16位单片机] 红外NEC协议接收代码借助一个定时中断

    [复制链接]
    215|4
    跳转到指定楼层
    楼主
    本帖最后由 chhyxf 于 2019-3-16 00:43 编辑

      
    NEC 协议的数据格式包括了引导码、用户码、用户码(或者用户码反码)、按键键码和键码反码,最后一个停止位。停止位主要起隔离作用,一般不进行判断,编程时我们也不予理会。其中数据编码总共是 4 个字节 32 位,如图 16-7 所示。第一个字节是用户码,第二个字节可能也是用户码,或者是用户码的反码,具体由生产商决定,第三个字节就是当前按键的键数据码,而第四个字节是键数据码的反码,可用于对数据的纠错。


    图 16-7  NEC 协议数据格式


    这个 NEC 协议,表示数据的方式不像我们之前学过的比如 UART 那样直观,而是每一位数据本身也需要进行编码,编码后再进行载波调制。

    • 引导码:9ms 的载波+4.5ms 的空闲。
    • 比特值“0”:560us 的载波+560us 的空闲。
    • 比特值“1”:560us 的载波+1.68ms 的空闲。

    结合图 16-7 我们就能看明白了,最前面黑乎乎的一段,是引导码的 9ms 载波,紧接着是引导码的 4.5ms 的空闲,而后边的数据码,是众多载波和空闲交叉,它们的长短就由其要传递的具体数据来决定。HS0038B 这个红外一体化接收头,当收到有载波的信号的时候,会输出一个低电平,空闲的时候会输出高电平,我们用逻辑分析仪抓出来一个红外按键通过HS0038B 解码后的图形来了解一下,如图 16-8 所示。


    图 16-8  红外??仄靼醇嗦?/font>


    从图上可以看出,先是 9ms 载波加 4.5ms 空闲的起始码,数据码是低位在前,高位在后,数据码第一个字节是 8 组 560us 的载波加 560us 的空闲,也就是 0x00,第二个字节是 8 组 560us的载波加 1.68ms 的空闲,可以看出来是 0xFF,这两个字节就是用户码和用户码的反码。按键的键码二进制是 0x0C,反码就是 0xF3,最后跟了一个 560us 载波停止位。对于我们的??仄骼此?,不同的按键,就是键码和键码反码的区分,用户码是一样的。这样我们就可以通过单片机的程序,把当前的按键的键码给解析出来。

    以上内容摘自CSDN
    猪怕肥
    的文章,如果不巧您看到了这帖子,你过来打我啊。


    /*声明变量*/
    extern UINT8 RecData[5];
    extern UINT8 RecDataLongPress;
    extern bit RecOK;
    extern UINT16 AfterRecTimeCt;
    extern bit AfterRecTimeStart;
    extern UINT8 PulseCount;  // 9ms -- 36 * 250
    extern UINT8 RecStu;
    extern UINT8 code RecBitTbl[];
    extern UINT8 code RecSpareTbl[];
    extern UINT8 code RecGuidanTbl[];
    extern UINT8 gWKeyRec;
    /*宏定义*/
    #define RecPt P1_1                                // 接收引脚IO上拉
    #define D_RecStartFlag   0                      // 从接收到0作为开始
    #define D_StartFlagMin   30// (8500/250)  // 由NEC协议知道引导码低电平需要持续9ms,由于进中断需要时间所以这边选择8500/250,250是定时器设定时间
    #define D_GuidanFlagMin   16//(4200/250) 由NEC协议知道引导码高电平需要持续4.5ms,由于进中断需要时间所以这边选择4200/250,250是定时器设定时间
    #define D_RecGuidanFlag  1
    #define D_logic_0_MAX 1  
    #define D_logic_1_MIN 3 // 逻辑1的持续时间至少需要3个250us

    /*变量定义*/
    UINT8 RecData[5];  // 存放接收数据
    UINT8 RecDataLongPress;  // 存放长按编码
    bit RecOK;
    UINT8 PulseCount;  // 电平持续时间计数器
    bit AfterRecTimeStart; // 长按开始判断标志位
    UINT16 AfterRecTimeCt; // 长按计数,由波形可以知大概100ms左右会发送一个长按波形,这边设定200ms左右
    UINT8 RecStu;   // 接收状态变量
    UINT8 code RecBitTbl[]={7,7,7,7};  // 接收bit数,可固定
    UINT8 code RecSpareTbl[] = {D_StartFlagMin,D_GuidanFlagMin};
    UINT8 code RecGuidanTbl[]={D_RecStartFlag,D_RecGuidanFlag};
    UINT8 gWKeyRec;

    /*
    代码说明:
    1、第一二状态判断引导码是否按NEC协议
    2、第三、四、五、六状态接收数据
    判断逻辑1高电平持续时间是否大于3个250us,实际测得是1600us左右,因为进入中断需要250us时间所以选择3*250,
    逻辑0的高电平不大于560us,不可能大于3个250,所以很好可以区分逻辑0和逻辑1.
    3、状态切换时需要特别注意引脚电平的状态
    4、注意这段代码也没做很多的验证只是简单的实现了功能,只是觉得从无到有的过程需要与人分享所以上传。
    */

    /*函数主体*/
    void RayReceive(void)
    {   
    static UINT8 byRecBitCt = 0;
    switch(RecStu)
    {
      case 0:
      case 1:
       if(RecPt == RecGuidanTbl[RecStu])  // 管脚引导码判断
       {
         // 开始计数
        PulseCount++;      //
       }
       else
       {
        if(PulseCount > RecSpareTbl[RecStu])
        {
         RecData[0] = 0;
         RecData[1] = 0;
         RecData[2] = 0;
         RecData[3] = 0;   
         RecStu ++;  // 状态变量自增
         PulseCount = 0;
        }
        else if((PulseCount > 6)&&(AfterRecTimeCt < 500)&&(RecStu == 1))  // 长按信号判断 2.86ms 150ms
        {
         RecOK = 1;
         RecData[2] = RecDataLongPress; // 从长按变量中取回按键值
         AfterRecTimeCt = 0;
         PulseCount = 0;
         RecStu = 0;     
         RecData[4]++;   // 长按次数统计,
        }
        else
        {
    //     AfterRecTimeStart = 0;
         PulseCount = 0;
         RecStu = 0;
        }
       }
      break;
      case 2:  
      case 3:
      case 4:
      case 5:
       if(RecPt == 1)
       {
        PulseCount++;   
       }
       else if(PulseCount!=0)  // 增加这个判断的原因是从第1状态进入2状态时电平可能还是低电平状态引起错误
       {
        if(PulseCount > D_logic_1_MIN)
        {
         RecData[RecStu-2] |= (1 << (byRecBitCt)); // 低位在前    // 因为接收数据是按位或的方式,所以进入接收数据时也就是接收状态要大于1一定要清接收buffer     
        }
        PulseCount = 0;   
        byRecBitCt++;
       }
       
       if(byRecBitCt > RecBitTbl[RecStu - 2])   // 接收一个字节判断
       {
        byRecBitCt = 0;
        PulseCount = 0;
        RecStu++;
        if(RecStu > 5) // 接收完毕
        {
         RecStu = 0;
         byRecBitCt = 0;
         PulseCount = 0;
         if( (RecData[2] | RecData[3]) == 0xff)  // 校验接收数据
         {
          RecOK = 1;
          RecData[4] = 0;
          RecDataLongPress = RecData[2];  // 保存长按按键值
          AfterRecTimeStart = 1;    // 开启长按超时计数
          AfterRecTimeCt = 0;
         }        
        }
       }
      break;
      default:break;
    }
    }

    /*定时中断--250us*/
    void Timer3_Interrupt(void)  interrupt  11
    {
    RayReceive();
    if(AfterRecTimeStart)  // 长按有效时间限定,超出200ms判定不是长按
        AfterRecTimeCt++;
    if(AfterRecTimeCt > 600)  // 200ms
    {
      AfterRecTimeCt = 600;
      AfterRecTimeStart = 0;
    }
    }




    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?注册

    x
    沙发
    | 2019-3-16 08:16 | 只看该作者
    外部中断+定时器做解码挺好的。我记得当初入门的时候也是看的这个文章。
    板凳
     楼主 | 2019-3-17 20:04 | 只看该作者
    本帖最后由 chhyxf 于 2019-3-17 20:16 编辑
    xyz549040622 发表于 2019-3-16 08:16
    外部中断+定时器做解码挺好的。我记得当初入门的时候也是看的这个文章。

    因为我的程序中还有用到一个外部中断(优先级最高),不想嵌套太多中断,所以就用查询的方式,还好nec协议高低电平还是很容易区分
    地板
    | 2019-4-14 12:09 | 只看该作者
    chhyxf 发表于 2019-3-17 20:04
    因为我的程序中还有用到一个外部中断(优先级最高),不想嵌套太多中断,所以就用查询的方式,还好nec协议 ...

    楼主这个应该是51单片机吧,刚入门也想学习一下红外???。
    5
    | 2019-4-15 21:23 | 只看该作者
    没怎么玩过红外,学习一下
    扫描二维码,随时随地手机跟帖
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    我要发帖 投诉建议 创建版块 申请版主

    快速回复

    您需要登录后才可以回帖
    登录 | 注册
    高级模式

    论坛热帖

    快速回复 广东快乐十分走势图 返回列表
  • “龙江二号”微卫星传回地月合影 2019-04-18
  • 中国驻泰国大使考察合艾国光中学孔子课堂 2019-04-18
  • 【清园20年】感恩大回馈!半价!半价! 2019-04-18
  • 中央纪委紧盯节点 4年来通报曝光问题近4000起 2019-04-13
  • 2013环球企业领袖宁夏圆桌会议嘉宾云集 2019-04-13
  • 《魔兽世界》未解之谜 那些仍不能被玩家们踏足的领地 2019-04-11
  • 钱江潮评 让高质量发展插上人才的翅膀 2019-04-10
  • 习近平两会期间谈社会主义核心价值观 2019-04-02
  • 文脉颂中华——黄河新闻网 2019-04-02
  • 陈小林的专栏作者中国国家地理网 2019-03-29
  • 中英航母大战谁能赢歼151枚炸弹就能炸瘫女王 2019-03-22
  • 独特“光捕捉器”可控制分子生化性质 2019-03-22
  • 女性之声——全国妇联 2019-03-19
  • 【理上网来·辉煌十九大】德国北威州经济部长:十九大报告表明中国有能力为世界做出更多贡献 2019-03-11
  • 全国小麦收获进度过八成 2019-03-07
  • 彩票中奖喜报怎么写 足彩进球彩玩法 足球比分007 云南时时彩11选 浙江飞鱼管业 江西时时彩74期 河南快赢481开奖视频 老时时彩开奖号码360 p3试机号码30期 加拿大快乐8 澳洲快乐时时彩 黑马分分彩计划软件 新浪彩票开奖 中彩网3d 顶呱刮好彩头中奖图片 十一运夺金走势图爱彩乐