单片机编码、解码2262用单片机编码2262来发射,2272接收成功;现在用单片机编码2262来发射,单片机解码2272来接收。
同步码头波形:
这是自己按照波形图写的解码,大家指教!!这样解码可以不??没有用到2272了,接收模块输出直接到单片机的I/O口,然后判断I/O口的高低电平来解码?
#include<reg52.h>
#define uchar unsigned char
void display();
void delay_1s(uchar);
bit T0Action;
bit Action;
bit RECEIVE; //接收标志
sbit P1_0=P1^0;
sbit P1_1=P1^1;
sbit P1_2=P1^2;
sbit P1_3=P1^3;
sbit P1_7=P1^7; //接收脚
sbit P3_5=P3^5; //发光二极管
sfr AUXR =0x8E;
sfr P1M0 =0x91;
sfr P1M1 =0x92;
sfr P3M0 =0xb1;
sfr P3M1 =0xb2;
void main()
{
uchar i;
uchar temp,data0,data1,counttime;
unsigned int time,time1,time2;
// AUXR=0x80; //定时器0不分频
T0Action=0;
RECEIVE=0; //接收标志位
Action=0;
TMOD = 0x01; // 定时器0 工作方式1
TH0=0x00;
TL0=0x00;
P1_0=0;
P1_1=0;
P1_2=0;
P1_3=0;
P3_5=0;
while(1)
{
do{}while(P1_7==1);
if((P1_7==0) && (T0Action==0)) //等待低电平,低电平开始记时
{
TR0=0;
TH0=0x00;
TL0=0x00;
TF0=0;
TR0=1;
T0Action=1;
while(1)
{
if((P1_7==1) && (T0Action==1))
{
TR0=0;
time=TH0*256+TL0; //记下低电平宽度时间
T0Action=0;
break;
}
}
}
if((time>9000) && (time<12000)) //检测同步码约11ms
{
counttime=0;
data0=0;
data1=0;
time=0;
RECEIVE=1; //检测到同步码时 置标志位 RECEIVE=1
P3_5=1; //绿发光二极管灯亮(调试用)
}
if(RECEIVE==1) //检测到同步码后开始解码
{
RECEIVE=0;
while(1)
{
L1:do{}while(P1_7==1);
if((P1_7==0) && (T0Action==0)) //等待第一个低电平,一有低电平马上记时
{
TR0=0;
T0Action=1;
TH0=0x00;
TL0=0x00;
TF0=0;
TR0=1;
while(1)
{
if((P1_7==1) && (T0Action==1))
{
TR0=0;
time=TH0*256+TL0; //记下第一个低电平宽度时间
T0Action=0;
TH0=0x00;
TL0=0x00;
TF0=0;
TR0=1; //开始记高电平时间
break;
}
}
}
do{}while(P1_7==1);
if((P1_7==0) && (T0Action==0)) //等待第二个低电平,一有低电平马上记时
{
TR0=0;
time2=TH0*256+TL0; //记下一个高电平宽度时间
T0Action=1;
TH0=0x00;
TL0=0x00;
TF0=0;
TR0=1;
while(1)
{
if((P1_7==1) && (T0Action==1))
{
TR0=0;
time1=TH0*256+TL0; //记下第二个低电平宽度时间
T0Action=0;
break;
}
}
}
if((time==time1) && (time<1500)) //判断两个低电平宽度时间是否相等,限时1500us
{
if((time>780) && (time<1150)) //低电平宽度时间
{
if((time2>210) && (time2<450)) //高电平宽度时间
{
temp=0x00; //0
}
else goto L1; //误码,返回重新接收数据
}
else if((time>210) && (time<450)) //低电平宽度时间
{
if((time2>780) && (time2<1150)) //高电平宽度时间
{
temp=0x01; //1
}
else goto L1; //误码,返回重新接收数据
}
else goto L1; //误码,返回重新接收数据
counttime++;
if(counttime<=8) //开始接收前8位 地址码
{
data0=(data0<<1)|temp;
}
else if((counttime>8) && (counttime<=12)) //开始接收后4位 数据码
{
data1=(data1<<1)|temp;
if(counttime==12) // 第12位
{
Action=1;
break; //接收完毕,退出解码程序
}
}
}
else goto L1; //误码,返回重新接收数据
}
最近要做一个用单片机模拟2272来解码2262的项目。现在刚刚有些结果,发现了一些问题,同大家分享。
1由于厂家是设定2262 2272配对使用,因此对一般应用来讲,不需要考虑中间详细的通信格式,所以在厂家(普城)的资料上没有相应的编码格式。我只好在网上找到了第三方的更详细的波形图。但是我找的两份资料上在细节上都有表述错误的地方。通过比较,得出了正确的结果。其中之一就是对于2262的振荡频率公式:f=32000/R(R是振荡电阻,以M为单位),所以如果为3.2M的振荡电阻,那么振荡频率为10kHZ,周期为T=100us,则窄脉冲是4倍的周期,宽脉冲为12倍周期,计算结果宽窄脉冲分别为:400us,1200us;这与实际的脉冲宽度有一定的差别,实际的是359us,1078us.由于2262是三进制,所以需要两位的二进制表示。表现在编码波形上,如果取窄高脉冲+宽低脉冲(--______)代表0(16倍T),宽高脉冲+窄低脉冲(-----__)代表1(16倍T),那么2262的三种管脚状态:接高电平、悬空、接地电平可以用11,01,00表示,所以每个码长度是32T,而不是其他。
2在写完解码并修正程序后,发现我的解码距离特别短。而且有的甚至只有几厘米。我先是在接收模块加上了一段30cm的天线。结果仅有的几个感应比较长的遥控器距离更短。接下来我发现我用的单片机是51的,从资料上看到这种单片机的辐射干扰很大。于是我就把接收模块拉远。供电隔离,但是仍然效果很差。离几百米的标称距离差距几个数量级,也满足不了本项目的要求。接着,我把焦点放在其他用电器的干扰上,因为旁边有好几台电脑,有可能是他们的原因。所以我就把实验装置放到比较干净的地方。增加天线到1M,并把天线竖起来,结果仍然没有什么明显改善。
最后,我沮丧地把天线扔到地上,结果发现这时候距离比前面远多了。感应距离3-10M,基本上满足了应用要求。我又观察了一下天线,发现感应距离有方向性,天线指向的方向感应距离比较,。垂直的方向比较短。
3我在测量接收模块输出端的时候,由于设备简陋,只能测直流电压,发现平常的时候2.5V左右随机波动,而且用单片机监测数据发现,明显有大量的乱码出现。而当按动遥控器的时候,发现直流电平下降到1.8V左右。从直流电平上看,好像是平常处于高电平,数据到来时为低电平。而实际上,单片机解码时必须采用高电平解码。否则解不出来。这种矛盾的现象可能是由于平时的杂波信号产生的。
4几米的的解码距离相比专用芯片的解码距离相差还是有一个数量级的差距。现在我还不知道到底是那个原因的使得传播距离这么短。考虑的因素接下来可能是传输速率的问题,我现在采用的振荡频率大概20K.还有就是增加天线的长度。
5续:对于距离太短也不能解码的解决。后来我发现了一个很奇怪的现象,就是对于大部分的遥控器,解码距离不能太短。太短的时候也不能解码。后来我发现2262的编码值也影响解码距离。全接高电平解码距离可以很近,全接低电平解码灵敏度很低,几乎解不出来。如果距离太短解不出码是因为信号太强,导致振荡间歇期太短,信号阻塞,那么应该是全接高电平解码效果最差,全接低电平效果最好。因为接高电平的振荡间歇期最短,最容易被强信号淹没。全接低电平恰好相反,因为振荡期窄,间歇期长,不容易形成阻塞。
所以问题应该在其他的方面。前面脉冲宽度都是按照理论值计算的,并没有直接测量具体的实际宽度值。这时候我采取检测实际脉冲宽度的方法。通过与pc连接,实时的查看实际的脉冲宽度。结果让我大吃一惊,宽高脉冲实际值与理论基本符合,而窄脉冲实际值竟然只是理论值的一半左右,而且,随着解码距离的远近不同,脉冲宽度大约有30%的变化。所以,实际的脉冲宽度接近程序中的
极限值,对于不同的编码值,其窄电平脉冲数量不一样,例如:全接高电平,窄脉冲最少(0个),结果就容易解;全接低电平窄脉冲最多,解码就非常难(只要所有的窄脉冲中一个出现错误就解不出来)。对于距离太近也不能解码,也是因为脉冲宽度随距离发生变化,导致超过极限宽度,结果就不能解码。