最近在用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;
}
2楼
不能这么写程序,你的中断里面处理的东西太多了!
因为编码接收到是很快的!你还没处理完一个个数据下一位码就过来了!你可以在while里面处理,终端的话只是检测到中断就行!剩下的交给中断外部来处理
因为编码接收到是很快的!你还没处理完一个个数据下一位码就过来了!你可以在while里面处理,终端的话只是检测到中断就行!剩下的交给中断外部来处理
9楼
中断最好是复杂接收信号就行?你说仅仅是减少代码量而已?不是的,你想想啊,假如说你在中断里面处理的话,那个处理函数还没有处理完毕的时候,这个时候还有信号呢?你采集么?不采集的话就造成了数据的丢失,采集的话函数再重新进入中断服务子函数,这个合适和你想要的逻辑不符合!
尽量不要在中断里面处理过多的数据!特别是延时,这是非常不好的!
尽量不要在中断里面处理过多的数据!特别是延时,这是非常不好的!
//该遥控器是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;
}
}
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
与电子爱好者谈读图二被打赏50分 | |
【FRDM-MCXN947评测】Core1适配运行FreeRtos被打赏50分 | |
【FRDM-MCXN947评测】双核调试被打赏50分 | |
【CPKCORRA8D1B评测】---移植CoreMark被打赏50分 | |
【CPKCORRA8D1B评测】---打开硬件定时器被打赏50分 | |
【FRDM-MCXA156评测】4、CAN loopback模式测试被打赏50分 | |
【CPKcorRA8D1评测】--搭建初始环境被打赏50分 | |
【FRDM-MCXA156评测】3、使用FlexIO模拟UART被打赏50分 | |
【FRDM-MCXA156评测】2、rt-thread MCXA156 BSP制作被打赏50分 | |
【FRDM-MCXN947评测】核间通信MUTEX被打赏50分 |