DSP原理及应用:TMS320F28335架构、功能模块及程序设计
上QQ阅读APP看书,第一时间看更新

1.4 定点DSP和浮点DSP的数值处理方法

定点DSP是指DSP器件只有一个32位定点中央处理单元(CPU)。浮点DSP是指DSP器件除有一个32位定点CPU外,还有一个32位浮点运算单元(FPU)。因为指令机器码是以二进制定点数形式存放在程序存储器中的,只有定点数CPU才能对指令机器码进行取指、译码、执行。另外,数据存储器、外设寄存器等存储数据格式也是二进制定点数,必须由定点CPU来存取。所以,定点CPU是DSP器件的主运算处理单元。

定点CPU不仅可以运算定点数,也可以运算浮点数,但是运算浮点数比运算定点数速度要慢,这是因为浮点数的运算是两个浮点数在阶码对齐(相等)后两个浮点数尾数的算术运算。两个浮点数的阶码对齐算法是小阶对大阶,即小阶码每加1,对应的尾数右移1位。阶码加法和尾数右移操作都需要定点CPU执行软件指令来实现,导致定点CPU运算浮点数很耗时。

浮点DSP的主运算处理单元是32位定点CPU,主要完成指令执行、定点数运算、存储器和外设寄存器访问等操作,32位浮点协处理器(即FPU)主要完成单精度浮点数运算。浮点数DSP比相同时钟频率的定点数DSP运算单精度浮点数快50%以上。因此,浮点DSP非常适合数字通信和数字信号处理算法混合高速实现的应用场合。

DSP集成开发环境CCS的C编译器自动完成定点DSP和浮点DSP的数值处理,但是,了解二进制定点数与浮点数的表示方法、算术运算规则、二-十进制数互相转换算法等,有助于加深理解定点DSP和浮点DSP的数值处理方法。

1.4.1 二进制定点数定标表示法

定点CPU能对一定字宽(即数据长度)的二进制数补码直接进行加、减、乘、除算术运算(CPU包含算术逻辑单元ALU和乘法器)。常用的微控制器,如51单片机,是一种8位定点CPU。定点CPU实际上完成二进制整数算术运算,定点CPU不知道小数点的存在,定点数的小数点位置完全是编程者人为默认的,别人也不知道小数点的位置。小数点位置的人为默认称为定标。定标不同,定点数表示的十进制数范围就不同。通常人们把n位二进制数补码看成整数来讨论,实际上就是把默认小数点位置定位在最低一位二进制数后面,称为Q0定标数,n位二进制数补码默认小数点位置共有n个,Q0表示有0位二进制小数,n位二进制整数。Q1表示有一位二进制小数,n-1位二进制整数;Qn-1)表示有n-1位二进制小数,1位二进制整数,如图1-4所示。可见,Q定标数越大,二进制小数位数越大,二进制整数位数越小。二进制整数位数越小,表示的十进制数范围越小。二进制小数位数越大,表示的十进制数的小数精度越高。

图1-4 n位二进制数补码的小数点位置分布

注意:n位二进制数补码的Qn-1)定标数,只有1位二进制整数,位于n位二进制数补码的最高位,二进制数补码的最高位有双重含义:既代表一位二进制数,又代表n位二进制数补码的符号位。定点CPU对二进制数补码进行算术运算时,并不把最高位看作符号位,而是看作一位普通二进制数(0/1),参与算术运算,但是算术运算结果的最高位又要看作符号位,这就是二进制数补码的神奇之处。

如果把n位二进制数补码小数点位置默认在最高位的左边,如图1-5所示,则n位二进制数补码就蜕变成无符号纯二进制小数,用Qn定标数表示。虽然在定点CPU运算中,很少用到无符号二进制数运算,但是无符号纯二进制小数却是浮点数格式数中尾数的表示格式,即浮点数中的尾数部分一定是无符号二进制小数。

图1-5 小数点默认在n位二进制数最高位左边(n位无符号纯二进制小数)

1.4.2 二进制定点数运算规则

(1)二进制定点数可以直接加减运算的必要条件是:字宽一致、Q定标数一致。若字宽不一致,要把短字定点数带符号扩展对齐长字定点数。带符号扩展规则是:若短字宽数最高位为0,则高位符号扩展全0;若最高位为1,则高位符号扩展全1。

若定标数不一致,要把大Q定标数带小数点右移,向小Q定标数对齐后,再做加减运算,结果才正确。大Q定标数右移规则:带默认小数点一起逻辑右移,即每右移1位,最高位填0,最低位丢失一位。

(2)二进制定点数可以直接相乘运算的条件是:字宽一致、Q定标数不需要一致。乘积的字宽为被乘数和乘数字宽之和,乘积的定标数是被乘数Q定标数与乘数Q定标数之和。

【例1-1】 0x0001+0x07,即被加数为16位,加数为8位,则加数8位要带符号扩展成16位,0x07带符号扩展变为0x0007,然后运算:0x0001+0x0007=0x0008。

【例1-2】 两个8位二进制定点数,AQ0定标数:0x01(对应十进制数1),BQ1定标数:0x02(对应十进制数1)。这两个数由于Q定标数不相等,直接进行加减运算,运算结果是错的:0x01(Q0)+0x02(Q1)=0x03,用Q0来解析0x03是十进制数3,用Q1来解析0x03是十进制数1.5,均不是正确加结果:1+1=2。

所以,先要进行大Q对齐小Q操作:0x02(Q1)右移1位,变为0x01(Q0),对齐后,0x01(Q0)+0x01(Q0)=0x02(Q0),结果正确。

【例1-3】 两个8位二进制补码数,AQ0定标数:0x01(对应十进制数1),BQ1定标数:0x02(对应十进制数1),则A×B的乘积为16位,乘积的定标数是16位字宽下的Q(0+1)=Q1,即16位乘积有15位整数,1位小数。

验证:0x01(对应十进制数1)×0x02(对应十进制数1)=1×1=1。

16位乘积运算结果:A×B=0x0002(Q1)=十进制数1。结果正确。

1.4.3 十-二进制数手工快速转换算法

编程者经常需要手工进行十-二进制数的相互转换,掌握手工快速转换算法可以提高计算效率。

转换条件:已知十进制数被转换为二进制定点数的字宽为n,定标数为Qm。二进制定点数字宽n和定标数Qm应满足十进制数表示范围与精度要求。十-二进制转换算法如下。

IF 十进制数是正数 THEN

{十进制数×2m=[十进制数乘积]取整=转换为n位二进制数,即为转换成功的二进制定点数。}

ELSEIF 十进制数是负数 THEN

{①|十进制数|×2m=[十进制数乘积]取整=转换为n位二进制数。

②再把n位二进制数求反加1,即为转换成功的二进制定点数。}

1.4.4 二-十进制数手工快速转换算法

转换条件:已知n位二进制定点数定标数为Qm,则二-十进制数转换算法如下。

IF 二进制数是正数 THEN

{①将二进制数看成二进制整数(Q0),转换为十进制整数。

②十进制转换整数/2m=十进制数商,取有效小数后,即为转换成功的十进制数。

ELSEIF 二进制数是负数 THEN

{①将二进制数看成二进制整数(Q0)求反加1的结果,转换为十进制整数。

②十进制转换整数/2m=十进制数商,取有效小数后,在该十进制数商前面再人为加一个负号,即为转换成功的十进制数。

【例1-4】 试把0.33转换为16位二进制定点数,定标数为Q13。

0.33×213=[2703.36]取整=2703=0x0A8F

0.33转换为16位二进制定点数

Q13=0x0A8F

【例1-5】 试把-0.33转换为16位二进制定点数,定标数为Q13。

|-0.33|×213=[2703.36]取整=2703=0x0A8F,对0x0A8F求反加1=0xF571。

-0.33转换为16位二进制定点数

Q13=0xF571

【例1-6】 请把定标数为Q13的16位二进制定点数0x0A8F转换为十进制数。

(1)0x0A8F=2703;(2)2703/213=0.329956,取0.3299为十进制转换数。

【例1-7】 请把定标数为Q13的16位二进制定点数0xF571转换为十进制数。

(1)0xF571求反加1=0x0A8F=2703;(2)2703/213=0.329956,取0.3299为十进制转换数,再人为加一个负号,-0.3299为十进制转换数。

1.4.5 二-十进制整数计算机典型转换算法

在计算机应用系统中,经常需要把二进制定点数计算的结果转换为十进制数(即BCD码,4位二进制数表示的十进制数),再转换为显示码,送到计算机显示屏上显示。由于二进制定点数小数点左边为二进制整数部分,小数点右边为二进制小数部分,所以,一个二进制定点数被转换为十进制数,需要分别把二进制整数部分转换为十进制整数,二进制小数部分转换为十进制小数。二-十进制整数计算机典型转换算法是“除10求余”,二-十进制小数计算机典型转换算法是“乘10取整”,转换条件:已知n位二进制定点数定标为Qm,则二-十进制数整数转换算法如下。

IF 二进制数是正数 THEN

{①取n-m位二进制数整数部分,符号扩展成字节的整数倍字宽。

②二进制数整数除10求余数,第1次余数为十进制整数最低位数BCD码,第1次部分商数作为下一次除10求余数的二进制整数基数,除10求余数,产生十进制整数较高一位数BCD码,继续除十求余数,直到部分商数为零为止。此时,各位BCD即为转换成功的十进制整数。

③在十进制整数BCD码的数符单元中,置一个正号标识符,构成转换成功的完整正数十进制数各位BCD码。

ELSEIF 二进制数是负数 THEN

{①二进制数求反加1的结果,取n-m位二进制数整数部分,符号扩展成字节整数倍的字宽。

②二进制数整数除10求余数(计算机除法指令或除法子程序一定是被除数字宽为除数字宽的2倍,如16/8、32/16、64/32,产生的商和余数字宽与除数字宽一致)。第1次余数为十进制整数最低位数BCD码,第1次部分商数作为下一次除10求余数的二进制数整数基数,产生十进制整数的较高一位数BCD码,直到部分商数为零为止,继续除10求余数,直到部分商数为零为止,此时,各位BCD即为转换成功的十进制整数。

③在十进制转换数BCD码的数符单元中,置一个负号标识符,构成转换成功的完整负数十进制数各位BCD码。

十-二进制转换算法只在人机接口输入十进制数据时才用到,留给用户思考。

1.4.6 二-十进制小数计算机典型转换算法

二-十进制小数计算机典型转换算法是“乘10取整”,转换条件:已知n位二进制定点数定标数为Qm。二-十进制数小数转换算法如下。

①取m位二进制数小数部分,最低位填0扩展为字节的整数倍字宽。

②二进制数小数乘10取整,乘积取整数部分。第一次整数部分为十进制转换小数最高位数BCD码,第一次乘积的小数部分,最低位填0扩展为字节的整数倍字宽,继续乘10取整,产生十进制转换小数的较低各位BCD码,直到十进制转换小数位数达到有效值范围为止。

1.4.7 二进制浮点数数据格式与运算规则

1.IEEE-754标准单精度32位浮点数数据格式

浮点数从存储格式上也是一定字宽的二进制数,但是数据格式与定点数有很大区别,浮点数由数符位、阶码(二进制整数补码)、尾数(无符号二进制小数)3部分组成。在相同数值精度下,浮点数的字宽比定点数的长。例如,一种尾数为16位的3字节自定义浮点数与16位定点数Q15的精度几乎相当,但浮点数总字宽为24位二进制数序列,如图1-6所示。

图1-6 3字节自定义浮点数数据格式

F28335的FPU支持IEEE-754标准的单精度32位浮点数,用4字节表示,数据格式如图1-7所示。

图1-7 IEEE单精度浮点数自定义格式

x(IEEE单精度浮点数真值)=(-1)s×2e-127×(1.f

当0<e<255时,x=(-1)s×2e-127×(1.f)。

e=0时,且f≠0时,x=(-1)s×2-127×(1.f)。

e=0时,且f=0时,x=0。

e=255时,且f≠0时,x=NaN(Not a Number,不是一个数),表示数据出错、无效。

e=255时,且f=0时,x=∝(无穷大)。s=0,x=+∝;s=1,x=-∝。

注意:虽然f为32位纯小数,但计算真值时,变为1.f即小数点左边自动填1,变为1<尾数<2的实数。

【例1-8】 将IEEE单精度浮点数03A00000H转换为十进制实数。

解:

s=0, e=07H, f=200000H(=200000H/223=0.25)

x=(-1)0×27-127×(1.25)=1.25×2-120

IEEE单精度浮点数的缺点:尾数不是小于1且大于0.5的规格化尾数,而是小于2且大于1的尾数。两个IEEE单精度浮点数的加、减运算的小阶对大阶时,尾数1.f进行运算比较麻烦。但是F28335的FPU完美支持IEEE-745标准的单精度浮点数运算,用户只需在CCS 3.3环境下,升级F2833x codegen Tool到5.0.2版本以上,在工程文件中添加F2833x_FPU支持库,即rts2800_fpu32.lib。

2.二进制浮点数运算规则

浮点数算术运算规则:在阶码相同下,尾数部分进行算术运算。浮点数乘除法运算结果的数符位遵循正负得负、负负得正。

若两个浮点数阶码不相同,则需要在保持数值精度一定的原则下,小阶码浮点数向大阶码浮点数对齐,小阶对大阶的算法是:小阶码每加1一次,该浮点数的尾数就要右移1位,以保持小阶码浮点数的数值精度一定(当然,尾数右移1位会产生一定精度损失),直到等于大阶码为止。

3.二进制浮点数的十进制数转换手工快速算法

转换条件:已知浮点数的数据格式:n位二进制整数阶码,m位二进制小数尾数,1位数符位(0/1)。二进制浮点数的十进制数转换手工快速算法如下。

m位二进制小数尾数×2m=十进制数小数尾数。

②调用二-十进制数转换算法,将n位二进制整数阶码转换为十进制整数阶码,因为n位二进制整数阶码有正有负,则十进制转换整数阶码有正有负。

③浮点数对应的十进制转换数=(-1)数符位×2十进制转换整数阶码×十进制数小数尾数。

4.二进制浮点数的十进制数转换计算机典型算法

转换条件:已知浮点数的格式,n位二进制整数阶码,m位二进制小数尾数,1位数符位(0/1)。二进制浮点数的十进制数转换计算机典型算法如下。

IF n位二进制整数阶码是正数 THEN

{①循环计数器初值=n位二进制正整数阶码

m位二进制小数尾数左移次数等于循环计数器的初值(每次左移最低位填0),产生等于循环计数器初值的高位是二进制整数部分,剩余的m位为小数部分。

②将第①步产生的二进制无符号定点数,调用二-十进制定点数转换计算机典型算法转换成十进制数BCD码。

③用浮点数的1位数符位(0/1)在十进制转换数BCD码的数符单元中,置一个正/负号标识符。十进制数各BCD码转换成功。

ELSEIF n位二进制整数阶码是负数 THEN

{①将n位二进制整数阶码符号扩展为字节的最小整数倍字宽,然后求反加1,转换为n位二进制正整数阶码。

②循环计数器初值=n位二进制正整数阶码

m位二进制小数尾数右移次数等于循环计数器的初值(每次右移最高位填0),产生二进制小数部分m位+等于循环计数器初值位数,转换的整数部分为0。

③将第②步产生的二进制无符号定点小数,调用二-十进制定点数转换计算机典型算法转换成十进制数BCD码。

③用浮点数的1位数符位(0/1)在十进制转换数BCD码的数符单元中,置一个正/负号标识符。十进制数各BCD码转换成功。