红外线遥控器解码程序文档格式.docx
- 文档编号:22405510
- 上传时间:2023-02-03
- 格式:DOCX
- 页数:68
- 大小:49.07KB
红外线遥控器解码程序文档格式.docx
《红外线遥控器解码程序文档格式.docx》由会员分享,可在线阅读,更多相关《红外线遥控器解码程序文档格式.docx(68页珍藏版)》请在冰豆网上搜索。
暂时关闭CPU的所有中断请求
MOVR6,#10
SB:
ACALLYS1;
调用882微秒延时子程序
JBP3.2,EXIT;
延时882微秒后判断P3.2脚是否出现高电平如果有就退出解码程序
DJNZR6,SB;
重复10次,目的是检测在8820微秒内如果出现高电平就退出解码程序
以上完成对遥控信号的9000微秒的初始低电平信号的识别。
JNBP3.2,$;
等待高电平避开9毫秒低电平引导脉冲
ACALLYS2;
延时4.74毫秒避开4.5毫秒的结果码
MOVR7,#26;
忽略前26位系统识别码
JJJJA:
JNBP3.2,$;
等待地址码第一位的高电平信号
LCALLYS1;
高电平开始后用882微秒的时间尺去判断信号此时的高低电平状态
MOVC,P3.2;
将P3.2引脚此时的电平状态0或1存入C中
JNCUUUA;
如果为0就跳转到UUUA
LCALLYS3;
检测到高电平1的话延时1毫秒等待脉冲高电平结束
UUUA:
DJNZR7,JJJJA
MOVR1,#1AH;
设定1AH为起始RAM区
MOVR2,#2;
接收从1AH到1BH的2个内存,用于存放操作码和操作反码
PP:
MOVR3,#8;
每组数据为8位
JJJJ:
JNBP3.2,$;
JNCUUU;
如果为0就跳转到UUU
UUU:
MOVA,@R1;
将R1中地址的给A
RRCA;
将C中的值0或1移入A中的最低位
MOV@R1,A;
将A中的数暂时存放在R1数值的内存中
DJNZR3,JJJJ;
接收满8位换一个内存
INCR1;
对R1中的值加1,换下一个RAM
DJNZR2,PP;
接收完8位数据码和8位数据反码,存放在1AH/1BH中
MOVA,1AH
CPLA;
对1AH取反后和1BH比较
CJNEA,1BH,EXIT;
如果不等表示接收数据发生错误,放弃
MOVP1,1AH;
将按键的键值通过P1口的8个LED显示出来!
CLRP2.5;
蜂鸣器鸣响-嘀嘀嘀-的声音,表示解码成功
LCALLYS2
SETBP2.5;
蜂鸣器停止
EXIT:
SETBEA;
允许中断
RETI;
退出解码子程序
YS1:
MOVR4,#20;
延时子程序1,精确延时882微秒
D1:
MOVR5,#20
DJNZR5,$
DJNZR4,D1
RET
YS2:
MOVR4,#10;
延时子程序2,精确延时4740微秒
D2:
MOVR5,#235
DJNZR4,D2
YS3:
MOVR4,#2;
延时程序3,精确延时1000微秒
D3:
MOVR5,#248
DJNZR4,D3
END
0A
01
11121314
15161718
19101A1B
0E02031C
0604050C
0D08091D
001F1E0B
07
0F
这是按照红外遥控器按键的实际位置给出的32个按键的键值(16进制)
37sina3228
AJMPMAIN
外部中断INT0入口地址
转中断服务子程序
MOVSP,#40H
MOVP1,#00H
开CPU中断
设定INT0触发方式
INT0请求中断
DSP:
MOVR2,#9;
将遥控器键值转化成A(0~9)
MOVDPTR,#TAB1
VV:
MOVA,R2
MOVCA,@A+DPTR
XRLA,1CH
JZABC
DJNZR2,VV
ABC:
MOVDPTR,#TAB;
将A的值通过数码管显示出来
MOVCA,@A+DPTR
RX1:
MOVP1,A
CLRP0.1
AJMPDSP
CLREA
ACALLYS1
JBP3.2,EXIT
DJNZR6,SB
JNBP3.2,$;
ACALLYS2;
延时4。
74毫秒判断是否连发
CPLP0.0
将32位代码分别放在1AH/1BH/1CH/1DH中
MOVR2,#4
MOVR3,#8
JNBP3.2,$
LCALLYS1
MOVC,P3.2
JNCUUU
JBP3.2,$
MOVA,@R1
RRCA
MOV@R1,A
DJNZR3,JJJJ
INCR1
DJNZR2,PP
MOVP2,1CH
MOVA,1AH;
进行代码识别
XRLA,#0;
判断1AH的值是否等于00000000
JNZEXI;
如果不同则无效将1CH清零
MOVA,1BH
XRLA,#11110111B;
再判断高8位地址是否正确
JNZEXI
MOVA,1CH
CPLA
XRLA,1DH;
将1CH的值取反后和1DH比较不同则无效丢弃核对数据是否准确
JNZEXI
AJMPEXIT
EXI:
MOV1CH,#0
SETBEA;
RETI
MOVR4,#20;
精确延时882微秒
MOVR4,#10;
精确延时4740微秒
TAB:
DB60H,7DH,0D0H,58H,4DH
DB4AH,42H,7CH,40H,48H
TAB1:
DB0CH,09H,1DH,1FH,0DH
DB19H,1BH,11H,15H,17H
;
TABLED数码管显示表TAB1遥控器键值表
这里我们以红外线遥控编码芯片为uPD6121G(或者是HT622、7461等芯片)为例来说明用单片机实现红外遥控解码的详细过程
以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示二进制的“1”,其波形如图2所示。
UPD6121G产生的遥控编码是连续的32位二进制码组,其中前16位为用户识别码,能区别不同的电器设备,防止不同机种遥控码互相干扰。
该芯片的用户识别码固定为十六进制01H;
后16位为8位操作码(功能码)及其反码。
UPD6121G最多额128种不同组合的编码。
遥控器在按键按下后,周期性地发出同一种32位二进制码,周期约为108ms。
一组码本身的持续时间随它包含的二进制“0”和“1”的个数不同而不同,大约在45~63ms之间,图4为发射波形图。
当一个键按下超过36ms,振荡器使芯片激活,将发射一组108ms的编码脉冲,这108ms发射代码由一个起始码(9ms),一个结果码(4.5ms),低8位地址码(9ms~18ms),高8位地址码(9ms~18ms),8位数据码(9ms~18ms)和这8位数据的反码(9ms~18ms)组成。
如果键按下超过108ms仍未松开,接下来发射的代码(连发代码)将仅由起始码(9ms)和结束码(2.5ms)组成。
代码宽度算法:
16位地址码的最短宽度:
1.12×
16=18ms16位地址码的最长宽度:
2.24ms×
16=36ms
易知8位数据代码及其8位反代码的宽度和不变:
(1.12ms+2.24ms)×
8=27ms
∴32位代码的宽度为(18ms+27ms)~(36ms+27ms)
1.解码的关键是如何识别“0”和“1”,从位的定义我们可以发现“0”、“1”均以0.56ms的低电平开始,不同的是高电平的宽度不同,“0”为0.56ms,“1”为1.68ms,所以必须根据高电平的宽度区别“0”和“1”。
如果从0.56ms低电平过后,开始延时,0.56ms以后,若读到的电平为低,说明该位为“0”,反之则为“1”,为了可靠起见,延时必须比0.56ms长些,但又不能超过1.12ms,否则如果该位为“0”,读到的已是下一位的高电平,因此取(1.12ms+0.56ms)/2=0.84ms最为可靠,一般取0.84ms左右均可。
2.根据码的格式,应该等待9ms的起始码和4.5ms的结果码完成后才能读码。
接收器及解码
这是站长最新用单片机AT89C51制作的30路红外遥控器,遥控器就是自家的VCD遥控器,接收板用了5片CD4069作为输出缓冲隔离,当按下遥控器30个按键中的一个,接收板对应的一个触点会变成高电平,松开按键,立即恢复成低电平,和TTL兼容。
45sina3228
红外遥控器软件解码原理及程序
红外一开始发送一段13.5ms的引导码,引导码由9ms的高电平和4.5ms的低电平组成,跟着引导码是系统码,系统反码,按键码,按键反码,如果按着键不放,则遥控器则发送一段重复码,重复码由9ms的高电平,2.25ms的低电平,跟着是一个短脉冲,本程序经过试用,能解大部分遥控器的编码!
#include"
at89x52.h"
#defineNULL0x00//数据无效
#defineRESET0X01//程序复位
#defineREQUEST0X02//请求信号
#defineACK0x03//应答信号,在接收数据后发送ACK信号表示数据接收正确,也位请求信号的应答信号
#defineNACK0x04//应答信号,表示接收数据错误
#defineBUSY0x05//忙信号,表示正在忙
#defineFREE0x06//空闲信号,表示处于空闲状态
#defineREAD_IR0x0b//读取红外
#defineSTORE_IR0x0c//保存数据
#defineREAD_KEY0x0d//读取键值
#defineRECEIVE0Xf400//接收缓冲开始地址
#defineSEND0xfa00//发送缓冲开始地址
#defineIR0x50//红外接收缓冲开始地址
#defineHEAD0xaa//数据帧头
#defineTAIL0x55//数据帧尾
#defineSDAP1_7
#defineSCLP1_6
unsignedcharxdata*buf1;
//接受数据缓冲
unsignedintbuf1_length;
//接收到的数据实际长度
unsignedcharxdata*buf2;
//发送数据缓冲
unsignedintbuf2_length;
//要发送的数据实际长度
bitbuf1_flag;
//接收标志,1表示接受到一个数据帧,0表示没有接受到数据帧或数据帧为空
bitbuf2_flag;
//发送标志,1表示需要发送或没发送完毕,0表示没有要发送的数据或发送完毕
unsignedcharstate1,state2;
//用来标志接收字符的状态,state1用来表示接收状态,state2用来表示发送状态
unsignedchardata*ir;
union{
unsignedchara[2];
unsignedintb;
unsignedchardata*p1[2];
unsignedintdata*p2[2];
unsignedcharxdata*p3;
//红外缓冲的指针
unsignedintxdata*p4;
}p;
//union{//
//unsignedchara[2];
//
//unsignedintb;
//unsignedchardata*p1[2];
//unsignedintdata*p2[2];
//unsignedcharxdata*p3;
//unsignedintxdata*p4;
//地址指针
//}q;
}count;
}temp;
unsignedchara[4];
unsignedintb[2];
unsignedlongc;
}ir_code;
unsignedchardata*p1[4];
unsignedintdata*p2[4];
unsignedcharxdata*p3[2];
unsignedintxdata*p4[2];
}i;
unsignedcharir_key;
bitir_flag;
//红外接收标志,0为缓冲区空,1为接收成功,2为缓冲溢出
voidsub(void);
voiddelay(void);
voidie_0(void);
voidtf_0(void);
voidie_1(void);
voidtf_1(void);
voidtf_2(void);
voidread_ir(void);
voidir_jiema(void);
voidir_init(void);
voidir_exit(void);
voidstore_ir(void);
voidread_key(void);
voidreset_iic(void);
unsignedcharread_byte_ack_iic(void);
unsignedcharread_byte_nack_iic(void);
bitwrite_byte_iic(unsignedchara);
voidsend_ack_iic(void);
voidsend_nack_iic(void);
bitreceive_ack_iic(void);
voidstart_iic(void);
voidstop_iic(void);
voidwrite_key_data(unsignedchara);
unsignedintread_key_data(unsignedchara);
voidie0(void)interrupt0{ie_0();
}
voidtf0(void)interrupt1{tf_0();
voidie1(void)interrupt2{ie_1();
voidtf1(void)interrupt3{tf_1();
tf_2();
voidtf2(void)interrupt5{//采用中断方式跟查询方式相结合的办法解码
EA=0;
//禁止中断
if(TF2){//判断是否是溢出还是电平变化产生的中断
TF2=0;
//如果是溢出产生的中断则清除溢出位,重新开放中断退出
EA=1;
gotoend;
EXF2=0;
//清除电平变化产生的中断位
*ir=RCAP2H;
//把捕捉的数保存起来
ir++;
*ir=RCAP2L;
*ir++;
F0=1;
TR0=1;
//开启计数器0
loop:
TL0=0;
//将计数器0重新置为零
TH0=0;
while(!
EXF2){//查询等待EXF2变为1
if(TF0)gotoexit;
//检查有没超时,如果超时则退出
};
//将EXF2清零
if(!
TH0)//判断是否是长低电平脉冲过来了
{//不是长低电平脉冲而是短低电平
if(F0)count.b++;
//短脉冲数加一
temp.a[0]=RCAP2H;
//将捕捉数临时存放起来
temp.a[1]=RCAP2L;
gotoloop;
//返回继续查询
else{//是低电平脉冲,则进行处理
F0=0;
*ir=temp.a[0];
//把连续的短脉冲总时间记录下来
*ir=temp.a[1];
//把长电平脉冲时间记录下来
if(ir>
=0xda){
gotoexit;
//判断是否溢出缓冲,如果溢出则失败退出
exit:
ir_flag=1;
//置ir_flag为1表示接收成功
end:
voidrs232(void)interrupt4{
staticunsignedcharsbuf1,sbuf2,rsbuf1,rsbuf2;
//sbuf1,sbuf2用来接收发送临时用,rsbuf1,rsbuf2用来分别用来存放接收发送的半字节
if(RI){
RI=0;
//清除接收中断标志位
sbuf1=SBUF;
//将接收缓冲的字符复制到sbuf1
if(sbuf1==HEAD){//判断是否帧开头
state1=10;
//是则把state赋值为10
buf1=RECEIVE;
//初始化接收地址
else{
switch(state1){
case10:
sbuf2=sbuf1>
>
4;
//把高半字节右移到的半字节
sbuf2=~sbuf2;
//把低半字节取反
if((sbuf2&
0x0f)!
=(sbuf1&
0x0f))//判断接收是否正确
{//接收错误,有可能接收的是数据帧尾,也有可能是接收错误
if(sbuf1==TAIL)//判断是否接收到数据帧尾
{//是接收到数据帧尾
//初始化接收的地址
if(*buf1==RESET)//判断是否为复位命令
{
ES=0;
sbuf2=SP+1;
for(p.p1[0]=SP-0x10;
p.p1[0]<
=sbuf2;
p.p1[0]++)*p.p1[0]=0;
state1=0;
//将接收状态标志置为零,接收下一个数据帧
buf1_flag=1;
//置接收标志为1,表示已经接收到一个数据帧
REN=0;
//禁止接收
else
{//不是接受到数据帧尾,表明接收错误
//将接收状态标志置为零,重新接收
//初始化发送的地址
*buf1=NACK;
//把NACK信号存入接收缓冲里
//置标志位为1,使主
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 红外线 遥控器 解码 程序