最近调试122检测小电流,有一种遇到鬼打墙的状态,就是看到寄存器的值在数据转移时改动了。要不是亲眼见,还真不会相信。在ADC中写入了这么一小段:
AD_Start=1;//Skip first ADC, can delete by your select
while(!AD_DONE)
ad_temp$1 = adcrh;
ad_temp$0 = adcrl;
你说要是有问题,你在检测内部1.2V时也有问题,那也更容易查找问题吧。可是在转换以内部1.2V为一路输入电压时又没有问题,而且这个程序,在以前的调试好象也问题。
可是一到转换另外一路小电压的时候,就出现问题了。看吧调试窗口里的数据明明提示ADCRH的值为0x01,ADCRL的值为0x17. 在转移到ad_temp 时,变成了ad_temp$1的值为00x03,ad_temp$0为0x17还是正常的。这个问题,以前也弄出来过,可能是后来把系统时钟改低了,系统时钟跑1mips,当时又正常了,所以就没有怀疑程序的问题了。
后来没有明白问题出在哪里,多弄了一次判断,不想等再读一次,想想虽然操作可笑,但也是一种方法:
AD_Start=1;//Skip first ADC, can delete by your select
while(!AD_DONE)
ad_temp$1 = adcrh;
ad_temp$0 = adcrl;
if(ad_temp$1 != adcrh) ad_temp$1 = adcrh;
ad_temp = ad_temp >> 4;
ad16 += ad_temp ;
这样一改,结果是对了,但是还是没有明白问题出在哪里?
后来想到可能系统时钟跑太快了,读数有问题,所以就在while(!AD_DONE)后面加了两个nop; 这样也正常了。后来终于想明白。数据转移出错,确实和系统时钟跑得快有关系,所以在频率较低时,上面的程序不会出问题。其实真正的问题就是出在“while(!AD_DONE)”这里,这里少了一个“;”,编译器没有提示错误,本来也是可以不提示错误的,编译器不知道你等待的时候具体是需要干嘛。因为有“;”时,在等待AD转换完的时间里,编译器会自动增加一条nop指令,而没有“;”时,在等待的时间里是一直在读AD转化的高位,等AD结束后,马上是读取AD转换的低位。所以在等待的过程中,读取的高位,是一个还没有转化完。而低位则是转换结束后的数据,所以读起来不会错了。加上NOP后,再等待的时间强制是执行空指令了,结束完还会执行一个空指令再取高位,所以都不会有问题了。
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !