C:表示没有 float 的分数

标签 c embedded fixed-point

我正在为没有硬件浮点支持的嵌入式系统 (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/

相关文章:

c - malloc 返回内存的空闲范围

c - unix socket send() 成功,但 recv() 失败

c - 位操作 : modify the 32 bit integer to include the substring

assembly - 学习 PIC 单片机的汇编语言的最佳资源是什么

multiplication - 两个定点数如何相乘?

c - 定点转换 : 31. ..24 指数与 23...0 小数到 Q25 值?

在 CUDA 上使用 __constant__ 内存的正确方法?

c - 使用 GNU make、嵌入式 C 进行 native 和交叉编译

c# - Windows 服务是否是 "correct"与必须运行 Windows 的嵌入式系统上的硬件交互的选择?

php - 使用 PHP 进行精确的实数运算