在特定的STM32微控制器上,系统时钟由PLL驱动,其频率由以下公式给出:FF := (S/M * (N + K/8192)) / PS是 PLL 输入源频率(或 64 MHz)。1 - 64000000其他因素、、和是用户可以修改以校准频率的参数。根据我使用的 SDK 中的位掩码判断,每个位掩码的值可以限制为 、 、 和 的最大值。MNKPM < 64N < 512K < 8192P < 128不幸的是,我的目标固件不支持FPU,因此浮点算术已经出来了。相反,我需要使用纯整数算术进行计算。F我试图重新排列给定的公式,并牢记3个目标:扩展和分布所有乘法因子最小化每个分母中的因子数最大限度地减少执行的除法总数如果两个表达式具有相同数量的除法,请选择其分母具有最小最大值的表达式(在前面的段落中标识)但是,我每次尝试扩展和重新排列表达式都会产生比原始公式更大的错误,因为它最初是逐字逐句表示的。为了测试公式的不同排列和比较错误,我写了一个小的Go程序,你可以在这里在线运行。是否可以改进此公式,以便在使用整数算术时将误差降至最低?另外,我上面列出的任何目标是否不正确或无用?
2 回答
慕勒3428872
TA贡献1848条经验 获得超6个赞
我拿走了你的程序(你的第一个括号是多余的,所以我删除了):
S K
--- * ( N + ------ )
M 8192
--------------------
P
并运行了QuickMath [1],我得到了这个:
S * (8192 * N + K)
------------------
8192 * M * P
或在 Go 代码中:
S * (8192 * N + K) / (8192 * M * P)
因此,它确实减少了除法的数量。您可以通过拉出下限常量来进一步改进它:
S * (8192 * N + K) / (M * P) >> 13
https://quickmath.com
波斯汪
TA贡献1811条经验 获得超4个赞
通过@StevenPerry来查看答案,我意识到大多数误差是由我们必须表示的有限精度引起的 。然后,此错误会传播到其他因素和红利中。K/8192
然而,推迟这种除法通常会导致整数溢出,然后再达到它。因此,不幸的是,我发现的解决方案取决于将这些操作数扩大到64位。
结果与其他答案具有相同的形式,但必须强调的是,将操作数扩大到64位至关重要。在 Go 源代码中,如下所示:
var S, N, M, P, K uint32 ... F := uint32(uint64(S) * uint64(8192*N+K) / uint64(8192*M*P))
若要查看所有这三个表达式的准确性,请在 Go Playground 上自行运行代码。
- 2 回答
- 0 关注
- 154 浏览
添加回答
举报
0/150
提交
取消
