在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

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

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

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

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

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

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

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

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

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

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

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

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



            當(dāng)一個鍵按下超過36ms,振蕩器使芯片激活,將發(fā)射一組108ms的編碼脈沖,這108ms發(fā)射代碼由一個引導(dǎo)碼(9ms),一個結(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)組成。(實際上人手的動作是很慢的,即使你快速的按下按鍵,可能對于芯片來說還是超過108ms,所以如何處理連發(fā)碼是很關(guān)鍵的)

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

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

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

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

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

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

            如果亂碼,請參考:

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

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

            [cpp]view plaincopy
            1. /*------------------------------------------------------------*-
            2. 紅外收發(fā).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. //---有無遙控信號判斷函數(shù)----------------------------------
            22. bitSTART_Judge();
            23. //---連發(fā)碼判斷函數(shù)----------------------------------------
            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;//關(guān)閉總中斷
            82. ES=0;//關(guān)閉串口中斷
            83. }
            84. bitSTART_Judge()
            85. {
            86. bitTEMP_Flag=1;
            87. unsignedchari=0;
            88. //在正常無遙控信號時,一體化紅外接收頭輸出是高電平,程序一直在循環(huán)。
            89. while(IR_Out==1);
            90. //重復(fù)10次,目的是檢測在6876~8352微秒內(nèi)如果出現(xiàn)高電平就退出解碼程序
            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毫秒低電平引導(dǎo)脈沖
            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;//是連發(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);//等待地址碼第一位的高電平信號
            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
            以上為對應(yīng)按鍵的編碼。

            過程中存在問題:

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

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

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

            還有就是本程序?qū)τ谘訒r函數(shù)的精度要求很高,因為本身處理的脈沖就是MS級別的。所以需要嚴格的測試延時函數(shù)的實際延時時間:

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

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

            代碼注釋很詳細,在此不在細述:

            [cpp]view plaincopy
            1. /*------------------------------------------------------------*-
            2. IR_Decoder.C(v1.00)
            3. ------------------------------------------------------------
            4. 名稱:遙控器紅外解碼,PO口接LED,顯示功能碼以供查看
            5. 編寫:mhjerry
            6. 日期:20011.7
            7. 內(nèi)容:按遙控器上的按鍵,會在PO口LED上顯示
            8. -*------------------------------------------------------------*/
            9. #include"reg52.h"
            10. //此口為紅外信號輸入MCU口
            11. sbitIR_Out=P3^2;
            12. //主程序運行標(biāo)志位,運行主程序時LED滅,運行中斷程序時LED亮
            13. sbitIR_Flag=P3^1;
            14. //LED顯示口
            15. #defineLED_PortP1
            16. //用于存放按鍵碼值,初始化為00000000這樣接受數(shù)據(jù)時可以只考慮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,下降沿觸發(fā)
            25. EX0=1;//準許外部中斷
            26. EA=1;//CPU準許中斷
            27. while(1)
            28. {
            29. IR_Flag=1;//執(zhí)行主程序時,LED燈滅
            30. }
            31. }
            32. /*------------------------------------------------------------*-
            33. 函數(shù)名稱:Int0()
            34. 函數(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í)行中斷程序時,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. //程序進行到這里,表明經(jīng)過9ms低電平
            63. TH0=0xf6;
            64. TL0=0xff;
            65. TR0=1;
            66. while(!TF0);
            67. TF0=0;
            68. TR0=0;//延時2.305ms
            69. //IR_Out為低表明是連發(fā)碼,不予理睬,跳出
            70. if(!IR_Out)
            71. {
            72. EX0=1;
            73. return;
            74. }
            75. //程序進行到這里,表明是引導(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;//延時0.793ms
            90. //若為數(shù)據(jù)"1",則延時后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. -*------------------------------------------------------------*/



            評論


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

            關(guān)閉