找回密码
 注册

QQ登录

只需一步,快速开始

搜索

基于51单片机的NEC协议编码红外解码方法与程序

[复制链接]
coolfire 发表于 2021-6-5 01:15:33 | 显示全部楼层 |阅读模式
记录一次使用NEC协议编码的红外遥控信号的解码方式。

NEC协议简要记录
NEC协议是红外遥控协议的一种,由其编码的数据帧分别由引导码、用户码、用户码(或者是用户码的反码)、数据码(即按键码)和数据码的反码这五部分组成,最后还有一个停止位。引导码表示即将开始传输32位的二进制数据;引导码之后的部分长度为4字节一共32位;第一字节为用户码;第二字节可能是用户码,也可能是用户码的反码,具体由厂商决定;第三字节是当前按键的按键码;第四字节是按键码的反码;停止位主要起隔离作用,一般不进行判断,也不需要理会。每一字节的数据从低位到高位依次发送。

NEC协议编码方式
NEC协议的每一比特数据本身也需要进行编码,编码后再进行载波调制。

引导码:9ms的高电平 + 4.5ms的低电平
比特值0:0.56ms的高电平 + 0.56ms的低电平
比特值1:0.56ms的高电平 + 1.68ms的低电平
发射端和接收端的电平相反,即:

引导码:9ms的低电平 + 4.5ms的高电平
比特值0:0.56ms的低电平 + 0.56ms的高电平
比特值1:0.56ms的低电平 + 1.68ms的高电平

源程序记录
按下红外遥控器的任一按键1~9,即可在开发板的数码管模块的左边第一位上显示对应的按键数字。

  1. #include<reg51.h>

  2. sbit OUTPUT=P3^2;                //P3.2引脚为单片机外部中断0的触发引脚,同时连接红外接收模块IR 1838的输出端,在模块输出信号的同时进入外部中断0的服务函数
  3. sbit Wei=P2^7;                //数码管模块位锁存

  4. unsigned char Code[9]={0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};                //数码管显示从“1”到“9”的段码
  5. unsigned char Code0[4];
  6. unsigned char Code1[33];
  7. unsigned char time;

  8. bit m,n;                //定义两个标志位;标志位m表示一帧数据解码完毕,标志位n表示一帧数据接收完毕

  9. void ET_0() interrupt 1 using 1                //定时器0中断
  10. {
  11.         time++;                //对两个下降沿之间的时间间隔进行计数
  12. }

  13. void EX_0() interrupt 0                //外部中断0
  14. {
  15.         static unsigned char i;
  16.         static bit START;
  17.         if(START)
  18.         {
  19.                 if(time<63&&time>=33)                //引导码,9ms+4.5ms
  20.                 {
  21.                         i=0;
  22.                 }
  23.                 Code1[i]=time;                //存储两个下降沿之间的时间间隔,将用于数据帧的“0”和“1”
  24.                 time=0;
  25.                 i++;
  26.                 if(i==33)
  27.                 {
  28.                         n=1;
  29.                         i=0;
  30.                 }
  31.         }
  32.         else
  33.         {
  34.                 time=0;
  35.                 START=1;
  36.         }
  37. }

  38. void ET0_init()                //定时器0中断初始化
  39. {
  40.         TMOD=0x02;                //定时器0工作在方式2
  41.         TH0=0x00;                //重载值
  42.         TL0=0x00;                //初始值
  43.         ET0=1;                //开启定时器0中断
  44.         TR0=1;
  45. }

  46. void EX0_init()                //外部中断0初始化
  47. {
  48.         IT0=1;                //设置外部中断0为下降沿触发
  49.         EX0=1;                //开启外部中断0
  50.         EA=1;                //开启总中断
  51. }

  52. void DECODE()                //红外解码
  53. {
  54.         unsigned char i,j,k;
  55.         unsigned char x,y;
  56.         k=1;
  57.         for(i=0;i<4;i++)                //对数据帧中的4个字节进行处理
  58.         {
  59.                 for(j=1;j<=8;j++)                //对一个字节中的8位进行处理
  60.                 {
  61.                         x=Code1[k];
  62.                         if(x>7)                //时间间隔大于某值则为1,与晶振(12MHz)相关,允许误差
  63.                         {
  64.                                 y|=0x80;
  65.                         }
  66.                         if(j<8)
  67.                         {
  68.                                 y>>=1;
  69.                         }
  70.                         k++;
  71.                 }
  72.                 Code0[i]=y;
  73.                 y=0;
  74.         }
  75.         m=1;
  76. }

  77. void NUMBER()                //将红外遥控器的按键值转换为数码管的段值
  78. {
  79.         switch(Code0[2])
  80.         {
  81.                 case 0x0c:P0=Code[0];break;
  82.                 case 0x18:P0=Code[1];break;
  83.                 case 0x5e:P0=Code[2];break;
  84.                 case 0x08:P0=Code[3];break;
  85.                 case 0x1c:P0=Code[4];break;
  86.                 case 0x5a:P0=Code[5];break;
  87.                 case 0x42:P0=Code[6];break;
  88.                 case 0x52:P0=Code[7];break;
  89.                 case 0x4a:P0=Code[8];break;
  90.                 default:break;
  91.         }
  92.         m=0;
  93. }

  94. void main()
  95. {
  96.         ET0_init();
  97.         EX0_init();
  98.         
  99.         P0=0xfe;                //取数码管模块左边第一位选通
  100.         Wei=1;
  101.         Wei=0;
  102.         
  103.         while(1)
  104.         {
  105.                 if(n)
  106.                 {
  107.                         DECODE();
  108.                         n=0;
  109.                 }
  110.                 if(m)
  111.                 {
  112.                         NUMBER();
  113.                 }
  114.         }
  115. }
复制代码
原理图:
1.png 2.png 3.png

您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|手机版|小黑屋|ELEOK |网站地图

GMT+8, 2024-3-28 16:50

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表