收藏0 举报
#include "N76E003.h" #include "SFR_Macro.h" #include "Function_define.h" #include "Common.h" #include "Delay.h" #define uchar unsigned char #define uint unsigned int sbit IR = P1^7; //定义红外脉冲数据接口 外部中断1输入口 sbit SCLK = P3^0; //初始时钟 sbit RST = P1^6; //CE端 sbit DATA = P0^7; //数据读写端 uchar IRtime; //检测红外高电平持续时间(脉宽) uchar IRcord[4]; //此数组用于储存分离出来的4个字节的数据(用户码2个字节+键值码2个字节) uchar IRdata[33]; //此数组用于储存红外的33位数据(第一位为引导码用户码16+键值码16) bit IRpro_ok, IRok; //第一个用于红外接收4个字节完毕。IRok用为检测脉宽完毕 void Init_T1() { TIMER1_MODE2_ENABLE;//定时器0和定时器1工作方式2,8位自动重装 TH1 = 0X00;//高8位装入0那么定时器溢出一次的时间是256个机器周期 TL0 = 0X00; EA = 1; //总中断 ET1 = 1; //定时器1中断 TR1 = 1; //启动定时器1 IT1 = 1; //设置外部中断1为跳沿触发方式,来一个下降沿触发一次 EX1 = 1; //启动外部中断1 } void Time1() interrupt 3 //定义定时器1 { IRtime++; //检测脉宽,1次为192uS } void EXT1_T1() interrupt 2 //定义外部中断1 { static uchar i; static bit startflag; if(startflag) { if((IRtime < 78) &&(IRtime >= 63)) /*判断是否是引导码,低电平电平9000us+高4500us 这个自己可以算我以11.0592来算了NEC协议的引导码低8000-10000+高4000-5000 如果已经接收了引导码那么i不会被置0就会开始依次存入脉宽*/ i = 0;//如果是引导码那么执行i=0把他存到IRdata的第一个位 IRdata[i] = IRtime; //以T0的溢出次数来计算脉宽,把这个时间存到数组里面到后面判断 IRtime = 0; //计数清零,下一个下降沿的时候在存入脉宽 i++; //计数脉宽存入的次数 if(i == 33) //如果存入34次 数组的下标是从0开始i等于33表示执行了34次 { IRok = 1; i = 0; //把脉宽计数清零准备下次存入 } } else { IRtime = 0; //引导码开始进入把脉宽计数清零开始计数 startflag = 1; //开始处理标志位置1 } } void IRcordpro() { uchar i,j, k,cord,value;/*i用于处理4个字节,j用于处理一个字节中每一位,k用于33次脉宽中的哪一位 cord用于取出脉宽的时间判断是否符合1的脉宽时间*/ k = 1; //从第一位脉宽开始取,丢弃引导码脉宽 for(i = 0; i < 4;i++) { for(j = 0; j < 8; j++) { cord = IRdata[k]; //把脉宽存入cord if(cord > 7) //如果脉宽大于我11.0592的t0溢出率为约278us*5=1390那么判断为1//1.3ms value = value |0x80; /*接收的时候是先接收最低位, 把最低位先放到value的最高位在和0x08按位或一下 这样不会改变valua的其他位的数值只会让他最高位为1*/ if(j < 7)//限制条件 value = value >> 1; //value位左移依次接收8位数据。 k++;//每执行一次脉宽位加1 } IRcord[i] = value;//每处理完一个字节把它放入IRcord数组中。 value = 0;//清零value方便下次在存入数据 } IRpro_ok = 1;//接收完4个字节后IRpro ok置1表示红外解码完成 } void Init_GPIO() { Set_All_GPIO_Quasi_Mode;//所有口设置为双向口 P01_PushPull_Mode;//左路输出 P02_PushPull_Mode;//左路输出 P03_PushPull_Mode;//左路输出 P04_PushPull_Mode;//左路输出 P10_PushPull_Mode;//左路输出 P00_PushPull_Mode;//左路输出 P11_PushPull_Mode;//左路输出 P17_Input_Mode;//P17输入上拉模式 clr_P00; clr_P01; clr_P02; clr_P03; clr_P04; clr_P10; clr_P11; clr_P12; clr_P13; } void main () { Init_T1(); Init_GPIO(); while(1) { if(IRok) //判断脉宽是否检测完毕 { IRcordpro(); //根据脉宽解码出4个字节的数据 IRok = 0; //重新等待脉宽检测 if(IRpro_ok) //解码完成 { uint i; i = IRcord[2] << 8; i |= IRcord[1];//将第一个用户反码和按键码结合判断 switch(i) { case 0x45ff: P04 = ~P04;break; case 0x44ff: P03 = ~P03;break; case 0x40ff: P10 = ~P10;break; case 0x43ff: P11 = ~P11;break; case 0x47ff: P02 = ~P02;break; case 0x15ff: P00 = ~P00;break; default:break; } } } } }
#include "N76E003.h" #include "Common.h" #include "Delay.h" #include "SFR_Macro.h" #include "Function_define.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 16000000 //输入主频,自适应解码(单位:Hz,范围:6MHz ~ 40MHz) #define CA_S 8 //长按时间设置,单位:108mS(即 108mS整数倍,10倍以上为宜) sbit IR = P1^7; //定义红外脉冲数据接口 外部中断1输入口 //无符号类型 #define uint8 unsigned char #define uint16 unsigned int /*┈┈┈┈┈┈┈┈┈┈ 基准 ┈┈┈┈┈┈┈┈┈┈┈*/ #define Boot_Limit (((9000+4500) +2000)/Step) //引导码周期上限 #define Boot_Lower (((9000+4500) -2000)/Step) //引导码周期下限 #define Bit1_Limit ((2250 +800)/Step) //“1”周期上限 #define Bit0_Limit ((1125 +400)/Step) //“0”周期上限 #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] = 0; //解码存放:16位用户码、操作码正反码 uint8 cntCA; //长按计数 uint16 cntStep; //步数计 bit IRa,IRb; //电位状态保存 bit IRsync; //同步标志 uint8 BitN; //位码装载数 void KZ0(); //短按处理 void KZ1(); //长按处理 void IR_Init(); void IR_NEC(); /***************** 主函数 ********************/ void main(void) { Set_All_GPIO_Quasi_Mode;//所有口设置为双向口 P17_Input_Mode; P15 = 0; P14 = 0; IR_Init(); //红外线解码初始化 NEC[4] = 0; while(1) { //遥控检测 if((IR_BT==2)||(IR_BT==3)) { if(IR_BT==2) { switch(NEC[2]) { case 0x45: P15 = ~P15; break; default:break; } } else { switch(NEC[2]) { case 0x45: P14 = ~P14;break; default:break; } } IR_BT =0; //清有效标志 } } void IR_Init() { TMOD &= 0xF0; //清定时器0 TMOD |= 0x01; //定时器0:16位定时器 TH0 = TH_H; //每一步的时间 TL0 = TH_L; EA = 1; //总中断 //ET1 = 1; //定时器1中断 ET0 = 1; //TR1 = 1; //启动定时器1 TR0 = 1; /*IT1 = 1; //设置外部中断1为跳沿触发方式,来一个下降沿触发一次 EX1 = 1; //启动外部中断1*/ } /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ 函数:红外线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,装载位码数 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; #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 } } /********************** 定时器1断函数************************/ void time0(void) interrupt 1 { IR_NEC(); }
本版积分规则 发表回复 回帖并转播 回帖后跳转到最后一页
人才类勋章
发帖类勋章
等级类勋章
时间类勋章
71
617
0
扫码关注 21ic 官方微信
扫码关注嵌入式微处理器
扫码关注电源系统设计
扫码关注21ic项目外包
扫码浏览21ic手机版
本站介绍 | 申请友情链接 | 欢迎投稿 | 隐私声明 | 广告业务 | 网站地图 | 联系我们 | 诚聘英才
京公网安备 11010802024343号