//////////////////////////////////////
//晶振频率为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();//数码管显示
}
}
}
这是我以前写的红外遥控器。。。你看看,有帮助的
#include <AT89X51h>
static bit
OP; //红外发射管的亮灭
static unsigned int
count; //延时计数器
static unsigned int endcount; //终止延时计数
static unsigned char
flag; //红外发送标志
char
iraddr1; //十六位地址的第一个字节
char iraddr2; //十六位地址的第二个字节
void SendIRdata(char p_irdata);
void delay();
void main(void)
{
count = 0;
flag = 0;
OP = 0;
P3_4 = 0;
EA = 1; //允许CPU中断
TMOD = 0x11; //设定时器0和1为16位模式1
ET0 = 1; //定时器0中断允许
TH0 = 0xFF;
TL0 = 0xE6; //设定时值0为38K 也就是每隔26us中断一次
TR0 = 1;//开始计数
iraddr1=3;
iraddr2=252;
do{
delay();
SendIRdata(12);
}while(1);
}
//定时器0中断处理
void
timeint(void) interrupt
1
{
TH0=0xFF;
TL0=0xE6; //设定时值为38K 也就是每隔26us中断一次
count++;
if (flag==1)
{
OP=~OP;
}
else
{
OP = 0;
}
P3_4 = OP;
}
void
SendIRdata(char p_irdata)
{
int i;
char irdata=p_irdata;
//发送9ms的起始码
endcount=223;
flag=1;
count=0;
do{}while(count<endcount);
//发送45ms的结果码
endcount=117
flag=0;
count=0;
do{}while(count<endcount);
//发送十六位地址的前八位
irdata=iraddr1;
for(i=0;i<8;i++)
{
//先发送056ms的38KHZ红外波(即编码中056ms的低电平)
endcount=10;
flag=1;
count=0;
do{}while(count<endcount);
//停止发送红外信号(即编码中的高电平)
if(irdata-(irdata/2)2)
//判断二进制数个位为1还是0
{
endcount=41;
//1为宽的高电平
}
else
{
endcount=15; //0为窄的高电平
}
flag=0;
count=0;
do{}while(count<endcount);
irdata=irdata>>1;
}
//发送十六位地址的后八位
irdata=iraddr2;
for(i=0;i<8;i++)
{
endcount=10;
flag=1;
count=0;
do{}while(count<endcount);
if(irdata-(irdata/2)2)
{
endcount=41;
}
else
{
endcount=15;
}
flag=0;
count=0;
do{}while(count<endcount);
irdata=irdata>>1;
}
//发送八位数据
irdata=p_irdata;
for(i=0;i<8;i++)
{
endcount=10;
flag=1;
count=0;
do{}while(count<endcount);
if(irdata-(irdata/2)2)
{
endcount=41;
}
else
{
endcount=15;
}
flag=0;
count=0;
do{}while(count<endcount);
irdata=irdata>>1;
}
//发送八位数据的反码
irdata=~p_irdata;
for(i=0;i<8;i++)
{
endcount=10;
flag=1;
count=0;
do{}while(count<endcount);
if(irdata-(irdata/2)2)
{
endcount=41;
}
else
{
endcount=15;
}
flag=0;
count=0;
do{}while(count<endcount);
irdata=irdata>>1;
}
endcount=10;
flag=1;
count=0;
do{}while(count<endcount);
flag=0;
}
void delay()
{
int i,j;
for(i=0;i<400;i++)
{
for(j=0;j<100;j++)
{
}
}
}
你要明白,你按数字键1,其实它是发射一个红外代码。一个遥控器的红外代码应由以下三部分组成:引导码,前16为用户识别码(即不同产家不用型号不同遥控有不同用户码),后16位为 *** 作码(里面8位功能码及8位功能反码,这16位就是遥控器上不同按键的区分)。上面32位码都是二进制数,即“0”、“1“。程序中第一个for语句,是把用户识别码和 *** 作码一起分成4部分,每部分8位(1个字节),接下来的for语句是对每一位进行判断,判断是0还是1,然后用value通过与来记住一个字节里面的每一位,最后再将value赋给date。
红外收发中,IRDATA[2]与IRDATA[3]是取反的关系。也就是说两个数对应各位前者为1后者就为0
其余的问题,都是根据红外接收时序来编的程序,以下总结以下红外收发时序供参考,你读懂就可以理解了。
采用脉宽调制的串行码,以脉宽为0565ms、间隔056ms、周期为1125ms的组合表示二进制的"0";;以脉宽为0565ms、间隔1685ms、周期为225ms的组合表示二进制的"1“上述"0"和"1"组成的32位二进制码经38kHz的载频进行二次调制以提高发射效率,达到降低电源功耗的目的。然后再通过红外发射二极管产生红外线向空间发射遥控编码是连续的32位二进制码组,其中前16位为用户识别码,能区别不同的电器设备,防止不同机种遥控码互相干扰。该芯片的用户识别码固定为十六进制01H后16位为8位 *** 作码(功能码)及其反码。
发射代码由一个起始码(9ms),一个结果码(45ms),低8位地址码(9ms~18ms),高8位地址码(9ms~18ms),8位数据码(9ms~18ms)和这8位数据的反码(9ms~18ms)组成。
解码的关键是如何识别"0"和"1",接收端而言,"0"是056ms的高+056ms的低。"1"是168ms的高+056ms的低。所以可以根据高电平的宽度区别"0"和"1"。当高电平出现时开始延时,056ms以后,若读到的电平为低,说明该位为"0",反之则为"1",为了可靠起见,延时必须比056ms长些,但又不能超过112ms,否则如果该位为"0",读到的已是下一位的高电平,因此取(112ms+056ms)/2=084ms最为可靠,一般取084ms左右均可。为了共用引导部分延时程序,一般用09ms延时。
由此可见,有效数据是4字节(32位)。前两个字节可定义用户编码,后两个字节分别是真正的数据及其反码。
这是我参考别人的代码适当修改后,测试可用。
注意:与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];//取码完成后判断读码是否正确
}
以上就是关于红外线遥控器解码C语言程序代码 SM0038接受头全部的内容,包括:红外线遥控器解码C语言程序代码 SM0038接受头、求一个简单的单片机红外遥控控制led灯的收发程序、谁能告诉我,这个红外解码程序是什么意思。如何我用遥控器发射一个数字,他是如何接受和处理的,下面是程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)