|
萬能遙控器在使用前一般要進行設置,針對RM-2008這款萬能遙控,設置方法如下:
先按住“設置”鍵不放,再按下“電源”(“開/關”)鍵,工作指示燈亮起,然后釋放兩鍵,在此時進入代碼輸入狀態(tài),依次鍵入 0 0 0 指示燈熄滅,設置成功!
說明一下:0 0 0 編碼shi日立公司初期de紅外編碼方式,也就shi網上到處都通用de紅外編碼方式(如下圖),另外本程序只能對此編碼進行解碼

數(shù)據(jù)頭de時間:Th=9+4.5=13.5ms
數(shù)據(jù)“0”de時間:T0=0.565+0.56=1.125ms
數(shù)據(jù)“1”de時間:T1=1.685+0.56=2.245ms
本程序通過使用輸入捕獲功能(ICP)捕捉紅外信號de高電平脈寬,達到解碼de目de;如果捕獲到de脈寬shi4.5ms 則表示此信號為同步碼,如果捕獲到de脈寬shi1.685ms de話則表示 “1” 否則表示“0”
測試電路如下:

使用DNW 串口調試軟件時de效果

/////////////////////////////////只有一個文件main.c///////////////////////////////////
#include <avr/io.h> #include <avr/signal.h> #include <avr/interrupt.h> #include <avr/wdt.h> #include <util/delay.h> #include <stdio.h>
/*----------------------遙控操作值--------------------*/
// key code (hex) #define Key_1 0x01 #define Key_2 0x02 #define Key_3 0x03 #define Key_4 0x04 #define Key_5 0x05 #define Key_6 0x06 #define Key_7 0x07 #define Key_8 0x08 #define Key_9 0x09 #define Key_0 0x00 #define Menu 0x5c // 菜單 #define Menu_up 0x56 // 菜單上 #define Menu_down 0x57 // 菜單下 #define Menu_left 0x5f // 菜單左 #define Menu_right 0x5b // 菜單右 #define Menu_ok 0x16 // 菜單確認 #define Channel_up 0x1b // 頻道+ #define Channel_down 0x1f // 頻道- #define Sound_up 0x1e // 音量+ #define Sound_down 0x1a // 音量- #define Open_Close 0x12 // 開/關 #define Mute 0x10 // 靜音 #define Pic_in_pic 0x51 //畫中畫 #define Standard 0x58 // 制式 #define Return 0x52 // 返回 #define Times 0x0b // 倍數(shù) #define Screen 0x16 // 屏幕 #define Audio 0x1d // 伴音 #define NICAM 0x13 // 麗音 #define TV_Vedio 0x0f // 電視/視頻 #define Sleep 0x0e //睡眠
/*----------------------常用參數(shù)定義-------------------*/
#define P0 0 #define P1 1 #define P2 2 #define P3 3 #define P4 4 #define P5 5 #define P6 6 #define P7 7
#define FREQ 8 //定義單片機工作頻率為 8M #define uint unsigned int #define uchar unsigned char
#define Start_T1 TCCR1B|=_BV(CS11);TCNT1=0//復位預計分頻器并開啟定時器T1 #define Stop_T1 TCCR1B&=~_BV(CS11) //關閉定時器T1
/*-----------------IR信號指示燈操作函數(shù)---------*/
#define EN_IR_LED DDRB|=_BV(P1) #define CLR_IR_LED PORTB&=~_BV(P1) #define SET_IR_LED PORTB|=_BV(P1)
/*----------------------某些端口操作-------------------*/
volatile unsigned char i,j,k;
volatile unsigned long IRcode; //定義一個長度為4字節(jié)de無符號long類型變量來存儲代碼
volatile unsigned char *IRcodePointer ; //定義一個無符號de單字節(jié)指針變量, //用此地址變量來分別讀取IRCodede //4個字節(jié) 其中操作碼為 IRcodePointer[2] //用戶碼為 IRcodePointer[0]
volatile unsigned char IRReceiveEffective=0; //IR信號接收有效 當程序響應接收以后請馬上清零 這樣才會繼續(xù)接收下一IR碼
volatile unsigned char IRReceiveCurrentBit=0; //IR信號當前接收位 0時表示第0位即同步碼(4.5ms高電平)
volatile unsigned int Pulse_length=0; //捕獲de脈沖寬度
volatile unsigned char ICP_Parity=0; //捕獲中斷奇偶次計數(shù) 1時為偶次 并在此時判斷脈寬
volatile unsigned char Received_Key_Temp; //紅外接收操作鍵緩存
const unsigned char String[]={"You Have Press Key : "};
/*----------------------串口定義-------------------*/
unsigned char SetPrintfConvertMode=0; //使用printf作其他轉換,并非輸出到UART
void Uart_Init(void);
int System_putchar(char c, FILE *stream); int System_getchar(FILE *stream);
FILE mystd = FDEV_SETUP_STREAM(System_putchar, System_getchar,_FDEV_SETUP_RW);
/*----------------------常用函數(shù)定義------------------*/
void delay_nms(unsigned int ms) //N ms延時函數(shù) { for(i=0;i<ms;i++) _delay_loop_2(FREQ*250); }
/*----------------------系統(tǒng)初始化函數(shù)定義------------------*/
void IO_INIT(void) { PORTB|=_BV(P0); //設置ICP引腳內部上拉 經過試驗驗證,上拉會提高紅外接收靈敏度 }
ISR(TIMER1_COMPA_vect) { IRReceiveCurrentBit=0;//重置IR接收位為第0位,為下次接收做準備 TIMSK&=~_BV(OCIE1A); //關閉溢出中斷 TCCR1B|=_BV(ICES1); //設置輸入捕獲 上升沿有效 ICP_Parity=0;
Stop_T1; CLR_IR_LED; }
ISR(TIMER1_CAPT_vect) { if(!IRReceiveEffective) { if(ICP_Parity==0) { ICP_Parity++; TIMSK|=_BV(OCIE1A); TCCR1B&=~_BV(ICES1); //設置輸入捕獲 下降沿有效 Start_T1 ; } else {
Stop_T1;
ICP_Parity=0; TCCR1B|=_BV(ICES1);//設置輸入捕獲 上升沿有效 Pulse_length=ICR1; if(IRReceiveCurrentBit==0) { if(Pulse_length>=3500&&Pulse_length<5500)// 如果shi引導碼 (4.5ms) 進入下一個bitde讀取 IRReceiveCurrentBit++; } else if(IRReceiveCurrentBit<33) //接收32位數(shù)據(jù) { IRcode>>=1; if(Pulse_length<1900&&Pulse_length>1400) //判斷shi否為 1 ( 1.685 ms) IRcode|=0x80000000; IRReceiveCurrentBit++; if(IRReceiveCurrentBit==33) { IRReceiveCurrentBit=0; //重置IR接收位為第0位,為下次接收做準備 if(IRcodePointer[0]==(unsigned char)(~IRcodePointer[1])&&IRcodePointer[2]==(unsigned char)(~IRcodePointer[3])) { SET_IR_LED; //開啟IR信號指示燈 IRReceiveEffective=1; //數(shù)據(jù)有效 } delay_nms(5); //因為32位數(shù)據(jù)后面還有一個信號上跳變,所以要適當延時,延時0.65ms以上即可 } } } } }
/////////////////////////////////////////////////////////////////
int main(void) {
wdt_disable();
IO_INIT();
Uart_Init();
TCCR1B=_BV(WGM12)|_BV(CS11);//采用8分頻 這樣de話 TCNT1de計數(shù)時基為 1us OCR1A=8000; //TCNT1 計數(shù)上限 設置IR接收超時 這里設置 8ms
TIMSK|=_BV(TICIE1);//開啟輸入捕獲中斷
TCCR1B|=_BV(ICES1);//輸入捕獲 上升沿有效
EN_IR_LED; //IR信號指示燈允許 CLR_IR_LED; //關閉IR信號指示燈
IRcodePointer=&IRcode;
sei();
while(1) { if(IRReceiveEffective) { Received_Key_Temp=IRcodePointer[2];//把接收到de操作鍵放入緩存 IRReceiveEffective=0; //允許下一次接收 switch(Received_Key_Temp) { case Key_1 : printf("\n%sKey_1",String);break; case Key_2 : printf("\n%sKey_2",String);break; case Key_3 : printf("\n%sKey_3",String);break; case Key_4 : printf("\n%sKey_4",String);break; case Key_5 : printf("\n%sKey_5",String);break; case Key_6 : printf("\n%sKey_6",String);break; case Key_7 : printf("\n%sKey_7",String);break; case Key_8 : printf("\n%sKey_8",String);break; case Key_9 : printf("\n%sKey_9",String);break; case Key_0 : printf("\n%sKey_0",String);break; case Menu : printf("\n%sMenu",String);break; case Menu_up : printf("\n%sMenu_up",String);break; case Menu_down : printf("\n%sMenu_down",String);break; case Menu_left : printf("\n%sMenu_left",String);break; case Menu_right : printf("\n%sMenu_right",String);break; case Menu_ok : printf("\n%sMenu_ok",String);break; case Channel_up : printf("\n%sChannel+",String);break; case Channel_down : printf("\n%sChannel-",String);break; case Sound_up : printf("\n%sSound+",String);break; case Sound_down : printf("\n%sSound-",String);break; case Open_Close : printf("\n%sOpen_Close",String);break; case Mute : printf("\n%sMute",String);break; case Standard : printf("\n%sStandard",String);break; case Return : printf("\n%sReturn",String);break; case Times : printf("\n%sTimes",String);break; //case Screen : printf("\n%sScreen",String);break;//Screen 與 menu_ok 值相同 case Audio : printf("\n%sAudio",String);break; case NICAM : printf("\n%sNICAM" ,String);break; case TV_Vedio : printf("\n%sTV_Vedio",String);break; case Sleep : printf("\n%sSleep",String);break; case Pic_in_pic : printf("\n%sPic_in_pic",String);break; default:printf("\n%sOther Key 0x%x",String,Received_Key_Temp);break; } CLR_IR_LED; //處理完數(shù)據(jù)以后關閉IR信號指示燈 } } }
/*----------------------串口函數(shù)實體------------------*/
void Uart_Init(void) { UCSRB=_BV(RXEN)|_BV(TXEN); UBRRL=25; //8M 19200 stdout=&mystd; stdin=&mystd; }
int System_putchar(char c, FILE *stream) { if(SetPrintfConvertMode==1) { } else { if (c == \n) System_putchar(\r, stream); loop_until_bit_is_set(UCSRA, UDRE); UDR = c; } return 0; }
int System_getchar( FILE *stream) { loop_until_bit_is_set(UCSRA,RXC); return UDR; }
|