十年专注单片机方案开发的方案公司英锐恩,分享3010T的解码程序。英锐恩现提供服务产品涉及主控芯片:8位单片机、16位单片机、32位单片机及各类运算放大器等。
#include
#include
#include
//###############################################
//晶体频率选择参数(遥控脉冲宽度计数用)
#define FHZ 1 //12M=1,24M=2
//###############################################
//**********************************
//12M
#define FMS 6 //标准值
#define FMSL 5 //离散值
#define FMSH 7 //离散值
#define FMM 9 //标准值
#define FMML 8 //离散值
#define FMMH 10 //离散值
#define FMBL 11
#define FMBH 15
/*遥控器键值*/
unsigned char code ykbiao[64]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0A,0x7F,0x8A,0x7F,0x8C,0x84,
0x85,0x86,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x89,0x7F,0x0B,0x7F,
0x88,0x82,0x7F,0x7F,0x7F,0x7F,0x86,0x7F,
0x7F,0x7F,0x7F,0x81,0x87,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x83,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x8A};
unsigned char ykcd; //遥控接收码(查表后码)?
unsigned char bzjsok;
bit bzjsone;
static unsigned char ykcode; //遥控接收码存放
static unsigned char ykbnum; //接收到的遥控位数
static unsigned char ykcodetemp; //遥控第一组接收码存放
static unsigned char ykhz; //遥控频率选择用(用来确定在2组信号之间的中断次数,12M一次,24M二次)
//12M 遥控接收码标记 (=1为在定时器1中断前刚刚接收完一组码,=0表示没有接收码)
//24M 遥控接收码标记 (=2为在定时器1中断前刚刚接收完一组码;=1表示第二次时钟中断;=0表示没有接收码)
//************************************************************
//外部中断0,使用寄存器组2
//遥控接收分析
void int1() interrupt 0 using 2
{unsigned char ykbtc;
ykbtc=TH1/FHZ;
TH1=0;TL1=0;TR1=1;ET1=1;
ykhz=FHZ;
//由于每次发送2组一样的代码,其间隔为50*1.778ms,只能引起一次(12M)或二次(24M)定时器1中断,此处设ykhz=FHZ
// 在定时器1第一次中断时,当ykhz=FHZ,说明是刚刚接收了信号,若ykbit5=0暂存信号;若ykbit5=1,处理信号
//12M时 如果在外部中断发生前再来一次定时中断(此时ykhz=0),说明先前接收的为代码的第二组,无法校验,故删掉
//24M时 如果在外部中断发生前再来一次中断(此时ykhz=1),ykhz--,不处理;再来一次中断(ykhz=0) 说明先前接收
//的为代码的第二组,无法校验,故删掉
switch(ykbnum) //ykbnum 接收的遥控信号位数
{case(0):ykbnum=1; //开始, 第一位 "1"
break;
case(1):if(((ykbtc>=FMSL)&&(ykbtc<=FMSH)))ykbnum=2; //第二位 同相 "1"
else ykbnum=0;
break;
case(2):if(((ykbtc>=FMSL)&&(ykbtc<=FMSH))||((ykbtc>=FMML)&&(ykbtc<=FMMH)))ykbnum=3; //第三位 同相 "1" 或反相 "0"
else ykbnum=0;
break;
case(3):if(((ykbtc>=FMSL)&&(ykbtc<=FMSH))||((ykbtc>=FMML)&&(ykbtc<=FMMH))){ykbnum=4;} //第四位 反相 "0" 或同相"1"
else ykbnum=0;
break;
default:if(ykbnum<7){if((ykbtc>=FMSL)&&(ykbtc<=FMSH))ykbnum++; //第五--七位 同相 "0"
else ykbnum=0;
}
else {if((ykbtc>=FMSL)&&(ykbtc<=FMSH))
{if(ykcode&1)ykcode=ykcode*2+1; //同相 遥控接收码上一位为"1",则此位也为"1"
else ykcode=ykcode*2; //上一位为"0",此位也为"0"
ykbnum++;
}
//9的情况 上位1 此一位0 上位0 此二位0 1
// | "1"| "0" | "0"| "0"|"1" |
// __ __ __ ____ __
// __| |____| |__ __| |__| |__|
//检测位址 | 9 | | 9 |
else if((ykbtc>=FMML)&&(ykbtc<=FMMH))
{if(ykcode&1){ykbnum++;ykcode=ykcode*2;} //9-反相 上一位为"1",此位为"0"
else {ykbnum+=2;ykcode=ykcode*2;ykcode=ykcode*2+1;}//上一位为"0",加2位,"0","1"
}
//11~15的情况 上位1 此二位0 1 上位0 不可能出现13
// | "1"| "0"|1 |
// __ ____
// __| |____| |__
//检测位址 | 13 |
else if(ykbtc>FMBL&&ykbtc<fmbh){ykbnum+=2;ykcode=ykcode*2;ykcode=ykcode*2+1;}
else ykbnum=0;
}
}
}
//****************************************************************
//定时器中断1 使用寄存器组3
//
void int2() interrupt 3 using 3
{if(ykhz==FHZ) // 在定时器1中断时,当ykhz=FHZ,说明是刚刚接收了信号,若ykbit5=0暂存信号;ykbit5=1,处理信号
//24M时 如果在外部中断发生前再来一次中断(此时ykhz=1),不处理.再来一次中断(ykhz=0)
//说明 先前接收的为代码的第二组,无法校验,故删掉
{ykhz--;
if(bzjsone==0) //ykbit5=0, 说明接收的应该是第一组代码
{if(ykbnum==13){ykcode*=2; //ykbnum=13,说明最后一位"0"丢失
ykcodetemp=ykcode; //第一组代码暂存
bzjsone=1; //设第一组代码以存标志位
}
else if(ykbnum==14){ykcodetemp=ykcode;bzjsone=1;}
else EX0=1;
ykbnum=0;
ykcode=0;
}
else{if(ykbnum==13) //以下应该为第二组代码
{ykcode*=2; // ykbnum=13,说明最后一位"0"丢失 ykcd=ykbiao[ykcode*=2];
if(ykcode==ykcodetemp) //两组代码一样,代码有效
{//buf[0]=ykcode/0x10; //调试遥控过程中显示接收的码
//buf[1]=ykcode%0x10;
ykcd=ykbiao[ykcode];
bzjsok=1;
}
else {/*buf[0]=0;buf[1]=0;*/} //两组代码不一样,代码无效
}
else if(ykbnum==14)
{
if(ykcode==ykcodetemp)
{//buf[0]=ykcode/0x10;
//buf[1]=ykcode%0x10;
ykcd=ykbiao[ykcode];
bzjsok=1;
}
else {/*buf[0]=0;buf[1]=0;*/}
}
bzjsone=0;
ykbnum=0;
ykcode=0;
}
}
else {if(ykhz==0){bzjsone=0;ykbnum=0;ykcode=0;}
//12M时 如果在外部中断发生前再来一次中断(此时ykhz=0),说明先前接收的为代码的第二组,
//无法校验,故删掉删掉原先接收的代码,清零
else ykhz--; //24m时允许二次时钟中断,ykhz-1,不作别的处理
}
}