30.3 复数FFT—基4算法 如果希望直接调用FFT程序计算IFFT,可以用下面的方法:
30.3.1 arm_cfft_radix4_f32 此函数已经不推荐使用,后面的版本会被删除,故不做介绍。
30.3.2 arm_cfft_radix4_q31函数定义如下:
void arm_cfft_radix4_q31(
const arm_cfft_radix4_instance_q31 * S,
q31_t * pSrc)
参数定义:
[in] *S points to an instance of the fixed-point CFFT/CIFFT structure.
[in, out] *pSrc points to the complex data buffer of size2*fftLen
. Processing
occurs in-place.
注意事项:
1. 结构const arm_cfft_radix4_instance_q31的定义如下(在文件arm_math.h文件):
typedef struct
{
uint16_t fftLen;
uint8_t ifftFlag;
uint8_t bitReverseFlag;
q31_t *pTwiddle;
uint16_t *pBitRevTable;
uint16_t twidCoefModifier;
uint16_t bitRevFactor;
} arm_cfft_radix4_instance_q31;
2. 为了防止数据饱和,每次蝶形运行的结果都要除以2,故不同的长度的FFT运算的最终结果输出格式不同。具体信息如下:
Q31 CFFT
Q31 CIFFT
下面通过在开发板上运行这个函数并计算幅频相应,然后再与Matlab计算的结果做对比。
- q31_t testInput_radix4_q31_50hz[TEST_LENGTH_SAMPLES];
- /*
- *********************************************************************************************************
- * 函 数 名: arm_cfft_radix4_q31_app
- * 功能说明: 调用函数arm_cfft_radix4_q31_app计算幅频。
- * 形 参:无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void arm_cfft_radix4_q31_app(void)
- {
- uint16_t i,j;
- arm_cfft_radix4_instance_q31 S;
-
- fftSize = 1024;
- ifftFlag = 0;
- doBitReverse = 1;
-
- /* 初始化结构S */
- arm_cfft_radix4_init_q31(&S, fftSize, ifftFlag, doBitReverse);
-
- /* 按照实部,虚部,实部,虚部..... 的顺序存储数据 */
- for(i=0; i<1024; i++)
- {
- testInput_radix4_q31_50hz[i*2+1] = 0;
-
- /* 51.2Hz正弦波,采样率1024Hz。
- arm_sin_q31输入参数的范围0-2^31, 这里每20次为一个完整的正弦波,
- 2^31 / 20 = 107374182.4
- */
- j = i % 20;
- testInput_radix4_q31_50hz[i*2] = arm_sin_q31(107374182*j);
- printf("%drn", testInput_radix4_q31_50hz[i*2]);
- }
-
- /* 输出结果分割线 */
- printf("**************************************************rn");
- printf("**************************************************rn");
-
- /* 计算CFFT */
- arm_cfft_radix4_q31(&S, testInput_radix4_q31_50hz);
-
- /* 计算模值 */
- arm_cmplx_mag_q31(testInput_radix4_q31_50hz, testOutputQ31, fftSize);
-
- /* 串口打印求解的模值 */
- for(i=0; i<1024; i++)
- {
- printf("%drn", testOutputQ31[i]);
- }
-
- }
运行如上函数可以通过串口打印出原始信号和计算的模值,下面我们就通过Matlab计算的模值跟arm_cfft_radix4_q31计算的模值做对比。
对比前需要先将串口打印出的数据加载到Matlab中,原始信号起名signal,函数arm_cmplx_mag_q31计算的模值起名sampledata,加载方法在前面的教程中已经讲解过,这里不做赘述了。Matlab中运行的代码如下:
- Fs = 1024; % 采样率
- N = 1024; % 采样点数
- n = 0:N-1; % 采样序列
- f = n * Fs / N; %真实的频率
-
- y = fft(signal, N); %对原始信号做FFT变换
-
- subplot(2,1,2);
- plot(f, abs(y)); %绘制幅频相应曲线
- title('Matlab计算结果');
- xlabel('频率');
- ylabel('幅度');
-
- subplot(2,1,1);
- plot(f, sampledata); %绘制幅频相应曲线
- title('复数FFT计算结果');
- xlabel('频率');
- ylabel('幅度');
Matlab运行结果如下:
从上面的对比结果中可以看出,Matlb和函数arm_cfft_radix4_q31计算的频率点基本是一致的,而幅值大小不一样是因为调用函数arm_cmplx_mag_q31和arm_cfft_radix4_q31对数据结果做了移位处理。
30.3.3 arm_cfft_radix4_q15函数定义:
voidarm_cfft_radix4_q15(
const arm_cfft_radix4_instance_q15 * S,
q15_t *pSrc)
参数定义:
[in] *S points to an instance of the fixed-point CFFT/CIFFT structure.
[in, out] *pSrc points to the complex data buffer of size 2*fftLen
.Processing
occurs in-place.
注意事项:
1. 结构const arm_cfft_radix4_instance_q15的定义如下(在文件arm_math.h文件):
typedef struct
{
uint16_t fftLen;
uint8_t ifftFlag;
uint8_t bitReverseFlag;
q15_t *pTwiddle;
uint16_t*pBitRevTable;
uint16_ttwidCoefModifier;
uint16_t bitRevFactor;
} arm_cfft_radix4_instance_q15;
2. 为了防止数据饱和,每次蝶形运行的结果都要除以2,故不同的长度的FFT运算的最终结果输出格式不同。具体信息如下:
Q15 CFFT
Q15 CIFFT
下面通过在开发板上运行这个函数并计算幅频相应,然后再与Matlab计算的结果做对比。
- q15_t testInput_radix4_q15_50hz[TEST_LENGTH_SAMPLES];
- /*
- *********************************************************************************************************
- * 函 数 名: arm_cfft_radix4_q15_app
- * 功能说明: 调用函数arm_cfft_radix4_q15计算幅频。
- * 形 参:无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void arm_cfft_radix4_q15_app(void)
- {
- uint16_t i,j;
- arm_cfft_radix4_instance_q15 S;
-
- fftSize = 1024;
- ifftFlag = 0;
- doBitReverse = 1;
-
- /* 初始化结构S */
- arm_cfft_radix4_init_q15(&S, fftSize, ifftFlag, doBitReverse);
-
- /* 按照实部,虚部,实部,虚部..... 的顺序存储数据 */
- for(i=0; i<1024; i++)
- {
- /* 虚部全部置0 */
- testInput_radix4_q15_50hz[i*2+1] = 0;
-
- /* 51.2Hz正弦波,采样率1024Hz。
- arm_sin_q15输入参数的范围[0, 32768), 这里每20次为一个完整的正弦波,
- 32768 / 20 = 1638.4
- */
- j = i % 20;
- testInput_radix4_q15_50hz[i*2] = arm_sin_q15(1638*j);
- printf("%drn", testInput_radix4_q15_50hz[i*2]);
- }
-
- /* 输出结果分割线 */
- printf("**************************************************rn");
- printf("**************************************************rn");
-
- /* 计算CFFT */
- arm_cfft_radix4_q15(&S, testInput_radix4_q15_50hz);
-
- /* 计算模值 */
- arm_cmplx_mag_q15(testInput_radix4_q15_50hz, testOutputQ15, fftSize);
-
- /* 串口打印求解的模值 */
- for(i=0; i<1024; i++)
- {
- printf("%drn", testOutputQ15[i]);
- }
-
- }
运行如上函数可以通过串口打印出原始信号和计算的模值,下面我们就通过Matlab计算的模值跟arm_cfft_radix4_q15计算的模值做对比。
对比前需要先将串口打印出的数据加载到Matlab中,原始信号起名signal,函数arm_cmplx_mag_q15计算的模值起名sampledata,加载方法在前面的教程中已经讲解过,这里不做赘述了。Matlab中运行的代码如下:
- Fs = 1024; % 采样率
- N = 1024; % 采样点数
- n = 0:N-1; % 采样序列
- f = n * Fs / N; %真实的频率
-
- y = fft(signal, N); %对原始信号做FFT变换
-
- subplot(2,1,2);
- plot(f, abs(y)); %绘制幅频相应曲线
- title('Matlab计算结果');
- xlabel('频率');
- ylabel('幅度');
-
- subplot(2,1,1);
- plot(f, sampledata); %绘制幅频相应曲线
- title('复数FFT计算结果');
- xlabel('频率');
- ylabel('幅度');
Matlab运行结果如下:
从上面的对比结果中可以看出,Matlab和函数arm_cfft_radix4_q15计算的频率点基本是一致的,而幅值大小不一样是因为调用函数arm_cmplx_mag_q15和arm_cfft_radix4_q15对数据结果做了移位处理。
30.3 复数FFT—基4算法 如果希望直接调用FFT程序计算IFFT,可以用下面的方法:
30.3.1 arm_cfft_radix4_f32 此函数已经不推荐使用,后面的版本会被删除,故不做介绍。
30.3.2 arm_cfft_radix4_q31函数定义如下:
void arm_cfft_radix4_q31(
const arm_cfft_radix4_instance_q31 * S,
q31_t * pSrc)
参数定义:
[in] *S points to an instance of the fixed-point CFFT/CIFFT structure.
[in, out] *pSrc points to the complex data buffer of size2*fftLen
. Processing
occurs in-place.
注意事项:
1. 结构const arm_cfft_radix4_instance_q31的定义如下(在文件arm_math.h文件):
typedef struct
{
uint16_t fftLen;
uint8_t ifftFlag;
uint8_t bitReverseFlag;
q31_t *pTwiddle;
uint16_t *pBitRevTable;
uint16_t twidCoefModifier;
uint16_t bitRevFactor;
} arm_cfft_radix4_instance_q31;
2. 为了防止数据饱和,每次蝶形运行的结果都要除以2,故不同的长度的FFT运算的最终结果输出格式不同。具体信息如下:
Q31 CFFT
Q31 CIFFT
下面通过在开发板上运行这个函数并计算幅频相应,然后再与Matlab计算的结果做对比。
- q31_t testInput_radix4_q31_50hz[TEST_LENGTH_SAMPLES];
- /*
- *********************************************************************************************************
- * 函 数 名: arm_cfft_radix4_q31_app
- * 功能说明: 调用函数arm_cfft_radix4_q31_app计算幅频。
- * 形 参:无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void arm_cfft_radix4_q31_app(void)
- {
- uint16_t i,j;
- arm_cfft_radix4_instance_q31 S;
-
- fftSize = 1024;
- ifftFlag = 0;
- doBitReverse = 1;
-
- /* 初始化结构S */
- arm_cfft_radix4_init_q31(&S, fftSize, ifftFlag, doBitReverse);
-
- /* 按照实部,虚部,实部,虚部..... 的顺序存储数据 */
- for(i=0; i<1024; i++)
- {
- testInput_radix4_q31_50hz[i*2+1] = 0;
-
- /* 51.2Hz正弦波,采样率1024Hz。
- arm_sin_q31输入参数的范围0-2^31, 这里每20次为一个完整的正弦波,
- 2^31 / 20 = 107374182.4
- */
- j = i % 20;
- testInput_radix4_q31_50hz[i*2] = arm_sin_q31(107374182*j);
- printf("%drn", testInput_radix4_q31_50hz[i*2]);
- }
-
- /* 输出结果分割线 */
- printf("**************************************************rn");
- printf("**************************************************rn");
-
- /* 计算CFFT */
- arm_cfft_radix4_q31(&S, testInput_radix4_q31_50hz);
-
- /* 计算模值 */
- arm_cmplx_mag_q31(testInput_radix4_q31_50hz, testOutputQ31, fftSize);
-
- /* 串口打印求解的模值 */
- for(i=0; i<1024; i++)
- {
- printf("%drn", testOutputQ31[i]);
- }
-
- }
运行如上函数可以通过串口打印出原始信号和计算的模值,下面我们就通过Matlab计算的模值跟arm_cfft_radix4_q31计算的模值做对比。
对比前需要先将串口打印出的数据加载到Matlab中,原始信号起名signal,函数arm_cmplx_mag_q31计算的模值起名sampledata,加载方法在前面的教程中已经讲解过,这里不做赘述了。Matlab中运行的代码如下:
- Fs = 1024; % 采样率
- N = 1024; % 采样点数
- n = 0:N-1; % 采样序列
- f = n * Fs / N; %真实的频率
-
- y = fft(signal, N); %对原始信号做FFT变换
-
- subplot(2,1,2);
- plot(f, abs(y)); %绘制幅频相应曲线
- title('Matlab计算结果');
- xlabel('频率');
- ylabel('幅度');
-
- subplot(2,1,1);
- plot(f, sampledata); %绘制幅频相应曲线
- title('复数FFT计算结果');
- xlabel('频率');
- ylabel('幅度');
Matlab运行结果如下:
从上面的对比结果中可以看出,Matlb和函数arm_cfft_radix4_q31计算的频率点基本是一致的,而幅值大小不一样是因为调用函数arm_cmplx_mag_q31和arm_cfft_radix4_q31对数据结果做了移位处理。
30.3.3 arm_cfft_radix4_q15函数定义:
voidarm_cfft_radix4_q15(
const arm_cfft_radix4_instance_q15 * S,
q15_t *pSrc)
参数定义:
[in] *S points to an instance of the fixed-point CFFT/CIFFT structure.
[in, out] *pSrc points to the complex data buffer of size 2*fftLen
.Processing
occurs in-place.
注意事项:
1. 结构const arm_cfft_radix4_instance_q15的定义如下(在文件arm_math.h文件):
typedef struct
{
uint16_t fftLen;
uint8_t ifftFlag;
uint8_t bitReverseFlag;
q15_t *pTwiddle;
uint16_t*pBitRevTable;
uint16_ttwidCoefModifier;
uint16_t bitRevFactor;
} arm_cfft_radix4_instance_q15;
2. 为了防止数据饱和,每次蝶形运行的结果都要除以2,故不同的长度的FFT运算的最终结果输出格式不同。具体信息如下:
Q15 CFFT
Q15 CIFFT
下面通过在开发板上运行这个函数并计算幅频相应,然后再与Matlab计算的结果做对比。
- q15_t testInput_radix4_q15_50hz[TEST_LENGTH_SAMPLES];
- /*
- *********************************************************************************************************
- * 函 数 名: arm_cfft_radix4_q15_app
- * 功能说明: 调用函数arm_cfft_radix4_q15计算幅频。
- * 形 参:无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void arm_cfft_radix4_q15_app(void)
- {
- uint16_t i,j;
- arm_cfft_radix4_instance_q15 S;
-
- fftSize = 1024;
- ifftFlag = 0;
- doBitReverse = 1;
-
- /* 初始化结构S */
- arm_cfft_radix4_init_q15(&S, fftSize, ifftFlag, doBitReverse);
-
- /* 按照实部,虚部,实部,虚部..... 的顺序存储数据 */
- for(i=0; i<1024; i++)
- {
- /* 虚部全部置0 */
- testInput_radix4_q15_50hz[i*2+1] = 0;
-
- /* 51.2Hz正弦波,采样率1024Hz。
- arm_sin_q15输入参数的范围[0, 32768), 这里每20次为一个完整的正弦波,
- 32768 / 20 = 1638.4
- */
- j = i % 20;
- testInput_radix4_q15_50hz[i*2] = arm_sin_q15(1638*j);
- printf("%drn", testInput_radix4_q15_50hz[i*2]);
- }
-
- /* 输出结果分割线 */
- printf("**************************************************rn");
- printf("**************************************************rn");
-
- /* 计算CFFT */
- arm_cfft_radix4_q15(&S, testInput_radix4_q15_50hz);
-
- /* 计算模值 */
- arm_cmplx_mag_q15(testInput_radix4_q15_50hz, testOutputQ15, fftSize);
-
- /* 串口打印求解的模值 */
- for(i=0; i<1024; i++)
- {
- printf("%drn", testOutputQ15[i]);
- }
-
- }
运行如上函数可以通过串口打印出原始信号和计算的模值,下面我们就通过Matlab计算的模值跟arm_cfft_radix4_q15计算的模值做对比。
对比前需要先将串口打印出的数据加载到Matlab中,原始信号起名signal,函数arm_cmplx_mag_q15计算的模值起名sampledata,加载方法在前面的教程中已经讲解过,这里不做赘述了。Matlab中运行的代码如下:
- Fs = 1024; % 采样率
- N = 1024; % 采样点数
- n = 0:N-1; % 采样序列
- f = n * Fs / N; %真实的频率
-
- y = fft(signal, N); %对原始信号做FFT变换
-
- subplot(2,1,2);
- plot(f, abs(y)); %绘制幅频相应曲线
- title('Matlab计算结果');
- xlabel('频率');
- ylabel('幅度');
-
- subplot(2,1,1);
- plot(f, sampledata); %绘制幅频相应曲线
- title('复数FFT计算结果');
- xlabel('频率');
- ylabel('幅度');
Matlab运行结果如下:
从上面的对比结果中可以看出,Matlab和函数arm_cfft_radix4_q15计算的频率点基本是一致的,而幅值大小不一样是因为调用函数arm_cmplx_mag_q15和arm_cfft_radix4_q15对数据结果做了移位处理。
举报