512826028 发表于 2012-4-26 20:06:13

【已解决】51简单的红外程序,出了邪门了,大家都来帮帮...

本帖最后由 512826028 于 2012-4-26 23:59 编辑

    我是今天买了一个红外的遥控器,写了一个红外接收的程序。一开始,解码都正常。后来,我在中断中添加一个加一,和减一的代码。但是,结果出人意料,程序会自动运行两边。本意是这样的,按下一个键,表示加一,计数增加一。程序放在中断中进行,进入中断就关闭了EA,应该不会再自动重复进入中断吧?我先给大家上中断部分的程序。
/************************中断0解码服务子程序**********************/
void int0(void) interrupt 0      
{
        EA=0;
        irdalow = IRDA_JIEMA();//得到解码的数据 这个数据只包括数据码!
        Delay_ms(255);//
        Delay_ms(255);//
        if(irdalow == 0x0df2) //如果按下的向上,就减一
                {
                Delay_ms(200);
                if(SCREEN_MUSIC>0)
                        SCREEN_MUSIC = SCREEN_MUSIC-1;                //向上翻
                }
        if(irdalow == 0x0ef1)//如果按下的是向下,就加一
                {
                Delay_ms(200);
                SCREEN_MUSIC = SCREEN_MUSIC+1;                //向下翻
                if(SCREEN_MUSIC>7)//不可以超出7
                        SCREEN_MUSIC=7;
                LCD12864S_WCOM(0x86);//这句和下句是在LCD的指定位置显示出SCREEN_MUSIC的值。+0x30是转换成字符。
                LCD12864S_WDATA(0x30+SCREEN_MUSIC);
                }
        Delay_ms(255);//       
        Delay_ms(255);//       
        SCREEN_DISP();//刷新显示函数
        SCREEN_GUANGBIAO(SCREEN_MUSIC-SCREEN_ROW);//这个是控制光标位置的。移动光标。
        Delay_ms(255);//
        Delay_ms(255);//       
        EA=1;
}
    我在说一下问题。这个中断程序就是这样。运行起来之后,我按下向下键,就会自动增加2,而不是一。为了能看出变化,我添加了LCD显示SCREEN_MUSIC值的语句,同时,在中断的多个地方,做了大量的延时处理,最后看出了程序执行的过程。
    程序是直接运行了两边!按下“向下键”之后,在LCD上可以看到显示的SCREEN_MUSIC从0显示为1,然后移动一下光标。然后,LCD上又看到SCREEN_MUSIC的值变为2,又移动了一次光标。
    这样,按下一次,程序就是增加的二!而且是从头到尾的执行了两遍!!
    我真的不知道这个事什么问题导致的。希望大家都能帮帮。。。。。。。。。。。谢谢啦!

512826028 发表于 2012-4-26 20:24:35

现在的感觉就是,按下一次之后,好像就是产生了两次中断。不知道怎么解决这个问题。延时再长,但是,都是运行两边。很是郁闷。。。{:dizzy:}

sf49ers 发表于 2012-4-26 21:27:58

用的什么格式遥控码,“一开始,解码都正常”,你是怎么知道正常的?

lxa0 发表于 2012-4-26 22:12:47

向上翻/向下翻的动作不要放在中断代码里面

HeP028 发表于 2012-4-26 22:23:34

本帖最后由 HeP028 于 2012-4-26 22:24 编辑

那你把中断最后的EA = 1先去掉测试嘛!先干一次看对不对塞!
另外把你红外读取的函数展览出来塞!指不定问题出那里面呢!

512826028 发表于 2012-4-26 23:51:43

sf49ers 发表于 2012-4-26 21:27 static/image/common/back.gif
用的什么格式遥控码,“一开始,解码都正常”,你是怎么知道正常的?

这个之前是先用LCD显示出所有的按键的用户码,做了一个表格。然后才进行的这一步。

512826028 发表于 2012-4-26 23:54:47

HeP028 发表于 2012-4-26 22:23 static/image/common/back.gif
那你把中断最后的EA = 1先去掉测试嘛!先干一次看对不对塞!
另外把你红外读取的函数展览出来塞!指不定问 ...

这个是拿的别人的程序改的。这个是源代码。
/************************中断0解码服务子程序**********************/
void int0(void) interrupt 0      
{

EA=0;

for(k=0;k<10;k++)
   {
           Delay0_9ms();
    if (IRDATA==1)         //如果0.9ms后IRDATA=1,说明不是引导码
                {k=10;break;}
    else if(k==9)         //如果持续了10×0.9ms=9ms的低电平,说明是引导码
                {
                        while(IRDATA==0);
                                Delay4_5ms();      //跳过持续4.5ms的高电平

                        for(i=0;i<4;i++)       //分别读取4个字节
                                {for(j=1;j<=8;j++)      //每个字节8个bit的判断
                                        {
                                                while(IRDATA==0);       //等待上升沿
                                                Delay0_9ms();      //从上升沿那一时刻开始延时0.9ms,再判断IRDATA
                                                if(IRDATA==1)   //如果IRDATA是"1",则向右移入一位"1"
                                                {
                                                        Delay1ms();
                                                        CodeTemp=CodeTemp|0x80;
                                                        if(j<8) CodeTemp=CodeTemp>>1;
                                                }
                                                else if(j<8)
                                                  CodeTemp=CodeTemp>>1;//如果IRDATA是"0",则向右移一位,自动补"0"
                                        }
                                        hongwaicode=CodeTemp;
                                        CodeTemp=0;
                                }
                }
        }
recodehigh=hongwaicode<<8|hongwaicode;
recodelow=hongwaicode<<8|hongwaicode;
recode=recodehigh;
recode=recode<<16;
recode=recode|recodelow;
//显示出读出的数据
// printf("%#X\n",hongwaicode);
// printf("%#X\n",recodehigh);
// printf("%#X\n",recodelow);
// printf("%#X\n",recode);
//LCD12864S_WSTR(1,0,hongwaicode);
IRDA_DISP();
EA=1;
}

再附上 全部的延时函数:
/**************************延时50us子程序**********************/
void Delay_50us(INT16U t)
{
      INT8U j;
      for(;t>0;t--)   
             for(j=20;j>0;j--);            
}

/**************************延时0.9ms子程序**********************/
void Delay0_9ms(void)
{INT8U j,k;
   for(j=18;j>0;j--)
       for(k=20;k>0;k--) ;
}
/***************************延时1ms子程序**********************/
void Delay1ms(void)
{INT8U i,j;
   for(i=2;i>0;i--)
      for(j=240;j>0;j--) ;
}
/***************************延时4.5ms子程序**********************/
void Delay4_5ms(void)
{INT8U i,j;
   for(i=10;i>0;i--)
      for(j=230;j>0;j--) ;
}


说明:此程序来源于 长沙太阳人”杯红外波形显示单片机设计大赛   制作人:小杨(杨再兴)   <2010.7.5>   

512826028 发表于 2012-4-26 23:58:59

lxa0 发表于 2012-4-26 22:12 static/image/common/back.gif
向上翻/向下翻的动作不要放在中断代码里面

谢谢大哥。这个是正解。

我设定了部分全局变量

在中断中,只是置位对应的变量,然后,在主程序的while循环里判断就可以解决这个问题了。呵呵

中断程序如下:
/************************中断0解码服务子程序**********************/
void int0(void) interrupt 0      
{
        EA=0;
        irdalow = IRDA_JIEMA();//得到解码的数据 这个数据只包括数据码!
        Delay_ms(20);
        //sprintf(yonghuma,"%04X",irdalow);
        //强制格式化,把数据转为4位的16进制数据。
        if(irdalow == 0x0af5)
                ;                                //你按下了音量+
        if(irdalow == 0x09f6)
                ;                                //你按下了音量—
        if(irdalow == 0x0df2)        {KEY_UP = 1;        }        //上翻标志置一
        if(irdalow == 0x0ef1)        {KEY_DOWN = 1;        }        //下翻标志置一
        if(irdalow == 0x02fd)        {KEY_PLAY = 1;        }        //播放音乐标志置位
        if(irdalow == 0x01fe)        {KEY_MENU = 1;        }        //菜单键意味着返回键的意思。
       
        if(irdalow == 0x09F6)        {KEY_VOL_LOW = 1;        }        //VOL--
        if(irdalow == 0x0AF5)        {KEY_VOL_HIGH = 1;        }        //vol++

        EA=1;
}
页: [1]
查看完整版本: 【已解决】51简单的红外程序,出了邪门了,大家都来帮帮...