我在使用外部中断实现红外解码时,更改闹钟时存入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;
sta
tic 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() 修改闹钟,但不是每次都正常。另外整个程序都用了高优先级的定时器。求各路大牛解答!
一周热门 更多>