苏州网站设计哪家公司好ghost wordpress比较
目录
一、ST 官方汇编 FFT 库(64点, 256 点和 1024 点)
1、cr4_fft_xxx_stm32
2、计算幅频响应
3、计算相频响应
二、复数浮点 FFT、IFFT(支持单精度和双精度)
1、基础支持
2、单精度函数 arm_cfft_f32
3、双精度函数 arm_cfft_f64
三、实数浮点 FFT(支持单精度和双精度)
1、基础支持
2、单精度函数 arm_rfft_fast_f32
3、双精度函数 arm_rfft_fast_f64
四、不限制点数 FFT 实现
1、函数 InitTableFFT
2、函数 cfft
一、ST 官方汇编 FFT 库(64点, 256 点和 1024 点)
这个汇编的FFT库是来自STM32F10x DSP library,由于是汇编实现的,而且是基4算法,所以实现FFT在速度上比较快。
1、cr4_fft_xxx_stm32
其实现32位定点数的运算,其中高16位为虚部,低16位为实部。
cr4_fft_1024_stm32 | 函数用于实现1024点数据的FFT计算 |
cr4_fft_256_stm32 | 函数用于实现256点数据的FFT计算 |
cr4_fft_64_stm32 | 函数用于实现64点数据的FFT计算 |
2、计算幅频响应
uint32_t input[1024], output[1024], Mag[1024];/* 输入,输出和幅值 */
float32_t Phase[1024]; /* 相位*/
/*
*********************************************************************************************************
* 函 数 名: PowerMag
* 功能说明: 求模值
* 形 参: _usFFTPoints FFT点数
* 返 回 值: 无
*********************************************************************************************************
*/
void PowerMag(uint16_t _usFFTPoints)
{int16_t lX,lY;uint16_t i;float32_t mag;/* 计算幅值 */for (i=0; i < _usFFTPoints; i++){lX= (output[i]<<16)>>16; /* 实部*/lY= (output[i]>> 16); /* 虚部 */arm_sqrt_f32((float32_t)(lX*lX+ lY*lY), &mag); /* 求模 */Mag[i]= mag*2; /* 求模后乘以2才是实际模值,直流分量不需要乘2 */}/* 由于上面多乘了2,所以这里直流分量要除以2 */Mag[0]= Mag[0]>>1;
}
3、计算相频响应
/*
*********************************************************************************************************
* 函 数 名: Power_Phase_Radians
* 功能说明: 求相位
* 形 参: _usFFTPoints FFT点数, uiCmpValue 阀值
* 返 回 值: 无
*********************************************************************************************************
*/
void Power_Phase_Radians(uint16_t _usFFTPoints, uint32_t _uiCmpValue)
{int16_t lX, lY;uint16_t i;float32_t phase;float32_t mag;for (i=0; i <_usFFTPoints; i++){lX= (output[i]<<16)>>16; /* 实部 */lY= (output[i] >> 16); /* 虚部 */phase = atan2(lY, lX); /* atan2求解的结果范围是(-pi, pi], 弧度制 */arm_sqrt_f32((float32_t)(lX*lX+ lY*lY), &mag); /* 求模 */if(_uiCmpValue > mag){Phase[i] = 0;}else{Phase[i] = phase* 180.0f/3.1415926f; /* 将求解的结果由弧度转换为角度 */}
}
二、复数浮点 FFT、IFFT(支持单精度和双精度)
新版 DSP 库浮点 FFT 推荐使用混合基函数 arm_cfft_f32,而基 2 函数 arm_cfft_radix2_f32 和基 4函数 arm_cfft_radix4_f32 将废弃。 ARM 说明如下:
DSP 库的早期发行版提供了单独的 radix-2 和 radix-4 对浮点数据进行运算的算法。 这些功能仍然提供,但已弃用。 相比新版函数,老版的功能较慢且通用性较低
1、基础支持
当前复数 FFT 函数支持三种数据类型,分别是浮点,定点 Q31 和 Q15。这些 FFT 函数有一个共同的特点,就是用于输入信号的缓冲,在转化结束后用来存储输出结果。这样做的好处是节省了 RAM 空间,不需要为输入和输出结果分别设置缓存。由于是复数 FFT,所以输入和输出缓存要存储实部和虚部。存储顺序如下: {real[0], imag[0], real[1], imag[1],………………} ,在使用中切记不要搞错。
2、单精度函数 arm_cfft_f32
支持16、32、64、128、256、512、1024、2048、4096点单精度复数FFT、IFFT。
3、双精度函数 arm_cfft_f64
支持16、32、64、128、256、512、1024、2048、4096点双精度复数FFT、IFFT
三、实数浮点 FFT(支持单精度和双精度)
CMSIS DSP 库里面包含一个专门用于计算实数序列的 FFT 库,很多情况下,用户只需要计算实数序列即可。计算同样点数 FFT 的实数序列要比计算同样点数的虚数序列有速度上的优势。
快速的 rfft 算法是基于混合基 cfft 算法实现的。
1、基础支持
一个 N 点的实数序列 FFT 正变换采用下面的步骤实现:
由上面的框图可以看出,实数序列的 FFT 是先计算 N/2 个实数的 CFFT,然后再重塑数据进行处理从而获得半个 FFT 频谱即可(利用了 FFT 变换后频谱的对称性)。
一个 N 点的实数序列 FFT 逆变换采用下面的步骤实现:
实数 FFT 支持浮点, Q31 和 Q15 三种数据类型。
2、单精度函数 arm_rfft_fast_f32
支持32、64、128、256、512、1024、2048、4096点单精度实数FFT、IFFT。
3、双精度函数 arm_rfft_fast_f64
支持32、64、128、256、512、1024、2048、4096点双精度实数FFT、IFFT
四、不限制点数 FFT 实现
可以看到前面的由于 ARM DSP 库限制最大只能 4096 点,有点不够用,所以整理了个更大点数的。不限制点数,满足 2^n 即可, n 最小值 4, 即 16 个点的 FFT,而最大值不限。
此 FFT 算法没有再使用 ARM DSP 库,重新实现了一个。
1、函数 InitTableFFT
这个函数用于 FFT 计算过程中需要用到的正弦和余弦表。 对于 8192 点和 16384 点已经专门制作了数值表,存到内部 Flash,其它点数继续使用的 RAM 空间。
/*
*********************************************************************************************************
* 函 数 名: Int_FFT_TAB
* 功能说明: 正弦和余弦表
* 形 参: 点数
* 返 回 值: 无
*********************************************************************************************************
*/
#if (MAX_FFT_N != 8192) && (MAX_FFT_N != 16384)
float32_t costab[MAX_FFT_N/2];
float32_t sintab[MAX_FFT_N/2];
void InitTableFFT(uint32_t n)
{uint32_t i;/* 正常使用下面获取 cos 和 sin 值 */#if 1for (i = 0; i < n; i ++ ){sintab[ i ]= sin( 2 * PI * i / MAX_FFT_N );costab[ i ]= cos( 2 * PI * i / MAX_FFT_N );}/* 打印出来是方便整理 cos 值和 sin 值数组,将其放到内部 Flash,从而节省 RAM */#elseprintf("const float32_t sintab[%d] = {\r\n", n);for (i = 0; i < n; i ++ ){sintab[ i ]= sin( 2 * PI * i / MAX_FFT_N );printf("%.11ff,\r\n", sintab[ i ]);}printf("};\r\n");printf("const float32_t costab[%d] = {\r\n", n);for (i = 0; i < n; i ++ ){sintab[ i ]= cos( 2 * PI * i / MAX_FFT_N );printf("%.11ff,\r\n", sintab[ i ]);}printf("};\r\n");#endif
}
#endif
2、函数 cfft
这个函数用于复数 FFT 变换,如果需要实数则直接把虚部设置为0即可。
void cfft(struct compx *_ptr, uint32_t FFT_N )
/*
*********************************************************************************************************
* 函 数 名: cfft
* 功能说明: 对输入的复数组进行快速傅里叶变换(FFT)
* 形 参: *_ptr 复数结构体组的首地址指针 struct 型
* FFT_N 表示点数
* 返 回 值: 无
*********************************************************************************************************
*/
void cfft(struct compx *_ptr, uint32_t FFT_N )
{float32_t TempReal1, TempImag1, TempReal2, TempImag2;uint32_t k,i,j,z;uint32_t Butterfly_NoPerColumn; /* 每级蝶形的蝶形组数 */uint32_t Butterfly_NoOfGroup; /* 蝶形组的第几组 */uint32_t Butterfly_NoPerGroup; /* 蝶形组的第几个蝶形 */uint32_t ButterflyIndex1,ButterflyIndex2,P,J;uint32_t L;uint32_t M;z=FFT_N/2; /* 变址运算,即把自然顺序变成倒位序,采用雷德算法 */for(i=0,j=0;i<FFT_N-1;i++){/*如果 i<j,即进行变址 i=j 说明是它本身, i>j 说明前面已经变换过了,不许再变化,注意这里一般是实数有虚数部分 设置成结合体*/if(i<j){TempReal1 = _ptr[j].real;_ptr[j].real= _ptr[i].real;_ptr[i].real= TempReal1;}k=z; /*求 j 的下一个倒位序 */while(k<=j) /* 如果 k<=j,表示 j 的最高位为 1 */{j=j-k; /* 把最高位变成 0 */k=k/2; /* k/2,比较次高位,依次类推,逐个比较,直到某个位为 0,通过下面那句 j=j+k 使其变为 1 */}j=j+k; /* 求下一个反序号,如果是 0,则把 0 改为 1 */}/* 第 L 级蝶形(M)第 Butterfly_NoOfGroup 组(Butterfly_NoPerColumn)第 J 个蝶形(Butterfly_NoPerGroup)****** */
/* 蝶形的组数以 2 的倍数递减 Butterfly_NoPerColumn,每组中蝶形的个数以 2 的倍数递增 Butterfly_NoPerGroup */
/* 在计算蝶形时,每 L 列的蝶形组数,一共有 M 列,每组蝶形中蝶形的个数,蝶形的阶数(0,1,2.....M-1) */Butterfly_NoPerColumn = FFT_N;Butterfly_NoPerGroup = 1;M = log2(FFT_N);for ( L = 0;L < M; L++ ){Butterfly_NoPerColumn >>= 1; /* 蝶形组数 假如 N=8,则(4,2,1) *///第 L 级蝶形 第 Butterfly_NoOfGroup 组(0,1, ....Butterfly_NoOfGroup-1)for ( Butterfly_NoOfGroup = 0;Butterfly_NoOfGroup < Butterfly_NoPerColumn;Butterfly_NoOfGroup++ ){
/* 第 Butterfly_NoOfGroup 组中的第 J 个 */for ( J = 0;J < Butterfly_NoPerGroup;J ++ ){ /* 第 ButterflyIndex1 和第 ButterflyIndex2 个元素作蝶形运算,WNC */
/* (0,2,4,6)(0,1,4,5)(0,1,2,3) */
/* 两个要做蝶形运算的数相距 Butterfly_NoPerGroup, ge=1,2,4 */
/* 这里相当于 P=J*2^(M-L),做了一个换算下标都是 N (0,0,0,0)(0,2,0,2)(0,1,2,3) */ButterflyIndex1 = ( ( Butterfly_NoOfGroup * Butterfly_NoPerGroup ) << 1 ) + J;ButterflyIndex2 = ButterflyIndex1 + Butterfly_NoPerGroup;P = J * Butterfly_NoPerColumn;
/* 计算和转换因子乘积 */TempReal2 = _ptr[ButterflyIndex2].real * costab[ P ] + _ptr[ButterflyIndex2].imag *
sintab[ P ];TempImag2 = _ptr[ButterflyIndex2].imag * costab[ P ] - _ptr[ButterflyIndex2].real *
sintab[ P ] ;TempReal1 = _ptr[ButterflyIndex1].real;TempImag1 = _ptr[ButterflyIndex1].imag;
/* 蝶形运算 */_ptr[ButterflyIndex1].real = TempReal1 + TempReal2;_ptr[ButterflyIndex1].imag = TempImag1 + TempImag2;_ptr[ButterflyIndex2].real = TempReal1 - TempReal2;_ptr[ButterflyIndex2].imag = TempImag1 - TempImag2;}}Butterfly_NoPerGroup<<=1; /* 一组中蝶形的个数(1,2,4) */
}