所有微处理器分为两大类,即“浮点”和“定点”。
常见的定点处理器有
1)基于Atmel AVR、ARM7和Cortex-M3内核的处理器。
2)Freescale HCS12X、MC56F83x、MCF523x。
3)Renesas SH4。
4)Texas Instruments MSP430、TMS320F280xx、Stellaris M3。
5)Infineon XE166、XC878。
6)ST Microelectronics STM32。
7)NEC V850ES/IE2。
8)Fujitsu MB91480。
9)MicrochipdsPIC 33FJxx。
10)NXP LPC2900。
11)Toshiba TMP370。
常见的浮点处理器有
1)Intel x86 Pentium。
2)Freescale MPC556、PowerPC。
3)Texas Instruments C6000、DaVinci、TMS320F2833x。
定点数,俗称小数点固定的数。浮点数,就是小数点不固定的数。例如,数字“1234”,就是纯整数的定点数,若将其写成浮点数,可以写成1.234×10 3 、12.34×10 2 或者123.4×10 1 。
TMS320F2833x涵盖了定点和浮点两种数据格式。其中所包含的硬件浮点运算单元(FPU)支持IEEE 754标准。当需要操作浮点数据或进行高动态范围数值计算时,这种浮点处理器非常有效。但当进行位操作、输入输出控制、中断操作等相关控制任务时,效率不高。具有硬件浮点处理能力的微处理器价格比定点微处理器价格高。
定点处理器内部的硬件结构支持整型数据。算术逻辑单元ALU和硬件乘法器单元MAC要求参与运算的数据格式为整型,这就大大限制了定点处理器进行数据运算的动态范围。在定点处理器中使用C语言声明一个浮点型数据(“float”或“double”)时,会发生什么情况?相关的库函数会支持这类操作。但是标准ANSI C函数会消耗大量的CPU资源,在实时性较高的场合并不适用。
TMS320F2833x提供两种解决方案:调用“IQMath”优化库函数和FPU浮点单元。IQMath是一套高度优化的库函数,它能实现浮点算法与数学定点代码进行无缝链接。使用IQMath可明显地缩短嵌入式控制开发时间。
IEEE 754单精度32bit浮点包含以下几个部分,如图2-2所示。
图2-2 IEEE 754 单精度32bit浮点格式
其中:
1bit符号位S:0表示正,1表示负;
8bit指数位E:指数位可为正也为负,位于S与M之间;
23bit尾数位M:有时被称为有效数字位,甚至被称为“小数位”。
按照上述格式构成的十进制数据可由式(2-1)表示:
例:0x3FE0 0000=0011 1111 1110 0000 0000 0000 0000 0000B
则
S=0
E=0111 1111=127
M=(1).11000=1+0.5+0.25=1.75
Value=(-1) 0 ×1.75×2 127-127 =1.75
例:0xBFB0 0000=1011 1111 1011 0000 0000 0000 0000 0000B
则
S=1
E=0111 1111=127
M=(1).011=1+0.25+0.125=1.375
Value=(-1) 1 ×1.375×2 127-127 =-1.375
例:Value=-2.5
则
S=1
2.5=1.25×2 1
1=E-offset=>E=128
M=1.25=(1).01=1+0.25
二进制结果为1100 0000 0010 0000 0000 0000 0000 0000 B=0xC020 0000
浮点运算的优势在于具有较大的数据运算动态范围:±2 128 ≈±3.403×10 38 ;单精度浮点的分辨率为2 -23 ×2 -126 =2 -149 ≈1.401×10 -45 。
如此看来,这种分辨率和数据范围能够解决很多数学操作。然而,在进行一个简单的大数据和小数据加法时,即使浮点设备也可能失败。以图2-3所示的加法操作Z=X+Y来说明问题,应该得到10.000000240的结果,但实际上结果并不等于10.000000240。因为0x41200000=10.000000000,而0x41200001=10.000001000,所以10.000000240无法表示。因此,图2-3所示的结果应该是10.000000000。
图2-3 Z=X+Y
然而使用IQMath进行10.0和0.00000024的加法运算时,会得出10.00000024的正确结果,这方面定点数比浮点数更有优势。
在这里复习一下二进制补码的计算方式,这部分内容在相应的教材有详细的介绍。
(1)二进制数
(0110) 2 =(0×8)+(1×4)+(1×2)+(0×1)=(6) 10
(11110) 2 =(1×16)+(1×8)+(1×4)+(1×2)+(0×1)=(30) 10
(2)二进制补码
(0110) 2 =(0×-8)+(1×4)+(1×2)+(0×1)=(6) 10
(11110) 2 =(1×-16)+(1×8)+(1×4)+(1×2)+(0×1)=(-2) 10
在有符号整数格式中,最高有效位(MSB)的负权重为-1。若MSB被置位,必须将其系数乘以“-1”。
将两个补码相乘,如图2-4所示,十进制数4×(-3)得到十进制数-12。但需注意,图2-4所显示的并不是TMS320F2833x使用整数相乘的方法,它只是一种观察二进制数算术运算的过程。
上述的两种方法可表示正整数及负整数两种情况,但是小数如何表达?我们可以用图2-5所示的数据进行表达。
图2-4 3×4数据乘法
图2-5 计算数值=-1+1/4+1/8=-5/8
输入数字现在分为两部分:整数部分(I—“整数”)和小数部分(Q—“商”)。这类定点数据通常被称为“IQ”数据,或者简单地称为Q数据。图2-6所示为两个I1Q3的数据相乘。
这种方式的优点是计算速度高,但缺点也不容忽视:计算结果很可能不够精确。实际计算结果应为-3/16,但计算机存储结果为-1/4,bit4~bit6被截断。
图2-6 1/2 ×(-3/8)
IQ格式与浮点格式有相似的地方,但若把一个Uint16型数据赋给IQ15型,再转换回整型时,数值已经改变了。而先将Uint16型数据赋给float型,再使用语句temp=_IQ(float32)(浮点型转换为IQ15格式),转换回的整型数据和原始数据相同。
float型的固定长度为4B(32bit器件)。int型是简单地按照“0”“1”进行存储的,而float是把4个字节划分为“符号位”“指数位”“尾数位”(比如1.123123×10^32)。因为有指数位的存在,所以存储范围比int型大很多,但是这3个部分具有范围限制:单精度浮点型的有效数字长度为7位,数字2.1234567891×10 14 赋给float型后变为2.1234567×10 14 ,该数字的无效范围为21345670000000~2134567999999999,可见其精确度不高。
IQMath是不是可以按照相似的方法理解呢?答案是肯定的。IQMath的IQ型分成了两个部分,整数位(包括符号位)和小数位。每个IQ都是long型,通过不同的位数定标(其实就是定小数点的位置)来实现不同精度的小数和取值范围。例如,IQ15就是用低15位来表示小数位,高16位来表示整数位。按照这个思路,把一个Uint16型直接赋给IQ15型也是很容易的,只要赋值后将IQ值向左移15位就可以。图2-7所示为小数的表达方式。
图2-7 小数表达方式