在嵌入式C中铸造字符使其浮动
我在一个微控制器上读取一个10位的数据,我想在几千次调用中取这个值的平均值,然后再将平均值作为一个字符结束。返回的值是一个16位字符 我想做一些类似的事情:在嵌入式C中铸造字符使其浮动,c,embedded,C,Embedded,我在一个微控制器上读取一个10位的数据,我想在几千次调用中取这个值的平均值,然后再将平均值作为一个字符结束。返回的值是一个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
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.
if ( f < CHAR_MIN || f > CHAR_MAX )
ch = 0; // and maybe output a message
else
ch = f;
float f=0.0;
对于(int i=0;i1023
f=f+(浮点数)n;
}
f=f/5000.0;
n=(char)f;
//将n作为最终字符发送到某个地方,这意味着向ADC调用5000次。
我得到了奇怪的值,好像我没有正确地施法。我如何修复它?因为
char
通常只有8位,如果输入数据>127,很可能会得到一个不好的值。将n
更改为无符号短
并更改:
n=(char)f;
致:
由于
char
通常只有8位,如果输入数据大于127,则很可能会得到一个错误的值。将n
更改为无符号短
并更改:
n=(char)f;
致:
如果您的读数最大为1023(10位),并且希望将其平均为5000次(约13位),那么很明显,用于平均的16位累加器(远)太小了 如果输入卡在1023,则5000次加法后的和将为5000*1023=5115000,这显然不适合16位变量。即使是
无符号
变量也不适合,它的最大输出为65535,太少了78倍多
对累加器总和使用uint32\u t
也考虑平均4096或8192个值,因此除法可以通过12或13位右移来完成。
< P>如果你读了max 1023(10位),并且想要平均5000次(13位),那么应该清楚的是,16位累加器的平均值(远)太小。 如果输入卡在1023,则5000次加法后的和将为5000*1023=5115000,这显然不适合16位变量。即使是无符号
变量也不适合,它的最大输出为65535,太少了78倍多
对累加器总和使用uint32\u t
也考虑平均4096或8192个值,所以除法可以通过12或13位右移来完成。
< P>不存在效果;当使用<代码> +<代码> < <代码>浮动>代码>和<代码> char < /代码>时,<代码> char < /代码>的整数值被转换为最接近的<代码>浮点< /代码>值。C具有隐式Co。这两种类型之间的转换 例如: 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
的范围,则会出现问题。行为是由实现定义的,这意味着您的编译器可以执行它喜欢的任何操作,但它必须对此进行记录。为了安全起见,您应该检查以下内容:
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.
if ( f < CHAR_MIN || f > CHAR_MAX )
ch = 0; // and maybe output a message
else
ch = f;
然后以某种方式输出
u
的值,或者对其进行测试。如果得到255,则为8位;如果得到65535,则为16位。此强制转换无效;当对浮点和字符使用+
时,字符的整数值转换为最接近的浮点值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
的范围,则会出现问题。行为是由实现定义的,这意味着您的编译器可以执行它喜欢的任何操作,但它必须对此进行记录。为了安全起见,您应该检查以下内容:
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.
if ( f < CHAR_MIN || f > CHAR_MAX )
ch = 0; // and maybe output a message
else
ch = f;
然后以某种方式输出u
的值,或者对其进行测试。如果您得到255,则为8位;如果您得到65535,则为16位。您绝对确定char为16位吗?对于古代PIC来说似乎不太可能。为什么您使用完全不合适的char类型来存储16位无符号整数值?我会使用定点这里的数学是32位累加器。char
肯定是8位。如果您的编译器支持它(我不确定MPLAB是否支持),我建议使用stdint.h
中指定的宽度类型。这些类型是uint8_t,int8_t,…,uint32_t,int32_t
类型。如果MPLAB不支持它,那么您可能会找到一个第三方标头,为每个PIC部分提供适当的typedef
。它只是在类型中明确了值的范围将有效。我的错误是,n是一个无符号的短字符(16位),不是字符你绝对确定字符是16位吗?对于古代PIC来说似乎不太可能。为什么你要使用完全不合适的字符类型来存储16位无符号整数值?我在这里使用定点数学,带有32位累加器。char
肯定是8位。如果你的编译器支持它(我不确定MPLAB是否支持),我建议使用stdint.h
中指定的宽度类型。这些类型是uint8_t,int8_t,…,uint32_t,int32_t
类型。如果MPLAB不支持它,那么您可能会找到一个第三方标头,为每个PIC部分提供适当的typedef
。它只是在类型中明确了值的范围将是有效的。我的错误是,n是一个无符号的短字符(16位),而不是charthanks-will(短字符)转换为有符号或无符号的短字符?我需要一个无符号的短字符-我把它称为字符的错误。如果它只是一个10位的值,那么它没有什么区别,但是可以随意使用无符号的短字符。@user2633388正如Paul所指出的,是不正确的转换导致了您最初的问题。但是如果n
已经是一个字符,您根本不需要转换<代码>未签名短码
。谢谢-威尔(短码)转换为有符号或无符号的短字符?我需要一个无符号的短字符-我把它称为字符的错误。如果它只是一个10位的值,那么它没有什么区别,但是可以随意使用无符号的短字符。@user2633388正如Paul所指出的,是不正确的转换导致了您最初的问题。但是如果n
是alr,您根本不需要转换