我正在使用MikroC尝试对PIC4550进行编程,以从pH传感器检索数据。该程序包括检索数据40次,并使用函数平均值计算其平均值
double Average(int* arr, int number)
{
int i;
int ave;
int sum = arr[0];
for(i = 0;i<number;i++)
{
sum=sum+arr[i];
}
ave = sum/number;
return ave;
}
我的问题是它在大多数情况下提供随机值与正确答案相去甚远。例如,正确答案是 633,但它提供 -185。谁能指出我的错误?谢谢。我的整个代码如下
#define volt 5.00 //system voltage
#define arraylength 40 // number of data collection
#define offsetph 5 //deviate compensate
double Average(int*, int);
void main() {
float ph_res=0;
float pHsensor_output[40];
double avepH;
double pHvoltage;
float offsetpH=0.38; //change to actual pH offset
float pHlevel;
char testing[20];
char pher[20];
int i;
int pH_index=0;
UART1_Init(9600);
ADCON1=0x00;
CMCON=7;
TRISA=0xFF;
while(1){
UART1_Write_Text("Reading pH....rn");
for(i = 0; i<40; i++) {
pHsensor_output[i] = ADC_Read(1);
sprintf(testing,"READING: %.2frn",pHsensor_output[i]);
UART1_Write_Text(testing);
delay_us(1000);
}
avepH = Average(pHsensor_output, 40);
sprintf(testing,"AVG: %frn",avepH);
UART1_Write_Text(testing);
pHvoltage = avepH*5/1024;
pHlevel = 3.5*pHvoltage+offsetph;
if(pHlevel!=pH_res){
pH_res = pHlevel;
}
sprintf(pher,"pH: %frn",pH_res);
UART1_Write_Text(pher);
delay_ms(2000);
} }
double Average(int* arr, int number)
{
int i;
int ave;
int sum = arr[0];
for(i = 0;i<number;i++)
{
sum=sum+arr[i];
}
ave = sum/number;
return ave;
}
一些评论指出,您在求和期间有溢出的风险。 如果这是一台 16 位计算机,则INT_MAX为 32767。 根据你的例子,你没有接近这一点,但这是要小心的事情。
无论如何,您正在将值收集到一个floats
数组中:
float pHsensor_output[40];
...
pHsensor_output[i] = ADC_Read(1);
但后来将其传递给一个期望int
数组的函数:
double Average(int* arr, int number)
...
avepH = Average(pHsensor_output, 40);
(事实上,Average
使用int
s 计算并返回一个double
意味着你可能会得到一个截断的答案,但这不是这里的问题。
您的计算机现在正在查看一种位模式,当被视为浮点数时,该模式可能是"633",但在被视为整数时几乎肯定不会。 那么谁知道当你取它们的平均值时会是什么结果?!
尝试将函数更改为以下内容:
double Average(float* arr, int number)
{
int i;
double ave;
double sum = 0.0; // NOTE: not arr[0];
for(i = 0;i<number;i++)
{
sum=sum+arr[i];
}
ave = sum/number;
return ave;
}
附录:你的编译器真的应该抱怨这一点。 它真的保持沉默吗? 海湾合作委员会立即吠叫。
error: cannot convert ‘float*’ to ‘int*’ for argument ‘1’ to ‘double Average(int*, int)’
编辑:通过观看来理解总是很高兴,所以我尝试了一个小例子。 我的是台式机,而不是 PIC,所以int
是 32 位而不是 16 位,但希望重点是一样的......
int main()
{
union {
float my_float;
int my_int;
} hack;
printf ("sizeof(float) %lu, sizeof(int) %lun", sizeof(float), sizeof(int));
hack.my_float = 633.0;
printf( "%f -> %dn", hack.my_float, hack.my_int );
int sum = 40 * hack.my_int;
int average = sum / 40;
printf( "sum %d --> %dn", sum, average );
return 0;
}
收益 率:
sizeof(float) 4, sizeof(int) 4
633.000000 -> 1142833152
sum -1531314176 --> -38282854
这"表明"了一个不错的float
变成了一个疯狂的int
(当相同的位模式被不同地看待时1(,之后,所有的赌注都关闭了。 显然,求和溢出,因此平均值为负数; 完全不是你所期望的!
1我在示例中使用的"联合黑客"对计算机说:"获取保存float
的内存位置,查看完全相同的位,但假装它是int
。 当您将指向某些浮点数的指针传递给期望指向整数的指针的函数时,就会发生这种情况。
但是,如果你"干净利落地"完成一项作业,你就会得到你所期望的:
int nice_int = hack.my_float; // 633.0
printf( "good %f -> %dn", hack.my_float, nice_int );
收益 率:
good 633.000000 -> 633