|
这个是通过红外遥控器控制单片机的实验,详情见 附件. 平台:FDR-1 51开发板 主程序代码: /*11.0592MHz晶振*/ #include #include"delay52.h" #include"LCD1602_4.h" sbit beep="P3"^7; sbit inf="P3"^3; sbit led1=P1^3; uchar key_code=0;/*key_code:遥控键值*/ uint buf_key_code=0;/*键值暂存对应功能看主函数*/ uchar key_bit_count=0;/*键编码脉冲计数*/ uint count_T=0,buf_CT=0;/*count_T:定时器中断次数计数,buf_CT用来截获某一时间的count_T值以供判断*/ uchar common_code_count=0;/*前导码脉冲计数*/ uchar inf_status=0;/*inf_status:脉冲接收器所处的状态,0:无信号,1:前导码接收区,2:数据编码接收区*/ void main() { LCM1602_Init(); EA=1; //开全局中断 ET0=1; //开定时器0中断 TMOD=0x02;//T0设置为8位自动装载模式 TH0=0xCA; //自动装载值为202,中断间隔为50us TL0=0xCA; //初值为202 IT1=1; //INT1为下降沿触发 EX1=1; //开外部中断 TR0=1; //启动定时器计数 while(1) { /*收到数字键则显示数字*/ if(key_code<10) { beep=0;//响蜂鸣器 //CLEARSCREEN; LCM1602_write_string(0,0,"number:"); num(0,7,key_code);//其它数字和编码值相同,直接显示键值 LCM1602_write_string(1,0,"code:"); num(1,5,key_code); key_code=255;//清键值 delayms(20); beep=1; } /*收到功能键则显示相应的功能*/ else if(key_code<50) { beep=0; // CLEARSCREEN;//清屏 switch(key_code) { case 22:LCM1602_write_string(0,9,"mute");break; case 18:LCM1602_write_string(0,9,"power");break; case 10:LCM1602_write_string(0,9,"--");break; case 31:LCM1602_write_string(0,9,"s.sys");break; case 15:LCM1602_write_string(0,9,"BASS");break; case 27:LCM1602_write_string(0,9,"CALL");break; case 11:LCM1602_write_string(0,9,"TV/AV");break; case 25:LCM1602_write_string(0,9,"HOBBY");break; case 26:LCM1602_write_string(0,9,"recall");break; case 19:LCM1602_write_string(0,9,"CH+");break; case 23:LCM1602_write_string(0,9,"CH-");break; case 20:LCM1602_write_string(0,9,"VOL-");break; case 16:LCM1602_write_string(0,9,"VOL+");break; case 24:LCM1602_write_string(0,9,"MENU");break; case 28:LCM1602_write_string(0,9,"SLEEP");break; case 30:LCM1602_write_string(0,9,"PRE");break; case 12:LCM1602_write_string(0,9,"SCAN");break; } LCM1602_write_string(0,0,"function:"); LCM1602_write_string(1,0,"code:"); num(1,5,key_code); key_code=255;//清键值 delayms(30); beep=1; } delayms(50); } } void Time0(void) interrupt 1 { count_T++;//周期累加 /*如果外部中断处于无信号区,则滤除前导宽脉冲中间的跳变毛刺*/ if(inf_status==0&&count_T<160) { EX1=0; } /*如果外部中断处于信号区,则滤除宽脉冲中间的跳变毛刺*/ else if((inf_status==1||inf_status==2)&&count_T<12) { EX1=0; } /*渡过上升沿后重新开放外部中断*/ else { EX1=1; } /*超过25ms,则锁定count_T值,等待下一次信号脉冲下降沿来解开*/ if(count_T>500) { inf_status=0; count_T=600; } } /*************************************************************** 外部中断1,用于捕获红外脉冲信号 ****************************************************************/ void int_1(void) interrupt 2 { led1=0; TR0=1; if(count_T>15&&count_T<250)//如果信号合法,则捕进buf_CT,count_T清0,对下一个脉冲信号计时 { buf_CT=count_T; count_T=0; } delay10us(10);//延时100us以消除下降沿跳变抖动 if(inf==0)//INT1引脚稳定为低电平,则表示确实是信号,count_T重新计时,因上面延时了100us,故要补偿2次T0中断 { count_T=2; } if(buf_CT>15&&buf_CT<250)//若收到的信号合法,则再进行以下的信号分析 { if(inf_status==0)//若当前信号接收系统处于空闲状态,则标志进入前导码接收区 { if(buf_CT>210&&buf_CT<250)//捕捉前导码 { inf_status=1;//标志进入前导码接收区 buf_key_code=0; key_bit_count=0; buf_CT=0; } } else if(inf_status==1)//前导码接收区(收到的脉冲全部忽略) { if((buf_CT>15&&buf_CT<25)||(buf_CT>32&&buf_CT<45))//脉冲接收 { common_code_count++;//脉冲数计算 if(common_code_count>=26)//若收够了26个脉冲 { inf_status=2;//则标志进入数据接收区 common_code_count=0;//脉冲计数清0 key_bit_count=0; buf_key_code=0; } } } else if(inf_status==2)//数据接收区 { if(buf_CT>15&&buf_CT<25)//窄脉冲接收 { buf_key_code>>=1;//接收0 key_bit_count++; } else if(buf_CT>32&&buf_CT<45)//宽脉冲接收 { buf_key_code>>=1; buf_key_code|=0x80;//接收1 key_bit_count++;//数据脉冲数累加,一共有8个 } if(key_bit_count>=8)//若收完8位个数据脉冲,则进行以下的处理 { inf_status=0;//标志接收系统返回空闲状态 key_bit_count=0; key_code=buf_key_code; buf_key_code=0; TR0=0; count_T=600; } } buf_CT=0; } led1=1; EX1=1; }
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|