摘要:这篇文章按照芯片解读,硬件调试,数据分析仪三大部分来写。
目前发布的有两颗料,终于有厂家的 ADC 的产品我可以像追星一样的跟了
我们这次的主角是这颗 SAR 的,就是分辨率的区别:
三颗料是共用一个数据手册的
MPS好的一点就是有方便的小程序存数据手册:戳这个地方MDC9747X
型号 | 分辨率 | SINAD (120kHz) | SNR | 采样率 | 功耗(1MSPS@3.3V) |
---|---|---|---|---|---|
MDC97476 | 12-bit | 72.06 dB | 72.26 | 1 MSPS | 4.9 mW |
MDC97477 | 10-bit | 61.76 dB | 61.81 | 1 MSPS | 4.9 mW |
MDC97478 | 8-bit | 50.03 dB | 50.04 | 1 MSPS | 4.9 mW |
正好在吃葡萄,放上去看看大小
超小封装,引脚就6个
当然也有严谨一点的游标卡尺
因为长文怕大家没有动力看完,可以先看视频:
最早的视频
这是更新了上位机版本
正好 DHO804 有个简易的电压表:
非常的好用
看看背面
右下角看上去有个环岛
有颗 DAC,我对这个设计还比较疑惑,后面问了 MPS 的 FAE 解惑了,不得不说,速度和质量是真的高。
因为我看原理图的时候发现了很多的:
有 L 和 F 后缀的引脚
遇到问题直接论坛问
也就是说,为了兼容不同的电平:
跳线控制
MDC97476 的 IO 电平追踪 VDD 电源电压,即:
若 VDD = 5V → 输出 IO 电平为 5V 兼容;
若 VDD = 3.3V → IO 电平为 3.3V;
多数 MCU/FPGA IO 电平 仅支持最高 3.3V,若 VDD 配成 5V,直连会烧坏外部芯片 IO 口。
EVB 板上添加了 电平转换器(Level Shifter) 来适配这个问题:
信号名(带 _F) | 含义 |
---|---|
ADC_CSn_F | 原始 ADC 输出信号(高电平,跟随 VDD) |
ADC_CSn_L_F | 经电平转换后的信号(恒定 3.3V 兼容) |
“_L_F” 后缀中的 “L” 表示 Level shifted 的版本。
那上面的 DAC 是什么意思?
是为了测量不同供电下的情况
怪不得 MPS 的片子卖的好,服务就是好。
继续说片子
架构:SAR(Successive Approximation Register)
接口:三线 SPI 兼容
电源电压:2.7V-5.2V
工作温度:**-40 到125**
封装:6-pin TSOT-23
参考电压:内部参考 = VDD
内部的架构也很清爽,就是输入加量化级到 SPI 输出
芯片内部模块包括:
采样保持电路(T/H)
电容阵列 DAC(Charge Redistribution DAC)
SAR 控制器
比较器
SPI 接口输出
这个芯片使用起来很简单,不需要寄存器什么的,直接就是三线 SPI
我拿到的是 76
时序:
CS 拉低:开始转换 + SDATA 输出低
13 个 SCLK 上升沿后:进入采样状态
第 16 个 SCLK 下降沿:SDATA 输出完成,进入三态
SDATA 输出格式:前导 4 个零,后接 N 位数据(N = 12/10/8),剩余位补 0 或进入高阻态
根据时序可以写出来:
// GPIO 控制 CS 低电平,开始转换
HAL_GPIO_WritePin(GPIOx, CS_Pin, GPIO_PIN_RESET);
// SPI 接收 2 字节(16 位)
uint8_t adc_buf[2] = {0};
HAL_SPI_Receive(&hspi1, adc_buf, 2, HAL_MAX_DELAY);
// GPIO 拉高 CS,结束通信
HAL_GPIO_WritePin(GPIOx, CS_Pin, GPIO_PIN_SET);
// 解析数据
uint16_t raw_code = ((adc_buf[0] << 8) | adc_buf[1]) >> 4; // 只取中间12位
上面的时序不好看,可以直接仿真一个:
Clock 默认是高电平,我就不改动了,以数据手册为准
CS(片选):从高拉低启动转换,持续低电平直到数据传输完成
SCLK(串行时钟):模拟连续 16 个 SCLK(20MHz);占空比 50%,芯片是下降沿吐数据,MCU测是上升沿还是下降沿要看MCU引脚处CLOCK 和 data的相位关系,确保setup/hold time 满足要求。
SDATA(串行输出):以 0000 + D11...D0
顺序输出,在 SCLK 的下降沿前稳定数据
手册写的很清晰
参数 | 典型值 |
---|---|
INL | ±0.5 LSB |
DNL | ±0.4 LSB |
偏移误差 | ±0.7 LSB |
增益误差 | ±3.2 LSB |
ADC(MDC97476/7/8)的动态参数按官方手册汇总(统一测试条件:VDD=3.3 V,fSCLK=20 MHz,采样率 fSAMPLE=1 MSPS,正弦输入 fIN=120 kHz,TA=25 °C):
MDC97476(12-bit)
SNR:71–72.2 dBFS;SINAD:68–71.9 dBFS;THD:−84…−78 dB;SFDR:81–87 dB。
典型图示(1 MSPS)读数:SNR 72.26 dB、SINAD 72.06 dB、THD −84.67 dB、SFDR 87.9 dB、ENOB 11.68 bits。
补充说明
以上指标均在手册指定的条件下测得(VDD=3.3 V、fSCLK=20 MHz、1 MSPS、fIN=120 kHz),手册相应页脚注已标明测试条件;ENOB 可由公式 ENOB ≈ (SINAD−1.76)/6.02 验证;例如 12 位器件典型 SINAD≈72.06 dB 对应 ENOB≈11.7 bit,与典型曲线标注一致。
厂商测试时一般不是满量程输入去测,所以满量程测试时,ENOB还会更高。
可视化的对比
引脚 | 名称 | 类型 | 功能说明 |
---|---|---|---|
1 | VDD | 电源 | 正电源输入,2.7v-5.2v |
2 | GND | 地 | 接地 |
3 | VIN | 输入 | 模拟输入,0V 至 VDD |
4 | SCLK | 输入 | SPI 时钟,最大 20 MHz |
5 | SDATA | 输出 | SPI 输出数据(下降沿更新) |
6 | CS | 输入 | SPI 片选,下降沿启动转换 |
CS 保持低电平 > 10 个 SCLK 下降沿;可连续采样,保持最大吞吐率(1 MSPS)
SCLK 周期:50 ns,对应最高 20 MHz
SCLK 最大:20 MHz,对应最大采样率:1 MSPS,SPI要分频的,也就是 APB 上面要 40M
节能模式,适合低频采样;CS 在第二个和第10个clock期间拉高进入sleep → 进入 Sleep
芯片型号 | 数据格式 |
---|---|
MDC97476 | 4 个前导零 + 12 位有效数据 + 高阻 |
MDC97477 | 4 个前导零 + 10 位有效 + 2 个 0 |
MDC97478 | 4 个前导零 + 8 位有效 + 4 个 0 |
一般的单片机内置 ADC 速度较慢,通常标称值可以到 1MSPS 以内,但是受单片机处理多任务时的资源限制,其实际连续采样速率远小于标称值。对于低速信号采集够用,但如果需要处理高速信号,如无线通信、音频或视频数据,会无法满足系统采样速率要求。
外部独立 ADC 通常可以达到更高的采样率,如 1MSPS 或以上,总之就是很灵活。
其次由于 ADC 内置在单片机内部,其抗干扰能力通常会受到单片机其他模块的影响,如 CPU、PWM、电源模块等。这些模块的切换和操作可能会在 ADC 工作时引入内部噪声干扰,且无法消除, 显著降低 ADC 的有效位数 (ENOB)。
外部 ADC由于其设计,制造过程更为专业,通常在芯片内部模拟和数字接口部分做了更好的隔离,抗干扰能力更强,特别是在恶劣外部干扰环境下工作时,独立 ADC 的性能优势非常明显。
好了我们继续学习:
Hold Phase(保持阶段)
这张图是 Figure 5,表示 ADC 正处于“保持”阶段,即采样完成,进入转换。
元件 | 说明 |
---|---|
V_IN | 模拟输入电压,来自外部信号源 |
SW1 | 控制开关,用于连接输入或断开后接地 |
SW2 | 控制开关,用于将采样电容负端接到 VDD/2 |
Sampling Capacitor | 采样电容,负责保持输入电压信息(电荷) |
Comparator | 比较采样电压和 DAC 电压是否相等 |
Capacitive DAC | 电容阵列 DAC,逐步逼近采样值 |
SAR + Control Logic | SAR 逻辑控制器,逐位控制 DAC 设置、判断电压是否逼近输入值 |
SW1 接地:使采样电容的一端(靠近 V_IN
端)断开输入,接地;
SW2 断开:此时 VDD/2
未连接进来;
电容两端保持电荷 → 等价于“维持电压”,此时:比较器输入端电压 = 采样电容维持的电压;控制逻辑开始逐步调整 DAC 输出,使之与采样电压匹配。
逐次逼近转换典型步骤如下:
V_IN
;SW2 接 VDD/2
,提供偏置;控制逻辑未工作。VDD/2
?SAR ADC 通常为单电源供电;中点电压 VDD/2
提供“零点参考”,DAC 输出是围绕它正负跳变;这有助于提升共模范围和线性度。
电容分布式 DAC 的优点:低功耗;可实现非常小芯片面积;快速转换速度;静态状态下无电流消耗。
等效模拟输入电路(Figure 8)
图中展示了 ADC 的 等效输入建模电路,用于理解采样瞬间信号的加载情况。
元件 | 描述 |
---|---|
D_ESD1, D_ESD2 | ESD 防护二极管,钳位输入在 GND−300mV 与 VDD+300mV 之间 |
C_PIN = 2pF | 封装与管脚等效输入电容 |
SW1 | Track-and-Hold 控制开关 |
R_ON = 125Ω | Track/Hold 开关闭合后的等效导通电阻 |
C_SAMPLING = 14pF | ADC 的内部采样保持电容,决定采样动态响应 |
→ Comparator | 比较器输入端,与 DAC 输出比较 |
上面这个小电容有些优点:
输入电容越小 → RC 充放电时间常数越小 → 模拟带宽越高
输入端等效电路是 信号源阻抗 R_source
和 C_PIN
构成低通滤波器,带宽大约为
当 C_PIN 从 10 pF 降到 2 pF 时,带宽提升 5 倍,可以更好地响应快速变化的信号;对高速 ADC(特别是采样频率在 MHz 级)很重要,否则高频分量会被输入 RC 滤掉。
SAR ADC 在采样瞬间,SW1 闭合 → C_sampling(14 pF)瞬时充电,会把输入信号拉动一个小幅度的电压跳变,这就是 kickback。
C_PIN 越大,这个跳变幅度越大,因为它与 C_sampling 之间存在电荷共享;小的 C_PIN 意味着前级驱动器不需要快速补偿大电流,减轻前级运放带宽与驱动能力的要求,尤其在多通道复用时好处更明显。
小电容在静态时几乎没有额外漏电消耗,结合电容分布式 DAC 架构的 SAR ADC,在静态状态下功耗非常低。
虽然小 C_PIN 带来高带宽与低 kickback,但它也减少了对高频干扰的自然滤波作用,可能增加 EMI/噪声的进入机会,因此 PCB 端仍需合适的 RC 滤波器或前端缓冲;对高阻抗信号源来说,小电容意味着采样瞬间电压会被拉动得更明显,所以通常搭配低输出阻抗的缓冲运放。
仿真是数据比较夸张的,为了好看:
好处
这个仿真直观看出了小输入电容的好处:
小 C_PIN(2 pF)
带宽高(≈ 796 MHz);Kickback 电压小(≈ 125 mV);恢复速度快,对前级运放带宽要求低
大 C_PIN(10 pF)
带宽低(≈ 159 MHz);Kickback 电压大(≈ 417 mV);恢复慢,对前级运放瞬态响应要求高
这解释了为什么高速 ADC 会尽量把 C_PIN 设计得很小,从而减少前端驱动负担并提升高频性能。
Track Phase(采样):
SW1 闭合
,VIN → C_SAMPLING
;信号通过 R_ON
给 C_SAMPLING
充电;形成 **RC 延迟 τ = R_ON × (C_PIN + C_SAMPLING)**;
影响采样带宽。
Hold Phase(保持):
SW1 断开
,电容保持采样电压;SAR 开始逐位逼近。
在 对 SNR / THD / 谐波失真 敏感的应用中,建议注意以下事项:
因为存在 R_ON = 125Ω
和 C_TOTAL ≈ 16pF
,所以:输入源阻抗必须远低于 1kΩ,最好 < 100Ω;否则 RC 充电不完全,采样误差增大。
等效带宽限制:
前级:使用低阻抗缓冲驱动器,如:运放缓冲器。
加了 buffer
幅频响应
上图展示了 ADC 前端输入通路中由开关电阻 和采样电容 组成的一阶 RC 低通滤波器的幅频响应:
截止频率(-3 dB 点)为约 90.95 MHz,见红色虚线标注;在高于该频率的信号将显著衰减,这有助于抑制高频噪声和混叠(aliasing)信号。
我太讨厌这个接口了,数的真麻烦,下次连在一起
官方的原理图非常的简单
搞过硬件的都知道,这个事情就没有你们简单的,即使是数据手册里面写的那么简单:
脆弱瞬间
就是这个 STM32 的 三线 SPI 绝对有问题(Receive Only Master),打死不要用,软件拉也拉不下来,后来是 4 线 SPI。
main()
中加入 ADC 上电后稳定延时(建议 ≥ 200us):HAL_Delay(1); // 上电后延时 ≥ 200us,确保 ADC 准备好
在 main()
中 MX_GPIO_Init()
之后加入:
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET); // 确保 CS 默认高电平
对,这个就是 bug,先拉高,
打开 STM32CubeMX
在 Peripherals 栏中启用:
Connectivity > USB_DEVICE → Communication Device Class (Virtual Port Com)
设置参数:
Mode: Device_Only
Class For FS IP: Communication Device Class (CDC)
会自动启用:USB_OTG_FS,并使用 PA11
(DM), PA12
(DP)
main.c
:替代 fputc
int _write(int file, char *ptr, int len)
{
while (CDC_Transmit_FS((uint8_t *)ptr, len) == USBD_BUSY)
{
HAL_Delay(1);
}
return len;
}
批量发送整串字符串,而不是一字节一字节发。你可以这样(最终的代码使用了这个):
char usb_buf[64];
while (1)
{
uint16_t adc_raw = MDC97476_ReadRaw();
float voltage = MDC97476_ConvertToVoltage(adc_raw, 3.3f);
int len = sprintf(usb_buf, "ADC = %u, Voltage = %.3f V\r\n", adc_raw, voltage);
CDC_Transmit_FS((uint8_t*)usb_buf, len);
HAL_Delay(1000);
}
波特率可随意设置(无效,USB CDC 不依赖波特率);F411 不支持 USB 全速自带 PHY 直接供电,需要外接 USB 供电(5V via VBUS)
MX_USB_DEVICE_Init();
即可初始化 USB CDC 设备,HAL 会默认设置虚拟串口的参数为:
波特率:115200(或其他默认值)
数据位:8
停止位:1
校验位:无
如果需要修改,可以修改:
USBD_CDC_LineCodingTypeDef LineCoding = {
.bitrate = 115200, // 可改为 921600 等
.format = 0x00, // 停止位:1
.paritytype = 0x00, // 无奇偶校验
.datatype = 0x08, // 8位数据
};
因为 USB 的输出和串口不一样,需要加入一个检测:
// 等待 USB 枚举完成
while (hUsbDeviceFS.dev_state != USBD_STATE_CONFIGURED)
{
HAL_Delay(10);
}
USB FS(全速):
实际最大传输速率约为 1 MB/s(8 Mbps);一帧最多 64 字节,每毫秒最多传输一次.
USB HS(高速):
实际最大传输速率高达 30-40 MB/s;512 字节/帧,1ms 多帧传输.
所以比串口高得多,即使你设置 "波特率" 为 9600,USB CDC 实际仍然以几百 KB/s 的速率传输,只是软件兼容层设置为了 9600。
供电 VDD = 3.3V
,存在以下几种模式:
模式 | 输入类型 | 范围估计 |
---|---|---|
单端输入 | VIN 对 AGND | 0 ~ VDD(即 0~3.3V) |
差分输入 | VIN+ - VIN- | ±VREF/2 或 0~VREF 范围 |
输入钳位电路 | 内部钳位/外部保护 | 输入必须在 AGND - 0.3V ~ VDD + 0.3V 内 |
这里没有后面的钳位电路,而从实际原理图看:使用了 单端输入(VIN
是单一引脚,没有 VIN+ / VIN-);前级缓冲运放供电为 +7V / -2V,输出可能为 负电压。
自动读取帧格式:
0xAA + ADC低字节 + ADC高字节 + 电压低字节 + 电压高字节 + 0x55
实时绘图:
电压范围 0~3.3V
;图像自动刷新
键盘控制:
按下空格 space
:开始 / 暂停采集
按下 ESC
:退出并关闭文件与串口
自动保存 CSV 日志:
包括原始 ADC 值和电压值(单位:V);保存为 adc_log_年月日_时分秒.csv
这是第一次的数据
Mean Voltage (V) Min Voltage (V) Max Voltage (V) RMS Voltage (V) \
Value 1.594536 0.0 3.096 1.812197
Std Deviation (V)
Value 0.861112
数据在 0~3.3V 范围内波动(最大值约 3.096V,最小值为 0V)。
波形在 1.6V 附近居中,有一定周期性,可能是某种低频信号(如慢变化电压或模拟波形)。
主频率成分集中在低频部分(如 < 10 Hz),整体频谱没有明显尖锐的高频成分,符合慢变电压的特征。
指标 | 数值 |
---|---|
平均电压 | 1.594 V |
最小电压 | 0.000 V |
最大电压 | 3.096 V |
RMS(有效值) | 1.812 V |
标准差(波动性) | 0.861 V |
此时我还没有意识到这里没接,文档里面也没有写
那就顺便写一下即使信号源未连接或无信号输出,ADC仍然会采集到“漂浮的”随机数据或电平噪声有哪些原因:
若 ADC 输入引脚悬空(未接信号源或信号源为高阻态),其电压处于不确定状态,称为“漂浮”。
浮空输入会导致 ADC 采样到环境电磁干扰(EMI)、电源纹波、邻近 IO 的耦合信号、电容充放电残留电压等。
电压值随机波动;数值不稳定、无规律;偶尔出现 0 或满量程,更多是中间电压。
某些 ADC(MDC97476)内部带有采样保持电路、偏置电流源、电荷注入结构,即使没有外部信号,也可能在输入端形成一定偏置电压或干扰响应;如果使用的是电容耦合、未加下拉电阻,也会导致浮空电压残留。
ADC 通常具有 >1MΩ 的输入阻抗,在未连接低阻抗源时,相当于“天线”,极易感应周围 50Hz / 60Hz 电源噪声、开关电源纹波等;即使加了低通滤波,也不能完全去除这种低频干扰。
ADC 的基准电压或供电电压如果不稳定,特别是在模拟地与数字地耦合较差时,也可能在无信号下采集到虚假的非零电压值。
问题 | 建议 |
---|---|
悬空导致不稳定 | 用 电阻下拉(如10kΩ~100kΩ)至 GND,或者连接一个稳定的信号源/参考电压 |
电源纹波引起干扰 | 使用 LDO 稳压 + 适当的 旁路电容(0.1μF + 10μF) |
浮空电容注入影响 | 增加前端 RC 滤波器 或缓冲运放 |
不希望采集浮值 | 固件中可判断采样值是否连续低于阈值,做“无信号”判断 |
这是调试的一个图,被干扰的样子
我这里就用第一开始的稿子了:对于这个上位机,我首先想要丰富的数据分析呈现,所以时域,频域,时频分析是有的,而且 ADC 本身缺失了滤波器的功能,所以我加入了数字滤波器。
在开始采集后,会把所有的数据保存为 CSV,做后处理工作。
然后整体流程是这样的:
Start program
│
▼
串口初始化,创建图形界面
│
▼
定义 update() 函数:读取数据 → 更新图像
│
▼
FuncAnimation() 注册 update 函数
│
▼
plt.show() 启动事件循环(每隔 interval ms 调用一次 update)
│
▼
┌────────────┐
│每次刷新过程│
└────────────┘
└─> update()
└─> 读取串口帧
└─> 滤波处理
└─> FFT 分析
└─> 更新图形
└─> 返回更新的 Line 对象
这是最终的效果
也经过了 UI 的调整
但是以下是最开始的程序设计,所以大体思路按照如下设计。
MCU → 上位机 发送帧格式(总长 6 字节):
字节序号 | 内容 | 说明 |
---|---|---|
0 | 0xAA | 帧头(同步) |
1 | ADC 低字节 | 原始 ADC 值低 8 位 |
2 | ADC 高字节 | 原始 ADC 值高 8 位 |
3 | 电压低字节 | 毫伏值低 8 位 |
4 | 电压高字节 | 毫伏值高 8 位 |
5 | 0x55 | 帧尾 |
安装依赖项(如果尚未安装):
pip install pyserial matplotlib scipy numpy
运行环境必须包含串口 COM16
,并有设备按照帧结构:
帧头(0xAA) + 原始数据(2字节) + 电压mv(2字节) + 帧尾(0x55)
ser = serial.Serial("COM16", 115200, timeout=1)
打开串口 COM16,波特率 115200,超时时间 1 秒。
用于接收来自 STM32 的数据包(帧结构:0xAA + 原始数据(2B) + 电压mV(2B) + 0x55)
BUFFER_SIZE = 512
SAMPLE_RATE = 1000 # Hz
使用一个环形缓冲区(deque
)维护最近 512 个样本点。
采样率设为 1000Hz,决定 FFT 横坐标频率轴最大为 500Hz。
FILTER_LOW = 30
FILTER_HIGH = 200
默认带通滤波器的截止频率设置为 30Hz~200Hz。
csv_file = open(f"adc_log_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.csv", ...)
csv_writer = csv.writer(csv_file)
csv_writer.writerow(["Sample", "Voltage (V)"])
创建一个时间戳命名的 CSV 文件;每帧数据记录一行(ADC 原始值,电压值)。
fig, (ax_time, ax_freq) = plt.subplots(2, 1, figsize=(10, 6))
上图 ax_time
:显示 时域波形(原始+滤波)
下图 ax_freq
:显示 频域波形(FFT)
line_raw, = ax_time.plot(data, label="Raw")
line_filtered, = ax_time.plot(filtered_data, label="Filtered", linestyle='--')
蓝色实线:原始采样数据
虚线:带通滤波器输出
line_fft, = ax_freq.plot(np.linspace(0, SAMPLE_RATE/2, BUFFER_SIZE//2), np.zeros(BUFFER_SIZE//2))
peak_marker, = ax_freq.plot([], [], 'ro', label="Peak")
line_fft
是实时更新的频谱曲线
peak_marker
是频谱峰值的红色标记点
滤波器类型:二阶带通巴特沃斯滤波器
实时参数调节:
b, a = signal.butter(2, [low, high], btype='band', fs=SAMPLE_RATE)
filtered = signal.filtfilt(b, a, list(data))
低频和高频截止值由滑块 (Slider
) 控制
def read_frame():
while ser.read(1) != b'\xAA':
pass
frame = ser.read(5)
if len(frame) < 5 or frame[-1] != 0x55:
return None
raw = frame[0] | (frame[1] << 8)
voltage_mv = frame[2] | (frame[3] << 8)
return raw, voltage_mv / 1000.0
保证同步从帧头 0xAA 开始读取
提取两部分内容:
raw
:原始 ADC 码
voltage
: 计算后电压值(单位 V)
update(frame)
动画函数parsed = read_frame()
raw, voltage = parsed
data.append(voltage)
csv_writer.writerow([raw, voltage])
b, a = signal.butter(2, [low, high], btype='band', fs=SAMPLE_RATE)
filtered = signal.filtfilt(b, a, list(data))
butter
生成二阶滤波器系数
filtfilt
是前向后向滤波,避免相位偏移
line_raw.set_ydata(data)
line_filtered.set_ydata(filtered_data)
fft_data = np.fft.rfft(filtered - np.mean(filtered))
fft_freq = np.fft.rfftfreq(len(filtered), 1/SAMPLE_RATE)
fft_mag = np.abs(fft_data)
fft_mag /= np.max(fft_mag + 1e-8)
rfft
:仅计算实信号的正频部分
幅度归一化至 0~1
peak_idx = np.argmax(fft_mag)
peak_freq = fft_freq[peak_idx]
peak_amp = fft_mag[peak_idx]
peak_marker.set_data([peak_freq], [peak_amp])
ax_freq.set_title(f"FFT Spectrum - Peak: {peak_freq:.1f} Hz")
自动找出最大频率分量并在图中用红点标出;显示主频位置
def on_key(event):
if event.key == 'escape':
ser.close()
csv_file.close()
plt.close(fig)
ani = animation.FuncAnimation(fig, update, interval=10)
plt.show()
interval=10
毫秒刷新周期 ≈ 100Hz 界面更新速率
以上就是上位机的骨架,功能是在这个上面扩展的,可以给大家看一下现在的功能有哪些:
image-20250812111436597
FFT 的双游标测量功能
时域测量
包络,峰值保持和频点追踪等等
阅读原文戳进去是MPS 论坛ADC 版块,对这颗料感兴趣可以进去发帖逮住工程师一通问。