//*********************【 NEC解码头文件 】******************* // // 简介:本程序适用于NCE解码:(9ms+4.5ms)引导码+32位编码。 // 兼容STC所有型号(包括 1T 和 12T 系列),可以定义任意I/O作红外接收脚, // 自适应解码主频:6MHz ~ 40MHz。 // // 使用条件:占用系统定时器0,开启定时器0中断(如使用其它定时器请自改IR_Init();初始化函数) // // 使用说明:填相关宏定义:USER_H、USER_L、Check_EN、CPU_Fosc、IR, // 上电初始化函数IR_Init(), // 在定时器0中断中调用IR_NEC()解码函数, // 解码有效时,IR_BT=2即短按,IR_BT=3即长按,由用户清0, // 解码存放:用户码高8位NEC[0],用户码低8位NEC[1],操作码NEC[2],操作码反码NEC[3]。 // //【供用户调用的函数】 // 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 //输入主频,自适应解码(单位:Hz,范围:6MHz ~ 40MHz) #define CA_S 8 //长按时间设置,单位:108mS(即 108mS整数倍,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; //长按计数 uint16 cntStep; //步数计 bit IRa,IRb; //接收脚电位状态保存 bit IRsync; //同步标志 uint8 BitN; //位码装载数 /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ 函数:红外线解码初始化 ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/ void IR_Init() { TMOD &= 0xF0; //清定时器0 TMOD |= 0x01; //定时器0:16位定时器 TL0 = TH_L; //每步时间 TH0 = TH_H; ET0 = 1; EA = 1; TR0 = 1; } /*┈┈┈┈┈┈┈┈┈┈ 基准 ┈┈┈┈┈┈┈┈┈┈┈*/ #define Boot_Limit ((9000+4500 +1000)/Step) //引导码周期上限 #define Boot_Lower ((9000+4500 -1000)/Step) //引导码周期下限 #define Bit1_Limit ((2250 +800)/Step) //“1”周期上限 #define Bit0_Limit ((1125 +400)/Step) //“0”周期上限 /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ 函数:红外线NEC周期采样解码法(定时中断,下降沿查询周期时间) 全局变量:IR_BT = 0无效 1有效,待继续判断长、短按(如不需要判断长、短按,则直接使用) 2短按 3长按 ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/ void IR_NEC() { TL0 = TH_L; //重赋值 TH0 = TH_H; cntStep++; //步数累加 if(IR_BT==1)if(cntStep>300)IR_BT=2; //解码有效后,如果无长按,120ms(400us×300)后默认短按 IRb = IRa; //保存上次电位状态 IRa = IR; //保存当前电位状态 if(IRb && !IRa) //是否下降沿(上次高,当前低) { if(cntStep > Boot_Limit) //超过同步时间? { if(IR_BT==1)if(++cntCA>CA_S)IR_BT=3; //解码有效后,继续按住遥控>CA_S即长按 IRsync=0; //同步位清0 } else if(cntStep > Boot_Lower){ IRsync=1; BitN=32; } //同步位置1,装载位码数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; } //解码有效,接下来判断:短按?长按? #else if(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; //步数计清0 } } //取消相关宏定义 #undef CPU_Fosc #endif 主程序 #include "INCSTC89C52RC.H" #include "INCMY_SET.H" #include "INCIR_NEC.H" //调用NEC解码头文件 sfr SE = 0x80; //数码管段选 P0:0x80 P1:0x90 sbit WX1 = P2^0; //数码管位显 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(); //长按处理 /***************** 主函数 ********************/ 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; } } }[page] /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ 函数:遥控短按处理 ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/ void KZ0() { switch(NEC[2]) { case 0x12: P10 = !P10; break; case 0x05: break; case 0x1E: break; case 0x55: break; case 0x01: break; case 0x1B: break; case 0x03: break; case 0x6B: break; case 0x07: break; case 0x08: break; case 0x09: break; case 0x68: break; case 0x22: break; case 0xE6: break; case 0x33: break; case 0xE2: break; default:break; } } /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ 函数:遥控长按处理 ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/ void KZ1() { switch(NEC[2]) { case 0x12: P14 = !P14; break; case 0x05: break; case 0x1E: break; case 0x55: break; case 0x01: break; case 0x1B: break; case 0x03: break; case 0x6B: break; case 0x07: break; case 0x08: break; case 0x09: break; case 0x68: break; case 0x22: break; case 0xE6: break; case 0x33: break; case 0xE2: break; default:break; } } /*********************数码管扫描*************************/ void XS(void) { if(++Xn > 7)Xn=0; switch(Xn) { case 0: WX8=1; NOP; //屏蔽上个位显 SE=tab[X1]; //送段码 WX1=0; //开位显 break; case 1: WX1=1; NOP; SE=tab[X2]; WX2=0; break; case 2: WX2=1; NOP; SE=tab[X3]; WX3=0; break; case 3: WX3=1; NOP; SE=tab[X4]; WX4=0; break; case 4: WX4=1; NOP; SE=tab[16]; WX5=0; break; case 5: WX5=1; NOP; SE=tab[16]; WX6=0; break; case 6: WX6=1; NOP; SE=tab[X5]; WX7=0; break; case 7: WX7=1; NOP; SE=tab[X6]; WX8=0; break; default:break; } } /********************** 定时器0中断函数************************/ void time0(void) interrupt 1 { IR_NEC(); XS(); }
接收源程序+仿真
点击此处下载 http://www.51hei.com/f/hong1.rar
遥控器源程序
点击此处下载 http://www.51hei.com/f/hong2.rar
/*************************************************************** 作品:红外线遥控发射(NEC编码) 单片机:STC89C52RC 晶振:12M ***************************************************************/ // // 发射引脚(接PNP三极管b极) // PNP三极管e极接2Ω电阻,c极接红外发射管 #include#include "INCMY_SET.h" #include "INCLCD1602_6IO.h" sbit IR = P3^6; //发射引脚(接PNP三极管基极) #define USER_H P2 //用户码高8位 #define USER_L P0 //用户码低8位 uint8c tab[16] = { //操作码 0x12,0x05,0x1e,0x55, 0x01,0x1b,0x03,0x6b, 0x07,0x08,0x09,0x68, 0x22,0xE6,0x33,0xe2}; #define m9 (65536-9000) //9mS #define m4_5 (65536-4500) //4.5mS #define m1_6 (65536-1650) //1.65mS #define m_56 (65536-560) //0.56mS #define m40 (65536-40000) //40mS #define m56 (65536-56000) //56mS #define m2_25 (65536-2250) //2.25mS void SanZhuan(); uint8 KEY(void); void ZZ(uint8 x); //NEC编码发送程序 void Z0(uint8 temp); //单帧(8位数据)发送程序 void TT0(bit BT,uint16 x); //38KHz载波发射 + 延时程序 /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ 函数:主程序 ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/ void main(void) { TMOD = 0x01; //T0 16位工作方式 IR=1; //发射端口常态为高电平 L1602_Init(); L1602_clr(); L1602_xy(0,0); L1602_ZIFUC("UserCode :0x"); L1602_xy(0,1); L1602_ZIFUC("Opcode :0x"); while(1) { L1602_xy(12,0); L1602_JZ(USER_H,16,1); L1602_JZ(USER_L,16,1); SanZhuan(); } } /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ 函数:4×4矩阵键盘 【 线翻转法键值表 】 P1.0 P1.1 P1.2 P1.3 P1.4 P1.5 P1.6 P1.7 │ │ │ │ │ │ │ │ │ │ │ └──7e be de ee │ │ └─────7d bd dd ed │ └────────7b bb db eb └─────────── 77 b7 d7 e7 ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/ uint8 KEY(void) { uint8 Key = 0; P1 = 0xf0; //键盘初始:行值=0,列值=1 NOP; //缓冲,待IO端口电位稳定 Key = P1&0xf0; //得到行标志 P1 = 0x0f; //翻转键盘接口输出 NOP; Key |= (P1&0x0f); //列标志 + 行标志 return Key; //返回键值 } /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ 函数:散转程序 ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/ void SanZhuan() { uint8 v; v = KEY(); //键盘检测 switch(v) { case 0x7e:ZZ(tab[0]);break; case 0xbe:ZZ(tab[1]);break; case 0xde:ZZ(tab[2]);break; case 0xee:ZZ(tab[3]);break; case 0x7d:ZZ(tab[4]);break; case 0xbd:ZZ(tab[5]);break; case 0xdd:ZZ(tab[6]);break; case 0xed:ZZ(tab[7]);break; case 0x7b:ZZ(tab[8]);break; case 0xbb:ZZ(tab[9]);break; case 0xdb:ZZ(tab[10]);break; case 0xeb:ZZ(tab[11]);break; case 0x77:ZZ(tab[12]);break; case 0xb7:ZZ(tab[13]);break; case 0xd7:ZZ(tab[14]);break; case 0xe7:ZZ(tab[15]);break; default:break; } v=0; } /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ 函数:NEC编码发送程序 ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/ void ZZ(uint8 Value) { L1602_xy(12,1); L1602_JZ(Value,16,1); //更新显示 TT0(1,m9); //高电平9mS TT0(0,m4_5); //低电平4.5mS /*┈ 发送4帧数据┈*/ Z0(USER_H); //用户码高8位 Z0(USER_L); //用户码低8位 Z0(Value); //操作码 Z0(~Value); //操作码反码 /*┈┈ 结束码 ┈┈*/ TT0(1,m_56); TT0(0,m40); /*┈┈ 重复码 ┈┈*/ while(KEY() != 0xFF) { TT0(1,m9); TT0(0,m2_25); TT0(1,m_56); TT0(0,m40); TT0(0,m56); } } /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ 函数:单帧(8位数据)发送程序 入口:temp ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/ void Z0(uint8 temp) { uint8 v; for(v=0;v<8;v++) { TT0(1,m_56); //高电平0.65mS if(temp&0x01) TT0(0,m1_6); //发送最低位 else TT0(0,m_56); temp >>= 1; //右移一位 } } /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ 函数:38KHz载波发射 + 延时程序 入口:(是否发射载波,延时约 x (uS)) ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/ void TT0(bit BT,uint16 x) { TH0 = x>>8; //输入定时值 TL0 = x; TF0=0; //溢出标志位清0 TR0=1; //启动定时器0 if(BT == 0) while(!TF0); //BT=0时,不发射38KHz载波只延时; else while(1) //BT=1时,发射38KHz脉冲+延时;38KHz载波(低电平)占空比5:26 { IR = 0; if(TF0)break;if(TF0)break; IR = 1; if(TF0)break;if(TF0)break; if(TF0)break;if(TF0)break; if(TF0)break;if(TF0)break; if(TF0)break;if(TF0)break; if(TF0)break;if(TF0)break; } TR0=0; //关闭定时器0 IR =1; //载波停止后,发射端口常态为高 }
上一篇:Atmel和STC的51单片机通用ISP下载线制作
下一篇:一个24C读写函数,支持检测器件型号
推荐阅读最新更新时间:2024-03-16 14:25