简介:面向51单片机毕业设计或课程设计场景,这份资源给出了一套基于开尔文四线接法的电阻测量仿真方案。核心思路是用恒流源激励被测电阻,配合按键调节电流大小,让使用者直观观察不同测试电流下大约5%的误差变化;对电机内阻等低阻值对象,方案还提示需停止仿真后修改电阻值,或直接换用电位器调试。压缩包共78个文件,约30.32MB,按程序、原理图、仿真、流程图、器件清单等模块组织:C源码、Keil工程与hex文件用于烧录验证,SchDoc格式原理图及PDF预览便于制版,DSN仿真文件支持电路调试,xlsx清单和doc/pdf手册则覆盖元件选型与焊接装配。目前已有157人学习下载。此外还附带常用器件资料、常见问题解决、答辩技巧和所需软件下载地址,适合从原理理解、仿真验证到毕设文档整理的一站式参考。
1. 把电阻测准这件事,为什么值得用一片 51 去做
万用表测电阻人人会,但真到毫欧级或者接触电阻不可忽略的场景,普通两线测量就撑不住了。表笔夹上去的接触电阻、导线本身的电阻,都会串进测量回路,测出来的值比真实值大出不少。这个误差在小电阻上尤为致命——一根 0.2 米的杜邦线就有 20 毫欧上下,如果把导线电阻和接触电阻算进去,你要测的 100 毫欧采样电阻,表上读出来可能直接变成 1.5 倍。开尔文电路,也叫四线测量,就是为了解决这个问题而生的——它把电流回路和电压采样回路彻底分开,让引线电阻和接触电阻不再参与电压计算。
这个标题的项目适合两类人:一类是做传感器采集、电池内阻检测、线缆导通电阻测试的嵌入式工程师,想在仿真环境里先把四线法的逻辑和时序调通,再迁移到实际板子上;另一类是 51 单片机课程设计要交作品的学生,需要一套能在 Proteus 里跑起来的方案。开尔文电路本身并不复杂,核心就是一个恒流源加一个仪表放大器或者差分采样,51 单片机的任务是把恒流源点亮、读 ADC、换算电阻值、显示到 LCD 上。难点不在单片机上,而在模拟前端的设计——恒流源怎么稳,量程怎么切换,采样放大倍数怎么匹配。这篇文章就顺着这块板的完整落地路径来拆:先把开尔文电路的原理吃透,再给出仿真搭建的具体步骤、51 端的数据处理代码,最后落在排错和验证上。
2. 开尔文电路仿真模型设计:误差从哪来,四线怎么消掉
2.1 四线测量原理与仿真中的节点划分
开尔文测量的本质是四端子结构:恒流源从两个电流端子流入被测电阻,电压采样从另外两个电压端子引出。因为电压表输入阻抗极高,几乎不取电流,所以电压导线上的压降可以忽略,采样到的就是被测电阻两端的真实电压,再除以已知的电流,电阻值就出来了。
在 Proteus 仿真里体现这个结构,不能简单画四条线,而是要把“电流回路”和“电压回路”的电流路径分开。实际建模时,我给每个端子串一个 10 毫欧到 100 毫欧的接触电阻,用来模拟表笔接触不良的情况。手动修改这几个寄生电阻的阻值,就能看到两线测量和四线测量的读数差异,这是验证开尔文电路价值最直观的手段。
仿真中四个端子这样分配:
- I+ / I-:恒流源的输出和回流端,串接 R_contact1、R_contact4
- V+ / V-:ADC 采样端,串接 R_contact2、R_contact3 并接入仪表放大器输入端
如果去掉开尔文结构,把采样点挪到 I 端,就退化成两线测量。用同一个被测电阻跑两遍,对比结果,正好可以解释标题里“开尔文电路”这四个字存在的必要性。
2.1.1 为什么电压采样线几乎没有电流流过
仪表放大器的输入阻抗一般在 1G 欧以上,仿真模型里 LM324 这类普通运放输入阻抗稍低,但也有兆欧量级。根据并联分流原理,流过电压采样线的电流是恒流源电流乘以一个极小的比例,在电压线上产生的压降可以忽略。实际制作 PCB 时,V+ 和 V- 要单独走线到被测电阻的焊盘内侧,不能在放大器输入端直接短接,这是开尔文测量在版图上的关键约束。
仿真时用一个数字万用表探针分别点在电阻两端,读数与理论值的偏差就是电压采样线上的压降。这个数值如果大于 0.1%,通常意味着输入阻抗不够,或者差分放大器的共模抑制比参数设置有问题。
2.2 恒流源设计:仿真用什么器件,参数怎么设
恒流源是开尔文测量的心脏。常见方案有 JFET 恒流管、运放加稳压管、三极管镜像恒流源。仿真里最稳、最好调的是运放恒流源,因为它的输出电流只取决于基准电压和采样电阻,元件参数的离散性影响最小。
我一般用 LM358 加 TL431 的组合:TL431 提供一个 2.5V 精密基准,分压后得到 Vref,接在运放的同相端;运放的反相端接采样电阻 R_sense 上的电压,运放输出驱动一个 MOSFET 或三极管调整电流,直到 R_sense 上的电压等于 Vref。
这个拓扑在 Proteus 里的连接顺序是:
- TL431 阴极接 12V,阳极接地,REF 端分压后输出 0.5V 作为目标电压
- LM358 同相端接 0.5V,反相端接 1 欧采样电阻的高端,运放输出接 2N2222 基极
- 2N2222 的发射极接采样电阻到地,集电极接被测电阻,流过集电极的电流就是恒流值
仿真参数设定:
- R_sense = 1 欧,Vref = 0.5V,输出电流 500mA——不,这个电流太大,实际仿真里发热和压降都难控制。我一般设 10mA 到 50mA,线性度足够,也不会让运放输出饱和
- 电源电压取 12V,被测电阻上限 100 欧,恒流 50mA 时最大压降 5V,留足余量
# 恒流源输出电压与电流的关系(手算校验用) V_out = Vref * (1 + R_feedback / R_sense) I_const = Vref / R_sense代码块里写的是运放反馈环的电压表达式,实际恒流值由第二式决定。如果把 Vref 从 0.5V 改成 1V,电流就翻倍,但要注意运放输出端的电压余量——电流越大,被测电阻上的压降越大,运放输出电压就得越高,12V 供电下最大输出大约 10V,被测电阻压降超过这个值电流就会掉下来。
2.3 仪表放大器选型与 Proteus 元件清单
电压采样需要把差模信号提取出来,同时抑制共模干扰。仿真里可以偷懒用两个 LM358 搭差分放大器,但这样共模抑制比只有几十 dB,交直流混合的信号进来误差明显。更接近工程实践的做法是用 INA128 仪表放大器,Proteus 元件库里有这个模型,三运放结构,外部只接一个电阻就能设定增益。
增益公式:
G = 1 + 50k / R_G- 被测电阻 1 欧、恒流 50mA 时,差分电压 50mV,放大 100 倍后 5V,接近 ADC 满量程
- 被测电阻 100 欧时,差分电压 5V,不需要放大,增益设为 1,用直通模式
Proteus 元件清单和参数按下面这张表选:
| 元件 | 型号 | 关键参数 | 作用 |
|---|---|---|---|
| 运放 | LM358 | 单电源,输入共模范围含地 | 恒流源比较器 |
| 精密基准 | TL431 | 2.5V,1% | 提供定电流基准电压 |
| 恒流管 | 2N2222 | 最大 800mA | 电流通道开关管 |
| 仪表放大器 | INA128 | 共模抑制比 120dB | 差分电压采样 |
| 采样电阻 | 金属膜 1 欧 | 0.1% 精度,50ppm 温飘 | 电流换算基准 |
| 双掷模拟开关 | CD4052 | 导通电阻 100 欧 | 量程切换 |
CD4052 放在量程切换的位置:一个通道负责把不同阻值的 R_G 接入 INA128 的增益引脚,另一个通道切换恒流源的 Vref 分压值。注意 Proteus 里模拟开关的导通电阻会参与分压,选 100 欧以内的小阻值型号对增益精度影响可以忽略。
3. 51 单片机最小系统与 ADC 采集电路:从 Proteus 到代码
3.1 最小系统搭建与各引脚功能分配
51 单片机在 Proteus 里跑仿真,最常翻车的地方是晶振和复位电路的参数没对上仿真模型的要求。我给的方案是 12MHz 晶振,两个 30pF 电容到地,复位脚接 10uF 电容和 10k 电阻。仿真里复位时间太长会导致单片机启动后直接跑飞,所以电容选 10uF 而不是常见的 22uF,上电等 100ms 就稳定。
引脚分配表:
| 引脚 | 功能 | 连接对象 |
|---|---|---|
| P0.0-P0.7 | 数据总线 | LCD1602 数据口,接 10k 上拉排阻 |
| P2.0-P2.2 | 控制线 | LCD RS、RW、E |
| P1.0 | 恒流源使能 | 2N2222 基极开关管门控 |
| P1.1 | 量程切换 | CD4052 A 通道地址 |
| P1.2 | 量程切换 | CD4052 B 通道地址 |
| P3.2 | ADC 转换启动 | 外部中断 0 触发 |
| P3.3 | ADC 数据就绪 | 查询等待 |
| P3.6/P3.7 | 串口 | 上位机调试输出,可不接 LCD |
这里最关键的改动是恒流源不能一直开着。一方面是为了省电,更重要的原因是:恒流源开启的瞬间,被测电阻上和寄生电容上有充放电过程,ADC 如果在这个瞬态采数,数据会偏大。所以 P1.0 拉高开启恒流源后,软件至少要延时 10ms 再启动转换。
3.1.1 用定时器控制恒流源脉宽与采样节拍
51 单片机的定时器在这里不只是做延时,而是直接参与采样的时序编排。我用 T0 工作在模式 1,产生 10ms 的中断节拍,每个节拍内完成一轮完整的测量:
- 第 0-2ms:P1.0 输出低电平,恒流源关闭,模拟前端归零
- 第 2-3ms:P1.0 拉高,恒流源启动,等待电流稳定
- 第 3-9ms:P3.2 拉低触发 ADC,连续采集 8 次,每次间隔约 700us
- 第 9-10ms:P1.0 拉低,一轮测量结束
用定时器而不是 delay 函数的好处是:采集过程中的时间戳是确定的,仿真和实机行为一致。如果某个通道的开关切换引入毛刺,可以在示波器上对比 P1.0 的波形和 ADC 采样窗口,直接看出时序有没有错位。
3.2 ADC 采样电路:ADC0809 还是 TLC1543
51 单片机内部没有 ADC,必须外扩。Proteus 里最常用的型号是 ADC0809:8 通道、8 位分辨率、逐次逼近型。它的缺点是转换速率慢(100us 左右),但对电阻测量这种慢速场景完全够用。另外 8 位分辨率意味着量化台阶是 5V/256 ≈ 19.5mV,配合仪表放大器放大 100 倍,理论能分辨到 0.2 欧,做演示没问题,要做到精确测量就偏吃力。
如果想做 12 位精度,可以换成 TLC1543,SPI 接口,Proteus 模型同样稳定。需要注意的是 51 没有硬件 SPI,要用 IO 口模拟时序,代码会稍微长一点。本文下面的代码以 ADC0809 为主,因为上手快、出图直观,适合先把开尔文电路验证跑通。
ADC0809 的连接方式:
- 地址线 A/B/C 接 P1.0-P1.2 复用,通过段选选择模拟通道 0 作为差分信号输入
- START 接 P3.2,ALE 与 START 短接,转换启动信号由 P3.2 产生
- EOC 接 P3.3,转换完成后输出高电平,软件查询
- OE 接 P3.4 反向后打开输出三态门
#include <reg51.h> sbit ADC_START = P3^2; sbit ADC_EOC = P3^3; sbit ADC_OE = P3^4; sbit CC_EN = P1^4; // 恒流源使能 unsigned char adc_read(unsigned char channel) { unsigned char result; P1 = (P1 & 0xF8) | (channel & 0x07); // 选择模拟通道 ADC_START = 0; ADC_START = 1; ADC_START = 0; // START 上升沿复位,下降沿启动转换 while (ADC_EOC == 0); // 等待转换完成,EOC 拉高 ADC_OE = 1; // 打开输出使能 result = P0; // 读取 8 位结果 ADC_OE = 0; return result; }这段代码的逻辑顺序很关键:先把通道地址通过 P1 的低三位设置好,然后给一个 START 脉冲。START 从 0 到 1 再回 0,ADC0809 内部先复位再启动转换,EOC 在转换期间保持低电平。单片机死等 EOC 变高,然后拉高 OE 才能读到数据。
有一个容易被忽略的坑:P0 口是开漏输出,读取之前必须有外部上拉。Proteus 里不加排阻,P0 读回来的值全是 0xFF,这个时候第一反应不应该怀疑 ADC 时序,而是检查上拉。
3.3 软件主循环与均值滤波
ADC0809 的单次转换结果波动非常大,8 位分辨率下,信号噪声稍大一点低位就乱跳。直接显示原始值,LCD 上的数字会在两三个值之间来回跳。
我一般分两级滤波:第一级是硬件上的,ADC 输入端并联一个 0.1uF 的陶瓷电容,高频噪声在进入采样保持器之前就被旁路掉;第二级是软件上的,连续采 8 次,去掉一个最大值和一个最小值,剩下 6 个数取平均。这种去极值均值滤波在慢变信号上的表现比简单平均好很多——它对毛刺脉冲免疫,不会把突变值带进平均结果。
unsigned int adc_filter(void) { unsigned char i, j, temp; unsigned char buf[8]; unsigned long sum = 0; unsigned char max_idx, min_idx; for (i = 0; i < 8; i++) { buf[i] = adc_read(0); } max_idx = 0; min_idx = 0; for (i = 1; i < 8; i++) { if (buf[i] > buf[max_idx]) max_idx = i; if (buf[i] < buf[min_idx]) min_idx = i; } buf[max_idx] = buf[7]; // 用最后一个采样顶替极值位置 buf[min_idx] = buf[6]; for (i = 0; i < 6; i++) { sum += buf[i]; } return (unsigned int)(sum / 6); }这段代码没做冒泡排序,而是直接找最大值最小值的位置,然后拿最后两个采样值覆盖掉,之后对前 6 位求和平均。这样省掉了完整的排序过程,8 个数据的场景下执行时间只有冒泡排序的四分之一。注意 sum 的类型是 unsigned long,因为 6 个 0-255 的数加起来最大 1530,用 unsigned int 也不会溢出,但统一成长整型不容易在后续扩展 12 位 ADC 时出错。
4. 电阻值换算与误差修正:查表、最小二乘和系统误差补偿
4.1 电压转电阻的物理公式与代码实现
ADC 读到的数字量不能直接当电阻用,要经过两级换算。第一级是电压:V_adc = ADC_value / 255 * V_ref,其中 V_ref = 5V。第二级是电阻:R_x = V_adc / I_const,其中 I_const = Vref / R_sense。把两级展开合并,就能看出最终结果和哪些变量相关:
R_x = (ADC_value / 255) * V_ref * R_sense / Vref从公式看,V_ref 出现在分子和分母里,理论上可以约掉,恒流源基准电压的精度对结果没有直接影响。这是因为仪表放大器的增益和恒流源的基准来自同一个 Vref,两者的偏差相互抵消。但这个结论只在两个 Vref 完全相等时成立,实际电路里电阻分压的精度会留下残余误差。仿真里可以用同一个分压节点同时驱动 TL431 和 INA128 的稳压端来逼近这个理想条件。
换算的 C 代码:
float voltage_to_resistance(unsigned int adc_val) { float v_adc, r_x; const float I_const = 0.05f; // 恒流源电流,单位 A const float ADC_REF = 5.0f; v_adc = (float)adc_val / 255.0f * ADC_REF; r_x = v_adc / I_const; return r_x; }4.2 标定方法:仿真里如何建立 ADC 值与电阻值的映射表
仿真里的元件参数都是理想值,看起来直接套公式就行。但真正的板子上,采样电阻 1 欧可能实际是 1.05 欧,恒流基准 0.5V 可能实测是 0.49V,这些误差乘以放大倍数后会形成可观偏差。常见的做法是标定而不是修正硬件——用一组已知阻值的精密电阻去测,记录 ADC 值,然后建立映射表或拟合曲线。
在仿真里做标定的好处是可以随时改参数重新跑。我建议先跑一遍理想标定,然后把 INA128 的增益电阻改成非标称值,比如把 50k 换成 48k 模拟误差,再看标定表能不能把误差纠回来。
标定数据的典型记录格式:
标称值(欧) ADC值 计算值(欧) 误差(%) 1 24 1.04 4.0 2 51 2.06 3.0 5 127 5.09 1.8 10 254 10.18 1.8误差从 4% 到 1.8% 递减,说明低阻区间的偏差来源主要是接触电阻和导线压降——在高阻区间这些固定误差占比下降,误差率就变小。
4.3 两点校准与最小二乘拟合实战
映射表方式直观,但表是离散的,插值计算会引入新的误差。更优雅的方案是标定时把 ADC 值和真实电阻值做线性回归,拟合出一条直线 R = k * ADC + b,然后把 k 和 b 存进单片机。
我用最小二乘法计算 k 和 b 的公式:
- k = (N * Σ(x*y) - Σx * Σy) / (N * Σ(x²) - (Σx)²)
- b = (Σy - k * Σx) / N
其中 x 是 ADC 值,y 是用高精度万用表测出的真实电阻。在 Proteus 里可以用数据表手动完成这个计算,也可以用 Excel 的 LINEST 函数核对。得到 k 和 b 后写入 51 的 code 区,运行时直接调用:
code float K_GAIN = 0.402f; code float B_OFFSET = -0.012f; float get_resistance(unsigned int adc_val) { return K_GAIN * (float)adc_val + B_OFFSET; }这段代码把原先的物理公式换算整个替换成了线性拟合公式。K_GAIN 是从标定数据拟合出来的,B_OFFSET 用于修正零点偏移。实际应用中,B_OFFSET 如果算出来是个很大的负数,说明恒流源没有完全关断或者差分放大器有较大的失调电压,这时候不是靠软件能完全纠回来的,要回过去查电路。
4.3.1 仿真的一个关键场景:用标定表验证开尔文结构是否失效
把 R_contact1 从 0 改到 1 欧,跑标定流程,观察 k 和 b 的变化。如果 k 变化明显,说明恒流源回路的接触电阻影响了电流值,这是预期的——恒流源的负载变了,电流必须重新稳定。如果 b 变化超过 0.1,就要怀疑电压采样回路串入了电阻,也就是开尔文结构在版图上被破坏了。仿真时用探针分别检查 INA128 输入引脚的对地电压,如果两个引脚之间的差值不等于 I_const × R_x,那问题一定出在采样回路本身。
5. 量程切换与显示模块:CD4052 和 LCD1602 的协同逻辑
5.1 量程自动切换:什么时候切,切换后做什么
电阻测量的老问题是动态范围。恒流 50mA 时测 1 欧电阻没问题,测 10k 电阻时电压高达 500V,直接击穿整个前端。所以量程切换的本质是切换恒流源电流大小和放大增益的配对关系。
常见的双量程方案是:
- 小电阻量程:恒流 50mA,增益 1,适用 0.01 到 10 欧
- 中电阻量程:恒流 2mA,增益 10,适用 10 到 500 欧
- 大电阻量程:恒流 50uA,增益 100,适用 500 到 10k 欧
CD4052 的地址位由 P1.1/P1.2 控制,切换动作必须在恒流源关闭状态下进行。因为模拟开关在导通瞬间会有一个短暂的阻抗波动,如果此时恒流源还在工作,会在采样电阻上产生一个尖峰脉冲,轻则读数异常,重则把 INA128 的输出打到电源轨,之后恢复需要很长时间。
void set_range(unsigned char range) { CC_EN = 0; // 先关恒流源 delay_ms(5); // 等待模拟前端放电完成 P1_1 = range & 0x01; P1_2 = (range >> 1) & 0x01; delay_ms(2); // 等待 CD4052 通道切换稳定 CC_EN = 1; // 重新开启恒流源 delay_ms(10); // 电流稳定后再采样 }这个函数的顺序不能错:关闭恒流源、切换通道、重新开启、等待稳定。如果 switch 和 delay 的顺序调反,CD4052 的导通电阻在切换瞬间的跳变会直接反应到 ADC 输出上。
5.2 LCD1602 显示驱动与数值格式化
LCD1602 的显示逻辑不复杂,但要注意写入时序:初始化时先等 15ms 以上,然后连续写入 0x30 三条指令,最后设置功能、显示开关和清屏。Proteus 仿真里 CPU 跑得比时序要求快得多,不会出问题,但如果是实机调试,必须确认忙标志位 BF 读到 0 才能继续写。
数值格式化有几个容易踩的坑:
- sprintf 在 51 上非常耗资源,Keil 里默认的小型 printf 不支持浮点数,需要手动把浮点拆成整数和小数部分
- 电阻值跨度大,显示精度要按量程动态调整:小量程显示 3 位小数,大量程显示 1 位小数
void display_resistance(float resistance) { unsigned long int_part; unsigned int frac_part; char buffer[17]; if (resistance < 10.0f) { int_part = (unsigned long)resistance; frac_part = (unsigned int)((resistance - int_part) * 1000); sprintf(buffer, "R=%lu.%03u Ohm", int_part, frac_part); } else { int_part = (unsigned long)resistance; frac_part = (unsigned int)((resistance - int_part) * 100); sprintf(buffer, "R=%lu.%02u kOhm", int_part, frac_part); } lcd_write_string(0, buffer); }注意这个函数里如果 resistance 大于 10,显示单位是 kOhm 但 int_part 没有除以 1000,这是一个故意留出的逻辑错误标记——实际使用中要先把电阻值按量程换算成带单位的数值再传给显示函数,避免把 12345 欧显示成 12345 kOhm 这种灾难。
5.3 串口输出与虚拟示波器联动
仿真时用 LCD 看最终数值没问题,但如果要观察恒流建立过程和 ADC 采样的毛刺,LCD 无能为力。Proteus 里搭载虚拟示波器(VIRTUAL INSTRUMENTS 面板)可以直接看 INA128 输出端的波形。
建议在代码里增加一个调试开关:通过串口把每次滤波后的 ADC 原始值和换算后的电阻值发送到 COMPIM 虚拟串口,用 PC 端的串口助手接收。这样能在不打断主流程的情况下观察数据变化趋势。
void debug_output(unsigned int adc_val, float resistance) { SBUF = adc_val >> 8; while (!TI); TI = 0; SBUF = adc_val & 0xFF; while (!TI); TI = 0; }这个函数把 ADC 值拆成高低字节从串口发出。配合上位机读数和记录,可以看到仿真过程中接触电阻变化时 ADC 值的响应曲线。电压导线的干扰源在仿真里很难建模,串口数据能帮你判断软件滤波的参数是不是合理。
6. 仿真排错的 4 个高频问题与最终验证方法
6.1 恒流源电流起不来或者漂移
现象是 INA128 输出电压始终接近 0 或者逐渐增大停不下来。先查 TL431 的 REF 端电压是否为稳定的 0.5V——如果这个电压在跳变,说明基准分压电阻的接地点和恒流源的功率地没有分开,回流电流串进了基准地。仿真里把接地符号分开成 AGND 和 PGND 两个网络,然后用 0 欧电阻单点连接,基本能解决。
电流漂移还有一个常见来源:2N2222 的基极电流从运放输出取电,运放的输出电流能力有限,如果恒流电流超过运放的驱动上限,基极电压就会掉下去。实测运放在开环状态下输出 20mA 没问题,超过 50mA 就开始软。所以恒流电流要控制在运放驱动能力的三分之一以内。
6.2 ADC 读数乱跳,滤波也压不住
优先怀疑地线布局。Proteus 仿真里所有地都是同一个网络,不存在实机的地线噪声问题,这时候读数跳大概率是信号源本身的问题。把虚拟示波器接到 INA128 输出端,观察波形是否干净。如果出现高频振铃,在输出端和地之间并联一个 10nF 电容,截止频率大约在 1.6kHz,对慢变信号没有影响。
如果示波器波形干净但 ADC 输出还是跳,那问题就在时序上。检查 EOC 引脚是不是真的拉了低电平——Proteus 里 ADC0809 的 EOC 有时不按手册工作,如果仿真模型有缺陷,可以直接用 74HC00 搭一个延时替代 EOC 信号。用延时替代的好处是仿真跑得慢一点,但逻辑完全可控。
6.3 量程切换后读数整体偏差一个固定比例
这种情况是增益电阻的值和理论值对不上。CD4052 的导通电阻约 100 到 200 欧,如果 R_G 取值较小(比如 500 欧),开关电阻占了接近三成,增益公式直接失效。解决方法是把 R_G 的阻值选大,至少是开关导通电阻的 100 倍以上。如果增益精度要求高,可以改成每个量程用独立的继电器或者直接用 INA128 在仿真里换成理想运放模型。
6.4 最终验证方法:虚拟探针对照与误差曲线确认
一篇仿真项目的验收,不是看 LCD 显示的值对不对,而是看误差曲线的形态。方法是在 Proteus 里做参数扫描:把被测电阻从 0.1 欧扫到 100 欧,记录每个点的显示值和理论值,计算相对误差。
- 如果误差线平直,说明系统误差是常数,线性拟合修正即可
- 如果误差线呈 U 形,说明低阻端受接触电阻影响,高阻端受 ADC 量化噪声影响,需要分别处理
- 如果误差线没有规律,先怀疑量程切换逻辑,再怀疑滤波代码丢掉了有效数据
对于低阻端误差,可以做末端校准:将恒流源的两个电流端子短接,此时测到的电压除以电流就是引线电阻的等效值,软件保存这个值并在后续测量中减去。对于高阻端误差,增大采样次数和滤波深度,用 16 次采样替代 8 次,标准差通常能减半。
验证的最后一步是看恒流源开启前后的读数变化。理论上 P1.0 拉高前 ADC 输出应该是 0,如果此时读到非零值,说明差分放大器的失调电压没有调零,需要在软件里加入一个零点采样流程:恒流源关闭时采一次 ADC 值作为 base_offset,每次测量结果减掉这个值。这就是开尔文测量完整落地的最后一块拼图——理论电路决定了测量上限,而软件补偿决定你是否真正达到了这个上限。
本文还有配套的精品资源,点击获取