初学时序,50462的红外解码拆腾了好几天也没解出来,发上代码和时序图高手帮我看看【
程序是用网上公布的9012解码改的,整了好多天,没整出来// 本程序主要是遥控器解码和1602驱动程序
//-------------------------------------------------------
// LCD1602 IR-DECODE
// writed by nxp---2006.12.29
//-------------------------------------------------------
// 连线表: CPU=89S52
// SysClock=12MHz
// LCD: 1602
// 功能:解码红外遥控器
// 遥控器芯片:50462
#include <at89x52.h>
#define uchar unsigned char
#define uint unsigned int
/*----------------------------控制I/O口设置,根据实际而定---------------*/
#define RS P2_7 //RS数据命令选择端,高电平数据,低电平命令
#define RW P2_6 //RW读写选择端,高电平读操作,低电平写操作
#define E P2_5 //E使能控制端,E高电平跳变为低电平时LCD执行命令
#define DATA P0 //数据端口定义
#define D0 P0_0
#define D1 P0_1
#define D2 P0_2
#define D3 P0_3
#define D4 P0_4
#define D5 P0_5
#define D6 P0_6
#define D7 P0_7
#define IR_RE P3_2
/*------------------------------------------------------------------------------*/
bit k=0; //红外解码判断标志位,为0则为有效信号,为1则为无效
uchar n=0; //用来控制外部中断
uchar code str0=" REMOTE CONTROL"; //开机画面显示
uchar code str1=" IR-CODE: ";
uchar code str2="ERROR";
uchar *p0=str0;
uchar *p1=str1;
uchar *p2=str2;
delay1ms(uint k);
void disp(void); //红外键值显示程序
uchar data date; //date数组为存放地址原码,数据原码
/*------------------------LCD忙判断子程序--------------------------------------*/
void busy()
{
RS=0;RW=1;
E=0;E=1;DATA=0xff;
while(D7);
}
/*----------------------- 写命令子程序-----------------------------------------*/
void wcom(uchar com)
{
busy();
RS=0;RW=0;
E=1;
DATA=com;
E=0;
}
/*-------------------------写数据子程序--------------------------------------*/
void wdata(uchar dat)
{
busy();
RS=1;RW=0;
E=1;
DATA=dat;
E=0;
}
/*--------------------------读命令子程序-----------------------------------*/
uchar rcom(void)
{
uchar com;
busy();
RS=0;RW=1;
DATA=0xff;
E=1;
com=DATA;
E=0;
return(com);
}
/*----------------------------读数据子程序-----------------------------*/
uchar rdat(void)
{
uchar dat;
busy();
RS=1;RW=1;
DATA=0xff;
E=1;
dat=DATA;
E=0;
return(dat);
}
/*--------------------------延时1.05ms程子程序-----------------------*/
delay1050()
{
uint i,j;
for(i=0;i<1;i++)
for(j=0;j<130;j++)
;
}
/*---------------------------延时920us子程序-----------------------*/
delay920()
{
uint i,j;
for(i=0;i<1;i++)
for(j=0;j<113;j++)
;
}
/*--------------------------延时2400ms程子程序-----------------------*/
delay2400()
{
uint i,j;
for(i=0;i<3;i++)
for(j=0;j<99;j++)
;
}
/*--------------------------以下为初始化程序,由上面子程序组成,根据个人爱好-----------*/
/******************************清屏程序***********************************/
void clear()
{ wcom (0x01);}
/******************************归位程序********************************/
void rehome()
{ wcom(0x02); }
/*******************8*****888**88888显示模式设定8888888888888888888888*/
void mode(bit x)
{
if(x==1)wcom(0x38); //两行5*8 mode
else wcom(0x34); //一行5*10 mode
}
/*------------------------显示开关控制命令----------------------------*/
void on_off(bit x)
{
if(x==1)wcom(0x0f); //显示开,光标开,光标闪烁
else wcom(0x0c); //显示开,光标关
}
/*------------------------init初始化组合-------------------------*/
void init()
{
clear(); //清屏
mode(1); //模式设置
on_off(1); //显示设置
wcom(0x06); //移动方式
}
/*---------------------------对字符串的处理------------------------*/
void strchar(uchar *p)
{
while(*p!='\0')
{
wdata(*p);
p++;
}
}
/*----------------------------------------------------------*/
/*-----------------------红外解码程序(核心)-----------------*/
/*----------------------------------------------------------*/
void IR_decode()
{
uchar i,j;
for(i=0;i<2;i++)
{
for(j=0;j<8;j++)
{
while(IR_RE==1); //等待低电平到来
while(IR_RE==0); //等待地址码第1位高电平到来
delay920(); //延时920ms判断此时引脚电平
if(IR_RE==1)
{
delay920();
date>>=1;
date=date&0x80;
}
else if(IR_RE==0)
{
date>>=1;
date=date|0x7f;
}
} //1位数据接收结束
} //32位二进制码接收结束
delay1050();
delay1050();
delay1050();
}
/*------------------二进制码转换为压缩型BCD码,并显示---------------*/
void two_2_bcd(uchar date)
{
uchar temp;
temp=date;
date&=0xf0;
date>>=4; //右移四位得到高四位码
date&=0x0f; //与0x0f想与确保高四位为0
if(date<=0x09)
{
// wcom(0xcb);
wdata(0x30+date); //lcd显示键值高四位
}
else
{
date=date-0x09;
//wcom(0xcb);
wdata(0x40+date);
}
date=temp;
date&=0x0f;
if(date<=0x09)
{
wdata(0x30+date); //lcd显示低四位值
}
else
{
date=date-0x09;
wdata(0x40+date);
}
wdata(0x48); //显示字符'H'
}
//////////////////////////////转换程序结束///////////////////////////
/*----------------------解码成功后,1602显示键值子程序---------------*/
void disp()
{
wcom(0xc0);
two_2_bcd(date);
wdata(0x20);
two_2_bcd(date);
wdata(0x20);
}
/*------------------------外部中断0程序-------------------------*/
/*------------------主要用于处理红外遥控键值--------------------*/
void int0() interrupt 0
{
uint i;
if(k==0)
{
EX0=0; //检测到有效信号关中断,防止干扰
IR_decode(); //如果接收到的是有效信号,则调用解码程序
disp(); //解码成功,调用显示程序,显示该键值
}
EX0=1; //开外部中断,允许新的遥控按键
}
/*---------------------------------------------------------------*/
/* 以下为主程序,主要对LCD初始化,开始界面设置 */
/*---------------------------------------------------------------*/
void main(void)
{
SP=0x60; //堆栈指针
TMOD=0x11; //定时器模式设置所选为 模式1
TH0=0xd8; //定时器初值理论为 10ms;
TL0=0xf7; //实际取d8f7
ET0=1; //允许定时器0中断
EX0=1; //允许外部中断0,用于检测红外遥控器按键
EA=1; //总中断开
init(); //初始化LCD
wcom(0x80); //写入字符的地址为第1行第1列
strchar(p0); //调用显示字符串函数
wcom(0xc0);
//strchar(p1);
while(1);
}
http://cache.amobbs.com/bbs_upload782111/files_11/ourdev_530860.jpg
50462时序图 (原文件名:50462时序图.jpg)
本贴被 ciddy 编辑过,最后修改时间:2008-12-06,10:46:49. 红外解码最关键的是时序要控制得非常好,配合你的12M晶振,弄一个准确的延时试试(时间可用keil仿真得到,力求精确)
我有个帖讲红外解码的,LZ可以看下. 定时器还没学呢,找到了一个汇编的,不懂汇编,里边没有显示模块,没法测试,哪位帮忙把核心部分转成C的
;/////////////////////// 宏定义 ////////////////////////////////////////
STACK_START EQU 03Fh ;堆栈起始
DELAY_TIME_H EQU 0F8H ;计时器2ms中断
DELAY_TIME_L EQU 02FH
FLAG_REM BIT 00H ;已接收到遥控信号
FLAG_REM_TIMEOUT BIT 01H ;接收遥控信号超时
;/////////////////////// 变量 //////////////////////////////////////////
REM_CNT EQU 7EH ;已接收数据位数
REM_BUF EQU 7FH ;遥控数据缓冲区
;============================================================================
;------------------------- 主程序 -----------------------------------------
ORG 0000H
JMP MAIN
ORG 0003H ;外部中断
JMP INT_REM
ORG 000BH ;计时器中断
AJMP INT_TIMER
MAIN:
MOV SP,#STACK_START
MOV TH0,#DELAY_TIME_H
MOV TL0,#DELAY_TIME_L
MOV TMOD,#00100001B ;计时器模式
MOV TL1,#0FDH ; 9600 BPS
MOV TH1,#0FDH ; 8 位
MOV SCON,#01000000B ; 无校验
SETB TR0 ;开计数器
SETB TR1
SETB ET0 ;开中断
SETB EX0
SETB EA
CLR FLAG_REM
SETB FLAG_REM_TIMEOUT
MOV REM_CNT,#0
;-------------------------主循环---------------------------------------------
LOOP:
JB FLAG_REM,REM_HANDLE ;有遥控信号未处理
JMP LOOP
;--------------------------遥控数据处理--------------------------------------
REM_HANDLE:
MOV A,REM_BUF ;通过串口发送数据
MOV SBUF,A
JNB TI,$
CLR TI
ACALL DELAY_100MS
CLR FLAG_REM
JMP LOOP
;--------------------------外部中断(遥控输入)--------------------------------
; 遥控芯片: M50462AP
;
INT_REM:
CLR EX0 ;关中断
PUSH PSW ;保存现场
PUSH ACC
JB FLAG_REM,INT_REM_END ;有遥控信号未处理
;拒绝接收
SETB RS0
MOV R5,#50 ;延时200US去干扰
REM_DELAY:
JB P3.2,INT_REM_END
DJNZ R5,REM_DELAY
JB FLAG_REM_TIMEOUT,REM_START
;已超时,重新开始
MOV A,TH0 ;粗略计算两次间隔
ANL A,#0FH
CJNE A,#0BH,REM_SKIP_CHK_0
BIT_IS_0:
CLR C ;BIT IS 0
JMP REM_CHK_OK
REM_SKIP_CHK_0:
JC INT_REM_END ;<0BH
CJNE A,#0EH,REM_CHK_1 ;干扰
BIT_IS_1:
SETB C ;BIT IS 1
JMP REM_CHK_OK
REM_CHK_1:
JC BIT_IS_0 ;<0EH
JMP BIT_IS_1 ;>0EH
REM_CHK_OK:
MOV A,REM_BUF ;将一位数据存储
RRC A
MOV REM_BUF,A
INC REM_CNT ;接收位数计数器加一
MOV A,REM_CNT
CJNE A,#10H,REM_CHK_NEXT ;已接收到16位数据
SETB FLAG_REM ;接收到有效的遥控信号
;遥控码在 REM_BUF 里
REM_START:
MOV REM_CNT,#0
REM_CHK_NEXT:
MOV TH0,#DELAY_TIME_H ;设置超时计数器
MOV TL0,#DELAY_TIME_L
CLR FLAG_REM_TIMEOUT
INT_REM_END:
POP ACC ;恢复现场
POP PSW
SETB EX0
RETI
;-------------------------计时器中断-----------------------------------------
INT_TIMER:
SETB FLAG_REM_TIMEOUT
RETI
;--------------------------延时子程序----------------------------------------
DELAY_100MS:
MOV R7,#0C8H
DELAY_100MS_L0:
MOV R6,#0F8H
DELAY_100MS_L1:
DJNZ R6,DELAY_100MS_L1
NOP
DJNZ R7,DELAY_100MS_L0
RET
END 你用定时器读取值吧,很好用的 没有引导码的话可以参考下异步串口的检测方法 没有引导码的,我有9012和3010的程序,还是没整出来,还有一个网上找的时序图,也是50462的
http://cache.amobbs.com/bbs_upload782111/files_11/ourdev_530903.jpg
(原文件名:2005510176625.jpg)
图中波形为开机键的键码二进制表示11100010(引导码C0-C7)和01000000(键码D0-D7)
十六进制表示为#4702H,47为引导码 02为键码
http://cache.amobbs.com/bbs_upload782111/files_11/ourdev_530904.jpg
(原文件名:200551011237158.jpg)
一个0.25MS宽的低电平加一个0.75MS的高电平 表示“0”
一个0.25MS宽的低电平加一个1.75MS的高电平 表示“1”
本贴被 ciddy 编辑过,最后修改时间:2008-12-06,11:33:36. 我这是038的红外解码程序,不过原理应当差不多的,不知你是否需要,你所说的50462没有引导码吗?038是有的引导码的 mark 这个50462就是不大容易搞定~~~~~~~~~~~~
页:
[1]