基于STM32的ADC采样序列频谱分析

这篇具有很好参考价值的文章主要介绍了基于STM32的ADC采样序列频谱分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  本文主要介绍对ADC采集得到的数字序列进行FFT频谱分析。

确定采样率

  确定采样率除了要遵守奈奎斯特采样定律意外还需要考虑一些问题。在数字系统中,我们只能进行一些有限的离散的运算,对于有限长的序列,我们不可能拿它去做DTFT,只能做DFT。这就需要把有限长序列也当作一个周期序列来看待

归一化角频率

  已知采样率为 f s f_s fs,那么一个频率为 f 0 f_0 f0 f 0 < f s / 2 f_0<f_s/2 f0<fs/2)的理想余弦信号被采样后得到的序列应该是:

x [ n ] = A cos ⁡ ( 2 π f 0 ⋅ n T 0 ) = A cos ⁡ ( 2 π f 0 ⋅ n f s )      n ∈ Z x[n] = A\cos \left( {2\pi {f_0} \cdot n{T_0} } \right) = A\cos \left( {2\pi {f_0} \cdot {n \over { {f_s} } } } \right)\;\;n \in {\rm{Z} } x[n]=Acos(2πf0nT0)=Acos(2πf0fsn)nZ

  从上面的式子可以看出,我们实际得到的序列和具体的采样率或信号频率无关,而是由它们俩的比值 f 0 / f s f_0/f_s f0/fs决定的,就像是信号频率 f 0 f_0 f0被采样频率 f s f_s fs归一化了。
  在信号连续的时候,信号的频率 f f f可以是任意实数。而在这一离散的情况下, f 0 / f s f_0/f_s f0/fs已经将频率限制在了0~1之间,对应到角频率就是0~ 2 π 2\pi 2π
  再结合频谱的周期性可以知道 π \pi π~ 2 π 2\pi 2π的频谱和 − π -\pi π~ 0 0 0的频谱是相同的。
stm32频谱分析,日常调试记录,stm32,ADC,FFT
  对于一个实序列来说,0~ π \pi π的频谱对应频率0~ f s / 2 f_s/2 fs/2的复指数序列,而剩下的 π \pi π~ 2 π 2\pi 2π的频谱则是前者的复共轭。两个互为共轭的复指数序列叠加才构成实序列。根据这一特点,在计算一个实序列的DFT时,可以只算一半的长度,因为另一半只要取复共轭就好了。

有限长序列

  前面的分析都是在“理想”的条件下进行了,“理想”指的是这个余弦信号得一直存在,从宇宙诞生之初到遥远的未来始终都存在。这样的信号现实生活中是没有的,实际的信号总有开始和结束。

矩形窗

  直接从理想序列中截取几个周期的点构成一个有限长序列,相当于是理想序列在时域上与一个矩形窗相乘,也就是它们在频域的卷积。理想余弦序列的频域的表示已经在上面进行分析了,剩下的只需要关注窗函数的频谱。
stm32频谱分析,日常调试记录,stm32,ADC,FFT
计算矩形窗的DTFT,直接用DTFT的分析式:

X ( e j ω ) = ∑ n = 0 N − 1 e j ω n = 1 − e j ω N 1 − e j ω X\left( { {e^{j\omega } } } \right) = \sum\nolimits_{n = 0}^{N - 1} { {e^{j\omega n} } } = { {1 - {e^{j\omega N} } } \over {1 - {e^{j\omega } } } } X(ejω)=n=0N1ejωn=1ejω1ejωN

然后可以用下面这个公式进一步化简,

1 − e j 2 θ = 1 − ( cos ⁡ ( 2 θ ) + j sin ⁡ ( 2 θ ) ) = − j 2 sin ⁡ ( θ ) e j θ 1 - {e^{j2\theta } } = 1 - \left( {\cos \left( {2\theta } \right) + j\sin \left( {2\theta } \right)} \right) = - j2\sin \left( \theta \right){e^{j\theta } } 1ej2θ=1(cos(2θ)+jsin(2θ))=j2sin(θ)ejθ

最后得到:

X ( e j ω ) = e − j ω ( N − 1 ) / 2 sin ⁡ ( ω N / 2 ) sin ⁡ ( ω / 2 ) X\left( { {e^{j\omega } } } \right) = {e^{ - j\omega (N - 1)/2} }{ {\sin \left( {\omega N/2} \right)} \over {\sin \left( {\omega /2} \right)} } X(ejω)=ejω(N1)/2sin(ω/2)sin(ωN/2)

  在 ω = 0 \omega=0 ω=0的位置, X ( e j ω ) = 1 X\left( { {e^{j\omega } } } \right) = 1 X(ejω)=1,而在 ω \omega ω 2 π / N 2\pi/N 2π/N的整数倍时, X ( e j ω ) = 0 X\left( { {e^{j\omega } } } \right)=0 X(ejω)=0。因此当信号的周期正好为 N N N的时候,就不会有频谱泄露(请自行脑补卷积的过程)。

升余弦窗(Hann窗)

  升余弦窗也叫Hann窗,可以表示为:

w [ n ] = 1 2 ( 1 − cos ⁡ ( 2 π n N ) ) ,          n ∈ [ 0 , N − 1 ] w[n] = {1 \over 2}\left( {1 - \cos \left( {2\pi {n \over N} } \right)} \right),\;\;\;\;n \in \left[ {0,N - 1} \right] w[n]=21(1cos(2πNn)),n[0,N1]

计算它的DTFT:

X ( e j ω ) = 1 2 ∑ n = 0 N − 1 ( 1 − cos ⁡ ( 2 π n / N ) ) e − j ω n X\left( { {e^{j\omega } } } \right) = {1 \over 2}\sum\nolimits_{n = 0}^{N - 1} {\left( {1 - \cos \left( {2\pi n/N} \right)} \right){e^{ - j\omega n} } } X(ejω)=21n=0N1(1cos(2πn/N))ejωn

  我没能显式地求出解,但是可以代入一些特殊值观察一下。当 ω = 0 \omega=0 ω=0时, X ( e j ω ) = 1 / 2 X\left( { {e^{j\omega } } } \right) = 1/2 X(ejω)=1/2,而当 ω = ± 2 π / N \omega=\pm2\pi/N ω=±2π/N时, X ( e j ω ) = 1 / 4 X\left( { {e^{j\omega } } } \right) = 1/4 X(ejω)=1/4
   X ( e j ω ) X\left( { {e^{j\omega } } } \right) X(ejω)与理想序列的频谱卷积得到的结果将会出现频谱泄露。对于单频信号,就会在原来单一的峰值两侧产生两个 1 / 2 1/2 1/2峰值幅度的尖峰,同时峰值幅度也衰减为原来的 1 / 2 1/2 1/2
  虽然称之为“频谱泄露”,但是并不是真的泄露出来,而是由卷积得到的。因此一般情况下直接将泄露的频谱加起来只是一种近似。
  不同的窗函数的频谱特性不同,矩形窗的旁瓣比较高,一旦出现频谱泄露就会对特定频率的幅值测量引入很大的误差,但它的频率分辨率也是最高的。Hann窗虽然会有频谱泄露,但它的旁瓣衰减快。

采样率与序列长度

  DFT得到的频谱能够分辨的最小频率称为频率分辨力,N点序列做DFT能够得到N点的频谱,因此频率分辨力为 f s / N f_s/N fs/N。最好选取合适的采样率和序列长度使得待测信号的频率正好是频率分辨力的整数倍。如果待测信号的频率正好是频率分辨力的整数倍,那就可以直接用矩形窗;反之,如果待测信号频率不是频率分辨力的整数倍,那就要根据需求加窗。

模拟前端

  在确定ADC的采样率之后,ADC前面的抗混叠滤波器的截止频率也要设置在 f s / 2 f_s/2 fs/2以内。但也要大于你关心的信号的频率。
  采样一些低频的信号一般都是采用这种过采样的方式,ADC前的抗混叠滤波器是低通滤波器,采样率大于信号最高频率的两倍。但采样定理告诉我们只要采样率大于信号带宽的两倍就能恢复采样的信号。所以也有那种带通系统,ADC前用的是带通滤波器,利用数字序列的频谱周期延拓的特性,用低频采样率采高频信号。

仿真信号

  在ADC还没调通,或者有时候想自己生成一个单频的仿真序列时,可以直接写出在采样率 f s f_s fs下,频率 f 0 f_0 f0的余弦序列:

x [ n ] = cos ⁡ ( 2 π f 0 f s n ) x[n] = \cos \left( {2\pi { { {f_0} } \over { {f_s} } }n} \right) x[n]=cos(2πfsf0n)

DSP库函数

  在之前的一篇文章中,我提到了用CubeMX生成工程后,在Drivers/CMSIS/Lib目录下就有DSP库文件,所以觉得不用另外从外部导入库DSP库了。
  但这两个库文件是有点不同的,我在用CFFT的时候发现只有另外从外部导入的库文件才能正确计算。如果用原来就有的那个库文件,程序在link之后好像有什么奇怪的东西把复位地址的入口给覆盖了,上来就是hardfault。给所以最好还是再另外勾选这个DSP库。
stm32频谱分析,日常调试记录,stm32,ADC,FFT
  CMSIS的DSP库提供了两种FFT的函数,实数FFT和复数FFT,两者各有特点。都可以用来计算由ADC采样得到的序列的FFT。

实数FFT

  实数FFT计算快,是我们的首选!它能够处理长度为32, 64, 128, 256, 512, 1024, 2048, 4096的实数FFT。
  输入序列是连续的实数,我之前以为输入也是要和复数FFT一样,实部虚部间隔存放。但实际上它需要的是连续存放的实数。
  不是同址运算,输入和输出需要存放在不同地方。输出序列是一个复数序列,长度是输入序列的一半,因为另一半的结果和前一半的结果是互为共轭的关系,不需要重复计算。
  而因为复数存放是实部虚部间隔着存放,一个复数占的存储空间是一个实数的两倍。所以输入和输出的实际物理空间占用是一样长的。
  比如做1024点浮点数的RFFT,输入是一片长度1024个浮点数的地址空间的首地址,输出也需要同样大小的一篇空间,但是存放的会是512个复数。
  输出存放的也不全是复数,一个实数序列 x [ n ] x[n] x[n]做FFT之后得到 X [ k ] X[k] X[k] X [ 0 ] X[0] X[0]一定是实数, X [ N / 2 ] X[N/2] X[N/2]也一定是实数,这两个实数是一起存在第一个复数的位置。
  示例代码:

arm_rfft_fast_instance_f32 xInstFFT;
arm_rfft_fast_init_f32(&xInstFFT, 1024);
arm_rfft_fast_f32(&xInstFFT, pSrc, pDst, 0);

  在调用RFFT之前,需要先初始化一个实例,主要是设置旋转因子的查找表。RFFT一直都会进行bit reverse,这样输入和输出都是我们习惯的顺序,而CFFT是可以选择是否要bit reverse。arm_rfft_fast_f32中的最后一个参数是选择进行FFT还是IFFT。

复数FFT

#include "arm_const_structs.h"
arm_cfft_f32(arm_cfft_sR_f32_len1024, pData, 0, 1);

  复数FFT要求输入的数据就是实部和虚部交替存放的,而且是同址运算,输出结果会覆盖输入的数据。相比于RFFT,它不需要初始化,只需要include arm_const_structs.h这个头文件,就能找到现成的实例。
stm32频谱分析,日常调试记录,stm32,ADC,FFT
  这个头文件在CMSIS的DSP/Include路径下,虽然我们不能用这里提供的DSP库文件,但是头文件还是能拿来用的。倒数第二个参数是选择进行FFT还是IFFT;最后一个参数是是否需要bit reverse。

Hann窗

  Hann窗的系数可以用Matlab计算,可以把这些系数存成常量,方便加窗的时候直接调用。
stm32频谱分析,日常调试记录,stm32,ADC,FFT
  打开Matlab的窗设计器,选择Hann窗,然后采样选“周期性”。将系数保存到工作区,然后想办法再写到C/C++的源文件里去就好了。

function [w] = genHann()
    w = hann(1024, 'periodic');
end

  我是用Matlab Coder把上面这个函数转成C代码,但是也挺麻烦的,感觉还不如直接从工作区复制出来自己写到源文件里去。文章来源地址https://www.toymoban.com/news/detail-637052.html

到了这里,关于基于STM32的ADC采样序列频谱分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 基于STM32的频谱分析和波形识别系统

    目录 1、概述 2、硬件设计 3、软件设计  4、测试结果 本篇介绍了以STM32F103单片机为核心的频谱分析和波形识别系统,并对其硬件组成和软件设计做了详细讲解。该系统通过STM32F103ZET6主控芯片进行ADC采样,再使用DSP库提供的FFT函数对采集到的信号进行处理,最后将输入信号的

    2024年02月03日
    浏览(29)
  • STM32基于hal库的adc以DMA的多通道采样以及所遇问题解决

    目录 准备 配置 步骤  总结   正点原子的STM32F103ZET6开发板(精英版) CUBEMX配置软件 KEIL5  右对齐就是正常的数据格式。左对齐除以16后得正常数据。(当输出非常大时考虑是否改了对齐方式,默认都是右对齐)  扫描模式,连续转换模式使能。(多通道下扫描模式自动使能

    2024年02月04日
    浏览(52)
  • STM32 ADC采样

    目录 1.基础概念 2.原理:ADC采样过程分为四步:采样、保持、量化、编码。 3.采样定理 4.采样保持放大器(SHA) 5.ADC电压值转换 6.ADC轮询采样 1.基础概念 ADC 全称:Analog-to-Digital Converter,指模拟/数字转换器,就是将模拟信号转换成数字信号 ①模拟信号:是连续变化的,具有电

    2024年02月04日
    浏览(47)
  • STM32实现ADC采样

    功能:在单片机上对声音和光强进行采样,通过串口输出其采样值。 工具:实验用到CubeIDE和Cubeprogrammer两个软件,串口调试助手APP,以及STM32L431RCT6单片机。 1、配置使能串口: 2、ctrl+s生成代码。 3、在usart.h中添加头文件。 4、在usart.c中实现printf。  编译代码。可以在main.c文

    2024年02月09日
    浏览(55)
  • STM32ADC同步采样

    本文主要讲解如何实现STM32ADC同步采样。 所需工具: 开发板:STM32F103RCT6 STM32CubeMX IDE: Keil-MDK 同步采样可以让多个ADC同时采集它们各自的输入信号,并且保留它们之间的相位关系,这有助于更有效地捕捉信号的动态变化,特别是对于相位频率分析来说,它具有重要的应用价值。

    2023年04月14日
    浏览(46)
  • 基于stm32f407的示波器+FFT频谱分析

    1 设计思路 2 DMA传输ADC采样值 使用DMA直接将ADC-DR中的数据传输到ADC数据缓存区,节省cpu资源,高速AD采集,代码如下: 3 ADC定时器触发(可修改ADC采样率) 为了实现ADC采样率可调,我将AD的出发方式设置为定时器触发,使用TIM3来触发adc采集,首先初始化定时器,先预设几种初

    2024年02月05日
    浏览(54)
  • STM32-ADC过采样实验

    我们之前已经有过一些关于STM32-ADC的笔记和实验代码了,链接如下: 关于ADC的笔记1_Mr_rustylake的博客-CSDN博客 STM32-ADC单通道采集实验_Mr_rustylake的博客-CSDN博客 STM32-单通道ADC采集(DMA读取)实验_Mr_rustylake的博客-CSDN博客 STM32-ADC多通道输入实验_Mr_rustylake的博客-CSDN博客 首先简单

    2024年02月10日
    浏览(41)
  • STM32 多路ADC同时扫描采样

    在项目实际应用中,刚好有需求需要使用多路ADC同时采样,这里就选择STM32 ADC多路ADC同时采样,这里简单说明下配置过程,以及使用步骤 如下图所示,使用四路ADC输入 ADC_Voltage - 电压信号的采样,外部输入信号,交流电的输入信号,正选信号 ADC_Current - 电流电流的采样,外部

    2024年02月06日
    浏览(45)
  • stm32教程之三重ADC交错采样

    ps:本文基于stm32F407ZGT6单片机         stm32F4单片机单通道采集的最大采样率为2.4M,所以有时会难以满足较高频率的采样,于是查阅芯片手册,发现stm32F4支持多重ADC采集,利用每个通道的转换时间,错位采样,从而提高采样率,最大把采样率开到2.4*3=7.2M.  (去年初学AD

    2024年02月12日
    浏览(45)
  • 搭建stm32电机控制代码框架(三)——Stm32CubeMx配置ADC采样

    电机控制另一个关键的模块就是ADC采样,这个模块配置的好坏决定了采样电流和电压的精准度,因此有必要对其进行深入学习。 简介: STM32 在片上集成的ADC 外设非常强大。STM32F103xC、STM32F103xD 和STM32F103xE增强型产品内嵌3个12位的ADC,每个ADC 共用多达 21 个外部通道,可以实现

    2024年02月13日
    浏览(45)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包