stm32-HAL库-fft-测频率幅度

stm32-fft教程

目录

stm32-fft教程

前言:

FFT介绍:

正文:

基础知识:

DSP库调用:

代码示例: 

结语:

前言:

        学习单片机,就避不开stm32,学习stm32,就避不开ADC采样,学习ADC采样,就避不开fft-快速傅里叶变换。本文将给大家分享fft的使用,本教程使用stm32f407VET6,基于cubemx与keil5软件开发,将逐步带领大家实现fft测量采样信号的频率和幅度。(由于fft测量相位差需要用到ADC同步采样,所以将在下篇博客与大家分享哈)

FFT介绍:

        stm32---fft 究其根本其实就是三个函数的使用,下面也就是教大家如何去用。

	arm_cfft_radix2_instance_f32 scfft;
	arm_cfft_f32(&arm_cfft_sR_f32_len1024,fft_inputbuf,0,1);
	arm_cmplx_mag_f32(fft_inputbuf, fft_outputbuf, FFT_LENGTH); 

        快速傅里叶变换(FFT)是一种有效计算离散傅里叶变换(DFT)的算法,它将信号从时域转换到频域。通过频域分析,可以更容易地理解和处理信号的频率成分。在嵌入式系统中,特别是在像STM32F407这样的微控制器上,FFT常用于音频处理、振动分析和通信等领域。

STM32F407是一款基于ARM Cortex-M4内核的微控制器,具有DSP(数字信号处理)指令集,非常适合进行快速傅里叶变换等复杂的信号处理操作。使用CubeMX配置STM32硬件外设,通过Keil5搭配HAL库开发,使得我们可以在嵌入式系统中轻松实现FFT功能。

正文:

基础知识:

本文将直接进入fft的使用,关于ADC的配置与介绍,大家可以看看这两篇博客。

——《stm32-HAL 电赛信号教程

——《STM32——三重ADC交替采样—极限采样率7.2M

DSP库调用:

(1)先添加DSP库

(2)还得要添加下面三个宏

ARM_MATH_CM4,__CC_ARM,ARM_MATH_M

(3)再最后添加上这些头文件 ,OK,调用步骤完成。

#include "arm_math.h"
#include "arm_const_structs.h"
代码示例: 

(1)先进行采样数据个数,采样率,fft数据处理个数的定义。(注意:FFT_LENGTH需要与ADC1_DMA_Size 大小一致,采样率定义需要与cubemx中配置相同,具体请看前面提到的两篇博客)

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define  FFT_LENGTH		   1024
#define  ADC1_DMA_Size	   1024
int SAM_FRE = 2000000; //采样率

(2)再定义数组, fft_inputbuf [FFT_LENGTH*2] 是fft 输入数组;fft_outputbuf[FFT_LENGTH] 是fft 输出数组;ADC1_ConvertedValue[ ADC1_DMA_Size ]是ADC采集到的数据,这里先以1024个点为例。

/* USER CODE BEGIN PV */
 float    fft_inputbuf [FFT_LENGTH*2];	
 float    fft_outputbuf[FFT_LENGTH];
 uint32_t ADC1_ConvertedValue[ ADC1_DMA_Size ];

(3)调用函数   arm_cfft_radix2_instance_f32 scfft  ,定义结构体scfft。

调用函数arm_cfft_f32(&arm_cfft_sR_f32_len1024,fft_inputbuf,0,1);     
arm_cmplx_mag_f32(fft_inputbuf, fft_outputbuf, FFT_LENGTH) 进行计算。

我这里直接生成一个频率200k与400k,电压为0.825V的混合信号进行处理,添加了1.65V的抬升信号。

	
   arm_cfft_radix2_instance_f32 scfft;
  /* USER CODE END 2 */
  
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {	 
	  
	  while(flag==1)
	  {
		  HAL_ADC_Start_DMA(&hadc1,(uint32_t*)ADC1_ConvertedValue,ADC1_DMA_Size); //开启ADC_dma采集数据 
		  HAL_Delay(1000);
		
		  for(i=0;i<FFT_LENGTH;i++)
		  {
				//fft_inputbuf[2*i] = (float)ADC1_ConvertedValue[ i ]*3.3f/4095.0f; //数组实部放采集到的数据
			    fft_inputbuf[2*i] = ((sin(2*PI*200000*i/SAM_FRE)+1)*1024+ (sin(2*PI*400000*i/SAM_FRE)+1)*1024)*3.3f/4095.0f;
				fft_inputbuf[2*i+1]=0; //虚部都放0
		  }		
//		  for(i=0;i<FFT_LENGTH;i++)
//		  {
//				printf("%f\r\n",fft_inputbuf[2*i]*3.3f/4095.0f);			
//		  }
		  
		  arm_cfft_f32(&arm_cfft_sR_f32_len1024,fft_inputbuf,0,1);	  //其中1024表示需要处理的数据个数,这里可以是1024,2048,4096
		  arm_cmplx_mag_f32(fft_inputbuf, fft_outputbuf, FFT_LENGTH); //计算幅度
		  
		  for(i=0;i<FFT_LENGTH;i++)
		  {
				printf("%d,%f\r\n",i,fft_outputbuf[ i ]);	//未加窗
		  }

FFT结果如下图:

如果大家有了解FFT的原理,会知道,fft_outputbuf中的值并不是我们最终结果,这1024个点中,索引为0的点代表直流偏置信号,剩下的会关于第512个点对称,由于对称,我们只需要去分析前面512个点。那么我们怎么去计算信号的频率和幅度呢?

(1)直流偏置信号幅度:  U_d=\frac{U}{FFT-length}

由于单片机不能采集负电压,所以我们往往会先加上一个直流偏置。U表示索引为0的点的值,FFT_length表示FFT数据处理的个数。

Ud=1692/1024=1.6523

(2)频率: F=\frac{N*FS}{FFT-length}

N表示数据索引即1——512,FS表示采样率,FFT_length表示FFT数据处理的个数。(大家可以看到,我们计算出的频率是一个离散的范围)。

F1=102*2000000/1024=199218 HZ,F2=205*2000000/1024=400390 HZ

(3)幅度: U_a=\frac{U_n*2}{FFT-length}

Un表示索引为n的点的值,FFT_length表示FFT数据处理的个数。

结语:

        FFT处理往往会有频谱泄露,大家可以进行加窗处理(如下)。对了,提一嘴,反快速傅里叶变化——IFFT和这差不多,只不过改了个参数,也放在下面。好啦,希望这篇博客对大家有所帮助,有疑问或建议欢迎留言!如果需要完整代码,可以私我或留言。

	  for(i=0;i<FFT_LENGTH;i++)
	  {
		fft_inputbuf_win [i*2] *= (0.5-0.5*cos((2*PI*i)/FFT_LENGTH-1));		
	  }
	  arm_cfft_radix4_init_f32(&scfft,FFT_LENGTH,1,1);//反fft---ifft
	  arm_cfft_f32(&arm_cfft_sR_f32_len1024,fft_inputbuf,1,1);
	  
      for(i=0;i<FFT_LENGTH;i++)
	  {
			printf("%f\r\n",fft_inputbuf[ 2*i ]);
	  }	

  • 21
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用\[2\]中提到的几种量方法,可以使用基于STM32F4的FFT频率FFT是快速傅里叶变换的缩写,它可以将时域信号转换为频域信号,从而实现频率量。在使用STM32F4进行FFT频率时,可以参考引用\[2\]中提到的基于STM32F4的FFT信号频率并判断波形种类的方法。该方法可以通过采样率的调整来适应不同频率范围的量需求。 在使用STM32F4进行FFT频率时,可以使用HAL库来进行开发。HAL库STM32提供的硬件抽象层库,可以方便地进行外设的配置和控制。通过HAL库,可以使用ADC模块进行模拟信号的采样,然后将采样数据传输到FFT算法中进行频谱分析,最后得到频率信息。 需要注意的是,在进行FFT频率时,需要设置合适的采样频率和采样点数,以及计算频率分辨率。根据引用\[3\]中的公式,频率分辨率可以通过采样频率和采样点数来计算得到。 综上所述,使用STM32F4进行FFT频率时,可以借助HAL库进行开发,参考引用\[2\]中的方法,并根据引用\[3\]中的公式计算频率分辨率。 #### 引用[.reference_title] - *1* [STM32频率量](https://blog.csdn.net/phker/article/details/128213801)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [基于STM32F4的FFT+频率幅值相位差,波形显示,示波器,时域频域分析相关工程](https://blog.csdn.net/qq_50027598/article/details/126045155)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [2018年电赛A题 软件部分 STM32 FFT 时域到频域 STM32cubeMX HAL](https://blog.csdn.net/qq_53214662/article/details/130539447)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值