- // 用单片机进行红外遥控接收已经是很平常的应用了,基本上稍懂单片机就可以自己编//
- // 但往往很多人编的程序要么繁琐,要么占用大量存储器、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 欢迎与我交流! //
- //--------------------------------------------------------------------------//
- #include <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);
- }
- }
- */
- //太晚了,详细解释另文畅叙,大家可以先研究下哦