请告诉我 MCU 如何处理“23.3”、“3.24”等十进制数字?它是如何存储在内存寄存器中的?我知道在编程时处理这些数字时必须使用浮点数据类型。但实际上,在处理这些类型时,MCU 内部发生了什么。还告诉我没有 FPU 单元的 MCU 如何处理 Float 数据类型。
MCU中如何处理带小数点的数字?
典型的微控制器内的数字根本没有小数点。它们是二进制整数。机器内部没有小数点。编译器或汇编器可能允许您以这种方式指定常量,但它们会在机器看到它们之前转换为二进制。
但是,您可以决定整数值的任何单位。例如,假设您想在微型货币中表示美元。它本身不能做 3.21 美元,但它可以做 321 美分。micro 只是在值 321 上运行,但您知道它代表 1/100 美元的单位。
这只是说明任意单位概念的一个例子。通常数字用几个二进制小数位表示。这与说每个计数表示 2 -N的值相同,其中 N 是小数位数。这种表示称为“固定点”。您预先决定需要多少分辨率,并假设想象的二进制点右侧有足够的位来支持该分辨率。例如,假设您需要以至少 1/100 的分辨率表示某些东西。在这种情况下,您将使用至少 7 个小数位,因为 2 7 = 128。这实际上会给您 1/128 的分辨率。
机器不知道这是怎么回事。它会将这些数字作为普通整数进行加减运算,但一切仍然有效。当您乘以和除以定点值时,它会变得有点棘手。两个定点值与 N 个小数位的乘积将有 2N 个小数位。有时您只需跟踪新数字有 2N 个小数位这一事实,或者有时您可能会将其右移 N 位以恢复与以前相同的表示。
浮点数是一样的,但小数位数与整数部分一起存储,以便可以在运行时进行调整。对浮点数执行数学运算可能需要很多周期。浮点硬件为您完成所有这些工作,以便快速完成操作。然而,同样的操作也可以在软件中执行。没有理由你不能编写一个子程序来添加两个浮点数,只是它比做同样事情的专用硬件需要更长的时间。
我为 8 位 PIC 定义了一个 3 字节的浮点格式,并编写了一堆例程来操作它们。微控制器通常最多以 10 或 12 位精度处理真实世界的值。我的浮点格式使用 16 位精度,这对于几个中间计算来说已经足够了。
我还有一个 32 位格式的 16 位图片。这使用一个 16 位字作为尾数,这可以加快计算速度,因为这些 PIC 一次可以在 16 位上运行。
这些例程包含在我的PIC 开发工具版本中。安装后,在 SOURCE > PIC 目录中查看名称中带有“fp24”的文件,在 SOURCE > DSPIC 目录中查看名称中带有“fp32f”的文件。
除非您的 MCU 是带有浮点乘法器的 DSP,否则所有内容都存储为 16 位(或 8 位或 32 位,具体取决于您的平台)数字。这就是所有实际的 MCU 所知道的。
在此之上,您拥有“C”代码和 C 编译器。编译器“知道”各种数据类型,例如 char、int、uint、float、double 等。
硬件上最常见的浮点数表示是 IEEE 格式。这将尾数与指数分开,并使用两个 16 位字来存储信息。查看这篇关于 IEEE 数字格式的 wiki 文章。
因此,编译器知道尾数和指数在哪里,并将数学应用到它上面。还记得学习对数吗?当你想要多个时,他们如何通过增加力量使数学变得更容易?好吧,c编译器对指数做了类似的事情,并乘以尾数来计算答案。因此,对于浮点乘法,编译器将创建将指数相加并执行尾数乘法的汇编代码。
MCU不知道这个数字!!!就像它被告知要做的那样,将内存加载到寄存器中,将内存添加到寄存器并在需要时设置进位标志,依此类推,直到乘法完成。
是 C 编译器和您的代码从 MCU 中“抽象”出数字、小数点等概念。
附带说明一下,某些语言还支持对金融系统有用的“十进制”数据类型——在嵌入式平台上并不常见,因为浮点数使用更少的内存并有效地执行。
与没有 fpu 的完整处理器(例如大多数 ARM)处理浮点的方式相同。用一个软件fpu。有一个执行数学/按位运算的库。如果你记得在小学用铅笔和纸做加法、乘法等,那么你从整数到带小数点的数字的那一天并没有太大变化。您进行数学运算的方式与您必须调整数字相同,以便在开始之前(加法和减法)或完成后(乘法或除法)后排列小数点。硬 fpus 和软 fpus 没有区别,它们在运算前后调整位,但运算基本上是整数运算。
我不记得现在在哪里可以找到它,但是 texas Instruments 有一份与他们的 DSP 产品相关的非常好的文档。它解释了它们的浮点格式,甚至解释了操作是如何工作的。它们的格式没有像 IEEE 那样的舍入和非规范化、无穷大、安静和信令 nan,因此它比 IEEE 格式更容易理解并且速度明显更快。一旦看到该格式的实际应用,您就朝着 IEEE 格式迈出了第一步。舍入需要一些解释和思考,但其余部分,符号、指数和尾数的基础是相同的。
使用软浮点库非常昂贵,资源明智(内存、闪存、cpu 周期),我不鼓励在嵌入式系统或微控制器中使用它。12.3 和 24.5 作为整数 123 和 245 很容易管理,例如,只要您记得,或者如果您确保所有相关的数学都理解这些数字都乘以 1 并且如果/当您显示到用户在该转换中添加小数点。节省大量代码和性能。当然,整数除法对于微控制器和嵌入式系统来说是一件坏事,而且大多数处理器没有除法指令,其中包括除以 10 以转换为十进制以显示给用户。同样的答案是,您从 C 代码中获得的划分是使用库完成的。