×
单片机 > 单片机程序设计 > 详情

51红外解码调试笔记

发布时间:2020-08-24 发布时间:
|
    前阵子帮他们做实习小车的买东西,看着便宜就顺便买了个红外的遥控器和1838的红外接收头子。这两天闲着没事,看了很多资料才终于完成了红外解码,的确是久了没玩51,好多东西生疏了导致调试过程几经挫折,经过这次复习了好多51的东西,受益匪浅。
    查阅资料得知常见红外编码为PPM制式。红外发射端以脉宽0.565ms、间隔0.56ms的脉冲信号表示二进制“0”,以脉宽0.565ms,间隔1.65ms的脉冲信号为“1”。如下图.
上述“0”、“1”组成的32位二进制码经过38KHz的载波进行二次调制以提高发射效率、降低电源功耗。
32位二进制码组中,前16位为用户识别码,能区别不同电气设备防止不同机种遥控码相互干扰。后16位为8位操作码极其反码。遥控器在按下后周期性的发出一种32位二进制码,周期108ms。这108ms由一个起始码(9ms),一个结果码(4.5ms),低8位地址码、高8位地址码、8位数据码极其8位数据反码组成。
 
接受时使用1838通用红外接头

红外接头将38K载波信号过滤掉,得到与发射代码反向接受码。
上述是我自己整理的资料。后经示波器验证大致是这样的,便开始编写程序。

红外解码的关键就是识别“0”和“1”。以下是具体代码,通过51单片机接受红外信号,解码后将8位操作码通过串口以十六进制发送给电脑(比较粗糙,还没来得及完善,仅供参考)[page]

 
#include//单片机型号STC89C52
 
#define uchar unsigned char
#define uint unsigned int
 
sbit IR=P3^2;//位定义,使用P3^2口外部中断0
 
uint lowtime,hightime;
uchar a[4],m,flag;
 
bit decode();//解码程序
void sci();//串口初始化
 
void main()
{
// delay_ms(100);
TR0=0;
TH0=0;
TL0=0;
sci();
EA=1;
IT0=1;//设置外部中断0为下降沿触发方式
EX0=1;//开外部中断0
while(1)
{
if(flag==1) //验证前导码正确后才开始解码并向串口发送数据
{
decode();
for(m=0;m<1;m++)//向串口发射a[2],及8位操作码
{
SBUF=a[2];
while(!TI);
TI=0;
}
while(1);
}
}
}
 
void ext0() interrupt 0
{
EX0=0;//进外部中断0后立即关闭中断0,防止二次中断
TR0=1;//开定时器0
while(IR==0);//一直计数,直到IR由0跳变到1
TR0=0;//关闭定时器0
lowtime=256*TH0+TL0;//lowtime储存引导码低电平持续时间
TH0=0;
TL0=0;//清空定时器0寄存器值,以备下一次计数
TR0=1;
while(IR==1);//等待IR由1跳表到0
TR0=0;//关闭定时器0
hightime=256*TH0+TL0;//hightime存储结果码高电平持续时间
if((lowtime>7800)&&(lowtime<8800)&&(hightime>3600)&&(hightime<4700))
//9000us/1.085=8294,判断区间8800-7800
//4500us/1.085=4100,判断区间3600-4700
//此值为11.0592MHz晶振时的值。  
flag=1;//符合判断条件则将flag标志置1,否则认为是干扰信号不予解码
}
 
bit decode()
{
uchar temp;
uchar i,j;
for(i=0;i<4;i++)
{
for(j=0;j<7;j++)
{
temp>>=1;
TH0=0;
TL0=0;
TR0=1;
while(IR==0);
TR0=0;
lowtime=256*TH0+TL0;
TH0=0;
TL0=0;
TR0=1;
while(IR==1);
TR0=0;
hightime=256*TH0+TL0;
if((lowtime<370)||(lowtime>640))//低电平时间长度不合理
return 0;
if((hightime>420)&&(hightime<620))//高电平持续时间560us左右即位“0”
temp&=0x7f;
if((hightime>1300)&&(hightime<1800))//高电平持续时间1680us左右即位“1”
temp|=0x80;
}
a[i]=temp;
}
}
 
void sci()
{
SM0=0;
SM1=1;
REN=1;
TMOD=0x21;//此处注意设置定时器0的方式为工作方式1
TH1=0xfd;
TL1=0xfd;
TR1=1;
ES=1;
}

串口显示出的十六进制的编码(每次单片机断电的时候都会向电脑发送00,不知道为什么...)
 
 
这只是初步的程序,调试过程中状况百出。显示串口显示问题,SBUFS是8位寄存器,只能存储8位二进制数据,故32位二进制需要发送四次,每次到串口为1位十六进制数据。还有定时器0的模式,之前一直没有设置,结果郁闷了一晚上。
 
另外,关于红外的用途的话,有人说这东西接受距离不远,也就几米(有资料说在输出段并上1uf电容可将接收距离增加至十多米,待验证),最致命的是它是红外线,必须要将发射端对准接收端才能接收到信号,这就是它比不上蓝牙、NRF24L01等无线通信最主要的原因。不过,NRF24L01之麻烦,以我的智商估计没有半个月是做不出来的。
关键字:红外解码  调试笔记 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
浅谈AVR中定时器几种工作模式