这是一段51单片机的红外遥控代码,主要就是用了遥控器上的三个键。看不懂呀,求大神帮助注释或解释下

这是一段51单片机的红外遥控代码,主要就是用了遥控器上的三个键。看不懂呀,求大神帮助注释或解释下,第1张

这就是一个红外解码程序,按标准来做就行了。普及一下红外解码知识:

采用脉宽调制的串行码,以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示二进制

的"0";以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示二进制的"1,上述"0"和

"1"组成的32位二进制码经38kHz的载频进行二次调制以提高发射效率,达到降低电源功耗的

目的。然后再通过红外发射二极管产生红外线向空间发射,遥控编码是连续的32位二进制码

组,其中前16位为用户识别码,能区别不同的电器设备,防止不同机种遥控码互相干扰。该

芯片的用户识别码固定为十六进制01H后16位为8位 *** 作散隐码(功能码)及其反码。

当一个键按下超过36ms,振荡器使芯片激活,将发射一组108ms的编码脉冲,这108ms发射代码

由冲亮厅一个起始码(9ms),一个结果码(4.5ms),低8位地址码(9ms~18ms),高8位地址码

(9ms~18ms),8位数据码(9ms~18ms)和这8位数据的反码(9ms~18ms)组成。如果键按下超

过108ms仍未松开,接下来发射的代码(连发代码)将仅由起始码(9ms)和结束码(2.5ms)

组成。

解码的关键是如何识别"0"和"键核1",接收端而言,"0"是0.56ms的高+0.56ms的低。"1"是1.68ms

的高+0.56ms的低。所以可以根据高电平的宽度区别"0"和"1"。当高电平出现时开始延时,

0.56ms以后,若读到的电平为低,说明该位为"0",反之则为"1",为了可靠起见,延时必须

比0.56ms长些,但又不能超过1.12ms,否则如果该位为"0",读到的已是下一位的高电平,因此

取(1.12ms+0.56ms)/2=0.84ms最为可靠,一般取0.84ms左右均可。

其实如果你是用单片机来解码或编码发送的话,我卖码锋可以提供电路图及程序(发送和接收)(c):

发送程序:

/*********************************************************

采用6221编码方式

晶振:12M

红外发送时模握,数据低位在前,高位在后

*********************************************************/

#include <reg52.h>

#include <intrins.h>

#define uint unsigned int

#define uchar unsigned char

#define nop()  _nop_()

uchar bdata tt

uchar x

sbit OP=tt^1        //红外发射管的亮灭

unsigned int count       //延时计数器

unsigned int endcount //终止延时计数

unsigned char flag      //红外发送标志

uchar iraddr1  //十六位地址的第一个字节

uchar iraddr2  //十六位地址的第二个字节

sbit yaokong = P3^2

void SendIRdata(char p_irdata)

void delay()

void main(void)

{

count = 0

flag = 0

OP = 0

yaokong = 0

EA = 1

TMOD = 0x11

ET0 = 1

TH0 = 0xFF

TL0 = 0xE6 //设定时值0为38K 也就是每隔26us中断一次

TR0 = 1

iraddr1=0x03

iraddr2=0xfc

do

{

for(x=125x<0x--)

SendIRdata(0x0c)

}while(1)

}

//定时器0中断处理

void timeint(void) interrupt 1

{

TH0=0xFF

TL0=0xE6 //设定时值为38K 也就是每隔26us中断一次

count++

if (flag==1)

{

OP=~OP

}

else

{

OP = 0

}

yaokong = OP

}

void SendIRdata(char p_irdata)

{

int i

char irdata=p_irdata

endcount=223

flag=1

count=0

do

{

}while(count<endcount)

endcount=117

flag=0

count=0

do

{

}while(count<endcount)

irdata=iraddr1

for(i=0i<8i++)

{

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=iraddr2

for(i=0i<8i++)

{

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=0i<8i++)

{

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=0i<8i++)

{

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=0i<400i++)

{

for(j=0j<100j++)

{

}

}

}

红外遥控程序

#include "SPCE061A.H"

#define LED_SEG 0x00ff //IOB0~IOB7

#define LED_DIG 0x3f00 //IOB8~IOB13

unsigned int Time=0,Code[40]={0},CodeNum=0//计数器,32位码,码字计数

//extern unsigned int Time,CodeNum,Code[40]

unsigned int Star_Flag,First_IRQ

//====================================================================================

//函数名称:unsigned getkey(void)

//函数功能:获得红外遥控器键值

//入口参数:无

//出口参数:无

//说明:适用于32位码字红外接收头及宏科万能遥控器

//====================================================================================

unsigned getkey(void)

{

unsigned int j=0

unsigned int DateCode,key=0

if(Code[0]==5) //判断头部是否是5;防止误接收

{ for(j=9j<=14j++)

{

*P_Watchdog_Clear = 0x01

if(Code[j]==1&&Code[j+1]==1&&Code[j+2]==1&&Code[j+3]==1&&Code[j+4]==1&&Code[j+5]==1&&Code[j+6]==0&&Code[j+7]==1)

{ //判断用户识别码是不是1111 1101

for(DateCode=0DateCode<8DateCode++)//若是,则开始接收八位数据码

{

Code[j+8+DateCode]<<=8

key|=Code[j+8+DateCode]

key>>=1 //将八位二进制数倒序转成16进制

}

break

}

}

Code[0]=0//将头部清零

return key//返回键值

}

else return(0)

}

//====================================================================

//函数名称:void IO_Init()

//函数功能:IO口初始化,主要是设置IOB2口,用于外中断

//入口参数:无

//出口参数:无

//====================================================================

void IO_Init()

{

*P_IOB_Attrib&=0xfffb //IOB2端口上拉电阻输入 外中断

*P_IOB_Dir&=0xfffb

*P_TimerA_Ctrl=C_SourceA_32768Hz+C_SourceB_1//TimerA:32768Hz

*P_TimerA_Data=0xfffe

*P_INT_Ctrl=C_IRQ3_EXT1|C_IRQ1_TMA// 外中断1,时基中断,定时中断

__asm("INT IRQ")

}

//做档=====================================================================

//函数并厅名称:

//函数功能绝胡隐:中断函数

//入口参数:无

//出口参数:无

//=====================================================================

void IRQ3(void) __attribute__ ((ISR))

void IRQ3(void)

{

if(*P_INT_Ctrl&C_IRQ3_EXT2)

{ //IRQ3_Ext1

*P_INT_Clear=C_IRQ3_EXT2

}

else if(*P_INT_Ctrl&C_IRQ3_EXT1)

{//外中断1用于判断脉冲个数

if(!First_IRQ) {Time=0First_IRQ=1}//第一次外中断来时设置

else

{

if(Time>180&&Time<240)//判断起始码

{Star_Flag=1CodeNum=0Code[0]=5CodeNum=1Time=0}//起始码来时设置

if(Star_Flag)//开始接收

{

if((Time>=10)&&(Time<25))Code[CodeNum]=0//计数值设置

else if((Time>25)&&(Time<40))Code[CodeNum]=1

CodeNum++//码字计数器加1

Time=0//计数值清零,以对下一个脉冲宽度进行计时

if(CodeNum>40) {CodeNum=0Star_Flag=0First_IRQ=0}//脉冲个数判断,共32个,此处设为40,是为防止漏接收

}

}

*P_INT_Clear=C_IRQ3_EXT1

}

else

{

*P_INT_Clear=C_IRQ3_KEY//IRQ3_KeyWakeUp

}

}

void IRQ1(void) __attribute__ ((ISR))

void IRQ1(void)

{ Time++//计数以获得脉冲宽度

*P_INT_Clear=C_IRQ1_TMA//clear INT flag

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12400027.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-25
下一篇 2023-05-25

发表评论

登录后才能评论

评论列表(0条)

保存