你用的是HT6221吗,一般学习应该都用这个红外芯片。
根据你在问题中提的问题和与别人的交流,我说两点:
时间的计算,在接收和解码红外线是,要用到单片机的两个内部功能,外部中断和定时器,定时器用于捕捉红外接收时间,外部中断用于捕捉接收的逻辑,那么外部中断不参与时间的工作,这时用到的只是定时器,这个定时器就当普通定时器就好了,建议使用能自动重装初值的定时器,更稳定,只要定时器能让它多少时间中断一次,然后对一个变量计数一次就行,晶振的大小只是初值的不同,稍微修改就行,没必要大费周折的去算。
关于程序没反应:程序正误由编译器检查了,没错,但是你不该说程序逻辑没错,程序逻辑没错就肯定能运行了,在红外的逻辑没错情况下,检查程序逻辑,是否是对时间计数上没把握到位,是否是初始化错误,是否是中断函数用错了关键词,等等因素编译器都不可能检查出来,最好贴出你的程序,好帮助你。
希望我的回答能帮助到你吧。
这是我参考别人的代码适当修改后,测试可用。
注意:与NEC协议中说明的高低电平是反转的
程序采用计时器,当下降沿到来时,进入外部中断程序interrup 2中,计时器装入值清0,即从0计数到下一个下降沿到来,得到的计数值就是一个“低电平+高电平”的时间,对时间进行判断就可以区分是引导码,数据1或0,还是重复码
没有做抗干扰
#include "reg52h"
sbit ir=P3^3; //红外接收IO口
unsigned char duan,wei,flag,jc,jc1;
unsigned int m,Tc; //12M晶振
#define tmin 13220 //协议中高电平560us平分,提高容限
#define tmax 13780 // 9+45=135 + -280:1322~1378
#define thh 2530 //数据1
#define thl 1970 //225ms 不能大于 重复码9+225=1125 1097~1153
#define tlh 1400 //数据0
#define tll 840 // 112ms
unsigned char dat[4]={0,0,0,0};//接收32为地址和命令码
//数码管显示表
unsigned char code tableduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
unsigned char code tablewei[]= {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
void display();
void main()
{
ir=1;//开外部中断INT1
m=0;
EA=1;
EX1=1;
IT1=1;
ET0=0;//启动定时器0,只做计数不开启中断
TMOD=0x01;
TH0=0;
TL0=0;
TR0=1;
while(1)
{//---只显示了命令码,地址码可自行加入----
duan=flag/16;//得到命令码高4位,16进制显示
wei=6;
display();
duan=flag%16;//低4位
wei=7;
display();
duan=jc%16;//显示引导码获得次数、判断是否检测到引导
wei=0; //码,调试用
display();
duan=jc1%16;//显示接收到数据“1”次数,低四位的数据
wei=1;
display();
}
}
void display()
{
unsigned char i=100;
P2=tableduan[duan];//P2口输出数码管段选数据
P1=tablewei[wei]; //P1的P10~P12 3个IO实现8数码管位选控制
while(i--);
}
void int0() interrupt 2
{
Tc=TH0256+TL0;//得到一个低电平+高电平时序计时值
TH0=0;
TL0=0;//继续下一个计时
if((Tc>tmin)&&(Tc<tmax))
{
m=0;//检测到引导码
jc++; //不用管清零,加满后自动归0
}
if(m<32)
{
if((Tc>thl)&&(Tc<thh))//取码
{
dat[m/8]=(dat[m/8]>>1)|0x80;
m++;
jc1++;
}
else if((Tc>tll) && (Tc<tlh))
{
dat[m/8]=(dat[m/8])>>1;
m++;
}
}
else m=0;//在没接收到引导码的情况下清0,调试用
if(dat[2]==~dat[3])//判断数据是否正确,正确就取出
flag=dat[2];//取码完成后判断读码是否正确
}
//////////////////////////////////////
//晶振频率为6MHz 一个机器周期2us //
//实现按键地址码、指令码的数码管显示//
//2010-06-01 //
//////////////////////////////////////
#include<reg52h>
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6;
sbit wela=P2^7;
bit overflag,dataover;//开始接收数据,数据处理完毕
uchar timedata;//定时器0溢出次数
uchar chubus[33];//33Byte数据 timedata组成的数组
uchar jieguos[4];//地址码,地址反码,数据码,数据反码;
void initial()//初始化
{
IT0=1;EX0=1;//负边沿触发
TMOD=0x01;ET0=1;TR0=1;//模式1,十六位定时器
TH0=0xff;TL0=0x06;//05ms溢出
EA=1; //开总中断
}
void time0() interrupt 1//定时器0中断
{TH0=0xff;TL0=0x06;
timedata++;
}
void ex0() interrupt 0//外部中断0,接收数据
{
static bit startflag;//开始接收
static uchar i;
if(startflag)
{
if(timedata<32&&timedata>=16) i=0;
chubus[i]=timedata;
timedata=0;
i++;
if(i==33){overflag=1;i=0;}
}
else
{
startflag=1;
timedata=0;
}
}
void chulidata()
{
uchar chubu;//初步数据
uchar jieguo;//结果数据
uchar x,y,z=1;
for(x=0;x<4;x++)//处理四组数据
{
for(y=1;y<=8;y++)//处理一组数据8Byte
{
chubu=chubus[z];
jieguo=jieguo>>1;
if(chubu>3) jieguo=jieguo|0x80;//大于15mS为1
z++;
}
jieguos[x]=jieguo;
jieguo=0;
}
dataover=1;
}
void delay(uint z)
{
uint x ,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void display()
{
uchar gao,gao1;
uchar di,di1;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
gao1=table[jieguos[0]/16];
di1=table[jieguos[0]%16];
gao=table[jieguos[2]/16];
di=table[jieguos[2]%16];
dula=1;
P0=gao1;
dula=0;
P0=0xff;
wela=1;
P0=0x7e;
wela=0;
delay(2);
dula=1;
P0=di1;
dula=0;
P0=0xff;
wela=1;
P0=0xfd;
wela=0;
delay(2);//地址码
dula=1;
P0=gao;
dula=0;
P0=0xff;
wela=1;
P0=0x77;
wela=0;
delay(2);
dula=1;
P0=di;
dula=0;
P0=0xff;
wela=1;
P0=0x6f;
wela=0;
delay(2);//指令码
}
void main()
{
initial();//初始化
while(1)
{
if(overflag)//数据接收完毕
{
chulidata();//处理数据,完成标志dataover
overflag=0;
}
if(dataover)
{
display();//数码管显示
}
}
}
以上就是关于单片机红外解码程序中关于接收时间的设定是怎么计算的呢全部的内容,包括:单片机红外解码程序中关于接收时间的设定是怎么计算的呢、谁能介绍一下红外线解码c51遥控程序、红外线遥控器解码C语言程序代码 SM0038接受头等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)