Q格式

如何在定点DSP上实现浮点运算 可以考虑用Q格式  

举个例子说明定点算法本质:
首先明确:CPU计算整数比浮点方便迅速。
例如:两个小数相乘0.123*0.456,可以先将二者各乘以1000倍,变成123*456,方便CPU计算。算完之后,再将结果除以1000000,就是真实的结果了。
假设Q16定点算法,就是0.123*2^16*0.456*2^16,将两个数同时扩大2^16倍,算完之后,再除回去。为什么要2^16而不是乘以1000呢?因为以2为基数的乘除法在CPU里通过移位完成,相当迅速。
基本原理就是这样,不过实际应用的时候还要考虑溢出,余数效应等影响。
这个Q格式我在AD的采样数据这一次块用过了,主要是你要先确定你现在程序处理中所需要的数据范围,然后选择一种Q格式,而不是你现在想到用什么Q格式就是什么格式,虽然Q格式中提供了格式转换函数,但是这些函数不能随意乱用,否着会编译出错,一般都是整体确定了数据范围,然后在这个范围内确定相同的Q格式,然后就可以开始利用Q格式提供的函数进行体会平常的函数,这个工程需要注意的是Q格式函数中的形参需要的类型一定要和你所给的实参类型一致,如果不一样的话,一样要利用Q格式的格式转换函数转换成一样的。然后在进行计算。其中Q格式库德添加以及函数的利用方法可以本论坛很多好心人的杰作。

我这里用加法进行样例说明:
浮点到定点Xq=X*2^q
定点到浮点X=Xq/2^q
设x=0.5 y=3.1 则浮点运算的结果为z=x+y=0.5+3.1=3.6
Qx=15//为什么x=0.5要定标为Q15呢?因为Q15能表示的范围为-1<=X<=1-1/32768,精度为1/32768,目的是为了提高精度
Qy=13//原因同上
Qz=13//原因同上
x=0.5*2^15=16384//Q15定标
y=3.1*2^13≈25395//Q13定标
temp=25395<<2=101580//为什么要左移两位呢?把y扩大到相同的标尺上进行运行,说白了就是统一单位进行运算。呵呵
temp=x+temp=16384+101580=117964
z=(int)(117964L>>2)=29491//结果用Q13表示
因为z的Q为13,所以定点值z=29491即为z=29491/2^13≈3.59998≈3.6//精度高
同样是上面的运算,我用Q4定标计算
Qx=4 //Q4表示的范围-2048<=X<=2048-1/16,精度为1/16
Qy=4
Qz=4
x=0.5*2^4=8
y=3.1*16≈50
temp=8+50=58
z=58/16=3.625≈3.6//精度度低

 

IQmath基本使用方法(2812为例子)  

 

IQmath基本使用方法(2812为例子)
一. 配置CMD
PRAMH0         : origin = 0x100000, length = 0x008000    
BOOT_ROM       : origin = 0x3ff000, length = 0x000fc0
IQmathTables   : > BOOT_ROM, type = NOLOAD, PAGE = 0
IQmath         : > PRAMH0,   PAGE = 0
二. 载入gel文件,加入IQmath库和头文件
IQmath.gel
IQmath.lib
IQmathLib.h
三.定义全局Q格式,和调试Q格式
#define GLOBAL_Q     20 //全局为Q20格式,默认为Q24格式
long GlobalQ = GLOBAL    //调试用为Q20格式(这样可以使用_IQ(x)在监视器中查看)
//-----------------------------
IQmath中常用的变量和字符
QN    16bitQ格式
IQN   32bitQ格式 N表示Q多少
int 16bit
long 32bit
_iq = _iqN = long
F 浮点数输入
S 浮点字符串
P 正数最大值
N 负数最大值
格式转化函数
一般情况下IQ都有IQN版本的函数
float _IQtoF(A)         //_iq浮点转成正常浮点
float _IQNtoF(A)
int _IQtoQN(A)          //iq和q(16bit)的转化
long _IQint(A)          //提取iq的整数部分
_IQ(float F)            //浮点转化成iq
_IQN(float F)
_atoIQ(char *s)         //字符串转化成iq
_IQfrac(A)              //提取iq的小数部分
_IQtoIQN(A)             //全局iq和普通iq的转化      
_IQNtoIQ(A)
_QNtoIQ(int A)
算术函数
long _IQmpyI32int(A, B) //N*long IQ乘long 返回整数部分
long _IQmpyI32frac(A, B)//N*long IQ乘long 返回小数部分
_IQmpy(A, B)            //N*N乘法
_IQrmpy(A, B)           //N*N四舍五入的乘法最后保存结果前(四舍五入)
_IQrsmpy(A, B)          //N*N四舍五入的饱和处理乘法(如果Q26[-32,+32],如果相乘结果超过也会限制到这个范围)
_IQmpyI32(A, B)         //N*long IQ乘long
_IQmpyIQX(A, A1, B, B1) //N1*N2两个不同的Q格式乘法,返回全局Q格式
_IQdiv(A, B)            // N/N iq除法
三角函数
_IQsin(A)
_IQsinPU(A)             //正弦函数(标幺值),你占这个圆周的几分之几为单位如果sin((0.25*PI)/(2*PI))
_IQcos(A)
_IQcosPU(A)
_IQatan2(A, B)           //第四象限反正切 tan-1(sin, cos)
_IQatan2PU(A, B)         //第四象限反正切 tan-1(sin, cos)
_IQatan(A, B)           //定点反正切    tan-1(1),,1=sin/cos
_IQNsin(A)
_IQNsinPU(A)            //正弦函数(标幺值),你占这个圆周的几分之几为单位如果sin((0.25*PI)/(2*PI))
_IQNcos(A)
_IQNcosPU(A)
_IQNatan2(_iqA, B)      //第四象限反正切 tan-1(sin, cos)
_IQNatan2PU(_iqA, B)    //第四象限反正切 tan-1(sin, cos)
_IQNatan(A, B)          //定点反正切    tan-1(1),,1=sin/cos
数学函数
_IQNsqrt(A)             //平方根        a^0.5
_IQNisqrt(A)            //平方根倒数    1/a^0.5
_IQNmag(A, B)           //求模运算(sqrt(A^2 + B^2)
_IQsqrt(A)              //平方根        a^0.5
_IQisqrt(A)             //平方根倒数    1/a^0.5
_IQmag(A, B)            //求模运算(sqrt(A^2 + B^2)
其它函数
_IQsat(A, long P, long N)//IQ数值的限幅函数 把A限制到[N P]之间
_IQNabs(A)              //IQ数据的绝对值    |A|
_IQabs(A)               //IQ数据的绝对值    |A|

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值