紅外接收頭的型號有很多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_BUSY sbit 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(); } } }