安安富富莱莱UUMM440033DDSSPP教教程程SSTTMM3322--VV55开开发发板板系系统统篇篇手手册册22001155年年0011月月1155日日版版本本::11..00第第11页页共共3322页页第第88章章BasicMathFunctions的的使使用用((一一))本期教程开始学习ARM官方的DSP库,这里我们先从基本数学函数开始。本期教程主要讲绝对值,加法,点乘和乘法四种运算。8.1绝对值(VectorAbsoluteValue)8.2求和(VectorAddition)8.3点乘(VectorDotProduct)8.4乘法(VectorMultiplication)88..11绝绝对对值值((VVeeccttoorrAAbbssoolluutteeVVaalluuee))这部分函数主要用于求绝对值,公式描述如下:pDst[n]=abs(pSrc[n]),0=nblockSize.特别注意,这部分函数支持目标指针和源指针指向相同的缓冲区。88..11..11aarrmm__aabbss__ff3322这个函数用于求32位浮点数的绝对值,源代码分析如下:/***@briefFloating-pointvectorabsolutevalue.(1)*@param[in]*pSrcpointstotheinputbuffer*@param[out]*pDstpointstotheoutputbuffer*@param[in]blockSizenumberofsamplesineachvector*@returnnone.*/voidarm_abs_f32((2)float32_t*pSrc,float32_t*pDst,uint32_tblockSize){uint32_tblkCnt;/*loopcounter*/#ifndefARM_MATH_CM0_FAMILY(3)/*RunthebelowcodeforCortex-M4andCortex-M3*/float32_tin1,in2,in3,in4;/*temporaryvariables*//*loopUnrolling*/blkCnt=blockSize2u;(4)/*Firstpartoftheprocessingwithloopunrolling.Compute4outputsatatime.**asecondloopbelowcomputestheremaining1to3samples.*/while(blkCnt0u){/*C=|A|*//*Calculateabsoluteandthenstoretheresultsinthedestinationbuffer.*//*readsamplefromsource*/安安富富莱莱UUMM440033DDSSPP教教程程SSTTMM3322--VV55开开发发板板系系统统篇篇手手册册22001155年年0011月月1155日日版版本本::11..00第第22页页共共3322页页in1=*pSrc;in2=*(pSrc+1);in3=*(pSrc+2);/*findabsolutevalue*/in1=fabsf(in1);(5)/*readsamplefromsource*/in4=*(pSrc+3);/*findabsolutevalue*/in2=fabsf(in2);/*readsamplefromsource*/*pDst=in1;/*findabsolutevalue*/in3=fabsf(in3);/*findabsolutevalue*/in4=fabsf(in4);/*storeresulttodestination*/*(pDst+1)=in2;/*storeresulttodestination*/*(pDst+2)=in3;/*storeresulttodestination*/*(pDst+3)=in4;/*Updatesourcepointertoprocessnextsampels*/(6)pSrc+=4u;/*Updatedestinationpointertoprocessnextsampels*/pDst+=4u;/*Decrementtheloopcounter*/blkCnt--;}/*IftheblockSizeisnotamultipleof4,computeanyremainingoutputsampleshere.**Noloopunrollingisused.*/blkCnt=blockSize%0x4u;#else(7)/*RunthebelowcodeforCortex-M0*//*InitializeblkCntwithnumberofsamples*/blkCnt=blockSize;#endif/*#ifndefARM_MATH_CM0_FAMILY*/while(blkCnt0u)(8){/*C=|A|*//*Calculateabsoluteandthenstoretheresultsinthedestinationbuffer.*/*pDst++=fabsf(*pSrc++);/*Decrementtheloopcounter*/blkCnt--;}}1.在这里简单的跟大家介绍一下DSP库中函数的通用格式,后面就不再赘述了。(1)基本所有的函数都是可重入的。安安富富莱莱UUMM440033DDSSPP教教程程SSTTMM3322--VV55开开发发板板系系统统篇篇手手册册22001155年年0011月月1155日日版版本本::11..00第第33页页共共3322页页(2)大部分函数都支持一组数的计算,比如这个函数arm_abs_f32就可以计算一组数的绝对值。所以如果只是就几个数的绝对值,用这个库函数就没有什么优势了。(3)库函数基本是CM0,CM3和CM4都支持的(最新的DSP库已经添加CM7的支持)。(4)每组数据基本上都是以4个数为一个单位进行计算,不够四个再单独计算。(5)大部分函数都是配有f32,Q31,Q15和Q7四种格式。2.函数参数,支持输入一个数组进行计算绝对值。3.这部分代码是用于CM3和CM4内核。4.左移两位从而实现每4个数据为一组进行计算。5.fabsf:这个函数不是用Cortex-M4F支持的DSP指令实现的,而是用C语言实现的,这个函数是被MDK封装起来的。6.切换到下一组数据。7.这部分代码用于CM0.8.用于不够4个数据的计算或者CM0内核。88..11..22aarrmm__aabbss__qq3311这个函数用于求32位定点数的绝对值,源代码分析如下:/***@briefQ31vectorabsolutevalue.*@param[in]*pSrcpointstotheinputbuffer*@param[out]*pDstpointstotheoutputbuffer*@param[in]blockSizenumberofsamplesineachvector*@returnnone.**bScalingandOverflowBehavior:/b(1)*\par*Thefunctionusessaturatingarithmetic.*TheQ31value-1(0x80000000)willbesaturatedtothemaximumallowablepositivevalue0x7FFFFFFF.*/voidarm_abs_q31(q31_t*pSrc,q31_t*pDst,uint32_tblockSize){uint32_tblkCnt;/*loopcounter*/q31_tin;/*Inputvalue*/#ifndefARM_MATH_CM0_FAMILY/*RunthebelowcodeforCortex-M4andCortex-M3*/q31_tin1,in2,in3,in4;/*loopUnrolling*/blkCnt=blockSize2u;/*Firstpartoftheprocessingwithloopunrolling.Compute4outputsatatime.**asecondloopbelowcomputestheremaining1to3samples.*/while(blkCnt0u){/*C=|A|*//*Calculateabsoluteofinput(if-1thensaturatedto0x7fffffff)andthenstoretheresultsinthedestinationbuffer.*/in1=*pSrc++;in2=*pSrc++;安安富富莱莱UUMM440033DDSSPP教教程程SSTTMM3322--VV55开开发发板板系系统统篇篇手手册册22001155年年0011月月1155日日版版本本::11..00第第44页页共共3322页页in3=*pSrc++;in4=*pSrc++;*pDst++=(in10)?in1:(q31_t)__QSUB(0,in1);(2)*pDst++=(in20)?in2:(q31_t)__QSUB(0,in2);*pDst++=(in30)?in3:(q31_t)__QSUB(0,in3);*pDst++=(in40)?in4:(q31_t)__QSUB(0,in4);/*Decrementtheloopcounter*/blkCnt--;}/*IftheblockSizeisnotamultipleof4,computeanyremainingoutputsampleshere.**Noloopunrollingisused.*/blkCnt=blockSize%0x4u;#else/*RunthebelowcodeforCortex-M0*//*InitializeblkCntwithnumberofsamples*/blkCnt=blockSize;#endif/*#ifndefARM_MATH_CM0_FAMILY*/while(blkCnt0u){/*C=|A|*//*Calculateabsolutevalueoftheinput(if-1thensaturatedto0x7fffffff)andthenstoretheresultsinthedestinationbuffer.*/in=*pSrc++;*pDst++=(in0)?in:((in==INT32_MIN)?INT32_MAX:-in);/*Decrementtheloopcounter*/blkCnt--;}}1.这个函数使用了饱和运算,其实不光这个函数,后面很多函数都是使用了饱和运算的,关于什么是饱和运算,大家看Cortex-M3权威指南中文版的4.3.6小节:汇编语言:饱和运算即可。对于Q31格式的数据,饱和运算会使得数据0x80000000变成0x7fffffff(这个数比较特殊,算是特殊处理,记住即可)。2.这里重点说一下函数__QSUB,其实这个函数算是Cortex-M4/M3的一个指令,用于实现饱和减法。比如函数:__QSUB(0,in1)的作用就是实现0–in1并返回结果。这里__QSUB实现的是32位数的饱和减法。还有__QSUB16和__QSUB8实现的是16位和8位数的减法。88..11..33aarrmm__aabbss__qq1155这个函数用于求15位定点数的绝对值,源代码分析如下:/***@briefQ15vectorabsolutevalue.*@param[in]*pSrcpointstotheinputbuffer*@param[out]*pDstpointstotheoutputbuffer*@param[in]blockSizenumberofsamplesineachvector*@returnnone.**b