STM32 DSP库CUBEMX配置+FFT频率计算


前言

使用DSP中的函数加快计算。
本文首先讲述如何通过添加dsp库。
再讲述使用DSP库进行实数FFT运算。(FFT运算用到了前面讲述的STM32CubeMX-ADC hal库 3定时器触发

参考1文章
参考2文章


一、DSP库添加

1.1 加一个define

,ARM_MATH_CM3//F1是M3,F4是M4,H7是M7

在这里插入图片描述

1.2 添加文件路径

先找到文件路径
在这里插入图片描述
在这里插入图片描述然后设置如下路径
在这里插入图片描述
双击如下并找到路径D:\STM32CubeMX\STM32Cube_FW_F4_V1.26.2\Drivers\CMSIS\Lib\ARM选择arm_cortexM4lf_math.lib
在这里插入图片描述

1.3 主函数

包含头文件

#include "arm_math.h"
#include "arm_const_structs.h"

进行编译

二、FFT运算求频率

FFT运算简单理解就是从时域来求解频域的问题。
对于FFT的思路和代码参考这位大佬写的
那我们根据他的步骤,将文章简化并复现代码。(在复刻的过程中发现了一些问题,所以不完全按照上面大佬的文章)
这篇大佬讲述了arm_rfft_fast_f32的用法
这里还列出一些其他参考。
参考1
参考2
参考3
参考4,,,这个用的不是实数而是complex。所以稍微看下
cmsis官网

2.1 初始版本

宏定义和全局变量

#define adc_SIZE 2048*2// ADC 采样大小的定义
uint32_t adcConvertValue[adc_SIZE]={0};// 存放 ADC 采样数据的数组
uint8_t flag=0;// 标记位,用于标识 ADC 采样是否完成
float32_t frequency ;// 用于存放计算结果的频率变量
// FFT 相关参数的定义
#define FFT_SIZE 2048
#define FFT_LEN FFT_SIZE 
#define SAMPLING_FREQUENCY 100000
float32_t inputSignal[FFT_SIZE*2];// FFT 输入信号数组
float32_t fftOutput[FFT_SIZE];// FFT 输出数组
uint32_t index_;// 存放 FFT 输出中最大值的索引

运算函数

void fftCalculate(void)// FFT 计算函数
{
    arm_cfft_f32(&arm_cfft_sR_f32_len2048, inputSignal, 0, 1);// 执行 FFT 计算
    arm_cmplx_mag_f32(inputSignal, fftOutput, FFT_LEN);// 计算 FFT 输出的幅度
    index_ = 0;// 查找 FFT 输出中的最大值
    float32_t maxValue = fftOutput[1];
//    for (uint32_t i = 1; i < FFT_LEN/2; i++)
//    {
//        if (fftOutput[i] > maxValue)
//        {
//            maxValue = fftOutput[i];
//            index = i;
//        }
//    }
		arm_max_f32(&fftOutput[1], FFT_LEN, &maxValue, &index_); // 使用 arm_max_f32 函数快速找到 FFT 输出中的最大值及其索引
    frequency = (float32_t)index_ * (float32_t)SAMPLING_FREQUENCY / (float32_t)FFT_SIZE;// 根据最大值的索引计算信号的频率

}

主函数

	HAL_TIM_Base_Start(&htim3);//启动定时器3
	HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adcConvertValue,adc_SIZE);//启动ADC的DMA传输,采200点

主循环

  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */

		if(flag==1)
		{
			flag=0;
			for(int j=0;j<FFT_SIZE;j++)//采样数据转换
			{
				inputSignal[j*2]=(adcConvertValue[j])*3.3f/4095.0f;//12位采样数字值对应为0-3.3伏
				inputSignal[j*2+1]=0;//交替插零,添加数据的虚部
			}

			fftCalculate();
//			HAL_Delay(2000);
			HAL_TIM_Base_Start(&htim3);	//重新启动定时器3
			HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adcConvertValue,adc_SIZE);//重新开始下一轮采集	
		}			
  }

版本2

文件

根据抽样定理我们可以知道,采样率要是最高频率的两倍,所以对文中的一些东西进行了优化。
就是将本来size的位置都设置为/2,这样既可以防止跳变也可以减少运算。

	float32_t fftOutput[FFT_SIZE/2];// FFT 输出数组
    arm_cmplx_mag_f32(inputSignal, fftOutput, FFT_LEN/2);// 计算 FFT 输出的幅度
    arm_max_f32(&fftOutput[1], FFT_LEN/2, &maxValue, &index_); // 使用 arm_max_f32 函数快速找到 FFT 输出中的最大值及其索引

总结

  • 13
    点赞
  • 107
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
引用\[1\]和\[2\]提供了关于在STM32F407上使用FFT进行频谱分析的代码示例。这些代码使用了ARM的CMSIS-DSP来执行FFT和频谱分析。在这些代码中,输入信号被转换为复数形式,并通过FFT得到频谱。然后,通过计最大值和索引来确定信号的频率。根据最大值的索引,可以判断信号的波形类型,如方波、三角波或正弦波。 引用\[3\]提供了对代码进行优化的建议,通过将数组大小设置为原来的一半,可以减少计量并提高性能。这是因为根据抽样定理,采样率应该是最高频率的两倍,因此可以将数组大小减半。 综上所述,这些代码示例展示了如何在STM32F407上使用FFT进行频谱分析,并根据频谱结果判断信号的波形类型。 #### 引用[.reference_title] - *1* *3* [STM32 DSPCUBEMX配置+FFT频率计](https://blog.csdn.net/qq_59953808/article/details/131405743)[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* [STM32+CubeMX 通过RMS和FFT进行波形识别](https://blog.csdn.net/Nothing_To_Say_/article/details/123606260)[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 ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值