// 用单片机进行红外遥控接收已经是很平常的应用了,基本上稍懂单片机就可以自己编// // 但往往很多人编的程序要么繁琐,要么占用大量存储器、CPU资源, // // 而且用于现场时还可能因为受到干扰而不能正常工作 // // 真正试过的都会发现,要想编个真正好用的接收程序不是那么简单的 // // 其实,所有遥控芯片的编码都是比较简单的(有限的状态),只要仔细分析它的编码// // 我们完全可以用状态机的方式来处理各种可能的情况,甚至从被干扰的杂乱波形中找出正确的编码// // 下面是基于状态机的SAA3010红外遥控接收程序示例: // //--------------------------------------------------------------------------// // // // (c) Copyright 2001-2003 xuwenjun // // All Rights Reserved // // V1.00 // //--------------------------------------------------------------------------// //标 题: SAA3010遥控芯片接收程序 // //文件名: ir_3010.c // //版 本: V1.00 // //修改人: xuwenjun E-mail:xuwenjun@21cn.com // //日 期: 03-06-14 // //描 述: SAA3010遥控芯片接收程序 // //--------------------------------------------------------------------------// //老版本: 无 老版本文件名: // //创建人: xuwenjun E-mail:xuwenjun@21cn.com // //日 期: 03-06-14 // //描 述: SAA3010遥控芯片接收程序 // // 当ykok=1时,ykcode中的数据就是接收到的遥控码(14位的最后8位) // //--------------------------------------------------------------------------// //占用以下资源: // // 1. 遥控使用外部中断0,接P3.2口 // // 2. 遥控使用定时计数器1 // // 3. 5.1字节data RAM // // 4. 293字节 code ROM // //--------------------------------------------------------------------------// //声 明: // // 以下代码仅免费提供给学习用途,但引用或修改后必须在文件中声明出处. // // 如用于商业用途请与作者联系. E-mail:xuwenjun@21cn.com // // 有问题请mailto xuwenjun@21cn.com 欢迎与我交流! // //--------------------------------------------------------------------------// #i nclude <reg52.h> #define uchar unsigned char // SAA3010存储定义 uchar ykcode; //遥控码(14位的最后8位) bit ykok; //遥控数据有效标志 uchar ykbnum; //遥控已接收位数 uchar ykbtc; //遥控中断时 ykbtc=TH1 uchar ykdelay; //遥控延时接收 bdata uchar ykcodetemp; //遥控临时码 sbit ykcodetemp0=ykcodetemp^0; // SAA3010端口定义 //sbit YKIO=P3^3; //遥控使用外部中断0,接P3.2口
// SAA3010函数原型: 公用函数 void YkInit(void); //遥控接收初始化 unsigned char YkGetcode(void); //返回遥控码 bit YkTest(void); //检查有无遥控信号 /* // SAA3010函数原型: 公用函数 extern void YkInit(void); //遥控接收初始化 extern unsigned char YkGetcode(void); //返回遥控码 extern bit YkTest(void); //检查有无遥控信号 */ /* // 外部引用四位LED显示模块 // extern unsigned char code tab_duam[]; //位映射 extern void led_send(unsigned char d); //发送子程序 extern void led_cls(void); //清除显示 extern void led_show(unsigned int n); //显示数字子程序 extern void led_showhh(unsigned int n); //16进制显示数字子程序 extern void led_test(void); //4LED测试函数 extern void led_delay(unsigned char ms); //延迟函数 */ // SAA3010函数内容 void YkInit(void) //遥控接收初始化 { TMOD=0x11; //TMOD T0,T1均选用方式1(16位定时) SCON=0x00; TH1=0; TL1=0; IE|=0x89; //SETB EX0 0x1 外部中断 0 允许 //SETB ET0 0x8 定时器 1 中断允许 //SETB EA 0x80 开中断 IP|=0x01; //SETB INT0 中断优先 TCON |= 0x41; //TCON EX0下降沿触发,启动T1 // ykbnum=0; ykcodetemp=0; ykdelay=0; } unsigned char YkGetcode(void) //返回遥控码 { return(ykcode); } bit YkTest(void) //检查有无遥控信号 { return(ykok); } void intx0() interrupt 0 using 2 //遥控使用外部中断0,接P3.2口 { ykbtc=TH1;TH1=0;TL1=0;TR1=1;ET1=1; switch(ykbnum) { case(0): ykbnum=1; break; case(1): if(ykbtc==6)ykbnum=2; else ykbnum=0; break; case(2): if(ykbtc==6||ykbtc==9)ykbnum=3; else ykbnum=0; break; case(3): if(ykbtc==9||ykbtc==6){ykbnum=4;} else ykbnum=0; break; default: if(ykbnum<7)if(ykbtc==6)ykbnum++; else ykbnum=0; else { if(ykbtc==6){if(ykcodetemp0)ykcodetemp=ykcodetemp*2+1; else ykcodetemp=ykcodetemp*2; ykbnum++; } else if(ykbtc==9){ if(ykcodetemp0){ykbnum++;ykcodetemp=ykcodetemp*2;} else {ykbnum+=2;ykcodetemp=ykcodetemp*2;ykcodetemp=ykcodetemp*2+1;} } else if(ykbtc>11&&ykbtc<15) {ykbnum+=2;ykcodetemp=ykcodetemp*2;ykcodetemp=ykcodetemp*2+1;} else if(ykbtc>30){EX0=1;} else ykbnum=0; } } } void intt1() interrupt 3 using 3 //遥控使用定时计数器1 { if(ykdelay){ykdelay--;EX0=0;} //ykdelay不为0暂停接收 else { if(ykbnum==13) //遥控码最后一位为0,补0 { ykcode=ykcodetemp*=2; ykdelay=3; EX0=0; //暂停接收 ykok=1; //遥控数据有效 } else if(ykbnum==14) //遥控码最后一位为1,不用补 { ykcode=ykcodetemp; ykdelay=3; EX0=0; //暂停接收 ykok=1; //遥控数据有效 } else EX0=1; //ykbnum不为13,14接收无效,继续接收 ykbnum=0; ykcodetemp=0; } } /* // SAA3010测试主函数内容 main() { YkInit(); led_test(); //4LED测试函数 for(;1;) //主程序 { if (YkTest()) led_showhh(YkGetcode()); led_delay(10); } } */ //太晚了,详细解释另文畅叙,大家可以先研究下哦
|