在STM32单片机上用C计算一个三年级函数

Calculate a third grade function with C on a STM32 microcontroller

我正在尝试实现以下由我的 STM32 计算的函数

y=0.0006*x^3 - 0.054*x^2 + 2.9094*x - 2.3578

x 的范围是 0 到 215

为了避免使用 pow 或任何其他函数,我编写了以下代码

static double tmp = 0;
static unsigned short c_m;
static unsigned short c_m_3;
static unsigned short c_m_2;

c_m_3 = c_m*c_m*c_m;
c_m_2 = c_m*c_m;
tmp = (0.0006*c_m_3) - (0.054*c_m_2) + (2.9094*c_m) - 2.3578;
dati->sch_g = tmp;

出于某种原因,计算完全错误,因为对于 istane,如果 c_m = 1 我应该 tmp = 0.4982 而不是 13

我是不是漏掉了什么?

short在所有STM32上都是16位。因此值 215 * 215 * 215 将不适合一个。 c_m_3 = c_m*c_m*c_m; 根据模数 USHRT_MAX+1 (65536) 截断结果:

Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

改用uint32_t

short只有16位,它可以容纳的最大值是65535。因此,如果你要计算三次方的数字超过40,它就会溢出。这意味着你必须使用更大的变量类型,如uint32_t。 您还可以使用 ifs 来检测溢出以获得更好的编程实践。

另请注意,在嵌入式编程中最好使用“uint8_t”和“uint16_t”而不是“unsigned char”和“unsigned short”,因为它们更能描述数据大小。

正如 Lundin 在评论中指出的那样,您的微控制器类型 (ARM Cortex M0) 不提供浮点单元。因此,这意味着您不能依赖自然浮点数学,而需要依赖浮点软件库,例如this one(注意:我没有评价,只是我在快速搜索中偶然发现的第一个!)。

或者——而且可能更可取——你可能想用普通整数进行计算;如果你另外将你的计算从模式 a*x*x*x + b*x*x + c*x + d 转换为 ((a*x + b)*x + c)*x + d 你甚至可以节省一些乘数:

int32_t c_m = ...;
c_m = ((6 * c_m - 540) * c_m + 29094) * c_m - 23578;

注意:unsigned short太小了,STM32无法保存结果,所以你至少需要切换到32位!此外,您需要一个带符号的值才能保存由 c_m == 0.

产生的负结果

当然,您的结果现在会太大 10 000 倍。由于用例不清楚,问题仍然悬而未决,您希望如何处理,可能将其四舍五入(c_m = (c_m + 5000) / 10000)或通过其他方式评估小数部分。