在嵌入式C中铸造字符使其浮动

在嵌入式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

我在一个微控制器上读取一个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 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,您根本不需要转换