这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » 红外解码的异常问题,求帮助

共14条 1/2 1 2 跳转至

红外解码的异常问题,求帮助

菜鸟
2011-03-29 16:16:37     打赏
最近在用51做红外遥控器的解码实验,出现异常的现象,异常现象如下:

解码程序下载进去后,当按下遥控器不同按键时,数码管都显示解码字段都一样,都显示

1A-dc,也就是说遥控器的所有按键的编码都一样,都为1A-dc。(我晕了,这不可能吧,要是所有按键的编码都一样,那做一个按键就行了。。。)

其次,当按下按键的时间较长时,数码管又都显示FF-FF


实验材料如下:

遥控器不知道是什么芯片编码的,遥控器上显示字样:57L5,58A3,54B4,55K2四合一。

红外线接收头是tl1838,接收头的数据引脚连接51的P3^3(P3^3是51的外部中断1引脚)



解码程序如下,用中断1解码,都有注释,很好读,希望大家能帮助分析出现此种现象可能原因,谢谢啦。



#include<reg52.h> //52单片机头文件,一般不要改动,里面包含特殊功能寄存器的定义
#include<intrins.h>

sbit hwx=P3^3; //定义红外接收脚,

code unsigned char table[]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};
//共阴数码管 0-9 a-f - 表
unsigned char l_tmpdate[8]={0,0,0x10,0,0};//显示管数据

unsigned char l_lhj[66]; //定义66位数组变量来存储接收的时间参数
void delay();//延时子函数
void display(unsigned char *lp,unsigned char lc);//数字的显示函数;lp为指向数组的地址,lc为显示的个数

void main(void) //入口函数
{
EA=1; //首先开启总中断
EX1=1; //开启外部中断 1
IT1=1; // 设置成 下降沿触发方式
while(1){ //循环显示,接收都由中断处理
display(l_tmpdate,5);
}

}
void display(unsigned char *lp,unsigned char lc)//显示
{
unsigned char i; //定义变量
P2=0; //端口2为输出
P1=P1&0xF8; //将P1口的前3位输出0,对应138译门输入脚,全0为第一位数码管
for(i=0;i<lc;i++){ //循环显示
P2=table[lp[i]]; //查表法得到要显示数字的数码段
delay(); //延时
P2=0; //清0端口,准备显示下位
if(i==7) //检测显示完8位否,完成直接退出,不让P1口再加1,否则进位影响到第四位数据
break;
P1++; //下一位数码管
}
}
void delay(void) //空5个指令
{
unsigned char i=13;
while(i)
i--;
}
void hongwai(void) interrupt 2 //外部中断 1 ,INT1(P3^3)连接红外线接收IC数据脚
{
unsigned char i,j,tmp;
EX1=0;
// hwx=1;
j=33; //传送一组数包括引导码1位,地址码8位加反码8位,指令码8位加反码8位,总共33位
i=0; //从第一维数组开始
tmp=100; //加八延时,
while(tmp){
tmp--;
}
if(hwx){ //然后再检测红线接收脚是有数据招收,有继续,没有则退出
EX1=1;
return;
}
while(j){ //循环接收33位数据,为何我们用到66位数组,我们可以不接收高电平时间常数,只接低电平常数就
//可以判断1或0了,在这里我们都接收,为串口调试软件接收计算波形
//还有一点要知道,接收波形是反向,在没有接收时端口为高电平
tmp=0;
l_lhj[i]=1; //时间量从1开始
while(!hwx){ //检测高低电平的变化
l_lhj[i]++; //没变继续加1
delay(); //加入延时,是因为我们采用8位二进来存储,如果不加延时,时间量将计满
tmp++; //此变量为防止干扰带来的死循环
if(tmp==250)
break;
}
i++;
tmp=0;
l_lhj[i]=1; //时间量从1开始
while(hwx){ //检测高低电平的变化
l_lhj[i]++; //没变继续加1
delay(); //同上
tmp++;
if(tmp==250)
break;
}
i++;
j--;
}
i=255; //加入循环延时,抗干扰
while(i){
tmp=255;
while(tmp){
P2=0XF0;
tmp--;
}
i--;
}
tmp=0;
for(i=3;i<19;i++,i++){ //处理地址位,对低电平时间数据的数理,这里我们只处理地址码和指令码,引导码和反码我们就忽略
tmp>>=1; //右移一位,接收低电平在前
if(l_lhj[i]>30) //检测低电平时间超过30就确认为1
tmp+=0x80;
}
l_tmpdate[0]=tmp/16; //分开2位以16进制显示
l_tmpdate[1]=tmp%16;
tmp=0;
for(i=35;i<51;i++,i++){ //同上,这里处理指令位
tmp>>=1;
if(l_lhj[i]>30)
tmp+=0x80;
}
l_tmpdate[3]=tmp/16;
l_tmpdate[4]=tmp%16;
EX1=1;
}



关键词: 红外     解码     异常     问题     帮助     显示     接收     unsi    

专家
2011-03-29 17:07:43     打赏
2楼
不能这么写程序,你的中断里面处理的东西太多了!
因为编码接收到是很快的!你还没处理完一个个数据下一位码就过来了!你可以在while里面处理,终端的话只是检测到中断就行!剩下的交给中断外部来处理

菜鸟
2011-03-29 18:27:01     打赏
3楼
也就是说,我在中断里只负责快速的接收编码,处理编码是留在中断外来做,是这样吗?

高工
2011-04-01 14:20:48     打赏
4楼

是不是可以这样理解,中断只负责接受任务,解决交给外部


高工
2011-04-01 14:21:58     打赏
5楼

把里面的一些中断处理变为外部函数调用?


菜鸟
2011-04-02 09:27:48     打赏
6楼
应该不是吧。因为这样做只是减少中断服务子程序的代码量,执行时间并没有减少。
应该是在中断服务子程序里只负责接收红外信号。

专家
2011-04-02 09:34:55     打赏
7楼
是的,中断复杂接收任务就行!要不然在中断处理的话会消耗很多时间

菜鸟
2011-04-02 09:37:25     打赏
8楼
遥控器上的字样:57L5,58A3,54B4,55K2四合一是什么意思啊?
该遥控器是是NEC的编码吗?
大家提点意见。。。。

专家
2011-04-02 09:39:30     打赏
9楼
中断最好是复杂接收信号就行?你说仅仅是减少代码量而已?不是的,你想想啊,假如说你在中断里面处理的话,那个处理函数还没有处理完毕的时候,这个时候还有信号呢?你采集么?不采集的话就造成了数据的丢失,采集的话函数再重新进入中断服务子函数,这个合适和你想要的逻辑不符合!
尽量不要在中断里面处理过多的数据!特别是延时,这是非常不好的!

菜鸟
2011-04-02 09:45:12     打赏
10楼

//该遥控器是NEC编码的,在中断里我这样接收红外信号,是否可行

uchar chubus[33],用于接收时间常数

void ex1() interrupt 2//外部中断1接收红外数据
{
 static bit startflag;//开始接收标志位
 static uchar i;

 if(startflag)
 {
  if(timedata<60&&timedata>=36)  i=0;//一位引导码 9+4.5毫秒
  chubus[i]=timedata;   //timedata用定时器方式1计时,0.25毫秒中断一次
  timedata=0;
  i++;
  if(i==33)
  {
  overflag=1;
  startflag=0;
  i=0;
  }  
 }
 else
 {
  startflag=1;
  timedata=0;
 }
}


共14条 1/2 1 2 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]