0

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

我有一个包含 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

4

2 回答 2

3

您还没有显示它(或者我忽略了它),但是如果是一个 int 数组,那么为了安全地平方值,您必须在这样做之前adc_temp[]将乘法的至少一侧转换为。long否则,乘法的结果仍然是int,并且它只会在unsigned long已经发生溢出后转换为赋值。

像这样:

calval = (long)(adc_temp[loop])*(adc_temp[loop]);

那个演员可能是unsigned long如果adc_temp[]也没有签名。

于 2013-07-05T14:01:14.983 回答
0

根据数据表,dsPIC30f5011 是 16 位微控制器,根据 C99,您正确的unsigned long应该是 2^32。但是,您使用的编译器似乎将其long视为别名,int它仍然符合 C90 的要求,只需sizeof(short) <= sizeof(int) <= sizeof(long). 如果您真的需要使用unsigned long long.

于 2013-07-05T13:17:46.413 回答