// 解码值在Im[2]中,当IrOK=1时解码有效。
/* 51单片机红外遥控解码程序 */
//用遥控器对准红外接收头,按下遥控器按键,在数码管前两位上就会显示对应按键的编码
#include <reg52.h>
#define uchar unsigned char
sbit dula=P2^6
sbit wela=P2^7
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}
uchar f
#define Imax 14000 //此处为晶振为11.0592时的取值,
#define Imin 8000 //如用其它频率的晶振时,
#define Inum1 1450 //要改变相应的取乱漏态值。
#define Inum2 700
#define Inum3 3000
unsigned char Im[4]={0x00,0x00,0x00,0x00}
uchar show[2]={0,0}
unsigned long m,Tc
unsigned char IrOK
void delay(uchar i)
{
uchar j,k
for(j=ij>0j--)
哗源 for(k=125k>0k--)
}
void display()
{
dula=0
P0=table[show[0]]
dula=1
dula=0
wela=0
P0=0xfe
wela=1
wela=0
delay(5)
P0=table[show[1]]
dula=1
dula=0
P0=0xfd
wela=1
wela=0
delay(5)
} //外部中断解码程序
void intersvr1(void) interrupt 2 using 1
{
Tc=TH0*256+TL0 //提取中断时间间隔时长
TH0=0
TL0=0 //定时中断重新置零
if((Tc>Imin)&&(Tc<Imax))
{
m=0
f=1
return
} //找到启始码
if(f==1)
{
if(Tc>Inum1&&Tc<Inum3)
{
Im[m/8]=Im[m/8]>>1|0x80m++
}
if(Tc>Inum2&&Tc<Inum1)
{
Im[m/8]=Im[m/8]>>1m++//取码
}
if(m==32)
{
m=0
f=0
if(Im[2]==~Im[3])
{
IrOK=1
}
else IrOK=0 //取码完成后判断读码是否正确
}
//准备读下一码
}
}
/*演示主程序*/
void main(void)
{
unsigned int a
m=0
f=0
EA=1
IT1=1EX1=1
TMOD=0x11
TH0=0TL0=0
TR0=1//ET0=1
while(1)
{
if(IrOK==1)
{
show[1]=Im[2] &0x0F //取键码的低四位
show[0]=Im[2] >>4
IrOK=0
}
for(a=100a>0a--)
{
display()
}
}
}
解码程序这个就能实现
这是我参考别人的代码适当修改后,测试可用。注意:与NEC协议中说明的高低电平是反转的
程序采用计时器,当下降沿到来时,进入外部中断程序interrup 2中,计时器装入值清0,即从0计数到下一个下降沿到来,得到的计数值就是一个“低电平裤谈+高电平”的时间,对时间进行判断就可以区分是引导码,数据1或0,还是重复码
没有做抗干扰
#include "reg52.h"
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+4.5=13.5 + -280:13.22~13.78
#define thh 2530 //数据1
#define thl 1970 //2.25ms 不能大于 重复码9+2.25=11.25 10.97~11.53
#define tlh 1400 //数据0
#define tll 840 // 1.12ms
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=TH0*256+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]//取码完成后判断读码是否正确
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)