紅外接收頭的型號有很多HS0038 VS838等 功能大致相同,只是引腳封裝不同。
紅外接收有幾種統一的編碼方式,採樣哪種編碼方式取決於遙控器使用的晶片,接收頭收到的都是一樣的。
電視遙控器使用的是專用整合發射晶片來實現遙控碼的發射,如東芝TC9012,飛利浦AA3010T等,通常彩電遙控訊號的發射,就是將某個按鍵所對應的控制指令和系統碼(由0和1組成的序列),調製在38KHz的載波上,然後經放大、驅動紅外發射管將訊號發射出去。不同公司的遙控晶片,採樣的遙控碼格式也不一樣,較普遍的有兩種,一種NEC標準,一種是PHILIPS標準。
NEC標準:遙控載波的頻率為38KHz(占空比1:3)當某個鍵按下時,系統首先發射一個完整的全碼,如果按鍵超過108ms仍未鬆開,接下來發射的代碼(連發代碼)將由起始碼(9ms)和結束碼(2.5ms)組成。
一個完整的全碼 = 引導碼 +使用者碼 +使用者碼 + 資料碼 + 資料碼 + 資料反碼。
其中,引導碼高電平9ms,低電平4.5ms;系統碼8位,資料碼8位,共32位;其中前16位為使用者識別碼,能區別不同的紅外遙控裝置,以防止不同的機種遙控碼互相干擾。後16位為8位的作業碼和8位的操作反碼,用於核對資料是否接收準確。收端根據資料碼做出應該執行上面動作的判斷。
連發代碼是在持續按鍵時發送的碼。它告知接收端。某鍵是在被連續的按著。
NEC標準下的發射碼錶示
發射資料0時用”0.56ms高電平 + 0.565ms低電平 = 1.125ms”表示;
資料1用”高電平0.56ms + 1.69ms = 2.25ms”表示。
遙控器發射訊號:
需要注意的是:當一體化接收頭收到38kHz紅外訊號時,輸出端輸出低電平,否則為高電平。所以一體化接收頭輸出的波形和發射波形是反向的
PHILIPS標準:
載波頻率38KHz:沒有筒,點按鍵時,控制碼1和0之間切換,若持續按鍵,則控制碼不變。
一個全碼 = 起始碼’11’ +控制碼 + 使用者碼 + 使用者碼
資料0用“低電平1.778ms + 高電平1.778ms”表示;
資料1用“高電平1.778ms + 低電平1.778ms”表示。
連續碼重複延時114ms。
所謂的解碼就是一個區分脈衝寬度的過程。紅矮訊號的0和1是通過脈衝期間的長短來區分的,
我的遙控器使用的是NEC標準的WD6122晶片,遙控器編碼如下:
以下是我用1602顯示紅外接收頭接收到編碼的程式:
①這個是對1602操作的函數
------------------------------------------------*/#include "1602.h"#include "delay.h"#define CHECK_BUSYsbit RS = P2^4; //定義連接埠 sbit RW = P2^5;sbit EN = P2^6;#define RS_CLR RS=0 #define RS_SET RS=1#define RW_CLR RW=0 #define RW_SET RW=1 #define EN_CLR EN=0#define EN_SET EN=1#define DataPort P0/*------------------------------------------------ 判忙函數------------------------------------------------*/ bit LCD_Check_Busy(void) { #ifdef CHECK_BUSY DataPort= 0xFF; RS_CLR; RW_SET; EN_CLR; _nop_(); EN_SET; return (bit)(DataPort & 0x80);#else return 0;#endif }/*------------------------------------------------ 寫入命令函數------------------------------------------------*/ void LCD_Write_Com(unsigned char com) { // while(LCD_Check_Busy()); //忙則等待 DelayMs(5); RS_CLR; RW_CLR; EN_SET; DataPort= com; _nop_(); EN_CLR; }/*------------------------------------------------ 寫入資料函數------------------------------------------------*/ void LCD_Write_Data(unsigned char Data) { //while(LCD_Check_Busy()); //忙則等待 DelayMs(5); RS_SET; RW_CLR; EN_SET; DataPort= Data; _nop_(); EN_CLR; }/*------------------------------------------------ 清屏函數------------------------------------------------*/ void LCD_Clear(void) { LCD_Write_Com(0x01); DelayMs(5); }/*------------------------------------------------ 寫入字串函數------------------------------------------------*/ void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) { if (y == 0) { LCD_Write_Com(0x80 + x); //表示第一行 } else { LCD_Write_Com(0xC0 + x); //表示第二行 } while (*s) { LCD_Write_Data( *s); s ++; } }/*------------------------------------------------ 寫入字元函數------------------------------------------------*//* void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) { if (y == 0) { LCD_Write_Com(0x80 + x); } else { LCD_Write_Com(0xC0 + x); } LCD_Write_Data( Data); }*//*------------------------------------------------ 初始化函數------------------------------------------------*/ void LCD_Init(void) { LCD_Write_Com(0x38); /*顯示模式設定*/ DelayMs(5); LCD_Write_Com(0x38); DelayMs(5); LCD_Write_Com(0x38); DelayMs(5); LCD_Write_Com(0x38); LCD_Write_Com(0x08); /*顯示關閉*/ LCD_Write_Com(0x01); /*顯示清屏*/ LCD_Write_Com(0x06); /*顯示光線標移動設定*/ DelayMs(5); LCD_Write_Com(0x0C); /*顯示開及游標設定*/ }
②延時函數
#include "delay.h"/*------------------------------------------------ uS延時函數,含有輸入參數 unsigned char t,無傳回值 unsigned char 是定義無符號字元變數,其值的範圍是 0~255 這裡使用晶振12M,精確延時請使用彙編,大致延時 長度如下 T=tx2+5 uS ------------------------------------------------*/void DelayUs2x(unsigned char t){ while(--t);}/*------------------------------------------------ mS延時函數,含有輸入參數 unsigned char t,無傳回值 unsigned char 是定義無符號字元變數,其值的範圍是 0~255 這裡使用晶振12M,精確延時請使用彙編------------------------------------------------*/void DelayMs(unsigned char t){ while(t--) { //大致延時1mS DelayUs2x(245); DelayUs2x(245); }}
③以下是主函數
#include<reg52.h> //包含標頭檔,一般情況不需要改動,標頭檔包含特殊功能寄存器的定義#include"1602.h"#include"delay.h"sbit IR=P3^2; //紅外介面標誌char code Tab[16]="0123456789ABCDEF";/*------------------------------------------------ 全域變數聲明------------------------------------------------*/unsigned char irtime;//紅外用全域變數bit irpro_ok,irok;unsigned char IRcord[4];unsigned char irdata[33];unsigned char TempData[16];/*------------------------------------------------ 函式宣告------------------------------------------------*/void Ir_work(void);void Ircordpro(void);/*------------------------------------------------ 定時器0中斷處理------------------------------------------------*/void tim0_isr (void) interrupt 1 using 1{ irtime++; //用於計數2個下降沿之間的時間}/*------------------------------------------------ 外部中斷0中斷處理------------------------------------------------*/void EX0_ISR (void) interrupt 0 //外部中斷0服務函數{ static unsigned char i; //接收紅外訊號處理 static bit startflag; //是否開始處理標誌位if(startflag) { if(irtime<63&&irtime>=33)//引導碼 TC9012的頭碼,9ms+4.5ms i=0; irdata[i]=irtime;//儲存每個電平的期間,用於以後判斷是0還是1 irtime=0; i++; if(i==33) { irok=1; i=0; } } else { irtime=0; startflag=1; }}/*------------------------------------------------ 定時器0初始化------------------------------------------------*/void TIM0init(void)//定時器0初始化{ TMOD=0x02;//定時器0工作方式2,TH0是重裝值,TL0是初值 TH0=0x00; //重載值 TL0=0x00; //初始化值 ET0=1; //開中斷 TR0=1; }/*------------------------------------------------ 外部中斷0初始化------------------------------------------------*/void EX0init(void){ IT0 = 1; //指定外部中斷0下降沿觸發,INT0 (P3.2) EX0 = 1; //使能外部中斷 EA = 1; //開總中斷}/*------------------------------------------------ 索引值處理------------------------------------------------*/void Ir_work(void){ TempData[0] = Tab[IRcord[0]/16]; //處理客戶碼 TempData[1] = Tab[IRcord[0]%16]; TempData[2] = '-'; TempData[3] = Tab[IRcord[1]/16]; //處理客戶碼 TempData[4] = Tab[IRcord[1]%16]; TempData[5] = '-'; TempData[6] = Tab[IRcord[2]/16]; //處理資料碼 TempData[7] = Tab[IRcord[2]%16]; TempData[8] = '-'; TempData[9] = Tab[IRcord[3]/16]; //處理資料反碼 TempData[10] = Tab[IRcord[3]%16]; LCD_Write_String(5,1,TempData); irpro_ok=0;//處理完成標誌 }/*------------------------------------------------ 紅外碼值處理------------------------------------------------*/void Ircordpro(void)//紅外碼值處理函數{ unsigned char i, j, k; unsigned char cord,value; k=1; for(i=0;i<4;i++) //處理4個位元組 { for(j=1;j<=8;j++) //處理1個位元組8位 { cord=irdata[k]; if(cord>7)//大於某值為1,這個和晶振有絕對關係,這裡使用12M計算,此值可以有一定誤差 value|=0x80; if(j<8) { value>>=1; } k++; } IRcord[i]=value; value=0; } irpro_ok=1;//處理完畢標誌位置1}/*------------------------------------------------ 主函數------------------------------------------------*/void main(void){ EX0init(); //初始化外部中斷 TIM0init(); //初始化定時器 LCD_Init(); //初始化液晶 DelayMs(20); //延時有助於穩定 LCD_Clear(); //清屏 LCD_Write_String(0,0,"www.doflye.net"); LCD_Write_String(0,1,"Code:"); while(1)//主迴圈 { if(irok) //如果接收好了進行紅外處理 { Ircordpro(); irok=0; } if(irpro_ok) //如果處理好後進行工作處理,如按對應的按鍵後顯示對應的數字等 { Ir_work(); } }}