c51解密红外 + c语言红外解码xyWord文件下载.docx
《c51解密红外 + c语言红外解码xyWord文件下载.docx》由会员分享,可在线阅读,更多相关《c51解密红外 + c语言红外解码xyWord文件下载.docx(13页珍藏版)》请在冰豆网上搜索。
1
incr1;
mov@r1,th1;
存低电平时间值,先存高8位,后存低8位;
2US
mov@r1,tl1;
2
movth1,#0;
重赋初值;
movtl1,#13;
13为停止T1到重启T1经过的时间;
重新启动定时器;
等待变低
存高电平时间值;
movtl1,#15;
15为停止T1到重启T1经过的时间;
ajmpnext;
循环检测,直到T1在遥控器无键按下时溢出时产生中断;
ajmp$
;
-----------------------------------------
;
定时器1中断程序
在遥控器无键按下时产生中断,便依次将BMHCQ中的高低电平时间值转换为BCD码并显示出来
t1zd:
setbtr0;
启动T0
关闭T1
setbet0;
T0开中断
mova,r5
movr2,a
movr3,#0
lcallhextoxcq
lcalldisplay
jbyszt,$;
延时一段时间,以便记录显示的时间值
setbyszt
movr0,#bmhcq
dispnext:
mova,@r0;
从BMHCQ中依次取出时间值(16位)调BTOD子程序将其转换为5位BCD码并放入XCQ中再调显示子程序显示
movr3,a;
取高8位
incr0
mova,@r0
movr2,a;
取低8位
lcallBtoD;
将高电平或低电平时间值转为BCD码放于XCQ中
lcallHEXtoXCQ;
将高电平或低电平时间值转为十六进制的LED码放于XCQ中
lcalldisplay;
显示
cplp2.5;
改变批示灯的状态,以此说明显示内容的改变
延时,以便抄录时间值
djnzr5,dispnext;
获取的时间值没显示完则继续
sjmp$;
显示完毕,在此踏步
reti
HEXtoXCQ:
push00h
movr0,#xcq
mova,r2
anla,#0fH
movdptr,#LED
movca,@a+dptr
mov@r0,a
swapa
mova,r3
mov@r0,#7eh
pop00H
ret
led:
db7eh,30h,6dh,79h,33h,5bh,5fh,70h,7fh,7bh,77h,1fh,4eh,3dh,4fh,47h
---------------------------------------------
将存于R3R2中高电平或低电平时间值转为BCD码放于XCQ中
BtoD:
movr0,#BCD
movr4,#3
bd0:
mov@r0,#0;
BCD缓冲区清0
djnzr4,bd0
movr6,#16
bd1:
clrc;
将R3R2中的16位二进制值转换为三字节BCD码存入BCD缓冲区中
rlca
movr3,a
movr1,#bcd
BD3:
mova,@r1
addca,@r1
daa
mov@r1,a
incr1
djnzr4,bd3
djnzr6,bd1
movr0,#xcq;
将转换结果从BCD缓冲中存入XCQ中
bd4:
mova,@r1
xchda,@r0
djnzr4,bd4
pop00h
通过上面的程序我们读出了按下一个键后的编码的本质的东西
那么动手把图画下来找规律解码
我把我例子长虹解码后的波形图发出来
01.jpg点击图片放大
01。
JPG是脉冲开始时所有键前8个完全一样的高低脉冲
02.jpg
02。
JPG大家注意看按不同的键中间只是有3个脉冲在变化是EXCLE的W列-AC列而这3位数值就是我们解码的关键01。
JPG中8位数大家应该看出所有键都是一样的11100010后面02。
JPG中我们把键码整理出来就是
按1键0000000000H
按2键0001000010H
按3键0000100008H
按4键0001100018H
按5键。
后面就不写了
为了大家清晰可见我把画出的最后的波形图03。
JPG贴出来大家看下规律
03.jpg点击图片放大
然后我们来分析应该怎么解码我相信到了这一步应该很简单了吧比如在这个例子中我们发现后面的键码改变的部分完全是重复那么为什么完全可以不去读后面的码只读前面的16位的脉冲放在寄存器中再用比较指令跳转下面是针对这个波形图的解码程序相信大家已经能用自己手中的利器把它搞定了
写到这里我觉得很疑惑感觉自己没能把具体问题简单化很多东西还是要靠大家自己去消化理解了
程序看不懂。
?
那么OK去翻指令查书一条一条看吧程序我敢保证都是编译通过的
下面是解码程序的关键代码:
DYKJZ:
JBP3.6,$
LCALLYKJM;
核心解码代码子程序
cpla
jzno;
判断是否为错误代码(0FFH)
AJMPJZPD
NO:
LJMPDYKJZ
RET
JZPD:
CJNEA,#09H,JZ1;
键码为09H吗?
AJMPKAIS;
键码为09H转开始程序()
JZ1:
;
不为09H转最开始等待下一次遥控器按键到来
AJMPDYKJZ
RET
KAIS:
放你需要执行的代码
比如点亮一个灯给单片机接上串口用单片机控制电脑的打开放音乐。
等等
这些不属于本问讨论的范围有兴趣的可以自己扩展
;
-----------------------
------------------------
YKJM:
PUSHPSW
PUSH02H
PUSH06H
PUSH07H
PUSHB
MOVB,#0FFH
JNBTF1,JMCW;
通过T1从0开始定时到溢出来避开遥控器的重发码,也就是说在读了一个遥控按键后
CLRTF1;
到少要等到T1从0开始定时到溢出才能读取第二个按键
引导码正确时执行以下代码
CLRYKBZ;
遥控标志清0
JM21:
MOVR2,#16;
每次循环读8位码
MOVR6,#0;
存放16位码中的低8位
MOVR7,#0;
存放16位码中的高8位
JM3:
JNBP3.6,$;
等待低电平结束,不管其宽度,因为是通过高电平的宽度来区分0(约为0.5ms)和1(约为1.6ms)
MOVTH1,#0
MOVTL1,#0
SETBTR1;
启动T1,统计高电平的宽度
CLRTR1
MOVA,TH1
CJNEA,#2,JM4;
若高电平宽度值大于2,则说明此高电平为宽脉冲
(1),否则为窄脉冲(0)
JM4:
CPLC;
当TH1的值大于2时,C=0,小于2时,C=1
MOVA,R7
RRCA
MOVR7,A
MOVA,R6
MOVR6,A
DJNZR2,JM3;
连读16位,先读的为低位,后读的为高位,高8位(数据码)存于R7中,低8位(地址码)存于R6中
CJNEA,#47H,JMCW;
判断地址码是否为47H,不是转出错返回
MOVA,R7;
若地址码正确,则R7中便为数据码
movr1,#jzh
mov@r1,A
LJMPJMFH
JMCW:
MOVA,B
JMFH:
T1的溢出标志清0
MOVTH1,#0;
为T1设定初值并启动它
MOVTL1,#0;
以此来避免对同一按键读两次(避开遥控器的重发代码)
SETBTR2
POPB
POP07H
POP06H
POP02H
POPPSW
RET;
此时,若引导码、地址码、键值码和键值反码中有一个有问题,A中便为错误代码,否则,A中便为所按键之键值码
*****************c语言红外解码**************************
#include"
STC89C51RC.H"
sbitDQ=P4^3;
sbitSPK=P1^0;
#include<
absacc.h>
#defineseg1XBYTE[0xffec]
#defineseg2XBYTE[0xffed]
#defineseg3XBYTE[0xffee]
#defineseg4XBYTE[0xffef]
unsignedcharIRMcode[4];
unsignedcharcodeledmap[]=//共阴LED数码管译码表
{
0x3f,0x06,0x5b,0x4f,0x66,//0,1,2,3,4,
0x6d,0x7d,0x07,0x7f,0x6f,//5,6,7,8,9,
0x77,0x7C,0x39,0x5E,0x79,//A,b,C,d,E,
0x71,//F,
};
voiddelay(unsignedint);
voidmain()
{
EA=1;
EX2=1;
while
(1)
{
if(IRMcode[2]==~IRMcode[3]){
seg1=~ledmap[IRMcode[2]/100];
seg2=~ledmap[IRMcode[2]/10%10];
seg3=~ledmap[IRMcode[2]%10];
seg4=0xff;
//熄灭
}
}
}
//
//通用延时函数
//22.1184,10=48.4us(5us+43.4)
//22.1184,100=439us(43.4*10+5)
//22.1184,1000=4345us(43.4*100+5)
//22.1184,10000=43450us(43.45*1000+5)
voiddelay(unsignedintt)
while(--t);
voidSound(void)
SPK=0;
delay(10000);
SPK=1;
voidIRMint(void)interrupt6using2
unsignedcharcount;
unsignedintcount1;
unsignedchari,j;
EA=0;
count=9;
while(--count)
delay(100);
//440us
if(DQ){EA=1;
return;
while(DQ==0);
//通过引导码余下的低电平
//以上完成引导码4.5ms的低电平检测
count1=0;
if(DQ==0){EA=1;
while(DQ==1)//通过引导码余下的高电平
{
if(count1++>
1000){
P1=0x55;
EA=1;
//以上完成引导码4.5ms的高电平检测
for(j=0;
j<
4;
j++)//有效字节数设定
for(i=0;
i<
8;
i++)//字节bit数
//通过编码低电平
delay(200);
//延时判断编码高电平维持长度
IRMcode[j]<
<
=1;
if(DQ)IRMcode[j]|=0x01;
while(DQ==1){//通过编码余下的高电平
2000){EA=1;
}
Sound();