【STM32】STM32F4调用DSP库实现FFT运算

news2024/11/30 13:44:19

写在前面

最近在整理之前的stm32笔记,打算把一些有价值的笔记发到CSDN分享一下。

奎斯特定理

在进行模拟/数字信号的转换过程中,当采样频率F大于信号中最高频率 fmax 的 2 倍时(F>2*fmax),采样之后的数字信号完整地保留了原始信号中的信息。

采样结果

  • 设采样频率(单位时间可以采多少个信号样本)为Fs,信号频率F,采样点数为N。那么FFT之后结果就是一个为N点的复数。每一个点对应一个频率点,并且这个点对应的幅值就是该频率下的幅度特性。

  • 而每个点的相位,就是在该频率下的信号的相位。

  • 假设原始信号的峰值为A

    那么FFT的第一个点(直流分量)的模值就是A的N倍

    FFT的其他点的模值就是A的N/2倍

    比如

  • 第一个点表示直流分量(即0Hz),而最后一个点N的再下一个点(实际上这个点是不存在的,这里是假设的第N+1个点,也可以看做是将第一个点分做两半分,另一半移到最后)则表示采样频率Fs,这中间被N-1个点平均分成N等份,每个点的频率依次增加。第n所表示的频率为:Fn=(n-1) * Fs/N。

    比如采样频率为10240Hz,采样点数为1024。即采样一次的时间为1/10240s,100ms可以采样1024个点,1s可以采样10次。则结果中第1个点代表0Hz,第2个点代表10Hz,第3个点代表20Hz,以此类推,第1024个点代表1024Hz。则频率分辨率为10Hz

  • 如果要提高频率分辨力,则必须增加采样点数,也即采样时间。频率分辨率和采样时间是倒数关系。 假设FFT之后某点n用复数a+bi表示,那么这个复数的模就是An=根号aa+bb,相位就是Pn=atan2(b,a)。根据以上的结果,就可以计算出n点(n≠1,且n<=N/2)对应的信号的表达式为An/(N/2)cos(2piFnt+Pn),即2An/Ncos(2piFn*t+Pn)。对于n=1点的信号,是直流分量,幅度即为A1/N。 由于FFT结果的对称性,通常我们只使用前半部分的结果,即小于采样频率一半的结果。

stm32中相关函数

/*
 * 函数1  初始化FFT运算相关参数
 *	fftLen 			用于指定 FFT长度(16/64/256/1024/4096)本章设置为1024
 *	ifftFlag 		用于指定是傅里叶变换(0)还是反傅里叶变换(1) 本章设置为0
 *	bitReverseFlag  用于设置是否按位取反 本章设置为 1
 * */
arm_status arm_cfft_radix4_init_f32(
	arm_cfft_radix4_instance_f32 * S,
	uint16_t fftLen,uint8_t ifftFlag,uint8_t bitReverseFlag)


/*
 *  函数2  执行基 4 浮点FFT运算
 * 	S结构体指针参数 先由 arm_cfft_radix4_init_f32 函数设置好 然后传入该函数的
 * 	pSrc 		  传入采集到的输入信号数据(实部+虚部形式)同时FFT变换后的数据也按顺序存放在pSrc里面pSrc 				  必须大于等于2倍fftLen长度
 * */
void arm_cfft_radix4_f32(const arm_cfft_radix4_instance_f32 * S,float32_t * pSrc)


/*
 *  函数3  计算复数模值 对 FFT 变换后的结果数据,执行取模操作
 *	pSrc 		复数输入数组(大小为 2*numSamples)指针,指向 FFT 变换后的结果
 *	pDst		输出数组(大小为 numSamples)指针,存储取模后的值
 *	numSamples  就是总共有多少个数据需要取模
 * */
void arm_cmplx_mag_f32(float32_t * pSrc,float32_t * pDst,uint32_t numSamples)

arm_cfft_radix4_init_f32 用于初始化 FFT 运算相关参数,

  • fftLen 用于指定 FFT 长度(16/64/256/1024/4096),本章设置为 1024;
  • ifftFlag 用于指定是傅里叶变换(0)还是反傅里叶变换(1),本章设置为 0;
  • bitReverseFlag 用于设置是否按位取反,本章设置为 1;
  • 最后,所有这些参数存储在一个 arm_cfft_radix4_instance_f32 结构体指针 S 里面

arm_cfft_radix4_f32 就是执行基 4 浮点 FFT 运算的

  • pSrc 传入采集到的输入信号数据(实部+虚部形式),同时 FFT 变换后的数据,也按顺序存放在 pSrc 里面,pSrc 必须大于等于 2 倍 fftLen 长度
  • S 结构体指针参数是先由 arm_cfft_radix4_init_f32 函数设置好,然后传入该函数的

**arm_cmplx_mag_f32 **用于计算复数模值,可以对 FFT 变换后的结果数据,执行取模操作

  • pSrc 为复数输入数组(大小为 2*numSamples)指针,指向 FFT 变换后的结果
  • pDst为输出数组(大小为 numSamples)指针,存储取模后的值;
  • numSamples 就是总共有多少个数据需要取模

stm32配置

配置时钟树

在这里插入图片描述

添加DSP库

可以从MDK中添加,可以手动添加,这里演示从STM32CubeMX添加
在这里插入图片描述
如果没有安装先点击Install,安装完之后点击框框选中
在这里插入图片描述
选择添加DSP库
在这里插入图片描述

配置定时器触发ADC

这里以TIM3触发ADC1-CH1为例

TIM3挂在APB1上, APB1默认timer时钟为84MHz,这里配置TIM3频率为84000000/(42*100)=20000Hz=20KHz

即采样频率为20KHz,50us触发一次ADC采一次数据,如果是1024个点0.0512s可以采完一次
在这里插入图片描述
配置ADC,先打开DMA
在这里插入图片描述
别忘了点circular
在这里插入图片描述
ADC基础设置
在这里插入图片描述

打开串口,方便调试

很简单,自行配置。打开串口是为了方便查看运算后的信息

生成代码

添加宏

ARM_MATH_CM4//F4是这个
ARM_MATH_MATRIX_CHECK   
ARM_MATH_ROUNDING    

在这里插入图片描述

验证库是否正常

添加头文件

#include "arm_math.h"

编译,可以通过!

编写用户函数

#define FFT_LENGTH		1024 		//FFT长度,默认是1024点FFT

/*添加的头文件*/
#include "arm_math.h"
#include "stdio.h"


/*printf重定向*/
int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}


/*全局变量,在main之前定义*/
arm_cfft_radix4_instance_f32 scfft;//定义scfft结构体
float FFT_InputBuf[FFT_LENGTH*2];	//FFT输入数组
float FFT_OutputBuf[FFT_LENGTH];	//FFT输出数组
uint16_t ADC_1_Value_DMA[1024] = {0};//存放ADC的值


/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start(&htim3);//开启TIM3
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)ADC_1_Value_DMA, FFT_LENGTH);//开启ADC
arm_cfft_radix4_init_f32(&scfft,FFT_LENGTH,0,1);//初始化scfft结构体,设定FFT参数
/* USER CODE END 2 */



/*while(1)中*/
for(int i=0; i < FFT_LENGTH; i++)
{
    FFT_InputBuf[2*i]=ADC_1_Value_DMA[i]; //实部
    FFT_InputBuf[2*i+1]=0;				  //虚部
}
arm_cfft_radix4_f32(&scfft,FFT_InputBuf);					//FFT计算(基4)
arm_cmplx_mag_f32(FFT_InputBuf,FFT_OutputBuf,FFT_LENGTH);	//取模得幅值

之后可以用vofa+软件方便地查看频谱图。

可以动手实现的小项目

外接一个mic采集、oled实现音乐频谱等

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/991594.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

高效采集模拟量模块数据方案

在现代工业自动化领域&#xff0c;模拟量采集是关键的环节之一。本文将详细介绍如何通过模拟量采集电压、电流和温度等数据&#xff0c;并利用上位机实现数据的获取和转化。同时&#xff0c;我们还将详细介绍模拟量采集上位机框架及其强大的功能&#xff0c;为企业实现高效的数…

华为认证系统学习大纲及课程

前言 任何学习过程都需要一个科学合理的学习路线&#xff0c;才能够有条不紊的完成我们的学习目标。华为认证网络工程师所需学习的内容纷繁复杂&#xff0c;难度较大&#xff0c;所以今天特别为大家整理了一个全面的华为认证网络工程师学习大纲及课程&#xff0c;帮大家理清思…

【DataV/echarts】vue中使用,修改地图和鼠标点击部分的背景色

引入&#xff1a;使用 DataV 引入地图的教程是参考别人的&#xff0c;主要介绍修改地图相关的样式&#xff1b; 引入地图 是参考别人的&#xff0c;这里自己再整理一遍&#xff0c;注意需要安装 5 版本以上的 echarts&#xff1b; DataV 网址&#xff1a;https://datav.aliyun.…

Unity Animation、Animator 的使用(超详细)

文章目录 1. 添加动画2. Animation2.1 制作界面2.2 制作好的 Animation 动画2.3 添加和使用事件 3. Animator3.1 制作界面3.2 一些参数解释3.3 动画参数 4. Animator中相关类、属性、API4.1 类4.2 属性4.3 API4.4 几个关键方法 5. 动画播放和暂停控制 1. 添加动画 选中待提添加…

Win10如何清理无效注册表

电脑中部分注册表文件其实是没有什么用的&#xff0c;如果用户不主动清理的话就会占用大量的内存空间&#xff0c;从而导致系统变得卡顿&#xff0c;那么Win10怎么清理无效注册表呢&#xff0c;下面小编就给大家详细介绍一下Win10清理无效注册表的方法&#xff0c;大家感兴趣的…

无涯教程-JavaScript - IMCOS函数

描述 IMCOS函数以x yi或x yj文本格式返回复数的余弦。 语法 IMCOS (inumber)争论 Argument描述Required/OptionalInumberA Complex Number for which you want the cosine.Required Notes Excel中的复数仅存储为文本。 当将格式为" a bi"或" a bj&quo…

门口通畅家运顺

每一次遇见&#xff0c;都是一个心愿&#xff0c;也许&#xff0c;前有未了的情缘&#xff0c;所以&#xff0c;此生才能得以见面&#xff0c;所有的遇见&#xff0c;一切都是最好的安排。前段时间&#xff0c;峰民再次故地重游&#xff0c;去到了呼伦比尔海拉尔区为预约客户来…

《protobuf》基础语法

文章目录 消息体定义字段规则编译选项实战&#xff1a;编写一个通讯录文件 消息体定义 文件内定义 message Phone {string number 1; }message PeopleInfo {string name 1;int32 age 2;Phone phone 3; }内嵌定义 message PeopleInfo {string name 1;int32 age 2;messa…

如何自启动MySQL服务与解决MySQL字符集问题

1、自启动mysql服务 &#xff08;1&#xff09;查看mysql是否自启动&#xff08;默认自启动&#xff09; systemctl list-unit-files|grep mysqld.service &#xff08;2&#xff09;如不是enabled可以运行如下命令设置自启动 systemctl enable mysqld.sercice2、字符集…

[DM8] DM-DM DBLINK DPI方式

前言 对于DM与DM之间的DBLINK&#xff0c;三种方式中&#xff0c;使用DPI方式配置上最为方便&#xff0c;ODBC方式需要安装ODBC包并配置ODBC数据源&#xff0c;dmmal方式需要设置MAL_INI数据库参数、配置dmmal.ini文件并需要重启数据库服务。 dpi类型的dblink&#xff0c;达梦…

eNSP与CRT配置

1、启动所有设备 2、右键设备&#xff0c;进入“设置” 3、在设置界面中&#xff0c;进入“配置选项卡”&#xff0c;记住串口号 4、打开CRT&#xff0c;进行快速连接 5、协议选择Telnet、Hostname输入“127.0.0.1”、端口输入设备的串口号 6、最终连接效果 eNSP连接CRT配置t…

2023年9月7日

1> 封装一个结构体&#xff0c;结构体中包含一个私有数组&#xff0c;用来存放学生的成绩&#xff0c;包含一个私有变量&#xff0c;用来记录学生个数&#xff0c; 提供一个公有成员函数&#xff0c;void setNum(int num)用于设置学生个数 提供一个公有成员函数&#xff1…

Nougat:一种用于科学文档OCR的Transformer 模型

随着人工智能领域的不断进步&#xff0c;其子领域&#xff0c;包括自然语言处理&#xff0c;自然语言生成&#xff0c;计算机视觉等&#xff0c;由于其广泛的用例而迅速获得了大量的普及。光学字符识别(OCR)是计算机视觉中一个成熟且被广泛研究的领域。它有许多用途&#xff0c…

测试岗位的不足和缺点-思考

软件测试岗位在实际工作中可能会面临一些不足和缺点&#xff0c;以下是一些常见的问题&#xff1a; 高压力、高强度的工作&#xff1a;软件测试工作往往需要在项目截止日期前完成测试&#xff0c;这可能会带来巨大的压力。同时&#xff0c;如果开发团队在项目中进行了大量的更改…

shell脚本详解

当你进入Linux世界的大门时&#xff0c;就会遇到一个强大而又神奇的工具——Shell。Shell是一种命令行解释器&#xff0c;为你在Linux系统中与计算机进行互动提供了无限的可能性。 学习Shell可以让你获得强大的自动化和脚本编程能力&#xff0c;让你更高效地处理文件和目录、管…

微信小程序使用 scss

一、在 vscode 中安装 easy sass 扩展 二、在微信开发者工具导入 vscode 安装的 easy sass 扩展 安装完成后会让重新加载扩展 再次打开后就可以看到扩展已经有 easy sass 了 三、修改 easy sass 配置 重新加载扩展后&#xff0c;默认情况下这个扩展是已经启动的&#xff0c…

Cadence 设计快速入门

概述 偶然的机会看到Cadence官方给的一篇入门文章,感觉相当不错,跟着一步一步做了一下,受益匪浅,在这里记录一下这个过程。 这篇文章主要包含一个风扇控制模块的原理图设计、pcb和仿真。主要涉及如下工具 OrCAD Capture CIS PSpice AD OrCAD PCB Editor原理图设计 在本章我…

C/C++输出绝对值 2019年9月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析

目录 C/C输出绝对值 一、题目要求 1、编程实现 2、输入输出 二、解题思路 1、案例分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 C/C输出绝对值 2019年9月 C/C编程等级考试一级编程题 一、题目要求 1、编程实现 输入一个浮点数&#xff0c;输出这个…

10-JVM调优工具详解

上一篇&#xff1a;09-JVM垃圾收集底层算法实现 前置启动程序 事先启动一个web应用程序&#xff0c;用jps查看其进程id&#xff0c;接着用各种jdk自带命令优化应用 1.Jmap 此命令可以用来查看内存信息&#xff0c;实例个数以及占用内存大小 jmap -histo 14660 #查看历史…

Vue3_pinia使用

安装 cnpm install pinia 新建store目录&#xff0c;在store目录下创建loginUser.js import { defineStore } from pinia import {ref} from vue export const userLoginStore defineStore(loginUser, () > {let loginUserInfo ref({})function setUserInfo(data){this.…