介紹
紅外遙控作為一種應用廣泛的遙控方式,紅外遙控裝置具有體積小、功耗低、功能強、成本低的特點。 錄音機、空調、音響等大型家用電器大多采用紅外遙控器。 控制住。 在這篇文章中,我將詳細講解紅外遙控信號的解碼方法。 這里只是簡單了解一下紅外信號的發送和接收原理。 紅外遙控系統必須有發射端和接收端。 發射端通過芯片調制信號,然后紅外發光晶閘管將信號以紅外光的形式發送出去。 接收端通過紅外檢測晶閘管接收紅外信號,然后通過放大、濾波、解調等操作輸出高低電平,從而完成紅外信號的發送和接收。本教程中我選擇的是紅外遙控器右圖傳輸紅外信號
選擇集成紅外接收頭作為紅外信號的接收端。 這是一種特殊的紅外接收電路。 它將紅外接收管和放大電路集成為一體。 外觀上只有二極管大小,如圖所示。
集成紅外接收頭共有三個引腳。 將突出的一側與自身對齊,從左到右依次為信號輸出、GND、VCC。 其工作電流為5V。 您可以選擇集成紅外接收模塊。 我們在使用時,只需要將其連接到5V電源,接地,然后將信號輸出引腳連接到單片機即可使用。 在本文中,我使用51單片機進行實驗。 51單片機足以解碼紅外信號,而且簡單易懂。 文章主要講解解碼原理。
硬件連接
第一步是硬件連接,所用的硬件非常簡單,只有集成紅外接收頭和單片機的最小系統。 首先我們將電源連接到單片機和紅外接收器的最小系統,注意共地,然后將紅外接收器的信號輸出引腳連接到單片機的外部中斷引腳單片機,從而完成硬件連接。 信號輸出引腳之所以與單片機的外部中斷引腳相連,是因為如上所述,紅外接收器接收到紅外信號后會輸出高低電平。 連接外部中斷引腳后,單片機可以快速響應,旁邊的程序也是由中斷程序實現的。
NEC合同
后面會提到紅外收發二極管電路,紅外接收器接收到紅外信號后會輸出高低電平,然后我們可以通過我們的程序分析電平變化來識別接收到的信號內容。 為了在接收端對信號進行解碼紅外收發二極管電路,我們需要知道發送端的數據是如何編碼的。 本文使用的紅外遙控器采用的是NEC編碼合約,所以我們首先需要解釋一下NEC合約的相關信息。 NEC合約是用于紅外通信的合約。 通過NEC合約發送的信息格式如右圖所示:
信息的開頭是一個9ms的高電平加上一個4.5ms的低電平引導代碼,用于告訴設備通信已經開始,信號已經發送。 然后是8位地址碼和原來的8位地址碼。 地址碼的作用是區分不同的接收部件,實現對某個部件的單獨控制。 最后是8位數據碼和8位原始數據碼。 數據代碼就是功能代碼。 我們可以為不同的數據代碼設置不同的功能。 原代碼的作用是檢查接收到的數據是否正確。 里面的信息中,‘0’用560us高電平加560us低電平表示,‘1’用560us高電平加低電平表示。 需要注意的是,里面的波形圖是發送端的波形。 我們的紅外接收端接收到的信號高低電平與上圖相反。 還需要注意的是,發送端是從最高位開始發送數據的,所以我們接收到的信號也是從最高位開始的。 另外,當我們持續按下同一個按鈕時,發射器不會重復發送地址碼和數據碼,而是發送一次后每隔一段時間發送一次啟動碼(重復),間隔約為108ms。 右圖為接收端導頻碼、導頻碼(重復)、‘0’、‘1’的波形:
了解了NEC合約的信息后,我們就可以開始編寫程序來控制MCU解碼紅外信號了。 首先解釋一下解碼程序的思路。 之前,我們將紅外接收器的信號輸出引腳連接到單片機的外部中斷引腳。 我們設置外部中斷的觸發方式為邊沿觸發。 當接收器收到信號后,會輸出低電平,低電平觸發外部中斷。 我們在中斷程序中啟動定時器,這樣在下一次低電平觸發中斷之前,我們可以比較這段時間定時器設定的時間來確定脈沖。 值的長度決定數據是“0”還是“1”。 那我就根據具體代碼來介紹一下。
#include"reg52.h"#define uint unsigned int #define uchar unsigned charuchar IRtime; //儲存檢測紅外高低電平持續時間uchar IRcord[4]; //儲存解碼后的4個字節數據uchar IRdata[33]; //包含起始碼在內的33位數據bit IRpro_ok; //解碼后4個數據接收完成標志位bit IRok; //33位數據接收完成標志位
在前面的函數中,我們添加了相應的頭文件和一些宏定義,然后我們定義了一些變量和鏈表作為一些標志位和一些數據存儲。 每個定義前面都有注釋來解釋相應的功能。 這里我就不重復了。
void init(){ TMOD |= 0x02; //設置定時器0工作模式2 TL0 = TH0 = 0; //初始化定時器0寄存器 EA = 1; ET0 = 1; TR0 = 1; IT0 = 1; EX0 = 1; TMOD |= 0x20; //設置定時器1工作模式2 TL1 = TH1 = 0xfd; //比特率9600 SM1 = 1; //設置串口工作模式1,10位異步收發 TR1 = 1; //啟動定時器1 }
然后我們定義一個初始化函數,用于定時器和中斷的初始化。 我們使用定時器0來估算紅外信號高低電平的時間,并使用定時器1通過并口發送數據。
void T0_ISR(void) interrupt 1 //定時器0中斷一次277.76us{ IRtime++;}
上一段是定時器0的程序,用于估算上面的時間。 定時器0的中斷時間為277.76us,我們可以通過它來估算紅外信號的持續時間。
void int0(void) interrupt 0{ static uchar i; //靜態變量用于存入33次數據計數 static bit startflag; //開始存儲脈寬標志位 if(startflag) { if((IRtime < 53) && (IRtime >= 32)) //判斷是否為引導碼 若為引導碼則從起始碼開始存 {i = 0;} IRdata[i] = IRtime; //以T0溢出的次數來計算脈寬把這個時間存放在數組中 IRtime = 0; //計數清零 i++; //計數脈寬存入次數自加 if(i == 30) { IRok = 1; //脈寬檢查完成 i = 0; //把脈寬計數清零準備下次存入 } } else { IRtime = 0; //定時器0計數清零 startflag = 1; //開始處理標志位置1 }}
上述程序是外部中斷處理程序。 當紅外接收頭接收到紅外信號時,會輸出相應的高低電平變化。 接收端波形圖中已經畫出了導頻碼和“1”、“0”的波形。 這樣,當接收端為高電平時,就會觸發外部中斷。 這是將要檢查的值。 根據這個值來判斷是否是9ms的啟動代碼。 如果是引導碼,則先清零,然后保存后續的脈沖時間,如果不是則清零,這樣紅外接收頭接收到的33個脈沖的長度就會保存在[]字段中。
void IRcordpro(){ uchar i; //用于計數處理4個字節 uchar j; //用于計數處理1個字節的8位數據 uchar k; //用于計數處理33次脈寬 k = 1; //從第一位開始處理 丟掉起始碼 for(i = 0;i < 4;i++) { for(j = 0;j <8;j++) { if(IRdata[k] > 5) //如果脈寬大于數據0標準的1125us就判定為數據1 { IRcord[i] |= 0x80; //置于最高位 } if(j < 7) //從最高位移位置低位 { IRcord[i] >>= 1; } k++; //處理下一次脈寬 } } IRpro_ok = 1; //解碼完成}
前面的函數是用來處理我們之前保存的33個脈沖長度,轉換成4個字節的數據存放在[]字段中。 具體操作是根據脈沖時間判斷是“1”還是“0”。 大家可以按照程序旁邊的注釋來了解函數的內容。
void main(){ uchar i; //計數串口發送字節數 init(); //初始化 while(1) { if(IRok) //判斷33次脈寬是否提取完成 { IRcordpro(); //根據脈寬解碼出4字節數據 IRok = 0; //清零脈寬檢查完成標志位等待下一次脈寬檢查 if(IRpro_ok) //判斷解碼是否完成 { for(i = 0;i < 4;i++) { SBUF = IRcord[i]; while(!TI); TI = 0; } IRpro_ok = 0; //清零解碼標志位 } } }}
最后我們在主函數中調用前面的函數,但是等待解碼完成后,我們將解碼后的4字節數據通過并口發送給筆記本。 最后我們來看看實際效果。 首先打開并口助手,將碼率設置為9600,接收模式設置為HEX模式,這樣當按下紅外遙控器的按鈕時,就會返回遙控器的通配符。
好了,本教程就到此結束,感謝您的觀看。
186信息網原創文章,轉載請注明本文來自:www.icocr.cn