<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 紅外遙控系統(tǒng)原理及單片機(jī)軟件解碼程序

          紅外遙控系統(tǒng)原理及單片機(jī)軟件解碼程序

          作者: 時(shí)間:2016-11-23 來源:網(wǎng)絡(luò) 收藏
          首先,必須要了解一些基本原理。其實(shí)按下遙控器的某一個(gè)鍵,遙控器會(huì)發(fā)出一連串經(jīng)過調(diào)制后的信號(hào),這個(gè)信號(hào)經(jīng)過紅外一體化模塊接收后,輸出解調(diào)后的數(shù)字脈沖,每個(gè)按鍵對(duì)應(yīng)不同的脈沖,故識(shí)別出不同的脈沖就能識(shí)別出不同的按鍵。

          本文引用地址:http://www.ex-cimer.com/article/201611/320460.htm

          上圖就是很常見的車載MP3遙控器,比較小巧,很好用。下面是紅外發(fā)射和接受原理:

          到此讀者可能會(huì)有疑惑,那么不同的調(diào)制解調(diào)方法那么出來的脈沖規(guī)則是不一樣的?是的,的確如此。

          遙控發(fā)射器專用芯片很多,根據(jù)編碼格式可以分成兩大類,這里我們以運(yùn)用比較廣泛,解碼比較容易的一類來加以說明,現(xiàn)以日本NEC的uPD6121G組成發(fā)射電路為例說明編碼原理(一般家庭用的DVD、VCD、音響都使用這種編碼方式)。當(dāng)發(fā)射器按鍵按下后,即有遙控碼發(fā)出,所按的鍵不同遙控編碼也不同。這種遙控碼具有以下特征:

          采用脈寬調(diào)制的串行碼,以脈寬為0.565ms、間隔0.56ms、周期為1.125ms的組合表示二進(jìn)制的“0”;以脈寬為0.565ms、間隔1.685ms、周期為2.25ms的組合表示二進(jìn)制的“1”,其波形如圖所示。

          如圖可見,0與1前端的低電平持續(xù)都是0.56ms,那么就是后面的高電平持續(xù)時(shí)間不同,0為0.56ms,1為1.685ms,找到不同之處,編程時(shí)就有識(shí)別的依據(jù)了!

          上述“0”和“1”組成的32位二進(jìn)制碼經(jīng)38kHz的載頻進(jìn)行二次調(diào)制以提高發(fā)射效率,達(dá)到降低電源功耗的目的。然后再通過紅外發(fā)射二極管產(chǎn)生紅外線向空間發(fā)射,如圖所示。

          UPD6121G產(chǎn)生的遙控編碼是連續(xù)的32位二進(jìn)制碼組,其中前16位為用戶識(shí)別碼,能區(qū)別不同的電器設(shè)備,防止不同機(jī)種遙控碼互相干擾。該芯片的用戶識(shí)別碼固定為十六進(jìn)制01H;后16位為8位操作碼(功能碼)及其反碼。UPD6121G最多額128種不同組合的編碼。

          請(qǐng)看下圖,來自網(wǎng)絡(luò):



          當(dāng)一個(gè)鍵按下超過36ms,振蕩器使芯片激活,將發(fā)射一組108ms的編碼脈沖,這108ms發(fā)射代碼由一個(gè)引導(dǎo)碼(9ms),一個(gè)結(jié)果碼(4.5ms),低8位地址碼(9ms~18ms),高8位地址碼(9ms~18ms),8位數(shù)據(jù)碼(9ms~18ms)和這8位數(shù)據(jù)的反碼(9ms~18ms)組成。如果鍵按下超過108ms仍未松開,接下來發(fā)射的代碼(連發(fā)碼)將僅由起始碼(9ms)和結(jié)束碼(2.25ms)組成。(實(shí)際上人手的動(dòng)作是很慢的,即使你快速的按下按鍵,可能對(duì)于芯片來說還是超過108ms,所以如何處理連發(fā)碼是很關(guān)鍵的)

          遙控器在按鍵按下后,周期性地發(fā)出同一種32位二進(jìn)制碼,周期約為108ms。一組碼本身的持續(xù)時(shí)間隨它包含的二進(jìn)制“0”和“1”的個(gè)數(shù)不同而不同,大約在45~63ms之間,圖為發(fā)射波形圖。

          下面是我寫的代碼,按鍵編碼通過串口發(fā)送到電腦端:

          由于時(shí)間關(guān)系,代碼注釋不多。

          其中START_Judge()函數(shù)是判斷9ms低電平,既是判斷有無遙控信號(hào)。

          BOOT_REPEATING_CODE_Judge()是判斷是引導(dǎo)碼還是連發(fā)碼,引導(dǎo)碼則進(jìn)入接受數(shù)據(jù)環(huán)節(jié),連發(fā)碼表明數(shù)據(jù)已經(jīng)接受結(jié)束。

          H_L_LEVEL_Judge()是接受數(shù)據(jù)時(shí)判斷高低電平。

          如果亂碼,請(qǐng)參考:

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

          注明:以下代碼為純軟件方式,沒有用到中斷,定時(shí)器方式,純CPU查詢,但測(cè)試結(jié)果倒也可以,至少比較穩(wěn)定,得到的碼值不管對(duì)不對(duì),都是那個(gè)值。

          [cpp]view plaincopy
          1. /*------------------------------------------------------------*-
          2. 紅外收發(fā).C
          3. ------------------------------------------------------------
          4. 遙控器測(cè)試
          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. //---有無遙控信號(hào)判斷函數(shù)----------------------------------
          22. bitSTART_Judge();
          23. //---連發(fā)碼判斷函數(shù)----------------------------------------
          24. bitBOOT_REPEATING_CODE_Judge();
          25. //---"0"和"1"識(shí)別------------------------------------------
          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;//關(guān)閉總中斷
          82. ES=0;//關(guān)閉串口中斷
          83. }
          84. bitSTART_Judge()
          85. {
          86. bitTEMP_Flag=1;
          87. unsignedchari=0;
          88. //在正常無遙控信號(hào)時(shí),一體化紅外接收頭輸出是高電平,程序一直在循環(huán)。
          89. while(IR_Out==1);
          90. //重復(fù)10次,目的是檢測(cè)在6876~8352微秒內(nèi)如果出現(xiàn)高電平就退出解碼程序
          91. for(i=0;i<9;i++)
          92. {
          93. DELAY_Us(800);//測(cè)試實(shí)際延時(shí)約為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毫秒低電平引導(dǎo)脈沖
          106. DELAY_Ms(1);//測(cè)試實(shí)際延時(shí)約為1.007ms
          107. DELAY_Ms(1);//測(cè)試實(shí)際延時(shí)約為1.007ms
          108. DELAY_Us(200);//0.086ms
          109. DELAY_Us(200);//0.086ms
          110. DELAY_Us(200);//0.086ms
          111. //共計(jì)2.272ms
          112. if(IR_Out==0)
          113. {
          114. TEMP_Flag=1;//是連發(fā)碼
          115. }
          116. else
          117. {
          118. TEMP_Flag=0;//不是連發(fā)碼,而是引導(dǎo)碼
          119. }
          120. returnTEMP_Flag;
          121. }
          122. bitH_L_LEVEL_Judge()
          123. {
          124. while(IR_Out==0);//等待地址碼第一位的高電平信號(hào)
          125. DELAY_Us(800);//測(cè)試實(shí)際延時(shí)約為764~928us
          126. if(IR_Out==1)
          127. {
          128. DELAY_Ms(1);//測(cè)試實(shí)際延時(shí)約為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
          以上為對(duì)應(yīng)按鍵的編碼。

          過程中存在問題:

          一是如何有效的識(shí)別引導(dǎo)碼和連發(fā)碼,因?yàn)檫@個(gè)能直接影響到長(zhǎng)時(shí)間按鍵,單片機(jī)的響應(yīng)與否。這個(gè)問題,貌似我以解決,就是長(zhǎng)時(shí)間按鍵后,單片機(jī)識(shí)別一次按鍵后,如果還是同一按鍵,就不與理睬。

          還有一個(gè)問題就是,如果連續(xù)按下兩次按鍵,該程序能夠識(shí)別出,但是如果間隔很短,第二下按鍵的編碼容易出錯(cuò),容易變成這樣:

          03 FE 8B 74.。。。就是第一個(gè)字節(jié)出現(xiàn)誤差,這個(gè)問題現(xiàn)在還未來得及解決。

          還有就是本程序?qū)τ谘訒r(shí)函數(shù)的精度要求很高,因?yàn)楸旧硖幚淼拿}沖就是MS級(jí)別的。所以需要嚴(yán)格的測(cè)試延時(shí)函數(shù)的實(shí)際延時(shí)時(shí)間:

          以上的代碼,可以看出許多問題,軟件延時(shí)不準(zhǔn)確,大量的“while( IR_Out == 0 ) ;”代碼,抗干擾能力弱,容易進(jìn)入死循環(huán)。

          下面介紹的這種解碼方法,利用外部中斷觸發(fā)程序,定時(shí)器定時(shí)(但沒有設(shè)置定時(shí)中斷程序,即判斷TF的值確定定時(shí)結(jié)束),在代碼過程中,開頭的一個(gè)7.93ms延時(shí),足以濾掉不合法的紅外信號(hào)。應(yīng)該說效率質(zhì)量更高的。

          代碼注釋很詳細(xì),在此不在細(xì)述:

          [cpp]view plaincopy
          1. /*------------------------------------------------------------*-
          2. IR_Decoder.C(v1.00)
          3. ------------------------------------------------------------
          4. 名稱:遙控器紅外解碼,PO口接LED,顯示功能碼以供查看
          5. 編寫:mhjerry
          6. 日期:20011.7
          7. 內(nèi)容:按遙控器上的按鍵,會(huì)在PO口LED上顯示
          8. -*------------------------------------------------------------*/
          9. #include"reg52.h"
          10. //此口為紅外信號(hào)輸入MCU口
          11. sbitIR_Out=P3^2;
          12. //主程序運(yùn)行標(biāo)志位,運(yùn)行主程序時(shí)LED滅,運(yùn)行中斷程序時(shí)LED亮
          13. sbitIR_Flag=P3^1;
          14. //LED顯示口
          15. #defineLED_PortP1
          16. //用于存放按鍵碼值,初始化為00000000這樣接受數(shù)據(jù)時(shí)可以只考慮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;//定時(shí)器0,方式1
          24. IT0=1;//外部中斷0,下降沿觸發(fā)
          25. EX0=1;//準(zhǔn)許外部中斷
          26. EA=1;//CPU準(zhǔn)許中斷
          27. while(1)
          28. {
          29. IR_Flag=1;//執(zhí)行主程序時(shí),LED燈滅
          30. }
          31. }
          32. /*------------------------------------------------------------*-
          33. 函數(shù)名稱:Int0()
          34. 函數(shù)輸入:無(容許中斷時(shí),外部觸發(fā))
          35. 函數(shù)輸出:無
          36. 函數(shù)說明:外部中斷0中斷處理
          37. -*------------------------------------------------------------*/
          38. voidInt0()interrupt0
          39. {
          40. unsignedchari,j;
          41. EX0=0;//關(guān)閉外部中斷0
          42. IR_Flag=0;//執(zhí)行中斷程序時(shí),LED燈亮
          43. i=10;//0.793ms延時(shí),運(yùn)行10次
          44. while(--i)
          45. {
          46. //定時(shí)0.793ms,延時(shí)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變高電平,就非合法的紅外信號(hào),跳出
          54. if(IR_Out)
          55. {
          56. EX0=1;//準(zhǔn)許中斷
          57. return;
          58. }
          59. }
          60. //程序進(jìn)行到這里,表明是合法的紅外信號(hào)(利用9ms判斷)
          61. while(!IR_Out);//等待9ms低電平過去
          62. //程序進(jìn)行到這里,表明經(jīng)過9ms低電平
          63. TH0=0xf6;
          64. TL0=0xff;
          65. TR0=1;
          66. while(!TF0);
          67. TF0=0;
          68. TR0=0;//延時(shí)2.305ms
          69. //IR_Out為低表明是連發(fā)碼,不予理睬,跳出
          70. if(!IR_Out)
          71. {
          72. EX0=1;
          73. return;
          74. }
          75. //程序進(jìn)行到這里,表明是引導(dǎo)碼,等待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;//把上次的數(shù)據(jù)位右移一位
          84. TH0=0xfc;
          85. TL0=0xe7;
          86. TR0=1;
          87. while(!TF0);
          88. TR0=0;
          89. TF0=0;//延時(shí)0.793ms
          90. //若為數(shù)據(jù)"1",則延時(shí)后IR_Out為高電平
          91. if(IR_Out)
          92. {
          93. dat[i]|=0x80;//所有數(shù)據(jù)位1放最高位
          94. while(IR_Out);//等待高電平過去
          95. }
          96. }
          97. }
          98. LED_Port=dat[2];
          99. EX0=1;//開中斷
          100. return;
          101. }
          102. /*------------------------------------------------------------*-
          103. ----ENDOFFILE-------------------------------------------
          104. -*------------------------------------------------------------*/



          評(píng)論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();