完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
4520的PORD4引脚控制一个三极管来 给ATT7022供电,当外部中断来的时候 启动7022采集电流数据,程序开始的一天都是好的,测量的电流也是对的,一天之后,采集的到数据就不对了全wei0
if(sendok_flag==0) { uchar i; if(Action_flag==1) { i=0; for(;(i<5)&&(sendok_flag==0);i++) { asm("CLRWDT"); Delay_ms(50); Send_Action_data(); Delay_ms(1500); } } if(work_flag==1) { i=0; for(;(i<5)&&(sendok_flag==0);i++) { Delay_ms(50); Send_work_data(); Delay_ms(1500); } 之前发送的函数在中断里就执行了,这段代码是我加在WHILE(1)循环里的,没加这段代码的时候,程序工作几个月都不会有问题,这段代码主要是防止通讯不成功,重复发送的,有没有大神帮忙看看,这段代码有什么问题吗 |
|
相关推荐
12个回答
|
|
程序信息太少,无法分析出问题原因,要确定数据采集的方式,是否中断方式,确定是采集的数据错误,还是发送数据部分错误,Action_flag,sendok_flag,work_flag这几个标志什么情况下会变更
|
|
|
|
人中狼 发表于 2017-6-12 19:34 if(RCIF==1) //UART中断程序 { asm("CLRWDT"); //看门狗喂狗 TMR0H=0xAB; //开启定时器,用于控制UART_Index清零,定时0.5s TMR0L=0xA0; //设置初值0xABA0,在16位定时器64分频情况下精确定时0.5s TMR0ON=1; //开定时器0 if(OERR) //如果接收溢出,则通过CREN重置OERR标志 { CREN=0; Delay_us(10); CREN=1; } ReBuffer[UART_Index++]=RCREG; if((UART_Index==10)&&(ReBuffer[0]==0x11)) { asm("CLRWDT"); //看门狗喂狗 UART_Index=0; //对报文接收索引清零 Connection(); //按照报文进行通讯 Delay_us(10); } if((UART_Index==8)&&(ReBuffer[0]==0x10)&&(ReBuffer[1]==0x5A)&&(ReBuffer[2]==Code_Number/16777216)&&(ReBuffer[3]==(Code_Number%16777216)/65536)&&(ReBuffer[4]==(Code_Number%65536)/256)&&(ReBuffer[5]==Code_Number%256)) { asm("CLRWDT"); //看门狗喂狗 UART_Index=0; //对报文接收索引清零 sendok_flag=1;// 中继器返回标志位 } } if(INT0IF==1) { asm("CLRWDT"); //看门狗喂狗 INT0IF=0; Action_flag=1; if(Action<99) { LED=1; Action++; asm("CLRWDT"); //看门狗喂狗 AT24C256_I2C_ByteWrite(0x0000,Action); AT24C256_I2C_ByteWrite(Action*7,Action); //次 AT24C256_I2C_ByteWrite(Action*7+1,BCD_Num(DS3231_I2C_ByteRead(0x06))); //年 AT24C256_I2C_ByteWrite(Action*7+2,BCD_Num(DS3231_I2C_ByteRead(0x05))); //月 AT24C256_I2C_ByteWrite(Action*7+3,BCD_Num(DS3231_I2C_ByteRead(0x04))); //日 AT24C256_I2C_ByteWrite(Action*7+4,BCD_Num(DS3231_I2C_ByteRead(0x02))); //时 AT24C256_I2C_ByteWrite(Action*7+5,BCD_Num(DS3231_I2C_ByteRead(0x01))); //分 AT24C256_I2C_ByteWrite(Action*7+6,BCD_Num(DS3231_I2C_ByteRead(0x00))); //秒 Send_Action_data(); asm("CLRWDT"); //看门狗喂狗 LED=0; //连续雷击灯灭 20170306 } else { asm("CLRWDT"); //看门狗喂狗 LED=1; Action=99; Send_Action_data(); LED=0; //连续雷击灯灭 20170306 } } if(INT1IF==1) { INT1IF=0; if((BCD_Num(DS3231_I2C_ByteRead(0x02))%4)==0) //小时为4的倍数 { asm("CLRWDT"); //看门狗喂狗 Get_Data(); if(Record_Index[1]<=1080) //6个月记录 { Record_Index[1]++; } else { asm("CLRWDT"); //看门狗喂狗 Record_Index[1]=1; //重新循环覆盖 Record_Index[0]++; AT24C256_I2C_ByteWrite(0x0001,Record_Index[0]); } AT24C256_I2C_ByteWrite(0x0002,Record_Index[1]/256); AT24C256_I2C_ByteWrite(0x0003,Record_Index[1]%256); AT24C256_I2C_ByteWrite(0x1000+6*Record_Index[1],BCD_Num(DS3231_I2C_ByteRead(0x06))); //年 AT24C256_I2C_ByteWrite(0x1000+6*Record_Index[1]+1,BCD_Num(DS3231_I2C_ByteRead(0x05))); //月 AT24C256_I2C_ByteWrite(0x1000+6*Record_Index[1]+2,BCD_Num(DS3231_I2C_ByteRead(0x04))); //日 AT24C256_I2C_ByteWrite(0x1000+6*Record_Index[1]+3,BCD_Num(DS3231_I2C_ByteRead(0x02))); //时 AT24C256_I2C_ByteWrite(0x1000+6*Record_Index[1]+4,I/256); AT24C256_I2C_ByteWrite(0x1000+6*Record_Index[1]+5,I%256); } if((BCD_Num(DS3231_I2C_ByteRead(0x0F))&0x02)!=0) { asm("CLRWDT"); //看门狗喂狗 LED=1; work_flag=1; Send_work_data(); // Delay_ms(1000); asm("CLRWDT"); //看门狗喂狗 LED=0; |
|
|
|
人中狼 发表于 2017-6-12 19:34 数据的采集是在外部中断来了以后 ,开始采集的,Action_flag(外部中断),sendok_flag(发送成功的标志,也就是本机收到返回后),work_flag,之前中断里发送的actiondata,第一次发程序是我加的,之前while里面只有一句休眠 |
|
|
|
人中狼 发表于 2017-6-12 19:34 这几个标志都是在中断里变的,之前这几个标志没加在主循环里的话,在中断里执行,程序都是正常的 |
|
|
|
程序只有这些,就这些程序来讲,假定几个条件,一,数据的采集已经完成,该保存的数据也已经保存,二,数据已经发送了,但认为不成功。
这样有几个问题,一,其他两个标志先不管,也不确定是否正确,但是sendok_flag标志只看到两种状态,而两种状态不能满足你现在功能的需要。二,sendok_flag标志在重发过程中没有变更,也就是重发成功后并没有置一。三,虽然限定了重发次数,但是没限定重发不成功的操作。四,看现在第一段程序,因为sendok_flag标志没有变更,那假如重发是否成功,将会不停的进行重发操作,那对采样是否用影响就不确定了。五,看到了发送中断程序,但是没看到Send_Action_data();和Send_work_data();,所以现在只能假定在发送中断程序里,发送成功了会sendok_flag=1,但是不知道什么时候sendok_flag会等于0。 |
|
|
|
人中狼 发表于 2017-6-13 16:17 真谢谢你的耐心解答,我第一段程序没有贴完全下面还有一段 if(sendok_flag==1) { sendok_flag=0; work_flag=0; Action_flag=0; } 如果发送成功的话,接收中断里的sendok-flag置1,试验我做过,如果发送成功的话,就只会发送一次,如果不成功就会重发直到发送成功,但最多只有限定的次数,程序也能能跑起来,大概一天左右,在这一天之中,所测量的数据也都是对的,之后就不对了数据,而且在数据不对的时候,我可以通过中断唤醒MCU,MCU上传出来的数据除了采集的数据不对之外,其他的诸如 设备号之类的信息都是对的,就只有测量的数据不对,还有一个情况,重新上电之后,采集的数据又都对了,Send_Action_data( ) // { uchar i=0; E30M1=0;//设置为唤醒模式 E30M0=1; Delay_ms(50); SeBuffer[17]=0; //清0校验和 SeBuffer[0]=0x68; SeBuffer[1]=0x0d; //事件标志位 SeBuffer[2]=0x0b; SeBuffer[3]=Myaddr; SeBuffer[4]=Code_Number/16777216; SeBuffer[5]=(Code_Number%16777216)/65536; SeBuffer[6]=(Code_Number%65536)/256; SeBuffer[7]=Code_Number%256; SeBuffer[8]= Action; SeBuffer[9]= AT24C256_I2C_ByteRead(Action*7+1); SeBuffer[10]= AT24C256_I2C_ByteRead(Action*7+2); SeBuffer[11]= AT24C256_I2C_ByteRead(Action*7+3); SeBuffer[12]= AT24C256_I2C_ByteRead(Action*7+4); SeBuffer[13]= AT24C256_I2C_ByteRead(Action*7+5); SeBuffer[14]= AT24C256_I2C_ByteRead(Action*7+6); Get_Data(); SeBuffer[15]=I/256; SeBuffer[16]=I%256; for(i=1;i<17;i++) SeBuffer[17]=SeBuffer[17]+SeBuffer; SeBuffer[18]=0x16; TXEN=1; for(i=0;i<19;i++) { TXREG=SeBuffer; while(TRMT==0); Delay_us(1); SeBuffer=0; } TXEN=0; Delay_ms(50); //等待模块发送完毕 E30M1=1; E30M0=0;//进入省电模式 Delay_ms(50); //等待模块下次发送 } |
|
|
|
人中狼 发表于 2017-6-13 16:17 还有一个情况 所有的数据采集都是在需要的时候才会采集,一个是action—flag另一个是work-flag,这两个状态来了才会采集数据,还有一个是主动召测的时候,奇怪的是所有的功能刚开始都是正常的 |
|
|
|
没用过这个芯片,需要确定几个问题,
一,在能正常工作的一天里有没有通讯中断的情况。 二,通讯中断的情况下,其他功能是否正常。 三,通讯中断的情况下,看程序应该是无限重发,直到发送正常,不会是有限的次数,for(;(i<5)&&(sendok_flag==0);i++),虽然是重发5次就退出,但sendok_flag仍然等于0,主程序应该会不断判断sendok_flag==0这个条件,所以似乎应该是无限重发。 四,重发的情况下,是否还能正确采集数据。 五,sendok_flag是这次为了重发功能而加的吗。 六,if(RCIF==1) , if(INT0IF==1),if(INT1IF==1)是在中断里执行,还是在中断里设标志,退出中断后再以查询方式执行。 七,如果采集是在中断里执行,有可能会对重发过程中的一些参数进行修改。 八,每天里采集的次数是否一样,是否有固定次数后设备失灵的情况。 九,看程序sendok_flag是放在接收程序里的,是否可以理解为PC会返回一个确认收到数据的数据包。 十,如果通讯中断超过一天,恢复通讯后,是否能正常。 十一,去除休眠模式,是否能正常。 十二,看门狗是否起作用了,如果没有,可以查查喂狗的部分是否死循环了。 感觉是程序跑飞了,可能是有些变量被多处同时修改,判断条件无法处理,死循环了。 |
|
|
|
这个重发只会在INT0,INT1的时候才会有重发一说,因为我主程序里用到了这两个中断里action_flag 和work_flag 这两个中断来的时候会置1, if(sendok_flag==0) { uchar i; if(Action_flag==1) { i=0; for(;(i<5)&&(sendok_flag==0);i++) { Delay_ms(50); RE_Send_Action_data(); Delay_ms(1500); } } if(work_flag==1) { i=0; for(;(i<5)&&(sendok_flag==0);i++) { Delay_ms(50); RE_Send_work_data(); Delay_ms(1500); } } sendok_flag=0; work_flag=0; Action_flag=0; } if(sendok_flag==1) { sendok_flag=0; work_flag=0; Action_flag=0; } 我里面加了这两个标志位的清零, |
|
|
|
这样看似乎也没什么问题,那看看是否能在数据包里增加一些判断信息,比如一些相关的寄存器数值,一些变量数值等。
理一理程序结构,看看有没有会误判断的地方。 看看模式转换时单片机的状态如何,E30M1=1;E30M0=0;,在单片机手册里没找到,或许不在芯片手册里,看看模式转换的设置位置是否合适。 另外建议设置一个类似resend_flag的标志,和sendok_flag区分一下,如果问题解决了和这个无关,可以再合并成一个。 评分
|
||
|
||
人中狼 发表于 2017-6-15 10:04 你分析的真实透彻,给的建议很好,E30M1=1;E30M0=0; 是我的一个模块信息,配置模块的工作方式,为了省电,今天上午看程序的编译,看到了数据空间占了188个字节,我在变量定义的时候没有区分bank,而每个bank最大128字节,所以我把部分变量的定义放在了bank1,其他的都默认在bank0,让bank0默认的在90个字节左右,也不知道这样可能解决这个问题 |
|
|
|
|
|
只有小组成员才能发言,加入小组>>
求解外围电路实现的是4脚给持续低电平复位并正常工作,高电平不工作的原因
2111 浏览 1 评论
3669 浏览 3 评论
PIC1946程序有一个变量在运行过程中恢复初始值其他变量保持不变
2357 浏览 2 评论
2782 浏览 0 评论
PIC16F1825的RC5引脚,在主程序中操作无效,在中断中可以改变是为什么?
4072 浏览 5 评论
1014浏览 0评论
用XC8编译PIC18F25K80时提示下面Error,求怎么解决这个问题
6399浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-28 12:54 , Processed in 0.697684 second(s), Total 72, Slave 66 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号