可定義任意I/O作接收腳,支持長/短按,自適應(yīng)主頻6MHz~40
本文引用地址:http://m.butianyuan.cn/article/201611/323430.htm//*********************【 NEC解碼頭文件 】*******************//// 簡介:本程序適用于NCE解碼:(9ms+4.5ms)引導(dǎo)碼+32位編碼。// 兼容STC所有型號(包括 1T 和 12T 系列),可以定義任意I/O作紅外接收腳,// 自適應(yīng)解碼主頻:6MHz ~ 40MHz。// // 使用條件:占用系統(tǒng)定時器0,開啟定時器0中斷(如使用其它定時器請自改IR_Init();初始化函數(shù))// // 使用說明:填相關(guān)宏定義:USER_H、USER_L、Check_EN、CPU_Fosc、IR,// 上電初始化函數(shù)IR_Init(),// 在定時器0中斷中調(diào)用IR_NEC()解碼函數(shù),// 解碼有效時,IR_BT=2即短按,IR_BT=3即長按,由用戶清0,// 解碼存放:用戶碼高8位NEC[0],用戶碼低8位NEC[1],操作碼NEC[2],操作碼反碼NEC[3]。////【供用戶調(diào)用的函數(shù)】// IR_Init(); //接收初始化,開啟定時器0中斷400us// IR_NEC(); //紅外線解碼(解NEC編碼)// //***************************************************************/ #ifndef __IR_NEC_H__#define __IR_NEC_H__//【用戶必填項:USER_H、USER_L、Check_EN、CPU_Fosc、IR】#define USER_H 0x80 //用戶碼高8位#define USER_L 0x7F //用戶碼低8位#define Check_EN 0 //是否要校驗16位用戶碼:不校驗填0,校驗則填1 #define CPU_Fosc 12000000L //輸入主頻,自適應(yīng)解碼(單位:Hz,范圍:6MHz ~ 40MHz)#define CA_S 8 //長按時間設(shè)置,單位:108mS(即 108mS整數(shù)倍,10倍以上為宜)sbit IR = P3^6; //紅外線接口(任意引腳) #define Step 400 //紅外采樣步長:400us#define TH_H ((65536-Step*(CPU_Fosc/300)/40000)/256) //定時器高8位基準賦值#define TH_L ((65536-Step*(CPU_Fosc/300)/40000)%256) //定時器低8位基準賦值uint8 IR_BT; //解碼效果返回:0無效,1有效,2短按,3長按uint8 NEC[4]; //解碼存放:16位用戶碼、操作碼正反碼uint8 cntCA; //長按計數(shù)uint16 cntStep; //步數(shù)計bit IRa,IRb; //接收腳電位狀態(tài)保存bit IRsync; //同步標志uint8 BitN; //位碼裝載數(shù)/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈函數(shù):紅外線解碼初始化┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/void IR_Init(){TMOD &= 0xF0; //清定時器0TMOD |= 0x01; //定時器0:16位定時器TL0 = TH_L; //每步時間TH0 = TH_H;ET0 = 1;EA = 1;TR0 = 1;}/*┈┈┈┈┈┈┈┈┈┈ 基準 ┈┈┈┈┈┈┈┈┈┈┈*/#define Boot_Limit ((9000+4500 +1000)/Step) //引導(dǎo)碼周期上限 #define Boot_Lower ((9000+4500 -1000)/Step) //引導(dǎo)碼周期下限 #define Bit1_Limit ((2250 +800)/Step) //“1”周期上限#define Bit0_Limit ((1125 +400)/Step) //“0”周期上限/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈函數(shù):紅外線NEC周期采樣解碼法(定時中斷,下降沿查詢周期時間)全局變量:IR_BT = 0無效1有效,待繼續(xù)判斷長、短按(如不需要判斷長、短按,則直接使用)2短按3長按┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/void IR_NEC(){ TL0 = TH_L; //重賦值TH0 = TH_H; cntStep++; //步數(shù)累加if(IR_BT==1)if(cntStep>300)IR_BT=2; //解碼有效后,如果無長按,120ms(400us×300)后默認短按IRb = IRa; //保存上次電位狀態(tài)IRa = IR; //保存當(dāng)前電位狀態(tài)if(IRb && !IRa) //是否下降沿(上次高,當(dāng)前低){if(cntStep > Boot_Limit) //超過同步時間?{ if(IR_BT==1)if(++cntCA>CA_S)IR_BT=3; //解碼有效后,繼續(xù)按住遙控>CA_S即長按IRsync=0; //同步位清0}else if(cntStep > Boot_Lower){ IRsync=1; BitN=32; } //同步位置1,裝載位碼數(shù)32 else if(IRsync) //如果已同步{if(cntStep > Bit1_Limit)IRsync=0; else{ NEC[3] >>= 1; if(cntStep > Bit0_Limit)NEC[3] |= 0x80; //“0”與“1”if(--BitN == 0) {IRsync = 0; //同步位清0#if (Check_EN == 1) if((NEC[0]==USER_H)&&(NEC[1]==USER_L)&&(NEC[2]==~NEC[3])) //校驗16位用戶碼、操作碼正反碼{ IR_BT=1; cntCA=0; } //解碼有效,接下來判斷:短按?長按?#elseif(NEC[2]==~NEC[3]){ IR_BT=1; cntCA=0; } //只校驗操作碼正反碼#endif }else if((BitN & 0x07)== 0) //NEC[3]每裝滿8位,移動保存一次(即 BitN%8 == 0){ NEC[0]=NEC[1]; NEC[1]=NEC[2]; NEC[2]=NEC[3]; }}}cntStep = 0; //步數(shù)計清0}} //取消相關(guān)宏定義#undef CPU_Fosc #endif主程序#include "INCSTC89C52RC.H"#include "INCMY_SET.H"#include "INCIR_NEC.H" //調(diào)用NEC解碼頭文件sfr SE = 0x80; //數(shù)碼管段選 P0:0x80 P1:0x90 sbit WX1 = P2^0; //數(shù)碼管位顯sbit WX2 = P2^1;sbit WX3 = P2^2;sbit WX4 = P2^3;sbit WX5 = P2^4;sbit WX6 = P2^5;sbit WX7 = P2^6;sbit WX8 = P2^7;uint8c tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0X88,0X83,0XC6,0XA1,0X86,0X8E,0xFF};uint8 Xn,X1,X2,X3,X4,X5,X6;void KZ0(); //短按處理void KZ1(); //長按處理/***************** 主函數(shù) ********************/void main(void){IR_Init(); //紅外線解碼初始化while(1){ //遙控檢測if((IR_BT==2)||(IR_BT==3)) {if(IR_BT==2)KZ0(); //短按處理 else KZ1(); //長按處理 IR_BT =0; //清有效標志X1 = NEC[0]/16; //更新顯示X2 = NEC[0]%16;X3 = NEC[1]/16;X4 = NEC[1]%16;X5 = NEC[2]/16;X6 = NEC[2]%16; }}}
評論