在STM32单片机上使用傅里叶解析信号

这篇具有很好参考价值的文章主要介绍了在STM32单片机上使用傅里叶解析信号。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

关于傅里叶变换的知识,可以看我之前的文章:傅里叶变换记录,里面记录了一些参数的含义还有使用python和matlab进行傅里叶分析,提取信号的一些过程,希望能对读者产生一点帮助。

下面记录使用stm32来对信号进行分析,这里一般是指一些adc采样的信号,对信号进行分析一方面是获取信号的一些成分,另一方面是对有可能信号中含有很多造成,通过分析可以对噪声进行处理。

本文采用单片机为stm32f103RCT6,后续可能会考虑使用F4的平台进行测试,这里暂时仅测试F1,相信如果F1都没什么问题,F4效果应该会更好的。

1、导入分析工具

写这篇文章之前也参考了一些文章,这里先贴一下大佬的帖子,F1的话需要导入一些数学库的

https://blog.csdn.net/weixin_43368814/article/details/103552114
https://shequ.stmicroelectronics.cn/thread-632949-1-1.html
https://blog.csdn.net/Simon223/article/details/105728567

这里目前看有两种方案,不过他们的测试方法好像也基本都差不多,互相借鉴吧应该hhh,第一种是直接导入需要的库,就是下面的几个文件了,把他们导入到keil的路径下即可
在STM32单片机上使用傅里叶解析信号
下面是导入.s文件
在STM32单片机上使用傅里叶解析信号
下面是引入.h文件
在STM32单片机上使用傅里叶解析信号

下面是第二种方案,也基本是一样的,我个人比较推荐第二种方案

在安装hal库的位置。就是下载了库的包的位置,有下面的目录,找到这个目录即可,找到下面这个lib文件,复制出来
在STM32单片机上使用傅里叶解析信号
再进入下面的目录,找到下面的3个.h文件也是一样的复制出来
在STM32单片机上使用傅里叶解析信号
把这四个文件一起复制到我们的工程目录下
在STM32单片机上使用傅里叶解析信号
在工程目录里面添加lib文件
在STM32单片机上使用傅里叶解析信号
在我们编译宏参数中加入

,ARM_MATH_CM3,__CC_ARM,ARM_MATH_MATRIX_CHECK,ARM_MATH_ROUNDING

编译的宏参数加入还有将刚才复制的文件路径添加到我们的目录下即可
在STM32单片机上使用傅里叶解析信号

2、信号生成与查看

先用我们之间提到过的分析工具查看下信号是什么样的,生成信号的函数如下所示,还是三个正弦函数叠加,这里采样率设置为100khz,这样比较贴合实际,采到后通过串口把数据发送出去,我们使用matlab来对捕捉的数据进行分析。

#define Fs 100000

void InitBufInArray(void)
{
  unsigned short i;
  float fx;
  for(i = 0; i < FFT_LENGTH; i++)
  {
    fx = 15 * sin(PI * 2 * i * 13500.0 / Fs) +
         27 * sin(PI * 2 * i * 45000.0 / Fs) +
         40 * sin(PI * 2 * i * 8500.0 / Fs);
//    lBufInArray[i] = ((signed short)fx) << 16;
    printf("%f\n", fx);
  }
}

使用matlab对采集到的数据,可以看到叠加起来的数据还是很乱的,这里基本看不出来原始数据有什么特征了,是很乱的一团信号,不过直接使用matlab还是分析出来他由三组信号组成,下面有三个很明显的尖峰。
在STM32单片机上使用傅里叶解析信号
这里把刚才截取的放大看下,这个部分的标准值应该是8500,40,是非常接近的,这个误差肯定是会有的,因为单片机进行sin计算等肯定进行了逼近等,本身计算就会存在误差。
在STM32单片机上使用傅里叶解析信号

3、使用STM32读取数据

1、使用第一种库

下面就使用stm32来进行分析,这里需要说明就是使用stm32来进行分析肯定是离散分析的,就是一段段的信号进行分析,那么如果对应到我们的实际采样中其实就是采样一段信号分析一段信号。

首先还是构建我们需要分析的数组,源码如下,下面进行介绍

#define Fs 100000
#define FFT_LENGTH 1024
int32_t lBufInArray[FFT_LENGTH] = {0};
uint16_t ADC_Value[FFT_LENGTH] = {0};
int32_t lBufOutArray[FFT_LENGTH / 2] = {0};
int32_t lBufMagArray[FFT_LENGTH / 2] = {0};

void InitBufInArray(void)
{
  unsigned short i;
  float fx;
  for(i = 0; i < FFT_LENGTH; i++)
  {
    fx = 1024*sin(2*PI*i * 13500.0 / Fs)
		+512*sin(2*PI*i * 8500.0 / Fs)
		+512*sin(2*PI*i * 3500.0 / Fs);
		ADC_Value[i] = fx+2048;
    lBufInArray[i] = ((signed short)ADC_Value[i]) << 16;
//		printf("%d\n", ADC_Value[i]);
  }
}

这里为了适应stm32的采集方式,把生成的序列转换为0-4096的整数格式,这个过程肯定会产生精度损失,所以后面结果应该是会变得不太准确,这里要注意,但是实际真实采样就不用担心。
在STM32单片机上使用傅里叶解析信号
这里是根据转换函数,需要把采样数据做下处理,32位的整形数据,高16位放实部,低16位放虚部,虚部一般都是0 ,就不处理了,默认即可。
在STM32单片机上使用傅里叶解析信号
这样就可以用下面的函数计算了,就可以生成FFT的序列了

	InitBufInArray();
	cr4_fft_1024_stm32(lBufOutArray, lBufInArray, FFT_LENGTH);

但是这个结果还不是我们最终要的,最终结果还需要进行一下优化的处理,这里就是提取他的谐波幅值

void GetPowerMag(void)
{
  signed short lX, lY;
  float X, Y, Mag;
  unsigned short i;
  for(i = 0; i < FFT_LENGTH / 2; i++)
  {
    lX  = (lBufOutArray[i] << 16) >> 16;
    lY  = (lBufOutArray[i] >> 16);
    X = FFT_LENGTH * ((float)lX) / 32768;
    Y = FFT_LENGTH * ((float)lY) / 32768;
    Mag = sqrt(X * X + Y * Y) / FFT_LENGTH;
    if(i == 0)
      lBufMagArray[i] = (unsigned long)(Mag * 32768);
    else
      lBufMagArray[i] = (unsigned long)(Mag * 65536);
  }
}

最后加上这个函数就行了,并加上结果打印函数
在STM32单片机上使用傅里叶解析信号
源码如下

void FFT(void)
{
	InitBufInArray();
	cr4_fft_1024_stm32(lBufOutArray, lBufInArray, FFT_LENGTH);
	GetPowerMag();	                      
  for(int16_t i = 1; i < FFT_LENGTH/2; i++)
  {
    printf("%d\n",lBufMagArray[i]);
  }
}

将程序下载到开发板,最终的结果如下所示,这个结果准不准确呢,不如直接用matlab来进行一下对比试验就知道了。
在STM32单片机上使用傅里叶解析信号
这里我们先把这个数据放到matlab中来查看下
在STM32单片机上使用傅里叶解析信号
再把我们生成的数据也导入matlab来进行一下分析,可以看到结果如下,还是比较准确的,这里的误差是上面的强制转换带来的
在STM32单片机上使用傅里叶解析信号

2、使用第二种库

第二种为arm自带的fft函数,函数为arm_cfft_f32,这里首先要注意的就是他的一个实部虚部的数据位置,这里发生了变化,不再是高16位和低16位存储的数据发生变化,而是在数组缓冲区里面间隔存在,如下图所示:
在STM32单片机上使用傅里叶解析信号
下面进行整个流程的介绍,首先还是生成需要的采样数据
在STM32单片机上使用傅里叶解析信号
下面就是傅里叶分析的部分了
在STM32单片机上使用傅里叶解析信号

最终结果如下所示:
在STM32单片机上使用傅里叶解析信号
完整代码:文章来源地址https://www.toymoban.com/news/detail-466461.html

#include "fft_test.h"

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


#define Fs 100000
#define FFT_LENGTH 1024

float32_t lBufInArray[FFT_LENGTH*2] = {0};
float32_t lBufOutArray[FFT_LENGTH / 2] = {0};
uint16_t ADC_Value[FFT_LENGTH] = {0};

void InitBufInArray(void)
{
  unsigned short i;
  float fx;
  for(i = 0; i < FFT_LENGTH; i++)
  {
    fx = 1024 * sin(2 * PI * i * 13500.0 / Fs)
         + 512 * sin(2 * PI * i * 8500.0 / Fs)
         + 512 * sin(2 * PI * i * 3500.0 / Fs);

    ADC_Value[i] = fx + 2048;
  }
}

void FFT(void)
{
  InitBufInArray();
  for (int i = 0; i < FFT_LENGTH; i++)
  {
    lBufInArray[i * 2] = ADC_Value[i]; //实部赋值
    lBufInArray[i * 2 + 1] = 0; //虚部赋值
  }
  arm_cfft_f32(&arm_cfft_sR_f32_len1024, lBufInArray, 0, 1);
  arm_cmplx_mag_f32(lBufInArray, lBufOutArray, FFT_LENGTH);

  for (int i = 1; i < FFT_LENGTH/2; i++)
  {
    lBufOutArray[i] /= 512;
  }

  for(int16_t i = 1; i < FFT_LENGTH/2; i++)
  {
    printf("%f\n", lBufOutArray[i]);
  }
}

到了这里,关于在STM32单片机上使用傅里叶解析信号的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于STM32F407实现快速傅里叶变化(FFT),计算指定频率的幅值

    前言: 本人的课题是关于EIT采集系统设计,所谓的EIT,简单的说就是往人体注入特定频率的电流信号,通过采集反馈的电压信号,进而使用成像算法重构人体内部的阻抗分布。由于采集到的电压包含其它频率的热噪声,为了只保留注入频率的信号成分,需要对采集到的电压信

    2024年02月12日
    浏览(31)
  • 信号处理与分析-傅里叶

    目录 一、引言 二、傅里叶级数 1. 傅里叶级数的定义 2. 傅里叶级数的性质 三、傅里叶变换 1. 傅里叶变换的定义 2. 傅里叶变换的性质 四、离散傅里叶变换 1. 离散傅里叶变换的定义 2. 离散傅里叶变换的性质 五、应用实例 1. 信号处理 2. 图像处理 六、总结 傅里叶变换是一种重

    2024年02月06日
    浏览(33)
  • 基于STM32F407实现离散傅里叶变换(FFT、DFT),计算指定频率的幅值

    前言: 本人的课题是关于EIT采集系统设计,所谓的EIT,简单的说就是往人体注入特定频率的电流信号,通过采集反馈的电压信号,进而使用成像算法重构人体内部的阻抗分布。由于采集到的电压包含其它频率的热噪声,为了只保留注入频率的信号成分,需要对采集到的电压信

    2024年02月16日
    浏览(40)
  • STM32:CMSIS-DSP使用指南(在单片机上运用常用的数学运算)

    1.keil环境搭建 在STM32中使用DSP库_linuxweiyh的博客-CSDN博客 2.官方文档 [STM32官方DSP文档](file:///E:/Professional_APP/stm32_cubeMX/install_pack/STM32Cube_FW_F4_V1.27.1/Drivers/CMSIS/docs/DSP/html/modules.html) -1.基本数学运算函数 -2.快速数学运算函数 -3.复数运算函数 -4.滤波器 -5.矩阵函数 -6.数学变换 -7.电机

    2024年02月13日
    浏览(42)
  • 信号处理 | 短时傅里叶变换实战

    短时傅里叶变换(Short-Time Fourier Transform, STFT)是一种分析时变信号频率特性的方法。它通过将长时间的信号分割成较短的时间片段,然后对每个时间片段进行傅里叶变换,从而克服了传统傅里叶变换无法同时提供时间和频率信息的限制。 原理 分割信号:STFT首先将连续的信号

    2024年02月22日
    浏览(30)
  • 实数信号的傅里叶级数研究(Matlab代码实现)

     💥💥💞💞 欢迎来到本博客 ❤️❤️💥💥 🏆博主优势: 🌞🌞🌞 博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️ 座右铭: 行百里者,半于九十。 📋📋📋 本文目录如下: 🎁🎁🎁 目录 💥1 概述 📚2 运行结果 🎉3 参考文献 🌈4 Matlab代码实现 实数信

    2024年02月13日
    浏览(32)
  • 实训关于stm32单片机的多个传感器应用(附C++源码和解析)

    目录 1.实验的目的和要求 2.设计的软件环境 3.思路流程图 4.关键代码解析 4.1温湿度传感器(要监测当前环境的温度、湿度,通过温湿度传感器来实现的) 4.2.光敏电阻传感器(要监测当前环境的光照(黑天和白天),通过光敏电阻传感器来实现的,如果是黑夜,LED灯就亮蓝色

    2023年04月25日
    浏览(29)
  • 【快速傅里叶变换(fft)和逆快速傅里叶变换】生成雷达接收到的经过多普勒频移的脉冲雷达信号(Matlab代码实现)

     💥💥💞💞 欢迎来到本博客 ❤️❤️💥💥 🏆博主优势: 🌞🌞🌞 博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️ 座右铭: 行百里者,半于九十。 📋📋📋 本文目录如下: 🎁🎁🎁 目录 💥1 概述 📚2 运行结果 🎉3 参考文献 🌈4 Matlab代码实现 本文的

    2024年02月10日
    浏览(31)
  • POWERLINK协议源码(最新)在stm32单片机上的移植指南

    最近着了powerlink的道,连续几晚十二点前没睡过觉。不得不说兴趣这东西劲太大了,让人睡不着。喜欢上研究POWERLINK,最新版的源码结构挺清晰的,移植并测试了嵌入式linux作为从站和电脑主站之间的通信,挺有趣的。接下来想尝试下在单片机上的移植,降低POWERLINK协议的使

    2024年02月06日
    浏览(28)
  • 【MATLAB】全网唯一的13种信号分解+FFT傅里叶频谱变换联合算法全家桶

    有意向获取代码,请转文末观看代码获取方式~ 大家吃一顿火锅的价格便可以拥有13种信号分解+FFT傅里叶频谱变换联合算法,绝对不亏,知识付费是现今时代的趋势,而且都是我精心制作的教程,有问题可随时反馈~也可单独获取某一算法的代码(见每一算法介绍后文)~ EMD 是

    2024年02月05日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包