红外遥控电子钟修改闹钟的问题

2019-07-16 00:29发布

我在使用外部中断实现红外解码时,更改闹钟时存入AT24c02中实现掉电保持。但是每次更改时好像写不进去,现象就是比如从2加到3,会闪跳到3然后又马上回到2,或者直接乱码。分析了一下应该是修改后没写到AT24c02,主程序读出来还是原来的值。红外解码部分程序如下:
/******************************************************************/
/*                    红外遥控模块                                */
/******************************************************************/
void IRInit()
{
    IE |= 0x81;                 //允许总中断中断,使能 INT0 外部中断
    TCON |= 0x01;               //触发方式为脉冲负边沿触发   
    IRIN=1;                    //I/O口初始化         
}

void IRdelay(unsigned char x)    //x*0.14MS
{
unsigned char i;
  while(x--)
{
  for (i = 0; i<13; i++) {}
}
}


void IR_IN(void) interrupt 0
{

  unsigned char j,k,flag=0,N=0;
  static unsigned char LastIR;

     EX0 = 0;   
         IRdelay(15);
         if (IRIN==1)                            //确认IR信号出现
     { EX0 =1;
           return;
          }                
        npress=4000;              
        while (!IRIN)            //等IR变为高电平,跳过9ms的前导低电平信号。
        {IRdelay(1);}
        while (IRIN)           //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
         {IRdelay(1);
           flag++;
         }
        if(flag<30){
          if(IRrepeat==1){
                  if(((LastIR==0x15)||(LastIR==0x09))&&(mode!=0)){
                    IRCOM[2]=LastIR;
                    IRrepeat=0;
                        }
                  else{
                    EX0 =1;
                    return;                       
                        }
                  }
          else{
            EX0 =1;
            return;                       
                        }
          }                             
         else{                                    
                 for (j=0;j<4;j++)         //收集四组数据
                 {
                  for (k=0;k<8;k++)        //每组数据有8位
                  {   
                    while (!IRIN)          //等 IR 变为高电平
                     {IRdelay(1);}
                     while (IRIN)           //计算IR高电平时长
                      {
                            IRdelay(1);
                            N++;           
                            if (N>=30)
                                 { EX0=1;
                                 return;}                  //0.14ms计数过长自动离开。
                      }                        //高电平计数完毕               
                     IRCOM[j]=IRCOM[j] >> 1;                  //数据最高位补“0”
                     if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;}  //数据最高位补“1”
                     N=0;
                  }//end for k
                 }//end for j                  
                   if (IRCOM[2]!=~IRCOM[3])
                   { EX0=1;
                     return;
                         }
                   LastIR=IRCOM[2];
                   IRrepeat=0;
                }
   if(endi)
         di();  
/*
;=========================
;**  红外遥控器键值表 **

;  45    46    47
;  44    40    43
;  07    15    09
;  16    19    0d
;  0c    18    5e
;  08    1c    5a
;  42    52    4a
;==========================  */       
       if(IRCOM[2]==0x45)
             endisp=~endisp;
           else if(IRCOM[2]==0x46){
                 mode=(mode+1)%3;
                         IRset=1;
                         }
           else if(IRCOM[2]==0x47)
                 endi=~endi;
           else if(IRCOM[2]==0x40){
                 pos=(pos+1)%2;
                         IRset=1;
                         }
           else if(IRCOM[2]==0x43){
                 pos=(pos+1)%2;
                         IRset=1;
                         }
           else if(IRCOM[2]==0x07){
                          aclkstop=1;       
                         }
           else if(IRCOM[2]==0x15){
               if(mode==0)
                     enaclk=~enaclk;
                   else if(mode==1){
                      if(l_tmpdate[pos+1]!=0)
                l_tmpdate[pos+1]--;
                      else if(pos==0)
                        l_tmpdate[pos+1]=59;
                      else
                        l_tmpdate[pos+1]=23;
                      Set_RTC();
                    }
                         else if(mode==2){
                           if(aclkdate[pos]!=0)
                      aclkdate[pos]--;
                           else if(pos==0)
                              aclkdate[pos]=59;
                           else
                             aclkdate[pos]=23;
                          Set_ACLK();
                           }
                }
                  
           else if(IRCOM[2]==0x09){
                if(mode==0)
                       enaclk=~enaclk;
                    else if(mode==1){
               l_tmpdate[pos+1]++;
                       if(l_tmpdate[1]==60||l_tmpdate[2]==24)
                          l_tmpdate[pos+1]=0;
                       Set_RTC();
                        }
                    else if(mode==2){
                       aclkdate[pos]++;
                       if(aclkdate[0]==60||aclkdate[1]==24)
                          aclkdate[pos]=0;
                           Set_ACLK();
                        }
                    }                                                                                 
           else{  
           switch(IRCOM[2])
           {
             case 0x0c: Y0=1; break;
             case 0x18: Y0=2; break;
             case 0x5e: Y0=3; break;
             case 0x08: Y0=4; break;
             case 0x1c: Y0=5; break;
             case 0x5a: Y0=6; break;
             case 0x42: Y0=7; break;
             case 0x52: Y0=8; break;
             case 0x4a: Y0=9; break;
             case 0x16: Y0=0; break;             
            }

            if(mode==1){
                 if(IRset)
                   l_tmpdate[pos+1]=l_tmpdate[pos+1]%10+Y0*10;
                 else
                   l_tmpdate[pos+1]=l_tmpdate[pos+1]/10*10+Y0;
                 IRset=~IRset;
                 if(l_tmpdate[1]>59||l_tmpdate[2]>24){
                    l_tmpdate[pos+1]=0;
                        IRset=1;
                        }
                 Set_RTC();
                }
                else if(mode==2){
                 if(IRset)
                   aclkdate[pos]=aclkdate[pos]%10+Y0*10;
                 else
                   aclkdate[pos]=aclkdate[pos]/10*10+Y0;
                 IRset=~IRset;
                 if(aclkdate[0]>59||aclkdate[1]>23){
                    aclkdate[pos]=0;
                        IRset=1;
                        }
                 Set_ACLK();
                }
          }
          EX0=1;         
}
以上Set_RTC()是修改时钟,这个是正常的。 Set_ACLK() 修改闹钟,但不是每次都正常。另外整个程序都用了高优先级的定时器。求各路大牛解答!


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。