我正在为没有硬件浮点支持的嵌入式系统 (MSP430) 编写一些代码。不幸的是,我在进行测距时需要在代码中使用分数,而精度为 1 米的短距离传感器并不是一个很好的传感器。
我可以在整数中做尽可能多的数学运算,但到最后,我肯定需要两个值来计算分数;范围和速度。范围将是 2-500 (cm) 之间的值,而速度不应高于 -10 到 10 (ms^-1)。如果可能的话,我不确定如何在没有浮点值的情况下表示它们。一种简单的向上或向下舍入分数的方法是最好的。
我有一些示例代码:
voltage_difference_new = ((memval3_new - memval4_new)*3.3/4096);
其中 memval3_new 和 memval4_new 是整数,但 voltage_difference_new 是 float 。
如果需要更多信息,请告诉我。或者,如果有一个非常简单的修复方法。
最佳答案
您宁愿用以下语句回答您自己的问题:
Range will be a value between 2-500 (cm),
以厘米(甚至毫米)而不是米为单位工作。
也就是说您不需要浮点硬件来进行 float 学运算;编译器将支持“软”浮点并生成执行浮点运算的代码——它会比硬件浮点或整数运算慢,但这在您的应用程序中可能不是问题。
尽管如此,即使有硬件支持,也有很多理由避免 float ,而且你的 FP 案例听起来并不特别引人注目,但如果不看你的代码和具体示例就很难判断。在 32 年的嵌入式系统开发中,即使是三角、对数、平方和数字信号处理,我也很少使用 FP。
一般方法是使用固定点 演示。我之前使用厘米的建议是 十进制定点数 的示例,但为了提高效率,您应该使用二进制定点数。例如,您可能以 1/1024 米为单位表示距离(精度 > 1 毫米)。因为定点是二进制的,所以所有必要的重新缩放都可以通过移位而不是更昂贵的乘法/除法运算来完成。
例如,假设您有一个 8 位传感器生成 0 到 255 的线性输出,对应于 0 到 0.5 米的实际距离。
#define Q10_SHIFT = 10 ; // 10 bits fractional (1/1024)
typedef int q10_t ;
#define ONE_METRE = (1 << Q10_SHIFT)
#define SENSOR_MAX = 255
#define RANGE_MAX = (ONE_METRE/2)
q10_t distance = read_sensor() * RANGE_MAX / SENSOR_MAX ;
distance
以 Q10 定点表示。对此类进行加法和减法是正常的整数运算,乘法和除法需要缩放:
int q10_add( q10_t a, q10_t b )
{
return a + b ;
}
int q10_sub( q10_t a, q10_t b )
{
return a - b ;
}
int q10_mul( q10_t a, q10_t b )
{
return (a * b) >> Q10_SHIFT ;
}
int q10_div( q10_t a, q10_t b )
{
return (a << Q10_SHIFT) / b ;
}
当然,您可能希望能够混合类型,比如将 q10_t
乘以 int
- 为定点提供综合库可能会变得复杂。为此,我个人使用 C++,其中有类、函数重载和运算符重载以支持更自然的代码。但是,除非您的代码具有大量通用的定点数学运算,否则临时编写特定定点运算的代码可能会更简单。
以您提供的一个例子为例:
double voltage_difference_new = ((memval3_new - memval4_new)*3.3/4096);
那里的 float 使用毫伏被简单地删除了:
int voltage_difference_new_mv = ((memval3_new - memval4_new) * 3300) /4096 ;
然后问题可能成为演示文稿之一。例如,如果您必须向用户显示或报告以伏特 为单位的值。在那种情况下:
int volt_fract = abs(voltage_difference_new_mv % 1000) ;
int volt_whole = voltage_difference_new_mv / 1000 ;
printf( "%d.%04d", volt_whole, volt_fract ) ;
关于C:表示没有 float 的分数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71725823/