本帖最后由 lzh12a3nf 于 2023-11-27 09:39 编辑
#申请原创#@21小跑堂
1、前言
最近在学习DSP库,有去关注到Ti的DSP库,从中又了解到了Ti的IQmath。IQmath定点库适用于M0,M0+,M3这些不带FPU的硬件FPU的内核上,但最近手头入手了一块极海的APM32F411的M4内核开发板,因此基于APM32F411开发板,进行一个IQmath库的移植操作记录,
2、相关知识介绍
2.1 定点数
定点数通常由固定的位数来表示整数和小数。定点数的小数位置是固定的,因此它们的精度也是固定的。例如,IQ24可以表示-128-128之间的实数,但它的小数位有24位,且它的小数精度为1/2^24=0.000000060,所以,IQ24可以表示的精度范围为-128-127.999999940。在实际使用中,为了提高计算精度,在把实际变量转换成IQ前,需要搞定IQ1-30的实际范围,如果不提前查看,存在数据溢出的风险。
2.2 相应函数的简单介绍
_IQN 将输入的浮点数进行IQ格式数转换
_IQtoF 将IQ格式数进行浮点数转换
long _IQmpyI32(A, B) //N*long IQ乘long
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四舍五入的饱和处理乘法(如果结果超过IQ范围也会限制计算结果值到这个范围)
_IQmpyIQX(A, A1, B, B1) //N1*N2两个不同的Q格式乘法,返回全局Q格式
_IQdiv(A, B) // N/N iq除法
_IQsin(A) //正弦值
_IQasin(A) //反正弦值,输入范围在-Π到Π
_IQsinPU(A) //正弦函数(标幺值),你占这个圆周的几分之几为单位如果sin((0.25*PI)/(2*PI)),输入范围在0-2Π
_IQcos(A) //余弦值
_IQacos(A) //反余弦值,输入范围在-Π到Π
_IQcosPU(A) //余弦函数(标幺值),输入范围在0-2Π
_IQatan(A) //反正切值
_IQatan2(A, B) //第四象限反正切 tan-1(sin, cos)
_IQatan2PU(A, B) //第四象限反正切 tan-1(sin, cos)
_IQatan(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|
_IQmpy2,4,8,16,32,64 //将输入数进行左移操作,即相乘多少倍
_IQdiv2,4,8,16,32,64 //将输入数进行右移操作,即相除多少倍
3、基于APM32F411 DSP IQmath移植
3.1、必备资料
1.IQmathLib-cm3.lib(IQ运算程序方法)
2.IQmathLib.h(各函数实现文件)
3.2 移植操作
1.将对应的文件加到路径上,如下图:
2.调用IQmath库函数进行操作,如下图代码
int main(void)
{
/* Init LED */
APM_MINI_LEDInit(LED2);
APM_MINI_LEDInit(LED3);
USART_Config_T usartConfigStruct;
/* USART1 configuration */
usartConfigStruct.baudRate = 115200;
usartConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;
usartConfigStruct.mode = USART_MODE_TX_RX;
usartConfigStruct.parity = USART_PARITY_NONE;
usartConfigStruct.stopBits = USART_STOP_BIT_1;
usartConfigStruct.wordLength = USART_WORD_LEN_8B;
APM_MINI_COMInit(COM1, &usartConfigStruct);
_iq X,Y,Z;
X = _IQ(5);
Y = _IQ(6);
Z = _IQmpy(X,Y);
printf("X = 0x%lX\r\n", X);
printf("Y = 0x%lX\r\n", Y);
printf("Z = 0x%lX\r\n", Z);
while (1)
{
APM_MINI_LEDToggle(LED2);
APM_MINI_LEDToggle(LED3);
Delay(0XFFFFFF);
}
}
3.输出结果,如下图:
其中,IQ函数:
#define _IQ30(A) ((_iq30)((A) * (1 << 30)))
#define _IQ29(A) ((_iq29)((A) * (1 << 29)))
#define _IQ28(A) ((_iq28)((A) * (1 << 28)))
#define _IQ27(A) ((_iq27)((A) * (1 << 27)))
#define _IQ26(A) ((_iq26)((A) * (1 << 26)))
#define _IQ25(A) ((_iq25)((A) * (1 << 25)))
#define _IQ24(A) ((_iq24)((A) * (1 << 24)))
#define _IQ23(A) ((_iq23)((A) * (1 << 23)))
#define _IQ22(A) ((_iq22)((A) * (1 << 22)))
#define _IQ21(A) ((_iq21)((A) * (1 << 21)))
#define _IQ20(A) ((_iq20)((A) * (1 << 20)))
#define _IQ19(A) ((_iq19)((A) * (1 << 19)))
#define _IQ18(A) ((_iq18)((A) * (1 << 18)))
#define _IQ17(A) ((_iq17)((A) * (1 << 17)))
#define _IQ16(A) ((_iq16)((A) * (1 << 16)))
#define _IQ15(A) ((_iq15)((A) * (1 << 15)))
#define _IQ14(A) ((_iq14)((A) * (1 << 14)))
#define _IQ13(A) ((_iq13)((A) * (1 << 13)))
#define _IQ12(A) ((_iq12)((A) * (1 << 12)))
#define _IQ11(A) ((_iq11)((A) * (1 << 11)))
#define _IQ10(A) ((_iq10)((A) * (1 << 10)))
#define _IQ9(A) ((_iq9)((A) * (1 << 9)))
#define _IQ8(A) ((_iq8)((A) * (1 << 8)))
#define _IQ7(A) ((_iq7)((A) * (1 << 7)))
#define _IQ6(A) ((_iq6)((A) * (1 << 6)))
#define _IQ5(A) ((_iq5)((A) * (1 << 5)))
#define _IQ4(A) ((_iq4)((A) * (1 << 4)))
#define _IQ3(A) ((_iq3)((A) * (1 << 3)))
#define _IQ2(A) ((_iq2)((A) * (1 << 2)))
#define _IQ1(A) ((_iq1)((A) * (1 << 1)))
相应的输入数会进行一个相乘的操作,此处采用IQ2,即5*4=20,用16进制表达为0x14,6*4=24,用16进制表达为0x18。
其次,_IQmpy函数
将输入的两个IQ数进行相乘操作,根据计算结果可知,还会对相应的IQ数进行除法操作。如0x14*0x18=0x1E0,0x1E0/4=0x78。
4、基于APM32F411 IQmath移植Demo
此次分享到这,如有问题,大家评论区一起讨论,谢谢!
|
感谢分享!奖励500家园币(可在家园币商城兑换物品)