我正在A/D converter微控制器上读取一个10位PIC,并希望将该值平均超过几千个调用,并将平均值最终再次作为字符。返回的值是16位字符。
我想做类似的事情:
float f = 0.0;
for (int i=0; i<5000; i++) {
n = readADC(); // Returns a char, 0->1023
f = f + (float)n;
}
f = f / 5000.0;
n = (char)f;
// Send n somewhere as the final char which is a mean of 5000 calls to the ADC.
我得到了奇怪的价值,好像我没有正确地投射。我该如何解决这个问题?
答案 0 :(得分:5)
如果你有一个最大1023(10位)的读数并希望平均5000次(~13位),那么很明显,用于平均的16位累加器(太)太小了。 / p>
如果输入卡在1023,5000次加法后的总和将为5000 * 1023 = 5115000,这显然不适合16位变量。甚至不是unsigned
一个,最大值为65535,超过78 次太少。
使用uint32_t
作为累加器总和。
还要考虑平均4096或8192值,因此可以通过右移12或13位来完成除法。
答案 1 :(得分:1)
由于char
通常只有8位,如果您的输入数据是&gt;,您可能会得到一个错误的值。 127.将n
更改为unsigned short
并更改:
n=(char)f;
为:
n=(unsigned short)f;
答案 2 :(得分:1)
此演员阵容无效;当您在+
和float
上使用char
时,char
的整数值将转换为最接近的float
值。 C在这两种类型之间进行了隐式转换。
例如:
char ch = -5;
float f = ch; // f is now -5.0 (or the closest representable value to that)
当你写n=(char)f;
时:f
被截断为零,例如:
float f = -44.3;
char ch = f; // ch is now -44
但是,如果此值超出char
的范围,则存在问题。行为是实现定义的,这意味着您的编译器可以做任何喜欢的事情,但它必须记录它。为了安全起见,您应该检查以下内容:
if ( f < CHAR_MIN || f > CHAR_MAX )
ch = 0; // and maybe output a message
else
ch = f;
关于你对16位字符的主张:有16位字符的系统确实存在,但它们非常专业,这就是为什么有些人怀疑这种说法。
要验证这一点,请检查CHAR_BIT
中定义的limits.h
。或者(如果您的实施不提供CHAR_BIT
,CHAR_MIN
和CHAR_MAX
,这是不合格的btw),请执行以下操作:
unsigned int u = (unsigned char)-1;
并以某种方式输出u
的值,或对其执行测试。如果你得到255那么它是8位;如果你得到65535那么它是16位。