新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 紅外通信—紅外遙控器NEC解碼程序

        紅外通信—紅外遙控器NEC解碼程序

        作者: 時間:2016-12-02 來源:網絡 收藏

        /**********************紅外解碼*************************************/

        /**
        * @brief 配置定時器T1,開啟外部中斷,T1用來計數
        * @param 無
        * @retval 無
        */
        void ConfigTimer1()
        {
        TMOD &= 0x0F;//清零T1控制位
        TMOD |= 0x10;//T1方式1
        TH1 = 0;
        TL1 = 0;//初始化計數值為0
        TR1 = 0;//在沒有進入外部中斷前,先關閉定時器T1
        ET1 = 0;//關閉T1中斷,只用來計數
        IT1 = 1;//設置外部中斷為下降沿觸發中斷
        EX1 = 1;//開啟外部中斷
        }

        /**
        * @brief 獲得高電平時間(空閑時間)
        * @param 無
        * @retval 無
        */
        unsigned int getHeighTime()
        {
        //在檢測外部電平之前,先將紅外檢測引腳拉高釋放
        IRD = 1;

        TH1 = 0;
        TL1 = 0;//重新清零
        TR1 = 1;//打開定時器T1開始計數
        while (IRD)
        {
        //進行超時判斷,若高電平時間大于9ms,即引導碼時間,則直接退出
        if (TH1 > 0x40) //(0x40*256) * (12/11059200) s = 17.7ms
        {
        break;//退出
        }
        }
        TR1 = 0;//關閉計數

        return (TH1*256 + TL1);//返回IRD引腳持續的高電平時T1計數值
        }

        /**
        * @brief 獲取低電平時間(載波)
        * @param 無
        * @retval 無
        */
        unsigned int getLowTime()
        {
        //釋放IRD檢測引腳
        IRD = 1;
        TH1 = 0;
        TL1 = 0;//清零T1計數值
        TR1 = 1;//啟動T1計數
        while (!IRD)
        {
        if (TH1 > 0x40) //TL1計數滿則進位TH1,時間:TH1*256*12/11059200 s = 17.7ms
        { //時間大于了NEC協議的引導碼載波時間9ms,進行強制退出,避免假等待
        break;
        }
        }
        TR1 = 0;//關閉計數

        return (TH1*256 + TL1);//返回低電平持續的計數值 每計數一次是一個機器周期的時間即1.08us
        }

        /**
        * @brief 外部中斷服務,檢測紅外信號
        * @param 無
        * @retval 無
        */
        void ExINT_ISP() interrupt 2 //外部中斷1中斷標號為2
        {
        unsigned int time;//時間
        unsigned char i, j;
        unsigned char byte = 0;

        time = getLowTime();//獲取低電平T1計數值,即引導碼的9ms載波
        if ((time < 7833) || (time > 8755)) //范圍8.5-9.5ms X=0.0085/(12/11059200)
        {
        //錯誤引導碼
        IE1 = 0;//清零外部中斷標志
        return;//退出中斷
        }
        //符合引導碼的9ms
        time = getHeighTime();//獲取高電平時間
        if ((time < 3686) || (time > 4608)) //范圍4ms-5ms
        {
        //不是4.5ms的空閑
        IE1 = 0;//清零外部中斷
        return;//退出中斷
        }
        //是正確的引導碼
        for (i = 0; i < 4; i++) //循環接收用戶碼 用戶反碼 鍵數值碼 鍵數值反碼
        {
        for (j = 0; j < 8; j++) //接收八位
        {
        //560us的載波(低電平)+560us的空閑(高電平) = 0 560us的載波(低電平)+1.68ms的空閑(高電平) = 1
        time = getLowTime();//載波時間
        if ((time < 322) || (time > 645)) //范圍350us-700us
        {
        IE1 = 0;//清零外部中斷標志
        return;//退出中斷
        }
        time = getHeighTime();//空閑時間
        if ((time > 322) && (time < 645)) //560us的空閑
        {
        //bit 0
        byte >>= 1;//地位在前,先接收低位
        }
        else if ((time > 1198) && (time < 1658)) //1300us-1800us 1.68ms的空閑
        {
        //bit 1
        byte >>= 1;
        byte |= 0x80;//高位置1
        }
        else
        {
        //無效碼
        IE1 = 0;
        return;
        }
        }
        ircode = byte;//接收數據
        }
        //全部接收完畢
        irflag = 1;
        IE1 = 0;//清零外部中斷標志位
        }


        上一頁 1 2 下一頁

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 阳东县| 涿鹿县| 樟树市| 新津县| 苍山县| 凤山市| 舟山市| 广宁县| 平昌县| 洛浦县| 图片| 磴口县| 克东县| 梁山县| 茶陵县| 汉川市| 定日县| 北碚区| 鹤壁市| 石台县| 南靖县| 寻甸| 隆安县| 柳河县| 阿拉尔市| 东丽区| 聂荣县| 广灵县| 子长县| 洮南市| 华容县| 余干县| 泸西县| 伊宁市| 会昌县| 虞城县| 新蔡县| 平江县| 双牌县| 云浮市| 凌云县|