完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
我在使用外部中断实现红外解码时,更改闹钟时存入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() 修改闹钟,但不是每次都正常。另外整个程序都用了高优先级的定时器。求各路大牛解答! |
|
相关推荐
2个回答
|
|
自己顶一下!!!
|
|
|
|
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
求助一下关于51系列单片机的Timer0的计时问题,TH0、TL0+1的时间是怎么算的?
195 浏览 0 评论
【RA-Eco-RA4E2-64PIN-V1.0开发板试用】开箱+Keil环境搭建+点灯+点亮OLED
172 浏览 0 评论
【敏矽微ME32G070开发板免费体验】使用coremark测试敏矽微ME32G070 跑分
453 浏览 0 评论
【敏矽微ME32G070开发板免费体验】开箱+点灯+点亮OLED
697 浏览 2 评论
602 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
11990 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-21 15:21 , Processed in 0.569098 second(s), Total 72, Slave 55 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号