Files
xdeSpace/FNIRSI_LCR-ST1_逆向分析.md
T

832 lines
30 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FNIRSI LCR-ST1 电桥镊子逆向分析 —— 硬件方案、BOM 估算与算法软件详解
> **作者:** 小德
> **分类:** 产品逆向 · LCR 电桥 · 嵌入式
> **版本:** V1.0
> **日期:** 2026-07-05
> **参考零售价:** ¥138(京东)
> **声明:** 以下分析基于公开的产品规格、该品类通用设计模式和工程经验推导,未经实测拆解验证,仅供技术研究参考。
---
## 概览
FNIRSI LCR-ST1 是一款手持式 LCR 电桥镊子,定位于"能用就行"的入门级元器件测试仪。¥138 的售价决定了它的每一步设计都在成本和性能之间做权衡。本文从硬件架构、BOM 估算、测量原理、算法实现四个层面展开逐级拆解。
---
## 一、已知规格与功能反推
### 1.1 公开规格
| 参数 | 标注值 | 可信度判断 |
|------|--------|-----------|
| 测量参数 | L / C / R / Q / D / ESR | 可信 |
| 测试频率 | 100Hz / 1kHz / 10kHz | 可信(三频点标准) |
| 量程 | L: 0.01μH~10H, C: 0.1pF~10mF, R: 0.01Ω~10MΩ | 可信 |
| 精度 | 1%(典型) | 可信(¥138 级别) |
| 显示 | 0.96" OLED 128×64 | 可信 |
| 供电 | CR2032 ×1 或 2×LR44 | 待确认(CR2032 概率大) |
| 镊子开口 | 2~3mm | 可信 |
| 自动关机 | 有 | 可信 |
### 1.2 从规格反推硬件框架
```
三频点(100Hz/1kHz/10kHz+ 自动量程 + 1% 精度 + OLED 显示 + ¥138 成本
必须用 MCU 产生测试信号 + 做 DFT 解调
必须用 I-V 转换法(非电桥平衡法,后者成本太高)
MCU 只能是国产 Cortex-M 或 RISC-V
模拟前端只能用通用运放,不可能用 AD8302/AD5933 等专用芯片
典型方案 = MCU (PWM+DAC) + 双运放 + 模拟开关 + OLED
```
---
## 二、硬件方案推理(最可能的 BOM)
### 2.1 核心芯片选型
#### MCUGD32F103C8T6 或 APM32F103C8T6
```
为什么选它:
72MHz Cortex-M3
64KB Flash / 20KB RAM — 够跑 DFT + OLED 驱动
双 12bit ADC(1Msps) — 同时采电压和电流
双 12bit DAC — 产生测试正弦波(或 PWM+LPF)
多个定时器 — 精确控制采样时序
价格 ¥5~8 — 比 STM32 便宜一半
替代可能:
- CH32V103 (RISC-V, ¥3~5) — 更便宜,但生态弱
- AT32F403 (Cortex-M4, ¥6~10) — 有 FPU,计算更快
```
#### 显示:0.96" OLED SSD1306
```
接口:I2C (¥6~8) 或 SPI (¥6~8)
分辨率:128×64
驱动芯片:SSD1306
价格:¥6~8(模块)、¥2~4(裸屏 COG)
```
#### 双运放:LMV358 或 SGM358
```
用途:
运放A:I-V 转换器(跨阻放大器),将被测件电流转为电压
运放B:电压缓冲/跟随器,提供参考电压
为什么选 LMV358
轨到轨输出(适合 3.3V 单电源)
增益带宽积 1MHz1kHz/10kHz 没问题,100Hz 更是轻松)
价格 ¥0.5~1.0
SGM358 是国产替代,¥0.3~0.5
```
#### 模拟开关:74HC4051 或 CD4051
```
用途:自动量程切换——选择不同的参考电阻 R_ref
通道:8 选 1,对应 8 个量程档位
量程电阻(典型值):
Ch0: 10Ω (低阻 R 测量)
Ch1: 100Ω (中低阻)
Ch2: 1kΩ (中阻)
Ch3: 10kΩ (中高阻 / 一般 L/C)
Ch4: 100kΩ (高阻)
Ch5: 1MΩ (极高阻 / 小电容)
Ch6: 10MΩ (超高阻 / 极小电容)
Ch7: 空/校准位
价格:¥0.5~1.0
```
#### 其他关键器件
| 器件 | 型号 | 数量 | 单价 | 用途 |
|------|------|------|------|------|
| 参考电阻 | 0805 1% 金属膜 | 8 | ¥0.08 | 量程网络 |
| 去耦电容 | 0805 100nF + 10μF | 10 | ¥0.03 | 电源去耦 |
| 电池座 | CR2032 贴片 | 1 | ¥1.5 | 供电 |
| 升压 | HT7750 或 S-8351 | 1 | ¥1~2 | 3V→5V(为运放供电) |
| 晶振 | 8MHz 无源 | 1 | ¥0.3 | MCU 主时钟 |
| 按键 | 贴片轻触 | 2 | ¥0.2 | 功能/保持 |
| 镊子 | 镀金磷铜 | 1对 | ¥2~3 | 被测件接触 |
| PCB | 双面板 1.6mm FR4 | 1 | ¥3~4 | 约 60mm×20mm |
| 电池 | CR2032 | 1 | ¥1 | 零售送电池 |
---
### 2.2 系统框图(推理)
```
┌───────────┐
┌───┤ CR2032 ├───┐
│ │ 3V │ │
│ └───────────┘ │
▼ ▼
┌───────────┐ ┌───────────┐
│ 升压 DC-DC │ │ --- │
│ HT7750 5V │ │ 直接 3.3V │
│ (供运放) │ │ (供MCU) │
└─────┬─────┘ └───────────┘
│ 5V
┌─────────────────────────────────────────────────┐
│ GD32F103C8T6 │
│ │
│ DAC0 ──→ LPF ──→ 量程开关(4051) ──→ 镊子探头──┐ │
│ (选择 R_ref) ↓ │ │
│ ↓ │ │
│ ADC0 ←── 运放A(跨阻) ←── 电流信号 ←──┘ │ │
│ ADC1 ←── 运放B(缓冲) ←── 电压信号 ←─────────┘ │
│ │
│ I2C ──→ OLED SSD1306 (128×64) │
│ GPIO ──→ 按键×2 │
│ GPIO ──→ ADC 量程切换 LED 指示 │
│ TIM ──→ 定时触发 ADC 采样 │
└─────────────────────────────────────────────────┘
```
### 2.3 模拟前端完整拓扑
```
┌─────────────────────┐
DAC0 ─── 二阶 LPF ──┬──────┤ 4051 量程开关 │
(正弦波) (f_c≈30kHz) │ 选择 R_ref[0..7] │
│ │ │
│ │ OUT ──┬── 镊子 + │
│ │ │ │
│ │ GND │
│ └─────────────────────┘
│ │
│ │ I_dut
│ ▼
│ ┌──────────┐
│ │ 运放A │
│ │ LMV358 │
│ │ 跨阻放大器│
│ │ V_I = I │
│ │ ×Rf │
│ └────┬─────┘
│ │
│ ADC0_CH0
│ (电流信号)
│ V_dut (经由另一引线取)
└─────────── 运放B ──┬── ADC0_CH1
LMV358 │ (电压信号)
缓冲器 │
```
**注意:** 单 ADC 芯片、双通道同时采样,需要 STM32 的 ADC 双规则组模式或注入模式。
### 2.4 信号产生(DAC + LPF
MCU DAC 生成正弦波,需要经过低通滤波器滤除采样阶梯:
```
DAC 输出(12bit,120kHz 更新率 → 每个正弦周期 12 个阶梯):
│ ████
│ █ ██ ██
│█ ██ ██
└────────────────
经 2 阶 LPF 后(f_c ≈ 30kHz):
│ ~~~~~~~~
│ ~~~~~~~~
│~~~~~~~~
└──────────────── → 干净正弦波
LPF 参数(二阶巴特沃斯,f_c=30kHz):
运放:用第三个运放(LMV358 是双运放,不够)
所以 LPF 用无源 RC
R=1k, C=5.6nF → f_c ≈ 28.4kHz(一阶)
再加一级 RCR=1k, C=3.3nF → 二阶共衰减 ~40dB@120kHz
```
这里有个问题:LMV358 只有双运放,一个做跨阻(运放A),一个做缓冲(运放B),没有第三个运放做有源 LPF。最可能的做法是:
1. **无源 RC LPF**:两级 RC 做正弦波滤波(DAC → RC → RC → 4051
2. **或者直接用 PWM + 有源 LPF**:省掉 DAC,用 MCU 的定时器 PWM 输出,经二阶有源 LPF 得到正弦波——需要一个额外运放
3. **或者 MCU 内置 DAC 直接输出** + 无源 RC 凑合用
¥138 级别的产品,最可能是方案1(无源 RC)。
---
### 2.5 总体 BOM 成本估算
| 编号 | 器件 | 参考型号 | 数量 | 单价¥ | 小计¥ |
|------|------|---------|------|-------|-------|
| 1 | MCU | GD32F103C8T6 | 1 | 6.5 | 6.5 |
| 2 | 运放 | LMV358 / SGM358 | 2 | 0.6 | 1.2 |
| 3 | 模拟开关 | 74HC4051 | 1 | 0.6 | 0.6 |
| 4 | OLED 屏幕 | SSD1306 0.96" 128×64 | 1 | 8.0 | 8.0 |
| 5 | DC-DC 升压 | HT7750 (3V→5V) | 1 | 1.5 | 1.5 |
| 6 | 量程电阻 | 0805 1% 10Ω~10MΩ×8 | 8 | 0.08 | 0.64 |
| 7 | 无源元件 | R/C 若干 | 20 | 0.03 | 0.6 |
| 8 | 晶振 | 8MHz 无源 | 1 | 0.3 | 0.3 |
| 9 | 按键 | 贴片轻触 4pin | 2 | 0.2 | 0.4 |
| 10 | 电池座 | CR2032 贴片 | 1 | 1.5 | 1.5 |
| 11 | 镊子 | 镀金磷铜 | 1对 | 2.5 | 2.5 |
| 12 | PCB | 双面板 60×20mm | 1 | 3.5 | 3.5 |
| 13 | 外壳 | 开模注塑(摊销量) | 1 | 3.0 | 3.0 |
| 14 | 其他(排针、焊锡、包装) | — | 套 | 2.0 | 2.0 |
| | | | | | **¥32.7** |
**BOM 估算结论:** 硬件 BOM 约 **¥30~35/台**(含外壳、包装),零售 ¥138,毛利约 75%。扣除运营、物流、平台抽成(~15%)、人工,净利润约 35~40%。
作为对比,如果换用 AD8302 方案,BOM 将飙升至 ¥60+,¥138 的零售价无法支撑。
---
## 三、测量原理——I-V 转换 + DFT 方法
### 3.1 基本原理
LCR-ST1 采用 **I-V 转换法**(也称伏安法、V-I 法):
```
向被测件 DUT 注入正弦波 V_source
测量 DUT 两端的电压 V_dut
测量流过 DUT 的电流 I_dut(通过跨阻放大器转换为 V_I = I_dut × R_f
计算复阻抗 Z = V_dut / I_dut = R + jX
```
**与方案B的核心关系:** LCR-ST1 使用的就是我们在前面讨论的 **DDS 注入 + 阻抗分析** 方法!只不过用 MCU 内置 DAC 替代了独立 DDS 芯片,用通用运放替代了 AD8302/AD8333,是**极致成本优化的方案C的数字IQ + 廉价前端的实现**。
### 3.2 测量模型
```
4051 选通的 R_ref
DAC ──┬─ R_ref ──┬───────── 镊子正极 ──┬── V_dut
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ 运放A(跨阻)│ │
│ │ V_I = I │ │
│ │ ×R_ref│ │
│ └──────────┘ │
│ │ I_dut │
│ ADC0_CH0 │
│ │
│ ADC0_CH1
└──────────────────────────── 参考地
镊子负极 ───────────────────────── 参考地
```
**重要细节:** 电流测量用的是"跨阻放大器"接法——也就是将运放接成电流→电压转换形式,DUT 电流流过反馈电阻 R_f,产生 V_out = -I_dut × R_f。R_f 就是 4051 选通的量程电阻。
### 3.3 等效电路
```
┌───────────────────┐
│ DUT │
│ ┌───────────┐ │
│ │ │ │
├──┤ R_dut+jX │────┤
│ │ │ │
│ └───────────┘ │
└───────────────────┘
测量的是 DUT 的复阻抗 Z_dut = V_dut / I_dut
对于不同 DUT
电阻:Z = R
电感:Z = jωL = j2πfL
电容:Z = 1/(jωC) = -j/(2πfC)
```
### 3.4 自动量程逻辑
```
上电后默认从最大量程(R_ref=10MΩ)开始:
1. 施加测试信号
2. 测量 V_dut 和 V_I
3. 如果 V_dut < 满量程×0.1 → 切换高一档(R_ref 变小,电流增大)
4. 如果 V_dut > 满量程×0.9 → 切换低一档(R_ref 变大,电流减小)
5. 建立稳定后再做 DFT → 计算 L/C/R/Q/D
量程切换判断:占用 50~200ms
测量+计算:每个频点需 100~500ms
三个频点扫描一次:约 0.5~2s
```
---
## 四、算法与软件实现详解
### 4.1 信号采样与 DFT 解调
这是 LCR-ST1 软件的核心。基于 MCU 的 DAC+ADC,通过 DFT 提取幅度和相位。
#### 采样时序
```
测试频率 f₀ = 1kHz(举例)
ADC 采样率 f_s:被配置为 f₀ × 64 = 64kHz
→ 每个正弦周期采 64 个点
→ 采样周期 T_s = 15.625μs
→ 采集 N = 128 个周期 → 共 8192 个点 → 耗时 128ms
DAC 更新率:同样是 64kHz,与 ADC 同步
→ DAC 每周期输出 64 个阶梯 ≈ 12 个阶梯已足够平滑
```
#### DFT 计算
```c
// ============================================================
// LCR-ST1 核心:单频 DFT 解调
// 输入:V_dut[N] 和 V_I[N] 的 ADC 采样值
// 输出:幅度和相位
// ============================================================
#define F_SAMPLE 64000 // 64kHz 采样率
#define N_SAMPLES 8192 // 128 个周期
#define F_SIG 1000 // 1kHz 测试信号
// 预计算 sin/cos 表(半波对称压缩)
// 实际上 MCU Flash 够大,可以直接存 64 个点(一个周期)
// 用查表 + 循环索引,避免运行时计算三角函数
int16_t cos_table[64]; // cos(2π×k/64), k=0..63
int16_t sin_table[64]; // sin(2π×k/64), k=0..63
void DFT_Init(void) {
for (int i = 0; i < 64; i++) {
cos_table[i] = (int16_t)(cosf(2*PI*i/64) * 32767);
sin_table[i] = (int16_t)(sinf(2*PI*i/64) * 32767);
}
}
// 注意:N_SAMPLES 必须能被样周期数 64 整除!
// 这里 N_SAMPLES = 8192 = 128 × 64 ✅
void DFT_Demodulate(
uint16_t *v_dut, // 电压通道采样数组
uint16_t *v_i, // 电流通道采样数组
float *mag_dut, // 输出电压幅度
float *mag_i, // 输出电流幅度
float *phase_diff // 输出相位差(弧度)
) {
int64_t I_dut = 0, Q_dut = 0;
int64_t I_i = 0, Q_i = 0;
for (int i = 0; i < N_SAMPLES; i++) {
int tbl_idx = i & 63; // i % 64,查表索引
// 电压通道 DFT
I_dut += (int64_t)v_dut[i] * cos_table[tbl_idx];
Q_dut += (int64_t)v_dut[i] * sin_table[tbl_idx];
// 电流通道 DFT
I_i += (int64_t)v_i[i] * cos_table[tbl_idx];
Q_i += (int64_t)v_i[i] * sin_table[tbl_idx];
}
// 归一化为幅度
// |V| = sqrt(I² + Q²) × 2/N_SAMPLES
float mag_I_dut = sqrtf(I_dut*I_dut + Q_dut*Q_dut);
float mag_I_i = sqrtf(I_i*I_i + Q_i*Q_i);
float norm = 2.0f / (float)N_SAMPLES * (3.3f / 4096.0f);
// 注意:12bit ADC,满量程 3.3V4096 码值
*mag_dut = mag_I_dut * norm; // V_dut 幅度(伏)
*mag_i = mag_I_i * norm; // V_i 幅度(伏)
// 相位差 = atan2(Q, I) 的差值
float phase_dut = atan2f(Q_dut, I_dut);
float phase_i = atan2f(Q_i, I_i);
*phase_diff = phase_i - phase_dut;
// 归一化到 -π ~ π 范围
if (*phase_diff > PI) *phase_diff -= 2*PI;
if (*phase_diff < -PI) *phase_diff += 2*PI;
}
// 对 GD32F103(无 FPU)运行的优化:
// 以上计算中有 sqrtf、atan2f 等浮点运算,FPU 在 M3 下不存在
// 实际实现中,多半用查表 + CORDIC 或 Q15 定点数运算
```
#### 无 FPU 定点数优化方案
GD32F103 是 Cortex-M3**无硬件 FPU**。用软件浮点计算 8192 点 DFT 会非常慢(可能耗时 > 1s)。实际产品必须用定点数:
```c
// 定点数 DFTQ15 格式)
// 用 32bit 累加器防溢出
int32_t I_dut = 0, Q_dut = 0;
for (int i = 0; i < N_SAMPLES; i++) {
// ADC 12bit 无符号 → 减去偏置 2048 转为有符号
int16_t vsig = (int16_t)v_dut[i] - 2048;
// 与查表 Q15 值相乘,64 位累加
I_dut += ((int32_t)vsig * cos_table[i & 63]) >> 15;
Q_dut += ((int32_t)vsig * sin_table[i & 63]) >> 15;
}
// 幅度用 |I| + |Q| 最大值近似(省掉 sqrt)
// 对 1% 精度 LCR,足够
int32_t mag_approx = (abs(I_dut) > abs(Q_dut))
? abs(I_dut) + abs(Q_dut) / 4
: abs(Q_dut) + abs(I_dut) / 4;
// 这给出了带 ±0.5% 误差的幅度估计
// 相位用查表法:theta = atan2(Q, I)
// 预存 256 点 arctan 表
// 因为 I/Q 对称性,只需要存 0~45°
int16_t phase_lut[256];
// 通过象限映射 + 查表得到相位
```
### 4.2 阻抗计算
```c
// 从 DFT 结果计算阻抗
// 电流通道:V_I = -I_dut × R_ref
// 所以 I_dut = -V_I / R_ref
// 取模:|I_dut| = |V_I| / R_ref
// DUT 复阻抗:
// Z_dut = V_dut / I_dut
// = -V_dut × R_ref / V_I
// 取模:
// |Z_dut| = |V_dut| × R_ref / |V_I|
//
// 相位:
// θ_z = phase(V_dut) - phase(V_I)
// = -(phase_i - phase_dut) = -phase_diff
float Z_mag = mag_dut * R_ref / mag_i; // |Z| (Ω)
float theta = -(*phase_diff); // ∠Z (rad)
// 分解为电阻和电抗
float R = Z_mag * cosf(theta); // 等效串联电阻 ESR (Ω)
float X = Z_mag * sinf(theta); // 电抗 (Ω)
// 识别元件类型
if (fabsf(X) < fabsf(R) * 0.01f) {
// 纯电阻
R_display = R;
type = TYPE_RESISTOR;
} else if (X > 0) {
// 感性:L = X / (2πf)
float L = X / (2.0f * PI * F_SIG);
L_display = L; // 电感值 (H)
Q_display = fabsf(X) / R; // 品质因数 Q
type = TYPE_INDUCTOR;
} else {
// 容性:C = -1 / (2πf × X)
float C = -1.0f / (2.0f * PI * F_SIG * X);
C_display = C; // 电容值 (F)
D_display = R / fabsf(X); // 损耗因数 D
type = TYPE_CAPACITOR;
}
```
### 4.3 多频点策略
LCR-ST1 在三个频点之间循环测量:
```
100Hz:适合大电容(>1μF)、大电感(>1H
1kHz:通用频点
10kHz:适合小电容(<1nF)、小电感(<10μH
```
**频点切换实现:**
```c
// 三个频点共用同一套 DFT 代码
// 唯一区别:DAC 波形表更新速率和 ADC 采样率
typedef struct {
uint32_t freq; // 测试频率 (Hz)
uint32_t sample_rate; // ADC/DAC 采样率 (Hz)
uint32_t periods; // DFT 采集周期数
uint32_t total_samples; // 总采样点数 = periods × 64
} TestFrequency_t;
TestFrequency_t freqs[] = {
{ 100, 6400, 32, 2048}, // 100Hz → 6.4kHz 采样 → 2048 点 → 320ms
{ 1000, 64000, 64, 4096}, // 1kHz → 64kHz 采样 → 4096 点 → 64ms
{10000, 640000, 128, 8192}, // 10kHz → 640kHz → 8192 点 → 12.8ms
};
// 注意:10kHz 需要 ADC 采样率 640kHz
// GD32F103 ADC 最大 1Msps → 640kHz 可行
// 但 DAC 更新频率同样 640kHz → 每个点 ~1.56μsDMA 驱动
```
### 4.4 自动量程切换(软件实现)
```c
// 量程电阻表(与 4051 通道对应)
// 选择原则:使 V_dut 接近 ADC 满量程的 30%~80%
// 电压信号过小 → SNR 差 → 精度下降
// 电压信号过大 → 超出 ADC 范围 → 削波失真
const float R_range[] = {
10.0f, // Ch0: 低阻测量
100.0f, // Ch1
1000.0f, // Ch2
10000.0f, // Ch3
100000.0f, // Ch4
1000000.0f, // Ch5
10000000.0f,// Ch6: 超高阻
0.0f // Ch7: 空(校准位)
};
uint8_t current_range = 4; // 从 100kΩ 开始
uint8_t AutoRange(uint16_t *v_dut, uint16_t *v_i) {
// 计算 V_dut 峰值
uint16_t v_max = 0, v_min = 4095;
for (int i = 0; i < 64; i++) { // 一个周期的快速检测
if (v_dut[i] > v_max) v_max = v_dut[i];
if (v_dut[i] < v_min) v_min = v_dut[i];
}
uint16_t v_pp = v_max - v_min;
// 判断是否在最佳区间(ADC 满量程的 20%~80%
// 12bit ADC → 满量程 4096 → 20%=819, 80%=3277
if (v_pp < 819 && current_range < 6) {
current_range++; // 增大 R_ref → 电流更小 → V_dut 变大
return RANGE_CHANGED;
} else if (v_pp > 3277 && current_range > 0) {
current_range--; // 减小 R_ref → 电流更大 → V_dut 变小
return RANGE_CHANGED;
}
return RANGE_OK;
}
```
### 4.5 校准与补偿
#### 开路校准(Open Cal
```
不连接 DUT,镊子悬空 → 测量系统偏移量
Z_open = 非常大 → 近似为 0 电流
记录 V_dut_open(运放的失调电压 + 串扰)
记录相位偏移
存储到 EEPROM
V_dut_offset[频点][量程]
phase_offset[频点][量程]
```
#### 短路校准(Short Cal
```
短路镊子 → 测量系统零位阻抗
记录 Z_short(导线电阻 + 接触电阻)
存储到 EEPROM
R_short[量程]
L_short[量程](引线电感)
```
#### 实时校正公式
```c
// 每次测量后做校正
// Step 1: 减去开路偏移
V_dut_corrected = V_dut_raw - V_dut_offset[freq][range];
V_I_corrected = V_I_raw - V_I_offset[freq][range];
// Step 2: 减去短路残留
if (type == TYPE_RESISTOR || type == TYPE_INDUCTOR) {
R_meas = R_meas - R_short[range];
}
if (type == TYPE_INDUCTOR) {
L_meas = L_meas - L_short[range];
}
// Step 3: 相位校正
phase_corrected = phase_raw - phase_offset[freq][range];
```
### 4.6 OLED 显示与 UI 逻辑
```c
// 显示刷新率:~4Hz250ms 一次)
typedef struct {
float value; // 测量值
uint8_t type; // 元件类型
float secondary; // 第二参数(Q/D/ESR
float frequency; // 当前频率
uint8_t range_idx; // 当前量程
uint8_t stable; // 读数稳定标志
uint32_t auto_off_timer;// 自动关机计时
} DisplayData_t;
void Display_Update(DisplayData_t *d) {
OLED_Clear();
// 主数值(大字体,2 行高度)
char main_val[16];
FormatValue(d->value, main_val,
(d->type == TYPE_CAPACITOR) ? "F" :
(d->type == TYPE_INDUCTOR) ? "H" : "Ω");
OLED_PrintBig(0, 0, main_val);
// 第二参数
char sec_val[16];
if (d->type == TYPE_RESISTOR) {
// 电阻模式不显示第二参数
} else if (d->type == TYPE_INDUCTOR) {
sprintf(sec_val, "Q=%.2f", d->secondary);
} else if (d->type == TYPE_CAPACITOR) {
sprintf(sec_val, "D=%.2f", d->secondary);
}
OLED_PrintSmall(0, 32, sec_val);
// 频率 + 量程指示
char info[16];
sprintf(info, "%dHz", (int)d->frequency);
OLED_PrintSmall(80, 48, info);
OLED_Display();
}
// 数值格式化(自动单位前缀)
void FormatValue(float val, char *out, char *unit) {
char prefix = ' ';
float disp = val;
if (val >= 1e6f) { disp = val/1e6f; prefix = 'M'; }
else if (val >= 1e3f) { disp = val/1e3f; prefix = 'k'; }
else if (val >= 1.0f) { /* 无前缀 */ }
else if (val >= 1e-3f) { disp = val*1e3f; prefix = 'm'; }
else if (val >= 1e-6f) { disp = val*1e6f; prefix = 'μ'; }
else if (val >= 1e-9f) { disp = val*1e9f; prefix = 'n'; }
else { disp = val*1e12f; prefix = 'p'; }
sprintf(out, "%.2f %c%s", disp, prefix, unit);
}
// 自动关机(10 分钟无操作)
void AutoOff_Check(void) {
if (HAL_GetTick() - last_key_press > 600000) { // 10 分钟
OLED_Clear();
OLED_PrintCenter("OFF");
OLED_Display();
HAL_Delay(1000);
Enter_DeepSleep();
}
}
```
---
## 五、整机软件流程图
```
上电
初始化系统
(RCC/GPIO/DAC/ADC/DMA/TIM/I2C/OLED)
显示 LOGO "FNIRSI"
短蜂鸣器响应
加载校准参数
(EEPROM → 开路/短路数据)
镊子类型检测?
┌──── 短路检测?→ 进入校准模式 ────┐
│ (长按按键启动) │
│ │
▼ │
┌─────────┐ │
│ 主测量循环│ │
└────┬────┘ │
│ │
┌────┴────┐ │
│ 自动量程 │ │
│(4051切换)│ │
└────┬────┘ │
│ │
┌────┴────┐ │
│ DAC 输出│ │
│ 正弦激励 │ │
└────┬────┘ │
│ │
┌────┴────┐ │
│ ADC采样 │ │
│ V_dut+V_I│ │
│ (DMA) │ │
└────┬────┘ │
│ │
┌────┴────┐ │
│ DFT解调 │ │
│ 幅度+相位 │ │
└────┬────┘ │
│ │
┌────┴────┐ │
│ 阻抗计算 │ │
│ R / L / C│ │
└────┬────┘ │
│ │
┌────┴────┐ │
│ 校准补偿 │ │
│ 开路/短路 │ │
└────┬────┘ │
│ │
┌────┴────┐ │
│ OLED显示 │ │
└────┬────┘ │
│ │
┌────┴────┐ │
│按键扫描 │──→ 功能切换/锁定 │
│自动关机 │──→ 超时休眠 │
└────┬────┘ │
│ │
┌────┴────┐ │
│频点切换 │──→ 100Hz/1kHz/10kHz │
└────┬────┘ │
│ │
└──→ 循环 ────────────────────────┘
```
---
## 六、与方案B(AD8333 路径)的对比
| 对比项 | LCR-ST1 (MCU+DAC+运放) | 我们设计的方案B (AD8333) |
|--------|----------------------|------------------------|
| 激励产生 | MCU DAC + 无源 LPF | DDS AD9834 + 有源 LPF + 变压器 |
| 解调方式 | MCU DFT 定点数 | AD8333 硬件 IQ 解调 |
| ADC 需求 | 12bit × 2ch @ 640kHz | 12bit × 2ch @ 1kHz |
| MCU 算力 | 无 FPU 定点数,50% 占满 | 有 FPUSTM32G4),<10% |
| 测量精度 | ~1%(典型) | ~0.1%(理论) |
| ΔR 分辨率 | ~1~2mΩ | ~0.1~0.3mΩ |
| 动态范围 | ~50~55dB | ~80dB |
| SNR(铝车架场景) | 不可用(<10dB | 可用(>30dB |
| 铝制车架检测 | ❌ 不适用 | ✅ 95~99% |
**核心差异:** LCR-ST1 适用于**离线的、已知好坏的元器件**测量(有足够信号、无强干扰),而我们的方案B需要处理**在线、弱信号、强干扰**的实车检测——两者的 SNR 需求差了两个数量级。
具体来说,LCR-ST1 在测量一个 10μH 电感时,信号幅度可能有几百 mV,SNR > 40dB。而方案B在检测铝制车架的 0.3μH 变化时,信号幅度仅几个 mV,环境噪声(发动机、变频器、电源纹波)可达几十 mV——这就需要 AD8333 的差分架构和 80dB 动态范围来应对。
---
## 七、小结
### 7.1 LCR-ST1 的设计哲学
```
¥138 造价 × 75% 毛利 × 30万/年销量
→ BOM ¥30×30万 = ¥900 万/年
→ 生产良率 98%+
→ 退换率 < 5%
每个元器件选型的边际优化 ¥0.05 都值得做:
用 1% 电阻而非 0.1% → 省 ¥0.3
用 GD32 而非 STM32 → 省 ¥3
用 LMV358 而非 OPA2188 → 省 ¥1.5
用 CR2032 而非锂电池+充电 → 省 ¥5
```
### 7.2 对我们方案B的启示
```
LCR-ST1 证明了 "MCU·DAC + 通用运放" 的 I-V 法可以做到 1% 精度。
→ 这意味着方案B的核心算法(DFT 解调)在原理上是成熟的。
但 LCR-ST1 做不到的事:
① 无法检测百毫欧级的 ΔR(铝制车架需要 0.1mΩ 分辨率)
② 无法在线抑制发动机/变频器/电源的共模噪声
③ 无法在 3V 单电池供电下驱动大动态范围前端
所以 LCR-ST1 是 "够用就好" 的消费级设计,
而我们的方案B是 "不惜成本保信号" 的工业级设计——两者定位完全不同。
```
---
## 文档结束