您的位置 首页 新品

红外遥控体系原理及单片机软件解码程序

首先,必须要了解一些基本原理。其实按下遥控器的某一个键,遥控器会发出一连串经过调制后的信号,这个信号经过红外一体化模块接收后,输出

首要,有必要要了解一些基本原理。其实按下遥控器的某一个键,遥控器会宣布一连串通过调制后的信号,这个信号通过红外一体化模块接纳后,输出解调后的数字脉冲,每个按键对应不同的脉冲,故辨认出不同的脉冲就能辨认出不同的按键。

上图便是很常见的车载MP3遥控器,比较细巧,很好用。下面是红外发射和承受原理:

到此读者或许会有疑问,那么不同的调制解调办法那么出来的脉冲规则是不一样的?是的,确实如此。

遥控发射器专用芯片许多,根据编码格局能够分红两大类,这儿咱们以运用比较广泛,解码比较简单的一类来加以阐明,现以日本NEC的uPD6121G组成发射电路为例阐明编码原理(一般家庭用的DVD、VCD、音响都运用这种编码办法)。当发射器按键按下后,即有遥控码宣布,所按的键不同遥控编码也不同。这种遥控码具有以下特征:

选用脉宽调制的串行码,以脉宽为0.565ms、距离0.56ms、周期为1.125ms的组合标明二进制的“0”;以脉宽为0.565ms、距离1.685ms、周期为2.25ms的组合标明二进制的“1”,其波形如图所示。

如图可见,0与1前端的低电平继续都是0.56ms,那么便是后边的高电平继续时刻不同,0为0.56ms,1为1.685ms,找到不同之处,编程时就有辨认的根据了!

上述“0”和“1”组成的32位二进制码经38kHz的载频进行二次调制以进步发射功率,到达下降电源功耗的意图。然后再通过红外发射二极管发生红外线向空间发射,如图所示。

UPD6121G发生的遥控编码是接连的32位二进制码组,其间前16位为用户辨认码,能差异不同的电器设备,避免不同机种遥控码相互搅扰。该芯片的用户辨认码固定为十六进制01H;后16位为8位操作码(功用码)及其反码。UPD6121G最多额128种不同组合的编码。

请看下图,来自网络:

当一个键按下超越36ms,振动器使芯片激活,将发射一组108ms的编码脉冲,这108ms发射代码由一个引导码(9ms),一个成果码(4.5ms),低8位地址码(9ms~18ms),高8位地址码(9ms~18ms),8位数据码(9ms~18ms)和这8位数据的反码(9ms~18ms)组成。假如键按下超越108ms仍未松开,接下来发射的代码(连发码)将仅由开端码(9ms)和完毕码(2.25ms)组成。(实践上人手的动作是很慢的,即便你快速的按下按键,或许关于芯片来说仍是超越108ms,所以怎么处理连发码是很要害的)

遥控器在按键按下后,周期性地宣布同一种32位二进制码,周期约为108ms。一组码自身的继续时刻随它包括的二进制“0”和“1”的个数不同而不同,大约在45~63ms之间,图为发射波形图。

下面是我写的代码,按键编码通过串口发送到电脑端:

由于时刻联系,代码注释不多。

其间START_Judge()函数是判别9ms低电平,既是判别有无遥控信号。

BOOT_REPEATING_CODE_Judge()是判别是引导码仍是连发码,引导码则进入承受数据环节,连发码标明数据现已承受完毕。

H_L_LEVEL_Judge()是承受数据时判别凹凸电平。

假如乱码,请参阅:

http://blog.csdn.net/mhjerry/article/details/6601324

注明:以下代码为纯软件办法,没有用到中止,守时器办法,纯CPU查询,但测验成果倒也能够,至少比较稳定,得到的码值不论对不对,都是那个值。

[cpp]view plaincopy

  1. /*————————————————————*-
  2. 红外收发.C
  3. ————————————————————
  4. 遥控器测验
  5. -*————————————————————*/
  6. #include
  7. //—红外接纳一体化输出口———————————-
  8. sbitIR_Out=P3^2;
  9. bitSTART_Flag=0;
  10. bitBOOT_REPEATING_CODE_Flag=0;
  11. unsignedcharDATA[4]={0};
  12. bdataunsignedcharTEMP_BIT;
  13. sbitB0=TEMP_BIT^0;
  14. sbitB1=TEMP_BIT^1;
  15. sbitB2=TEMP_BIT^2;
  16. sbitB3=TEMP_BIT^3;
  17. sbitB4=TEMP_BIT^4;
  18. sbitB5=TEMP_BIT^5;
  19. sbitB6=TEMP_BIT^6;
  20. sbitB7=TEMP_BIT^7;
  21. //—有无遥控信号判别函数———————————-
  22. bitSTART_Judge();
  23. //—连发码判别函数—————————————-
  24. bitBOOT_REPEATING_CODE_Judge();
  25. //—“0″和”1″辨认——————————————
  26. bitH_L_LEVEL_Judge();
  27. //—串口初始化——————————————–
  28. voidUART_Initial();
  29. voidDELAY_Us(unsignedintUs)
  30. {
  31. unsignedintx;
  32. for(x=0;x<=(Us/200-1);x++);
  33. }
  34. voidDELAY_Ms(unsignedintMs)
  35. {
  36. unsignedintx,y;
  37. for(x=0;x<=(Ms-1);x++)
  38. {
  39. for(y=0;y<=120;y++);
  40. }
  41. }
  42. voidmain()
  43. {
  44. unsignedchari;
  45. UART_Initial();
  46. IR_Out=1;
  47. while(1)
  48. {
  49. START_Flag=START_Judge();
  50. BOOT_REPEATING_CODE_Flag=BOOT_REPEATING_CODE_Judge();
  51. if(START_Flag&&!BOOT_REPEATING_CODE_Flag)
  52. {
  53. for(i=0;i<4;i++)
  54. {
  55. B0=H_L_LEVEL_Judge();
  56. B1=H_L_LEVEL_Judge();
  57. B2=H_L_LEVEL_Judge();
  58. B3=H_L_LEVEL_Judge();
  59. B4=H_L_LEVEL_Judge();
  60. B5=H_L_LEVEL_Judge();
  61. B6=H_L_LEVEL_Judge();
  62. B7=H_L_LEVEL_Judge();
  63. DATA[i]=TEMP_BIT;
  64. }
  65. for(i=0;i<4;i++)
  66. {
  67. SBUF=DATA[i];
  68. while(TI==0);
  69. TI=0;
  70. }
  71. }
  72. }
  73. }
  74. voidUART_Initial()
  75. {
  76. SCON=0x50;//SCON:形式1,8-bitUART,使能接纳
  77. TMOD|=0x20;//TMOD:timer1,mode2,8-bitreload
  78. TH1=0xFD;//TH1:reloadvaluefor9600baud@
  79. //11.0592MHz
  80. TR1=1;//TR1:timer1run
  81. EA=0;//封闭总中止
  82. ES=0;//封闭串口中止
  83. }
  84. bitSTART_Judge()
  85. {
  86. bitTEMP_Flag=1;
  87. unsignedchari=0;
  88. //在正常无遥控信号时,一体化红外接纳头输出是高电平,程序一直在循环。
  89. while(IR_Out==1);
  90. //重复10次,意图是检测在6876~8352微秒内假如呈现高电平就退出解码程序
  91. for(i=0;i<9;i++)
  92. {
  93. DELAY_Us(800);//测验实践延时约为764~928us
  94. if(IR_Out==1)
  95. {
  96. TEMP_Flag=0;
  97. break;
  98. }
  99. }
  100. returnTEMP_Flag;
  101. }
  102. bitBOOT_REPEATING_CODE_Judge()
  103. {
  104. bitTEMP_Flag=1;
  105. while(IR_Out==0);//等候高电平避开9毫秒低电平引导脉冲
  106. DELAY_Ms(1);//测验实践延时约为1.007ms
  107. DELAY_Ms(1);//测验实践延时约为1.007ms
  108. DELAY_Us(200);//0.086ms
  109. DELAY_Us(200);//0.086ms
  110. DELAY_Us(200);//0.086ms
  111. //合计2.272ms
  112. if(IR_Out==0)
  113. {
  114. TEMP_Flag=1;//是连发码
  115. }
  116. else
  117. {
  118. TEMP_Flag=0;//不是连发码,而是引导码
  119. }
  120. returnTEMP_Flag;
  121. }
  122. bitH_L_LEVEL_Judge()
  123. {
  124. while(IR_Out==0);//等候地址码第一位的高电平信号
  125. DELAY_Us(800);//测验实践延时约为764~928us
  126. if(IR_Out==1)
  127. {
  128. DELAY_Ms(1);//测验实践延时约为1.007ms
  129. return1;
  130. }
  131. else
  132. {
  133. return0;
  134. }
  135. }

修改如下:

01 FE 8B 74 — 01 FE 8D 72 — 01 FE 8F 70

01 FE 89 76 — 01 FE 81 7E — 01 FE 87 78

01 FE 0F F0 — 01 FE 2B D4 — 01 FE 13 EC

01 FE 2D D2 — 01 FE 33 CC — 01 FE 1B E4

01 FE 19 E6 — 01 FE 31 CE — 01 FE BD 42

01 FE 11 EE — 01 FE 39 C6 — 01 FE B5 4A
以上为对应按键的编码。

过程中存在问题:

一是怎么有用的辨认引导码和连发码,由于这个能直接影响到长时刻按键,单片机的呼应与否。这个问题,形似我以处理,便是长时刻按键后,单片机辨认一次按键后,假如仍是同一按键,就不与答理。

还有一个问题便是,假如接连按下两次按键,该程序能够辨认出,可是假如距离很短,第二下按键的编码简单犯错,简单变成这样:

03 FE 8B 74.。。。便是第一个字节呈现差错,这个问题现在还未来得及处理。

还有便是本程序关于延时函数的精度要求很高,由于自身处理的脉冲便是MS等级的。所以需求严厉的测验延时函数的实践延时时刻:

以上的代码,能够看出许多问题,软件延时不精确,很多的“while( IR_Out == 0 ) ;”代码,抗搅扰才能弱,简单进入死循环。

下面介绍的这种解码办法,使用外部中止触发程序,守时器守时(但没有设置守时中止程序,即判别TF的值确认守时完毕),在代码过程中,最初的一个7.93ms延时,足以滤掉不合法的红外信号。应该说功率质量更高的。

代码注释很具体,在此不在细述:

[cpp]view plaincopy

  1. /*————————————————————*-
  2. IR_Decoder.C(v1.00)
  3. ————————————————————
  4. 称号:遥控器红外解码,PO口接LED,显现功用码以供检查
  5. 编写:mhjerry
  6. 日期:20011.7
  7. 内容:按遥控器上的按键,会在PO口LED上显现
  8. -*————————————————————*/
  9. #include”reg52.h”
  10. //此口为红外信号输入MCU口
  11. sbitIR_Out=P3^2;
  12. //主程序运转标志位,运转主程序时LED灭,运转中止程序时LED亮
  13. sbitIR_Flag=P3^1;
  14. //LED显现口
  15. #defineLED_PortP1
  16. //用于寄存按键码值,初始化为00000000这样承受数据时能够只考虑1了
  17. unsignedchardat[4]={0,0,0,0};
  18. /*……………………………………………………*/
  19. voidmain()
  20. {
  21. IR_Out=1;//此口为MCU输进口,故需求置1
  22. IR_Flag=1;//灭LED灯
  23. TMOD=0x01;//守时器0,办法1
  24. IT0=1;//外部中止0,下降沿触发
  25. EX0=1;//允许外部中止
  26. EA=1;//CPU允许中止
  27. while(1)
  28. {
  29. IR_Flag=1;//履行主程序时,LED灯灭
  30. }
  31. }
  32. /*————————————————————*-
  33. 函数称号:Int0()
  34. 函数输入:无(容许中止时,外部触发)
  35. 函数输出:无
  36. 函数阐明:外部中止0中止处理
  37. -*————————————————————*/
  38. voidInt0()interrupt0
  39. {
  40. unsignedchari,j;
  41. EX0=0;//封闭外部中止0
  42. IR_Flag=0;//履行中止程序时,LED灯亮
  43. i=10;//0.793ms延时,运转10次
  44. while(–i)
  45. {
  46. //守时0.793ms,延时0.793ms*10=7.93ms
  47. TH0=0xfc;
  48. TL0=0xe7;
  49. TR0=1;
  50. while(!TF0);
  51. TF0=0;
  52. TR0=0;
  53. //这7.93ms期间只需IR_Out变高电平,就非合法的红外信号,跳出
  54. if(IR_Out)
  55. {
  56. EX0=1;//允许中止
  57. return;
  58. }
  59. }
  60. //程序进行到这儿,标明是合法的红外信号(使用9ms判别)
  61. while(!IR_Out);//等候9ms低电平曩昔
  62. //程序进行到这儿,标明通过9ms低电平
  63. TH0=0xf6;
  64. TL0=0xff;
  65. TR0=1;
  66. while(!TF0);
  67. TF0=0;
  68. TR0=0;//延时2.305ms
  69. //IR_Out为低标明是连发码,不予答理,跳出
  70. if(!IR_Out)
  71. {
  72. EX0=1;
  73. return;
  74. }
  75. //程序进行到这儿,标明是引导码,等候4.5ms高电平的曩昔
  76. while(IR_Out);
  77. //开端接纳用户码
  78. for(i=0;i<4;i++)
  79. {
  80. for(j=0;j<8;j++)
  81. {
  82. while(!IR_Out);//等候低电平曩昔
  83. dat[i]>>=1;//把前次的数据位右移一位
  84. TH0=0xfc;
  85. TL0=0xe7;
  86. TR0=1;
  87. while(!TF0);
  88. TR0=0;
  89. TF0=0;//延时0.793ms
  90. //若为数据”1″,则延时后IR_Out为高电平
  91. if(IR_Out)
  92. {
  93. dat[i]|=0x80;//一切数据位1放最高位
  94. while(IR_Out);//等候高电平曩昔
  95. }
  96. }
  97. }
  98. LED_Port=dat[2];
  99. EX0=1;//开中止
  100. return;
  101. }
  102. /*————————————————————*-
  103. —-ENDOFFILE——————————————-
  104. -*————————————————————*/

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/xinpin/261538.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部