微控制器上的定点算法


12

通常,我们使用微控制器在机器人中执行操作,但是需要用十进制进行一些计算。使用浮点变量非常慢,因为会自动包含软件浮点库(除非您拥有高端微控制器)。因此,我们通常使用定点算法。

每当我这样做时,我都只使用一个整数,并记住小数点在哪里。但是,确实要确保所有内容都是一致的,特别是当计算涉及小数点位于不同位置的变量时。

我已经实现了定点atan2函数,但是因为我试图挤压最后一滴有限精度(16位)的数据,所以我经常会更改小数点位置的定义,并且在对其进行调整时会改变。此外,我还有一些常量(作为准查询表),它们本身在某处具有隐含的小数点。

我想知道是否有更好的方法。是否有一个库或一组宏,可以简化定点变量的使用,简化混合变量之间的乘法和除法,并允许声明小数或常数表达式,但在编译时自动转换为所需的定点表示形式时间?


1
我认为这实际上对于stackoverflow更好,因为该解决方案是通用的,与机器人技术无关。
Shahbaz 2012年

1
@Jakob-请注意,所有这些问题都被认为不是建设性的。
Mark Booth

1
这种事情会使C ++对嵌入式系统非常有用。模板将自动生成正确和最佳的代码。
Rocketmagnet

1
我可以看看您的atan功能吗?我正在学术研究中尝试解决浮点到定点转换问题,我很乐意对此进行探讨。
Joe Hass 2012年

1
@ronalchn Arduino(AVR微型)语言的某些部分用C ++实现。还有一个AVR C ++库。而这个线程在哪个编译器上使用。
Embedded.kyle

Answers:


7

如果我们能告诉编译器每个定点输入变量的范围和精度(可能没有两个在相同位置的小数点)会很好,并且它会自动(在编译时)使用正确的范围一系列计算中的中间值和最终值的精度和重新缩放操作。我听说有传言说,有可能在Ada编程语言或C ++模板中做到这一点。

las,我所看到的最接近的是定点算术库,程序员需要您手动选择正确的表示形式,并手动验证每个操作是否保持足够的范围和精度。有时,它们使混合变量之间的乘法和除法更加容易。如:


使用C ++模板几乎可以做到这一点。
Rocketmagnet 2012年

我实际上正在做一些事情,就像您的“如果...会很好”评论一样。它是gcc的插件,可将浮点C代码转换为定点,从而优化沿途的所有二进制点位置。我有一篇论文提交给ACM期刊,还有另一篇论文正在准备中。如果您有用于atan函数的C代码,我将很高兴为您提供帮助...我可以还给您使用整数变量并完成所有定点操作的C代码。
Joe Hass 2012年

+1比我的答案更完整。我已经在我的链接中编辑了该链接,以包含指向某个地方的链接,该地方请求源代码以解决Mark Booth的评论。您可能还需要更新链接。我自己做,但建议的编辑正在排队中,并且阻止了我。
Embedded.kyle

1
@Rocketmagnet最肯定的是可以使用模板来实现固定点,请参见FixedPoints(免责声明:我写了这个,现在还很“年轻”)。
法拉普

gcc链接“ a”已损坏
Lesto

2

我使用TI IQMath库在其定点DSP上实现了虚拟浮点。

德州仪器(TI)TMS320C28x IQmath库是供C / C ++程序员使用的高度优化和高精度数学函数的集合,可以将浮点算法无缝移植到TMS320C28x器件上的定点代码中。这些例程通常用于计算密集型实时应用中,在这些应用中,最佳执行速度和高精度至关重要。通过使用这些例程,您可以比以标准ANSI C语言编写的等效代码更快地实现执行速度。此外,通过提供随时可用的高精度功能,TI IQmath库可以大大缩短您的DSP应用开发时间。

它使用了一些TI特定的东西,但我也以该代码为基础在其他微控制器上实现了虚拟浮点数学运算。移植需要一些工作,但是比从头开始要容易得多。


@downvoter关心评论我的答案有什么问题吗?
Embedded.kyle

+1:该库比他现在使用的库好(“仅使用整数”)。它并不能解决原始问题所要求的一切,但是我认为这样的回答(有用,但不是完整的解决方案)不应该被否决-除非确实存在完整的解决方案(在这种情况下,我对此表示怀疑) )。
大卫·卡里

在我看来,仅针对单个设备范围且仅在啤酒中而不是在语音中免费的答案对未来的访问者来说用途有限。
Mark Booth

@MarkBooth我将链接从C28x库更改为C64x库。如果您点击该链接,则可以请求源代码。您需要公司或大学的电子邮件才能访问。仍然像啤酒演讲一样免费。您只需要举手并等待被呼叫就可以讲话。有点烦人,但是一旦有了源代码,它就可以适应您喜欢的任何处理器。
Embedded.kyle

感谢@ embedded.kyle,源代码绝对比仅二进制文件要好,但是如果许可证仅允许您以有限的方式使用它,则源代码仍然很少使用。根据C6x软件库页面的说法,该来源仅根据TI商业许可发行,几乎可以肯定并非如演讲所述免费的
Mark Booth

1

Binary Scaling(又称B缩放)有多种实现方式(我没有立即意识到的库)

在这种情况下,您可以使用移位将小数点向上或向下移动,从而牢记小数点所在的位置(或什至更好地记录代码...)。

我在国防项目的汇编器中使用过B缩放,即使在最小的CPU上也是如此,因此可以保证它适用于其他任何东西...


可能是这样的,但我从未见过它被称为b缩放。我将其视为固定点-小数点永远不会浮动,因为即使在计算过程中可能会更改小数点,任何一个变量始终将小数点固定在特定位置
ronalchn 2012年

0

如果您使用的整数记得那里的“点”,它们是一种使用浮点运算。定点,确实有定点

atancosπ-π

这取决于您的应用程序所需的值范围,但是您可能希望完全移至定点表示形式。也就是说,例如,不要保留这样的数字:

struct num
{
    uint16_t number;
    uint16_t decimal_point;
};

这里number是整个数量和decimal_point说,其中小数点是,你可以将其存储这样的:

struct num
{
    uint16_t integer;
    uint16_t fraction;
};

其中的整数是integer.fraction,具有相同的内存使用量,更大的值范围并且通常更易于使用。


实际上存储小数点会使它更像是浮点数。通常,小数点是在编译时定义的,您可以根据操作在表示形式之间进行切换。
雅各布2012年

我不是要记住存储在变量中,而是要记住如何解释结果(通过知道小数点在哪里)
ronalchn 2012年

@ronalchn,我知道了。您的意思是带有#define,对吗?我以为您实际上存储了它,它可能根据您的数字大小而有所不同。
沙巴兹(Shahbaz)2012年

@ronalchn-您是否正在考虑B缩放?(请参阅我的回答)
安德鲁
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.