我正在为没有硬件浮点支持的嵌入式系统(MSP430)编写一些代码。不幸的是,我需要处理代码中的分数,因为我正在进行测距,而精度为1m的短程传感器并不是一个很好的传感器。
在ints中,我可以做很多我需要的数学运算,但是到了最后,我肯定需要有两个分数:范围和速度。范围将在2-500 (cm)之间,而速度不应高于-10至10 (ms^-1)。如果可能的话,我不知道如何在没有浮点值的情况下表示它们。一个简单的方法来舍入分数向上或向下将是最好的。
我有一些示例代码:
voltage_difference_new = ((memval3_new - memval4_new)*3.3/4096);中,memval3_new和memval4_new是ints,但voltage_difference_new是浮点数。
如果需要更多的信息,请告诉我。或者如果有一个令人眼花缭乱的简单的解决办法。
发布于 2022-04-03 16:10:49
你宁愿用以下声明回答你自己的问题:
范围将介于2-500 (cm)之间,
工作单位为厘米(甚至毫米)而不是米单位。
也就是说,您不需要浮点硬件来进行浮点运算;编译器将支持“软”浮点并生成代码来执行浮点操作--它将比硬件浮点或整数操作慢,但在应用程序中可能不是问题。
尽管如此,即使有硬件支持也有很多理由避免浮点,而且听起来FP的情况并不特别引人注目,但是如果不看到代码和一个具体的示例,就很难说了。在32年的嵌入式系统开发中,我很少使用FP,甚至在trig、log、sqrt和数字信号处理方面。
一般的方法是使用不动点表示。我先前建议使用厘米是十进制不动点的一个例子,但是为了更高的效率,您应该使用二进制不动点。例如,你可以用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);这里的浮点可以用毫伏来去除:
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 ) ;https://stackoverflow.com/questions/71725823
复制相似问题