溢出错误,RMS值显示错误

时间:2013-07-05 13:00:22

标签: c

我正在测量交流电压,我正在计算ADC的有效值。

我有一个数组,其中有128个我的信号样本。 虽然平方数字我得到一个错误。

unsigned long int calval=0;
unsigned int loop;
float adcbufval;
for(loop=0;loop<128;loop++)
{
    printf("adcval %d = %d\t ", loop, adc_temp[loop]);
    calval = (adc_temp[loop])*(adc_temp[loop]);
    printf("\t %ld \n", calval);

}

输出:

adcval 1 = 168 28224
adcval 2 = 32 1024 
adcval 3 = -88 7744 
adcval 4 = -211 44521 // sqr(211) 44521 , it fine here
adcval 5 = -314 33060 // sqr(314) 98596-65536 = 33060 instead of 98596.
adcval 6 = -416 41984 
adcval 7 = -522 10340 
adcval 8 = -655 35809
adcval 9 = -773 7705 
adcval 10 = -889 3889 

虽然我将'calval'定义为unsigned long int(范围0-4,294,967,295),但它以65536的值超过了流量。 在普通的C编译器中它的工作正常。 有什么建议吗?

硬件为dsPIC30f5011 / MPLAB 8.8x

2 个答案:

答案 0 :(得分:3)

你没有显示它(或者我忽略了它),但是如果adc_temp[]是一个int数组,那么为了安全地对这些值进行平方,你必须将乘法的至少一侧强制转换为{{ 1}}之前这样做。否则,乘法的结果仍为long,并且在溢出已经发生后,它将仅转换为int

像这样:

unsigned long

如果calval = (long)(adc_temp[loop])*(adc_temp[loop]); 也是未签名的,则该演员可能是unsigned long

答案 1 :(得分:0)

根据数据表,dsPIC30f5011是一个16位微控制器,根据C99你是正确的unsigned long应该是2 ^ 32。但是,您使用的编译器似乎将long视为int的别名,它仍然符合C90,只需要sizeof(short) <= sizeof(int) <= sizeof(long)。如果你真的需要使用unsigned long long进行32位数学运算,那么你可能会有更好的运气。