新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > PIC單片機的紅外遙控與解碼

        PIC單片機的紅外遙控與解碼

        作者: 時間:2016-11-09 來源:網絡 收藏
        今天玩紅外遙控解碼!

        先了解紅外接收的原理:

        本文引用地址:http://www.104case.com/article/201611/317656.htm

        遙控器使用方便,功能多.目前已廣泛應用在電視機、VCD、DVD、空調等各種家用電器中,且價格便宜,市場上非常容易買到。如果能將遙控器上許多的按鍵解碼出來.用作單片機系統的輸入.則解決了常規矩陣鍵盤線路板過大、布線復雜、占用I/O口過多的弊病。而且通過使用遙控器,操作時可實現人與設備的分離,從而更加方便使用。

        一、編碼格式
        1、0和1的編碼
        遙控器發射的信號由一串O和1的二進制代碼組成.不同的芯片對0和1的編碼有所不同。通常有曼徹斯特編碼和脈沖寬度編碼。TC9012的O和1采用PWM方法編碼,即脈沖寬度調制,其O碼和1碼如圖1所示(以遙控接收輸出的波形為例)。O碼由O.56ms低電平和0.56ms高電平組合而成.脈沖寬度為1.12ms.1碼由0.56ms低電平和1.69ms高電平組合而成.脈沖寬度為2.25ms。在編寫解碼程序時.通過判斷脈沖的寬度,即可得到0或1。
        2、按鍵的編碼

        當一個鍵按下超過36ms,振蕩器使芯片激活,將發射一組108ms的編碼脈沖,這108ms發射代碼由一個起始碼(9ms),一個結果碼(4.5ms),低8位地址碼(9ms~18ms),高8位地址碼(9ms~18ms),8位數據碼(9ms~18ms)和這8位數據的反碼(9ms~18ms)組成。如果鍵按下超過108ms仍未松開,接下來發射的代碼(連發代碼)將僅由起始碼(9ms)和結束碼(2.5ms)組成。

        當我們按下遙控器的按鍵時,遙控器將發出如圖2的一串二進制代碼,我們稱它為一幀數據。根據各部分的功能??蓪⑺鼈兎譃?部分,分別為引導碼、地址碼、地址碼、數據碼、數據反碼。遙控器發射代碼時.均是低位在前。高位在后。由圖2分析可以得到.引導碼高電平為4.5ms,低電平為4.5ms。當
        接收到此碼時.表示一幀數據的開始。單片機可以準備接收下面的數據。地址碼由8位二進制組成,共256種.圖中地址碼重發了一次。主要是加強遙控器的可靠性.如果兩次地址碼不相同.則說明本幀數據有錯.應丟棄。不同的設備可以擁有不同的地址碼.因此。同種編碼的遙控器只要設置地址碼不同,也不會相互干擾。圖中的地址碼為十六進制的0EH(注意低位在前)。在同一個遙控器中.所有按鍵發出的地址碼都是相同的。數據碼為8位,可編碼256種狀態,代表實際所按下的鍵。數據反碼是數據碼的各位求反,通過比較數據碼與數據反碼.可判斷接收到的數據是否正確。如果數據碼與數據反碼之間的關系不滿足相反的關系.則本次遙控接收有誤.數據應丟棄。在同一個遙控器上.所有按鍵的數據碼均不相同。在圖2中,數據碼為十六進制的0CH,數據反碼為十六進制的0F3H(注意低位在前).兩者之和應為0FFH。

        連續碼


        二、單片機遙控接收電路
        紅外遙控接收可采用較早的紅外接收二極管加專用的紅外處理電路的方法。如CXA20106,此種方法電路復雜,現在一般不采用。較好的接收方法是用一體化紅外接收頭,它將紅外接收二極管、放大、解調、整形等電路做在一起,只有三個引腳.分別是+5V電源、地、信號輸出。常用的一體化接收頭的外形及引腳見圖3和圖4。紅外接收頭的信號輸
        出接單片機的INTO或INTl腳.典型電路如圖5所示.圖中增加了一只PNP型三極管對輸出信號進行放大。

        針對遙控器端(解碼端,接收端對對此取反即可)
        引導碼:9ms高+4.5ms低
        系統碼:系統碼1+系統碼2(由定義高低電平的"0"和"1"組成)
        數據碼:數據碼1+數據反碼(由定義高低電平的"0"和"1"組成)
        剩余碼:108ms-引導碼占用時間-系統碼占用時間-數據碼占用時間.
        如果按"鍵"的時間超過108ms,遙控器還會發射重發碼:
        重發碼(108ms)的格式如下:
        9ms高+2.25ms低+0.56ms高+96.19ms低

        連接電路圖:

        下面開始寫程序:

        #ifndef MAIN_H
        #define MAIN_H
        #include

        #define bitset(var,bitno)(var |=1<#define bitclr(var,bitno)(var &=~(1<


        #define uint unsigned int
        #define uchar unsigned char

        //定義接受幀狀態
        #define IR_IDLE 0x01
        #define IR_START 0x02
        #define IR_ADD 0x03
        #define IR_ADDINV 0x04
        #define IR_DATA 0x05
        #define IR_DATAINV 0x06


        #define ms_168 0x0600
        #define ms_th 0x08CA
        #define ms_9 0x0800
        #define ms_306 0x0B00
        #define ms_125 0x1300
        #define ms_15 0x15F9
        //void DelayMS(uint ms);//毫秒級延時函數
        //void Delay10US(uint us);//10微秒級延時函數
        void init_all() ;

        #endif


        #include "main.h"
        #include "t232.h"

        typedef struct frame1
        {
        uint add ;
        uint addinv ;
        uchar data ;
        uchar datainv ;
        uchar ir_state ;
        uint count ;
        uint temp ;
        uchar ready ;
        } ir_frame ;

        void int_delay(uint count)
        {
        while(count--) ;
        }
        //define global variable
        ir_frame frame ;

        void interrupt main_int()
        {

        if(INTF&INTEDG)
        {
        GIE=0 ;
        INTF=0 ;
        TMR1ON=0;
        frame.count=TMR1H*256+TMR1L;
        TMR1H=0;
        TMR1L=0;
        TMR1ON=1;

        switch(frame.ir_state)
        {
        case IR_IDLE :
        if(frame.count>0x2000)//防止干擾
        frame.ir_state=IR_START ;
        break ;
        case IR_START :
        if(frame.ready==1)//沒有處理,等待
        {
        frame.ir_state=IR_IDLE ;
        return ;
        }
        if((frame.count>ms_125)&&(frame.count{
        frame.add=0 ;
        frame.addinv=0 ;
        frame.data=0 ;
        frame.datainv=0 ;
        frame.ir_state=IR_ADD ;
        frame.temp=1 ;
        frame.ready=0 ;

        }
        else if((frame.count>ms_9)&&(frame.count{
        frame.ready=1 ;
        frame.ir_state = IR_IDLE ;

        }
        else//噪聲?
        {
        frame.ir_state = IR_IDLE ;
        }
        break ;
        case IR_ADD :
        if(frame.count<0x280)//噪聲?
        return ;
        if((frame.count>ms_168))//高電平?
        frame.add|=frame.temp ;

        frame.temp=frame.temp<<1 ;
        if(frame.temp==0x2000)//13位OK?
        {
        frame.ir_state=IR_ADDINV ;
        frame.temp=1 ;
        }
        break ;
        case IR_ADDINV :
        //int_delay(75) ;
        //if(RB0)
        if(frame.count<0x280)
        return ;
        if((frame.count>ms_168))
        frame.addinv|=frame.temp ;

        frame.temp=frame.temp<<1 ;
        if(frame.temp==0x2000)//13位OK?
        {
        frame.ir_state=IR_DATA ;
        frame.temp=1 ;
        }
        break ;
        case IR_DATA :
        if(frame.count<0x280)//噪聲
        return ;
        if((frame.count>ms_168))//高電平
        frame.data|=frame.temp ;

        frame.temp=frame.temp<<1 ;
        if(frame.temp==0x0100)//8位 finished ?
        {
        frame.ir_state=IR_DATAINV ;
        frame.temp=1 ;
        }
        break ;
        case IR_DATAINV :
        if(frame.count<0x280)
        return ;
        if((frame.count>ms_168))
        frame.datainv|=frame.temp ;

        frame.temp=frame.temp<<1 ;
        if(frame.temp==0x0080)//7 位 finished?
        {
        frame.temp=frame.temp<<1 ;
        int_delay(75) ;//延時等待最后一位的電平
        if(RB0)
        frame.datainv|=frame.temp ;
        if((frame.data|frame.datainv==0xff)&&(frame.add==0x011F))
        {
        frame.ready=1 ;
        }
        frame.ir_state=IR_IDLE ;
        }
        break ;
        default :
        break ;
        }
        GIE=1 ;
        }
        }


        void init_all()
        {
        init_232() ;
        //init_hongwai() ;
        INTCON=0 ;
        INTE=1;//開RB電平中斷
        PEIE=1;
        INTEDG=1 ;
        TRISB0=1;//RB4為輸入
        T1CON=0 ;
        TMR1H=0xAA ;
        TMR1L=0xBB ;
        frame.ir_state=IR_IDLE ;
        GIE=1 ;
        ADCON0=0x06 ;
        TRISA0=0 ;
        }
        void main()
        {
        const char str[]= "hello world !" ;

        init_all() ;
        send_str(str) ;//測試串口
        while(1)
        {

        if(frame.ready==1)
        {
        put_char(frame.data) ;
        frame.ready=0 ;
        }

        }
        }



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 玉山县| 龙泉市| 桃园县| 奉化市| 霍林郭勒市| 文水县| 三门峡市| 朝阳区| 乌拉特后旗| 贵定县| 西乌| 铜梁县| 丹巴县| 自贡市| 新余市| 嘉兴市| 郎溪县| 新巴尔虎右旗| 雷波县| 鹰潭市| 密云县| 东城区| 易门县| 永顺县| 武邑县| 桂平市| 阿拉善右旗| 寻甸| 陆河县| 塔城市| 汪清县| 康定县| 镇宁| 北宁市| 上杭县| 随州市| 荆州市| 洪江市| 五莲县| 青川县| 天门市|