/***************红外遥控灯光控制系统***********************/
/*注意!这个代码不通用因为每个人的遥控器的按键代码不一样***/
/*相信花功夫看一下的人能看懂这个程序,能够根据这个程序画***/
/*出相应的电路图,并能够添加自己的发挥部分的功能。*********/
/**********************************************************/
#include #define uchar unsigned char//宏定义 uchar就等于 unsigned char #define uint unsigned int//宏定义 uint 就等于 unsigned int sbit LED0=P0^0;//LED的接口端 sbit IRIN=P3^2; //红外接收器数据线 uchar x,flag;//定义两个全局变量x,flag,x用于控制占空比,flag用于传递按键代码 uchar IRCOM[4]; /****************************************************/ /***************延时函数*****************************/ /************延时约为x*0.14ms************************/ /****************************************************/ void delay(unsigned char x) { unsigned char i; while(x--) { for (i = 0; i<13; i++) {}//执行x*13次循环,约为x*0.14ms } } /*****************************************/ /****************主函数*******************/ /*****************************************/ void main(void) { TMOD = 0x01; //配置方式:定时器0、软件置位、定时器模式、16位定时器 不懂查看后面的网址http://baike.baidu.com/view/2027288.htm TH0=(65536-50)/256; //高位赋值延时50us 不懂的百度搜 "TH0 TL0"这个关键词 TL0=(65536-50)%256; //低位赋值延时50us TR0 = 1; //开启定时器0 ET0 = 1; //定时器0中断打开 IRIN=1; //初始化LED的引脚电平,确保LED为关闭状态 EA = 1; //开启总中断 EX0=1; //使能 INT0 外部中断 IT0=1; //触发方式为脉冲负边沿触发 /**********************************************************/ /*当单片机上电后运行过以上的各种初始化代码后执行以下死循环*/ /**********************************************************/ while(1) { if(flag!=0)//flag不为0,即接收到代码 { EX0=0;//关闭外部中断防止干扰 switch(flag) //swich语句 不同flag的值即不同的按键代码对应不同的功能 { case 0x07: x=100*!x;break;//开关LED case 0x46: x++;break; //占空比加1% case 0x45: x--;break;//占空比减1% case 0x41: x+=10;break;//占空比加10% case 0x42: x-=10;break;//占空比减10% case 0x43: x+=20;break;//占空比加20% case 0x0b: x-=20;break;//占空比减20% default: break;//没有对应值,退出循环 } if(x>100)//占空比超过100 { if(x>120)x=0;//占空比小于0,占空比归零, 由于无符号数补码的原因,小于0的数会变得很大 else x=100;//占空比大于100并且小于120,占空比归为100最大值 } flag=IRCOM[2]=0;//清空传递变量数组按键码变量 EX0=1;//重新开启外部中断0 } } } /***************************************/ /*以下函数用来产生PWM即占空比可调的方波*/ /*用于调节LED亮度*x传递占空比调节亮度***/ /***************************************/ void Timer0_ISR(void) interrupt 1 //定时器0中断1服务程序每50us执行一次 { uchar i;//定义内部标志变量i if(i i++;//每执行一次定时器中断,i++ if(i>100)i=0;//i超过100,i归零,即周期为100*50us=5ms 频率200HZ,人眼已经察觉不到闪烁 TH0=(65536-50)/256;//重新装载时间 TL0=(65536-50)%256; TR0= 1; //重新开启定时器0 } /******************************/ /*以下外部中断函数用于红外解码*/ /******************************/ void IR_IN() interrupt 0 { unsigned char j,k,N=0; //定义内部变量 EX0=0; //关闭外部中断防止重复丢失 delay(15); //延时15*0.14ms if (IRIN==1) //如果高电平不满规定时间,判断为误码 { EX0=1; //重新开启外部中断0 return; //退出中断 } //确认IR信号出现 while (!IRIN) //等IR变为高电平,跳过9ms的前导低电平信号。 delay(1); //稍做延时 for (j=0;j<4;j++) //收集四组数据 { for (k=0;k<8;k++) //每组数据有8位 { while (IRIN) //等 IR 变为低电平,跳过4.5ms的前导高电平信号。 {delay(1);} //稍做延时 while (!IRIN) //等 IR 变为高电平 delay(1); //稍做延时 while (IRIN) //计算IR高电平时长 { delay(1); //稍做延时 N++; //每过0.14ms,N+1 if (N>=30) //计数时间过长判断为误码 { EX0=1; //重新开启外部中断0 return;//退出中断 } } //高电平计数完毕 IRCOM[j]=IRCOM[j] >> 1; //数据最高位补“0” if(N>=8) //当N>8即时间大于8*0.14ms则判断为数据“1”,否则为数据“0” { IRCOM[j] = IRCOM[j] | 0x80; //数据最高位补“1”否则不变则为“0” } N=0; //判断完成N归零 } } if(IRCOM[2]==~IRCOM[3]&&IRCOM[0]==0X86&&IRCOM[1]==0X6b)//判断初始码、结束码是否是自己的遥控器,判断数据码和数据反码是否是反向反系 { flag=IRCOM[2];//flag传递按键数据码 EX0=1; //重新开启外部中断0 return; //退出中断 } else { IRCOM[2]=0; //判断为 不是自己的遥控或者为误码,清零数据码 EX0=1; //重新开启外部中断0 return; //退出中断 } EX0=1; //重新开启外部中断0 }下载本文