![]() |
yzwzfyz 發表于 2017-4-17 23:14 謝謝了 這么詳細的回答 辛苦了 我慢慢看懂它 |
wosiyabo 發表于 2017-4-17 23:56 你這個用到兩個定時器?你看看我這個可以嗎? void intersvr1(void) interrupt 2 //紅外工作函數 { TR0=1; Tc=TH0*256+TL0;//提取中斷時間間隔時長 TH0=0; TL0=0; //定時中斷重新置零 if((Tc>Imin)&&(Tc<Imax)) { m=0; f=1; return; } //找到啟始碼 if(f==1) { if(Tc>Inum1&&Tc<Inum3) { Im[m/8]=Im[m/8]>>1|0x80; m++; } if(Tc>Inum2&&Tc<Inum1) { Im[m/8]=Im[m/8]>>1; m++; //取碼 } if(m==32) { m=0; f=0; if(Im[2]==~Im[3]) { IrOK=1; TR0=0; } else { IrOK=0; //取碼完成后判斷讀碼是否正確 } } //準備讀下一碼 } } |
例如:00FF45CB |
紅外編碼格式 廠商碼+廠商補碼+命令碼+命令補碼。 |
網上都有程序例子 先去試著看一下 然后自己在編寫 |
//STC89C52RC_雙倍速_外部晶振24MHz #include "reg51.h" #include "intrins.h" typedef unsigned char BYTE; typedef unsigned int WORD; #define uchar unsigned char #define uint unsigned int unsigned char ir_dat_buf[4] = {0}; //紅外遙控接收碼存放位置 unsigned char mode; //紅外線接收模式緩存 sbit P32 = P3^2; //IR void Delay1120us(void) { TL1 = 0xC4; TH1 = 0xEE; TR1 = 1; while(!TF1); TR1 = 0; TF1 = 0; } void Delay840us(void) { TL1 = 0x38; TH1 = 0xF3; TR1 = 1; while(!TF1); TR1 = 0; TF1 = 0; } unsigned char ir_read(void) // 數據 0: 0.56ms低電平,0.56ms高電平 { // 數據 1: 0.56ms低電平,1.58ms高電平 unsigned char i,ir_temp = 0; for(i = 0; i < 8; i++) { while(!P32); //等待0.56ms低電平結束 Delay840us(); //從高電平開始延時0.84ms if(P32 == 1) { ir_temp = (ir_temp << 1) + 1; //讀到數據1 Delay1120us(); //延時等待1.68ms高電平結束 } else { ir_temp = ir_temp << 1; //讀到數據0 } } return ir_temp; } void main() { TMOD = 0x11; //set timer0 as mode1 (16-bit) TL0 = 0; //定時4ms TH0 = 0; TR0 = 1; //timer0 start running TF0 = 1; IT0 = 1; //set INT0 int type (1:Falling 0:Low level) ET0 = 1; //enable timer0 interrupt EX0 = 1; //enable INT0 interrupt EA = 1; //open global interrupt switch mode = 0;//紅外線接收清除 while (1) { switch(mode) { case 1: {mode=0;}break; case 2: {mode=0;}break; case 3: {mode=0;}break; default: break; } } } void exint0() interrupt 0 //按鍵一次: 依次發送 引導碼 + 地址 + 地址取反 + 數據 + 數據取反 { static unsigned i; EX0 = 0; //關閉外部中斷,仍可以執行以下程序 for(i = 0; i < 10; i++) // 引導碼由9ms低電平及4.5ms高電平組成, 接著是低8位地址碼, 高8位地址碼 { // 連發碼由9ms低電平及2.25ms高電平組成, 跟著是0.56ms低電平, 然后都是高電平 Delay840us(); if(P32) //檢測引導碼9ms是否有高電平,有則退出 { EX0 = 1; return; } } while(!P32); //等待高電平的到來 注:盡量采用延時來檢測,不然可能會進入死循環 Delay840us(); Delay840us(); // 檢測連按; 延時2.52ms,檢測是否有低電平,有表示按鍵連按,且退出 Delay840us(); if(!P32) { EX0 = 1; return; } while(P32); //等待4.5ms高電平結束,開始接收數據 _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); ir_dat_buf[0] = ir_read(); ir_dat_buf[1] = ir_read(); ir_dat_buf[2] = ir_read(); ir_dat_buf[3] = ir_read(); EX0 = 1; //開啟外部中斷,等下次信號 } void tm0_isr() interrupt 1 using 1 { ET0 = 0;//禁止外部中斷,防止在接收到數據后處理過程中,再按遙控造成沖突 TL0 = 0x60; //定時4ms TH0 = 0xC1; if(((ir_dat_buf[0] == 0x00) && (ir_dat_buf[1] == 0xff))&&((ir_dat_buf[2])== ~(ir_dat_buf[3])))//用戶碼0x00,0xFF { switch(ir_dat_buf[2]) { case 0x45: {mode=1;}break; case 0x46: {mode=2;}break; case 0x47: {mode=3;}break; default: break; } ir_dat_buf[0]=0;//清除紅外線接收緩存 ir_dat_buf[1]=0;//清除紅外線接收緩存 ir_dat_buf[2]=0;//清除紅外線接收緩存 ir_dat_buf[3]=0;//清除紅外線接收緩存 } ET0 = 1; //充許外部中斷,處理完數據后再打開外部中斷 } |
得到鍵碼后的人機對話程序的復雜程度,與程序的目的相關。一般比較復雜,不在此細述。 |
很實用,很給力 |
本帖最后由 yzwzfyz 于 2017-4-17 23:28 編輯 解出:引導符、0、1后,依協議組裝即可得到鍵碼。 |
本帖最后由 yzwzfyz 于 2017-4-17 23:26 編輯 1、紅色用接收模塊HS0038B,從INT0輸入,下沿產生中斷。用T3計數紅外脈沖寬度(是下沿到下沿)。 紅外遙控器采用UPD6122控制芯片NEC編碼格式,只取下沿。但紅外模塊接收會反轉成上沿。 2、INT0中斷后,記錄上次紅外寬度(下沿到下沿),再復位T3重新計數,準備計數下個脈沖寬度。 3、紅外脈沖寬度數據:(有容錯范圍,即上下限) 3.1、引導碼=5900H-78FFH 容錯范圍84%-115% *(9ms+4.5ms),做一個標記B_INFRLEAD=1,表示已有引導符; 3.2、0=0800H-0AFFH 容錯范圍87%-119% *(1.125ms+0.56ms); 3.3、1=0F00H-13FFH 容錯范圍85%-114% *2.25ms; 3.4、其它:放棄作廢碼處理,清B_INFRLEAD=0,表示尚無引導符; 3.5、計數T3溢出時,清0停止計數。(紅外輸入已結束,則T3停止不再計數) 注:用的是24MHz的晶振。 |
前幾天也買了這個控制器。花了幾天,寫了人機對話程序。 現將紅外解碼部分的方案,告訴你。 |
小唐唐 發表于 2017-4-17 13:30 不太懂啊 ![]() |
紅外遙控的畢設,同求啊 |
紅外遙控編碼 主要是時序很重要 網上都有程序例子 先去試著看一下 然后自己在編寫 |