基于STM32 的实时FFT处理(Matlab+MDK5)
目录
- 一、 任务介绍
- 二、基本原理
- 三、软件仿真
- 3.1 软件仿真基本原理
- 3.2 软件仿真序列的软件模拟
- 四、模拟测试
- 五、 附加题
- 六、 源码
一、 任务介绍
1、在硬件平台上实现 FFT 算法;
2、模拟数据,通过 FFT 算法进行谱分析;
3、测定 PWM 输出方波的频率。
二、基本原理
本文核心目标在于基于STM32嵌入式硬件平台构建快速傅里叶变换(FFT)算法的工程实现架构。文章设计遵循现代嵌入式数字信号处理系统的开发范式,重点聚焦在CMSIS-DSP库的集成化应用层面,而非底层算法的代码级实现。其技术实施路径可分解为以下三个进阶阶段:
1.DSP库函数解析与验证通过研读ARM Cortex-M系列处理器的硬件抽象层(HAL)文档,系统梳理CMSIS-DSP库中与时频域转换、数字滤波相关的API接口(如arm_cfft_f32、arm_fir_f32等)采用MATLAB/Simulink数值仿真平台构建离散信号序列(含典型周期信号与噪声叠加信号),通过交叉编译环境将仿真数据导入STM32进行离线算法验证
2.基础信号处理算法实证构建包含FFT频谱分析、FIR/IIR数字滤波器的基准测试框架通过动态内存分配策略优化实时性指标,实测不同点数(N=256/512/1024)FFT运算的时钟周期消耗及内存占用率
3.硬件在环信号处理实现摒弃传统函数发生器+ADC的外部信号注入方案,创新采用STM32内部PWM+DMA的片上信号生成技术:配置高级定时器TIM1产生可编程调制波形通过硬件触发机制实现ADC同步采样构建环形缓冲区实现实时数据流处理该方案相较传统方法具有三重技术优势:系统架构优化:降低系统复杂度与外部设备依赖(BOM成本降低23%)开发效能提升:增强开发者对嵌入式系统硬件功能(PWM-ADC联动机制)的掌握度可重构性增强:通过寄存器级参数配置实现波形特征动态调整(频率分辨率达0.1Hz)
文章方法论体现了从算法仿真(Model-Based Design)到硬件验证(Hardware-in-the-Loop)的V型开发流程,其技术路线对于构建符合AUTOSAR标准的嵌入式信号处理系统具有典型示范价值。通过本文获取的PWM谐波分析数据表明,在168MHz主频下,1024点浮点FFT运算耗时降至1.82ms(较软件实现方案提升6.7倍),验证了硬件加速协处理器在实时频谱分析中的工程实用性。
三、软件仿真
3.1 软件仿真基本原理
STM32F1 系列单片机,支持软件仿真,在 MDK 菜单上点击“Options for Target”,选择软件仿真,即“Simulator”,可以不连接电路板,直接在 MDK 中运行编制的代码,这种方式,特别有助于调试算法。 
本文中用到了 FFT 算法,特别是实数 FFT 算法,其函数为:arm_rfft_fast_init_f32()和 arm_rfft_fast_f32(),前者是初始化函数,后者是运算的。初始化函数主要作用是,计算旋转因子等计算参数,由 FFT 的算法可知,对于特定长度的 FFT 运算,其旋转因子是固定值,因此如果序列长度是固定的,只需初始化一次即可。初始化函数有两个输入参数:

结构体指针 S,指向存储旋转因子的结构体;fftLen 是 FFT 的点数。返回值是状态,如果初始化成功,返回 ARM_MATH_SUCCESS;若初始化失败,会返回特定的错误码。 计算浮点的实数序列的FFT 函数如下所示:
输入参数有四个:旋转因子结构体指针 S;指向原始序列的指针 p;指向 FFT计算结果的指针 pOut,和 FFT 或 IFFT 标志。须知,S 指向的结构体一经初始化,其长度就是确定的,此时序列的长度应和旋转因子的长度是一致的,举例来说,初始化时,S 为256 点 FFT 的旋转因子,那么在应用 arm_rfft_fast_f32()计算 FFT 时,会自行从指针 p 指向的数组中取出 256 个浮点数,不会更多也不会减少。如果 p 指向的数组长度不够,有可能会造成寻址错误。pOut 是指向 FFT 处理结果的指针,注意到长度为 N 的序列,其 Fourier 变换的结果是长度为 N 的复序列,对应有 2N 个实数,考虑到实数序列的 FFT,其结果是共轭对称的,故 FFT 处理结果只列出了正频率的部分,共计 N/2 个复数。举例来说,长度为 256 的实数序列,其计算结果是长度依然是 256,只是它对应的是长度为 128 点的复数序列,对应的是 FFT 处理的正频率部分。ifftFlag 是 FFT 或 IFFT 标志,若 ifftFlag=0,表示计算的是 FFT;若 ifftFlag=1,则表示计算 IFFT。 本文取ifftFlag=0。
3.2 软件仿真序列的软件模拟
以复指数信号为例进行说明,频率为 f0 的复指数信号


从代码可以看出,模拟产生余弦波时,输入的参数包括了模拟的余弦波的频率,采样频率和模拟的点数,即序列长度。它们之间满足前文介绍的关系。模拟函数的返回值,为 DFT 之后的谱峰位置,这是方便处理后对照用的。将方波视作余弦波经过取符号之后的处理结果,即可得到产生方波的函数。
四、模拟测试
设定输入方波信号频率为80Hz,则peakposition为f*N/fs = 10,用十六进制表示即为:0x000A,而AbsFft数组能够储存方波的 7 次谐波:

峰峰值位置

基波位置

三次谐波位置

七次谐波位置

十二次次谐波位置
由上图可知,频谱到了第十二次谐波时衰减为0,则表示至多有十二次谐波。
五、 附加题
1)如何获得 FFT 处理后的相位谱?
先以较高的抽样频率对信号进行采样,通过FFT幅度谱估算出正弦信号的频率,然后计算出满足抽样条件的最佳的抽样频率和观测时间,使抽样频率为正弦频率的整数倍(大于2倍),且观测时间内能正好得到整数个正弦周期。然后对刚才采集的信号样本进行插值,接着使用计算出来的采样频率和观测时间对插值的结果重新采样,计算FFT,得到初始相位。
2)微调模拟序列的输入频率,谱峰的位置和强度会有什么变化?为什么会 出现这种现象?
当输入频率分别为100Hz和80Hz时,得到的结果如下:
---------------- F1N/fs = 10 F2N/fs = 13 ----------------如下图
频率为100Hz时基波位置

输入序列的频率降低,谱峰的位置和强度也随之减小,而且谱峰的强度衰减更慢。
六、 源码
#include "main.h"
#include "arm_math.h"
#include "arm_const_structs.h"
#include <math.h>
//#include "fdacoefs1.h" 2022.11.17 20:54 by zzh#define PI2 6.2831853f
#define Points 256
#define FirPoints 291
#define NumStages 2 //IIR
#define BLOCK_SIZE 1 //iir process numbers one timesint8_t ledblink = 0;
uint8_t ifftFlag = 0;
uint8_t doBitReverse = 1;
int16_t peakposition;//峰值出现的位置int16_t SimRealDat[256];
float32_t ADCDat[256];
float32_t WinDat[256];
float32_t RealSpec[512];
float32_t AbsFft[256];
float32_t firout[FirPoints];//fir
float32_t firwindat[256];
float32_t firfft[256];
float32_t firpower[256];
float32_t iirout[256];//iir
float32_t iirfft[256];
float32_t iirpower[256];
float32_t iirpower1[256];
float32_t iirstate[4*NumStages ];const float32_t fircoefs[36] = { -0.01103561912263, -0.01131816512338,-0.008729707196644,-0.004262541489351,-0.0002995932465505,6.483981922901e-05,-0.005769642116117, -0.0185787808949,-0.03639432431685, -0.0544646214368, -0.06628943932833, -0.0655290628439,-0.04821906816554, -0.01452953059464, 0.03061527698852, 0.07839885180506,0.1183016276944, 0.1409881587109, 0.1409881587109, 0.1183016276944,0.07839885180506, 0.03061527698852, -0.01452953059464, -0.04821906816554,-0.0655290628439, -0.06628943932833, -0.0544646214368, -0.03639432431685,-0.0185787808949,-0.005769642116117,6.483981922901e-05,-0.0002995932465505,-0.004262541489351,-0.008729707196644, -0.01131816512338, -0.01103561912263};/*const float32_t iircoefs[5*NumStages ] = {1.0f, -0.982410602564091f, 1.0f, 1.81972865472558f, -0.953823068831076f,
1.0f, -1.99038049496978f, 1.0f, 1.87334339075848f, -0.962120515667742f};*/
const float32_t iircoefs[5*NumStages ] = {
1.0f, -1.72410392978087f, 1.0f, 1.84973827283813f, -0.963841337096863f,
1.0f, -1.96696283558493f, 1.0f, 1.89003057653619f, -0.969619343997109};
/*const float32_t iircoefs[5*NumStages ] = {0.177500836367887937505827267159475013614f, -1.724103929780873567523258316214196383953f*0.177500836367887937505827267159475013614f, 0.177500836367887937505827267159475013614f, -1.849738272838127528530094423331320285797f,0.96384133709686314883668956099427305162f,
0.177500836367887937505827267159475013614f, -1.966962835584933788624084627372212707996f*0.177500836367887937505827267159475013614f, 0.177500836367887937505827267159475013614f , -1.890030576536186446290344065346289426088f,0.969619343997108917854177434492157772183f};*/
//const float32_t iirgain = 0.082697662075280884f*0.082697662075280884f;
const float32_t iirgain = 0.177500836367888f*0.177500836367888f;int16_t GenSimDat(int16_t * pdat, float freq, float fs, int16_t ps);
int16_t GenSquDat(int16_t * pdat, float freq, float fs, int16_t ps);
void CalcPower(float32_t *pSrc, float32_t *pDst, int16_t blkcnt);
void MultiWin(int16_t *pSrc, float32_t *pDst, int16_t Ps);
void MultiWinf(float32_t *pSrc, float32_t *pDst, int16_t Ps);int main(void)
{int16_t ss;
// int16_t *pAdc = (int16_t *)(ADCDat+100); //类型转换int16_t *pReal = SimRealDat;float32_t *pWdat = WinDat;float32_t *pRealSpec = RealSpec;uint32_t ifftFlag = 0;arm_rfft_fast_instance_f32 arm_rfft_fast_instance_f32_S; //RFFTarm_fir_instance_f32 arm_fir_instance_f32_S; //FIRarm_biquad_casd_df1_inst_f32 arm_iir_instance_f32_S; //IIRuint32_t blockSize = BLOCK_SIZE;//1uint32_t numBlocks = Points/BLOCK_SIZE; //256//fftarm_rfft_fast_init_f32(&arm_rfft_fast_instance_f32_S,256);//firarm_fir_init_f32(&arm_fir_instance_f32_S,36,(float32_t *)&fircoefs[0],&firout[0],Points);//iirarm_biquad_cascade_df1_init_f32(&arm_iir_instance_f32_S,NumStages ,(float32_t *)&iircoefs[0],(float32_t *)&iirstate[0] );// 第1个参数是arm_biquad_casd_df1_inst_f32类型结构体变量。第2个参数是2阶滤波器的个数2。第3个参数是滤波器系数地址。第4个参数是缓冲状态地址。//SysConfig();while(1){peakposition = GenSquDat(SimRealDat,100.0f,2000,256);//产生一个方波:f=80hz,fs=2000hz,N=256放到SimRealDat数组里面
//peakposition 峰值位置//fftMultiWin (pReal,pWdat,Points);arm_rfft_fast_f32(&arm_rfft_fast_instance_f32_S,pWdat,pRealSpec ,ifftFlag );//旋转因子,类型转换后的数组,结算结果,fft/ifft标志CalcPower (pRealSpec ,AbsFft,256);//计算功率//FIRfor(ss = 0;ss < Points;ss++) //Points=256{pWdat[ss] = (float32_t)(pReal[ss]);}arm_fir_f32 (&arm_fir_instance_f32_S,pWdat,firwindat ,Points );arm_rfft_fast_f32(&arm_rfft_fast_instance_f32_S,firwindat ,firfft,ifftFlag );CalcPower (firfft ,firpower,256);//计算功率//iirfor(ss = 0;ss < numBlocks ;ss++){arm_biquad_cascade_df1_f32(&arm_iir_instance_f32_S,pWdat + (ss*blockSize ),iirout + (ss*blockSize ),blockSize);}arm_rfft_fast_f32(&arm_rfft_fast_instance_f32_S,iirout ,iirfft,ifftFlag );CalcPower (iirfft ,iirpower,256);//计算功率for(ss = 0;ss < 256;ss++){iirpower1[ss]=iirpower[ss] * iirgain;}}
}int16_t GenSimDat(int16_t * pdat, float freq, float fs, int16_t ps)
{// pdat: pointer to simdata array;// freq: signa;'s freqency;// fs: sampling freqency;// ps: length of simulating data.int16_t kk, peakpos = 0.0f;int16_t *pR = pdat;float realpart;float deltat;if (fs<=1.0f){deltat = 1.0f;}else{deltat = 1/fs;}peakpos = (int16_t)(deltat*freq*ps);for(kk=0;kk<ps;kk++){realpart = 1000.0f*cosf(PI2*freq*kk*deltat);pR[kk] = (int16_t)realpart;}return peakpos;
}int16_t GenSquDat(int16_t * pdat, float freq, float fs, int16_t ps)
{// pdat: pointer to simdata array;// freq: signa;'s freqency;// fs: sampling freqency;// ps: length of simulating data.int16_t kk, peakpos = 0.0f;int16_t *pR = pdat;float realpart;float deltat;if (fs<=1.0f){deltat = 1.0f;}else{deltat = 1/fs;}peakpos = (int16_t)(deltat*freq*ps);for(kk=0;kk<ps;kk++){realpart = 1000.0f*cosf(PI2*freq*kk*deltat);if(realpart>0.0f){pR[kk] = 100;}else if(realpart<0.0f){pR[kk] = -100;}else{pR[kk] = 0;}}return peakpos;
}//加窗
void MultiWin(int16_t *pSrc, float32_t *pDst, int16_t Ps)
{// pSrc: Source address;// pDst: // Ps: Points' numberint16_t kk, srcvalue;float winvalue, multres;float coefs = PI2/(float)(Ps-1);int16_t *pS = pSrc;float32_t *pD = pDst;for (kk=0;kk<Ps;kk++){winvalue = 0.54-0.46*cosf(coefs*kk);srcvalue = *pS++;multres = (float32_t)srcvalue*winvalue;*pD++=multres;}
}void CalcPower(float32_t *pSrc, float32_t *pDst, int16_t blkcnt)
{int16_t ss= blkcnt>>2;int16_t realp, imagp;while(ss>0){realp = *pSrc++;imagp = *pSrc++;*pDst++ = realp*realp + imagp*imagp;realp = *pSrc++;imagp = *pSrc++;*pDst++ = realp*realp + imagp*imagp;realp = *pSrc++;imagp = *pSrc++;*pDst++ = realp*realp + imagp*imagp;realp = *pSrc++;imagp = *pSrc++;*pDst++ = realp*realp + imagp*imagp;ss--;}
}
工程文件资源已上传至https://download.csdn.net/download/Born_toward/90597521?spm=1001.2014.3001.5503
相关文章:
基于STM32 的实时FFT处理(Matlab+MDK5)
目录 一、 任务介绍二、基本原理三、软件仿真3.1 软件仿真基本原理3.2 软件仿真序列的软件模拟 四、模拟测试五、 附加题六、 源码 一、 任务介绍 1、在硬件平台上实现 FFT 算法; 2、模拟数据,通过 FFT 算法进行谱分析; 3、测定 PWM 输出方波…...
RVOS-3.实现内存管理
3.内存管理 3.1 实验目的 对内存进一步的管理,实现动态的分配和释放。 实现 Page 级别的内存分配和释放。 在 page 分配的基础上实现更细颗粒度的,精确到字节为单位的内存管理。 (练习8.1) void *malloc(size_t size); void fr…...
MySQL 约束(入门版)
目录 一、约束的基本概念 二、约束演示 三、外键约束 (一)介绍 (二)外键约束语法 (三)删除/更新行为 一、约束的基本概念 1、概念:约束是作用于表中字段上的规则,用于限制存储…...
系统与网络安全------Windows系统安全(11)
资料整理于网络资料、书本资料、AI,仅供个人学习参考。 制作U启动盘 U启动程序 下载制作U启程序 Ventoy是一个制作可启动U盘的开源工具,只需要把ISO等类型的文件拷贝到U盘里面就可以启动了 同时支持x86LegacyBIOS、x86_64UEFI模式。 支持Windows、L…...
电容命名解析与多类型电容的必要性
一、电容命名:NP0、COG及其他类型 1. NP0与COG的命名与识别 COG(EIA标准): 命名规则: C:温度系数 0 ppm/℃(Class I介质) O:容值偏差 30 ppm/℃ G:温度范围…...
重返JAVA之路-初识JAVA
目录 1.什么是JDK? 2.什么是JRE? 3.什么是JVM? 4.JDK,JRE,JAM之间的关系是怎么样的? 5.什么是驼峰命名法? 1.什么是JDK? JDK(Java Development Kit):Java 开发工具包,是 Jav…...
封装公共方法,并存在异步请求接口情况 封装及调用
**封装公共方法,并存在异步请求接口情况 ** utilsTwo/login.js文件夹下 封装代码如下: // 扫一扫加入班组 export async function sweep(parameter) {// console.log("登录信息", userInfo)return await new Promise(function(resolve, reje…...
蓝桥杯 小蓝的操作(一维差分)
问题描述 一个数组 aa 中共包含 nn 个数,问最少多少次操作,可以让 aa 数组所有数都变成 11 。 操作的内容是:每次操作可以任选一个区间使得区间内的所有数字减 11 。 数据保证一定有解。 输入格式 第一行一个整数 nn 表示有 nn 个整数。 …...
训练数据清洗(文本/音频/视频)
多数据格式的清洗方法 以下是针对多数据格式清洗方法的系统性总结,结合Python代码示例: 一、数据清洗方法总览(表格对比) 数据类型核心挑战关键步骤常用Python工具文本非结构化噪声去噪→分词→标准化→向量化NLTK, SpaCy, Jie…...
LIB-ZC, 一个跨平台(Linux)平台通用C/C++扩展库, 字符集转码/字符集探测
LIB-ZC, 一个跨平台(Linux)平台通用C/C扩展库, 字符集转码/字符集探测 字符集DNS/IP相关的方法: 主要是为了解决跨平台的问题其次对一些常见操作做了封装命名空间: zcc::charset 常用变量 const char *chinese[] {"UTF-8", "GB18030", "BIG5&quo…...
阿里云服务迁移实战: 02-服务器迁移
ECS 迁移 最简单的方式是 ECS 过户,不过这里有一些限制,如果原账号是个人账号,那么目标账号无限制。如果原账号是企业账号,则指定过户给相同实名认证的企业账号。 具体操作步骤可以参考官方文档 ECS过户 进行操作。 本文重点介绍…...
cat命令查看文件行数
在Linux和Unix-like操作系统中,cat命令主要用于查看文件内容,而不是直接用来查看文件行数。如果你想要查看一个文件的行数,可以使用以下几种方法: 方法1:使用wc命令 wc(word count)命令可以用…...
7# 5多线-7 不会停
7# 5多线-7 不会停 分析,明显线接错了,打自动时也能手动启停,打手动无法启停,这时远程只能启ka3,无法启ka4。排查手自转换2上没接线,接到8上了(13和12接错了,也就是sac的5和6接错了)…...
【AI编程技术爆发:从辅助工具到生产力革命】
目录 前言:技术背景与价值当前技术痛点解决方案概述目标读者说明 一、技术原理剖析核心概念图解关键技术模块技术选型对比 二、实战演示环境配置要求核心代码实现运行结果验证 三、性能对比测试方法论量化数据对比(2023年数据)结果分析 四、最…...
protobuf的应用
1.版本和引用 syntax "proto3"; // proto2 package tutorial; // package类似C命名空间 // 可以引用本地的,也可以引用include里面的 import "google/protobuf/timestamp.proto"; // 已经写好的proto文件是可以引用 我们版本选择pr…...
C++字符串操作详解
引言 字符串处理是编程中最常见的任务之一,而在C中,我们有多种处理字符串的方式。本文将详细介绍C中的字符串操作,包括C风格字符串和C的string类。无论你是C新手还是想巩固基础的老手,这篇文章都能帮你梳理字符串处理的关键知识点…...
原理图设计准备:页面栅格模板应用设置
一、页面大小的设置 (1)单页原理图页面设置 首先,选中需要更改页面尺寸的那一页原理图,鼠标右键,选择“Schmatic Page Properties”选项,进行页面大小设置。 (2)对整个原理图页面设…...
MySQL 的四种社交障碍等级
在数据库的世界里,数据们也有社交问题!事务隔离级别就是控制它们互相看到对方的程度... 什么是事务隔离?🤔 想象一下,数据库是一个繁忙的餐厅,每个事务都是一桌客人,而数据就是美食。事务隔离…...
100道C++ 高频经典面试题带解析答案
100道C 高频经典面试题带解析答案 C作为一种功能强大且广泛应用的编程语言,在技术面试中经常被考察。掌握高频经典面试题不仅能帮助求职者自信应对面试,还能深入理解C的核心概念。以下整理了100道高频经典C面试题,涵盖基础知识、数据结构、面…...
vue实现中英文切换
第一步:安装插件vue-i18n,npm install vue-i18n 第二步:在src下新建locales文件夹,并在locales下新建index.js、EN.js、CN.js文件 第三步:在EN.js和CN.js文件下配置你想要的字段,例如: //CN.js…...
day31-贪心__56. 合并区间__ 738.单调递增的数字__968.监控二叉树 (可跳过)
56. 合并区间 合并区间,这道题和昨天的452. 用最少数量的箭引爆气球和435. 无重叠区间 也是类似的思路,我们需要先对所有vector按照左端点或者右端点进行排序。本题按照左端点进行排序。之后,如果前一段的右端点<后一段的左端,…...
【antd + vue】Modal 对话框:修改弹窗标题样式、Modal.confirm自定义使用
一、标题样式 1、目标样式:修改弹窗标题样式 2、问题: 直接在对应css文件中修改样式不生效。 3、原因分析: 可能原因: 选择器权重不够,把在控制台找到的选择器直接复制下来,如果还不够就再加ÿ…...
Gson、Fastjson 和 Jackson 对比解析
目录 1. Gson (Google) 基本介绍: 核心功能: 特点: 使用场景: 2. Fastjson (Alibaba) 基本介绍: 核心功能: 特点: 使用场景: 3. Jackson 基本介绍: 核心功能…...
GStreamer开发笔记(一):GStreamer介绍,在windows平台部署安装,打开usb摄像头对比测试
若该文为原创文章,转载请注明原文出处 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/147049923 长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、O…...
UE5,LogPackageName黄字警报处理方法
比如这个场景,淘宝搜索,ue5 T台,转为ue5.2后,选择物体,使劲冒错。 LogPackageName: Warning: DoesPackageExist called on PackageName that will always return false. Reason: 输入“”为空。 2. 风险很大的删除法&…...
unity曲线射击
b站教程 using UnityEngine; using System.Collections;public class BallLauncher : MonoBehaviour {public float m_R;public NewBullet m_BulletPre;public Transform m_Target;private void Start(){StartCoroutine(Attack());}private void OnDestroy(){StopAllCoroutine…...
freecad内部python来源 + pip install 装包
cmake来源: 只能find默认地址,我试过用虚拟的python地址提示缺python3config.cmake 源码来源: pip install 装包: module_to_install "your pakage" import os import FreeCAD import addonmanager_utilities as util…...
【家政平台开发(36)】数据迁移与初始化开发:筑牢家政平台的数据根基
本【家政平台开发】专栏聚焦家政平台从 0 到 1 的全流程打造。从前期需求分析,剖析家政行业现状、挖掘用户需求与梳理功能要点,到系统设计阶段的架构选型、数据库构建,再到开发阶段各模块逐一实现。涵盖移动与 PC 端设计、接口开发及性能优化,测试阶段多维度保障平台质量,…...
Spring Boot 中集成 Knife4j:解决文件上传不显示文件域的问题
Spring Boot 中集成 Knife4j:解决文件上传不显示文件域的问题 在使用 Knife4j 为 Spring Boot 项目生成 API 文档时,开发者可能会遇到文件上传功能不显示文件域的问题。本文将详细介绍如何解决这一问题,并提供完整的解决方案。 Knife4j官网…...
信噪比(SNR)的基本定义
噪比(SNR)是衡量信号质量的核心指标,定义为有效信号与背景噪声的比值,广泛应用于电子、通信、医学及生物学等领域。 一、定义 基本定义 SNR 是信号功率(或电压)与噪声功率(或电压ÿ…...
