
简介这份资源是面向嵌入式初学者与电子设计爱好者的Proteus仿真工程围绕基于STM32F103的数字万用表展开帮助读者在虚拟环境中完成从电路搭建到固件调试的完整实践。压缩包共1020个文件约14.29MB以558个C源文件与243个头文件为主体配合51个汇编文件、28个链接脚本及若干工程配置与仿真工程文件覆盖ADC采集、DAC参考电压、LCD显示驱动、测量算法与用户交互等模块并附带Keil与IAR相关工程文件便于直接编译与仿真验证。资源已有3088人学习下载适合希望掌握STM32外设编程、HAL/LL库使用及Proteus联合仿真的读者可据此理解数字万用表在电压、电流、电阻测量中的数据处理流程与低功耗设计思路快速积累嵌入式产品开发经验。1. 从一块“测不准”的板子说起为什么数字万用表适合拿STM32F103练手很多同学做毕设或课设时第一反应是选一个“看起来高级”的题目结果卡在传感器驱动或者上位机通信上最后只能草草收场。数字万用表这个题目恰恰相反它足够经典需求边界清晰但真要把电压、电流、电阻、通断这几项测准并且用Proteus仿真跑通里面涉及的分压、分流、信号调理、ADC采样、量程切换、显示刷新每一个环节都能拉开差距。STM32F103作为主控资源刚好够用——12位ADC、多路GPIO、定时器、USART价格和资料门槛都友好配合Proteus仿真不用焊板子就能把原理图、PCB思路和固件逻辑全部验证一遍。这套方案适合正在做测控类、仪器仪表类毕设的学生也适合想补一块“从模拟前端到数字显示”完整链路的工程师。接下来我会按需求、架构、关键模块、避坑、验收的顺序把这份仿真方案拆开讲清楚。2. 需求分析与总体架构四类测量、三个层次、一条数据流2.1 功能需求与非功能约束数字万用表的核心需求可以拆成四类测量直流电压、直流电流、电阻、通断。交流测量在仿真阶段通常先不做因为Proteus里交流源和真有效值转换的模型不够直观强行加进去容易把仿真时间拖长也偏离“数字万用表基础功能”这个主线。非功能约束里最关键的是量程切换和采样精度。STM32F103的ADC是12位参考电压3.3V理论分辨率是3.3V/4096≈0.8mV但实际有效位数受噪声和参考源影响通常能做到10位左右稳定也就是约3mV。这个精度对于课设级别的万用表够用但前提是前端分压和分流电阻要用高精度、低温漂的型号仿真里至少要把阻值设准。另一个约束是显示刷新率。如果每次采样都刷新LCD屏幕会闪而且人眼也跟不上。通常的做法是每200ms更新一次显示中间用定时器做多次采样取平均。这个细节在需求阶段就要定下来不然后面调显示的时候会反复改。2.2 三层架构模拟前端、主控、人机交互整个系统按三层划分。第一层是模拟前端负责把被测信号转换成0~3.3V范围内的电压送给ADC。电压测量用精密电阻分压电流测量用采样电阻加运放放大电阻测量用恒流源加电压采集。第二层是STM32F103主控负责ADC采样、量程判断、数值换算、通断判断。第三层是人机交互包括LCD1602或OLED显示测量值和单位按键切换模式蜂鸣器做通断提示。数据流是单向的被测信号→模拟前端→ADC→主控换算→显示。没有复杂的反馈环路所以架构上不需要RTOS裸机加定时器中断就能跑得很稳。我一般会用一个1ms的定时器做时间基准每200ms触发一次采样和刷新中间的时间用来处理按键扫描和蜂鸣器逻辑。2.3 关键器件选型与Proteus模型对应主控选STM32F103C8T6Proteus里对应的是STM32F103C6或C8模型注意仿真模型的主频和Flash大小可能和实物有差异但外设寄存器行为基本一致。运放选LM358Proteus里有成熟模型单电源供电适合做电流采样放大。模拟开关用CD4051或CD4052做量程切换仿真里可以直接用继电器模型替代但继电器切换时有机械延迟仿真里要加延时否则ADC会采到切换瞬间的抖动。显示部分LCD1602在Proteus里模型稳定但占用IO多OLED I2C模型在仿真里偶尔会丢包如果时间紧优先用LCD1602并口模式。蜂鸣器用Proteus里的SOUNDER模型给方波就能响频率设2kHz左右比较接近实际。提示Proteus仿真STM32时ADC输入阻抗和实物有差异分压电阻的阻值不要选太大否则仿真里读数会偏低。通常分压电阻选100kΩ以内采样电阻选1Ω以下。3. 模拟前端设计分压、分流、恒流源与量程切换3.1 电压测量精密分压与输入保护电压测量是万用表最基础的功能。STM32的ADC输入范围是0~3.3V要测更高的电压必须分压。假设要测0~30V直流电压分压比就是30/3.3≈9.09。选R1900kΩR2100kΩ分压比正好10:1满量程30V时ADC端得到3V留了0.3V余量。这里有个血泪经验分压电阻的精度直接决定测量精度仿真里用理想电阻看不出问题但实物上1%精度的电阻在30V档会带来±0.3V的误差。所以仿真阶段就要养成习惯把电阻容差设成1%甚至0.5%提前看误差范围。输入保护也不能省。ADC引脚前面加一个3.3V稳压二极管再串一个1kΩ限流电阻防止输入过压烧片。Proteus里虽然没有真实的烧片效果但加上保护电路能让原理图更完整答辩时也经得起问。// 电压换算示例假设12位ADC参考电压3.3V分压比10:1 #define ADC_REF 3.3f #define ADC_RES 4096.0f #define DIV_RATIO 10.0f float get_voltage(uint16_t adc_raw) { float v_adc (adc_raw / ADC_RES) * ADC_REF; // ADC引脚电压 float v_in v_adc * DIV_RATIO; // 实际输入电压 return v_in; }这段代码里adc_raw是ADC读取的原始值v_adc是引脚上的电压v_in是分压前的实际电压。注意浮点运算在STM32F103上没有硬件FPU频繁调用会拖慢速度实际项目里我会用定点数或者查表法优化但仿真阶段用浮点更直观。3.2 电流测量采样电阻与运放增益电流测量需要串联一个采样电阻把电流转换成电压。假设要测0~1A电流采样电阻选0.1Ω满量程时压降0.1V。这个电压太小直接给ADC分辨率不够所以要用运放放大。LM358接成同相放大增益设为30倍0.1V放大到3V正好覆盖ADC量程。放大倍数由反馈电阻决定G1Rf/Rg。选Rf29kΩRg1kΩ增益30倍。这里要注意LM358的输入失调电压仿真里可以设成0但实物上几毫伏的失调经过30倍放大就是几十毫伏的误差。所以仿真时可以在运放输入端加一个小的失调电压源提前看误差有多大。// 电流换算示例采样电阻0.1Ω运放增益30倍 #define R_SHUNT 0.1f #define OP_GAIN 30.0f float get_current(uint16_t adc_raw) { float v_adc (adc_raw / ADC_RES) * ADC_REF; float v_shunt v_adc / OP_GAIN; // 运放输入端的电压 float current v_shunt / R_SHUNT; // 实际电流 return current; }这段代码的逻辑是反推先算ADC电压除以增益得到采样电阻上的压降再除以采样电阻得到电流。参数R_SHUNT和OP_GAIN要和硬件设计一致改硬件的时候这两个宏必须同步改否则读数会错得离谱。3.3 电阻测量恒流源方案与比例法电阻测量有两种常见方案恒流源法和分压法。恒流源法用运放搭一个恒流源给被测电阻注入已知电流测两端电压算电阻。分压法更简单用一个已知参考电阻和被测电阻串联测分压点电压通过比例算未知电阻。仿真阶段我推荐分压法因为不需要额外的恒流源电路元件少调试直观。假设参考电阻R_ref1kΩ被测电阻Rx串联后接3.3V。ADC测Rx上的电压Vx则RxVx/(3.3-Vx)*R_ref。这个公式在Rx接近R_ref时灵敏度最高所以量程切换就是切换不同的R_ref。比如200Ω档用200Ω参考电阻2kΩ档用2kΩ20kΩ档用20kΩ。量程切换用CD4051模拟开关STM32的GPIO控制通道选择。// 电阻换算示例分压法参考电阻R_ref float get_resistance(uint16_t adc_raw, float r_ref) { float v_x (adc_raw / ADC_RES) * ADC_REF; if (v_x ADC_REF - 0.01f) return 999999.0f; // 防止除零 float rx (v_x / (ADC_REF - v_x)) * r_ref; return rx; }注意v_x接近参考电压时分母趋近于零算出来的电阻会溢出。所以加一个判断超过量程就返回一个极大值显示“OL”表示超量程。这个细节在答辩时经常被问到提前处理掉能省很多解释。3.4 量程切换逻辑与CD4051控制量程切换的核心是“自动”还是“手动”。课设级别我建议做手动加自动混合默认自动根据读数判断是否超量程或欠量程自动切到合适的档位同时保留按键手动切换方便演示。自动切换的逻辑用状态机实现每200ms检查一次当前读数如果超过满量程的90%就升档低于10%就降档中间加一个迟滞区间防止频繁切换。CD4051的控制很简单三个GPIO选通道对应八个量程。仿真里CD4051的导通电阻约100Ω会在分压电路里引入误差所以分压电阻不能选得太小否则导通电阻的影响会变大。通常分压电阻选kΩ级别100Ω的导通电阻影响在1%以内可以接受。注意Proteus里CD4051的模型切换时间设成0但实物有几十纳秒的切换时间仿真里如果切换后立刻采样可能会采到旧值。稳妥的做法是切换后延时1ms再采样。4. 主控固件设计ADC采样、滤波、换算与显示刷新4.1 ADC多通道扫描与DMA搬运STM32F103的ADC1有多个通道电压、电流、电阻测量分别接不同的通道。用扫描模式加DMA可以让ADC自动按顺序转换转换结果直接搬到内存数组CPU不用干预。配置步骤RCC使能ADC1和DMA1时钟GPIO设成模拟输入ADC设成扫描模式、连续转换、外部触发关闭DMA设成循环模式、半字宽度。// ADC多通道DMA配置示例简化版 void adc_dma_init(void) { RCC-APB2ENR | RCC_APB2ENR_ADC1EN; RCC-AHBENR | RCC_AHBENR_DMA1EN; // PA0: 电压通道, PA1: 电流通道, PA2: 电阻通道 GPIOA-CRL ~(0xFFF); // 清0 GPIOA-CRL | 0x000; // 模拟输入 ADC1-SQR1 0; // 3个转换 ADC1-SQR1 | (2 20); // 规则序列长度3 ADC1-SQR3 (0 0) | (1 5) | (2 10); // 通道0,1,2 ADC1-CR2 | ADC_CR2_DMA | ADC_CR2_CONT; ADC1-CR2 | ADC_CR2_ADON; DMA1_Channel1-CPAR (uint32_t)ADC1-DR; DMA1_Channel1-CMAR (uint32_t)adc_values; DMA1_Channel1-CNDTR 3; DMA1_Channel1-CCR DMA_CCR_CIRC | DMA_CCR_MINC | DMA_CCR_PSIZE_16; DMA1_Channel1-CCR | DMA_CCR_EN; }这段代码配置了三个通道的循环扫描adc_values数组里会依次存放电压、电流、电阻的原始值。DMA循环模式意味着不需要手动重启ADC会一直转DMA会一直搬。注意ADC_CR2_CONT是连续转换如果设成单次每次都要软件触发反而麻烦。4.2 滑动平均滤波与中值滤波组合ADC原始值一定有噪声直接换算显示会跳得厉害。我一般用“中值滤波滑动平均”的组合先连续采5次去掉最大最小剩下3次取平均再把最近10次的结果做滑动平均。这样既能滤掉脉冲噪声又能平滑随机噪声。计算量不大STM32F103跑72MHz完全够用。// 中值滑动平均滤波 #define SAMPLE_NUM 5 #define AVG_NUM 10 uint16_t filter_adc(uint8_t ch) { uint16_t buf[SAMPLE_NUM]; for (int i 0; i SAMPLE_NUM; i) { buf[i] adc_values[ch]; delay_us(10); } // 冒泡排序取中间值 for (int i 0; i SAMPLE_NUM - 1; i) for (int j 0; j SAMPLE_NUM - 1 - i; j) if (buf[j] buf[j1]) { uint16_t t buf[j]; buf[j] buf[j1]; buf[j1] t; } static uint16_t avg_buf[AVG_NUM] {0}; static uint8_t idx 0; avg_buf[idx] buf[SAMPLE_NUM/2]; idx (idx 1) % AVG_NUM; uint32_t sum 0; for (int i 0; i AVG_NUM; i) sum avg_buf[i]; return sum / AVG_NUM; }这段代码里SAMPLE_NUM是每次滤波的采样次数AVG_NUM是滑动窗口长度。参数越大越平滑但响应越慢。200ms刷新周期下5次采样加10次滑动平均响应时间大约1秒对于万用表来说可以接受。如果测通断需要更快响应可以单独走一条快速通道不经过滑动平均。4.3 数值换算与单位自动切换换算部分前面已经给了电压、电流、电阻的公式这里补充单位自动切换。比如电压读数0.05V显示“50.0mV”1.5V显示“1.500V”25V显示“25.00V”。逻辑是根据数值大小选单位和小数点位置用查表法实现最简洁。// 电压单位自动切换 void display_voltage(float v) { if (v 1.0f) { lcd_printf(%.1fmV, v * 1000); } else if (v 10.0f) { lcd_printf(%.3fV, v); } else { lcd_printf(%.2fV, v); } }这段代码里小于1V显示毫伏1~10V显示三位小数10V以上显示两位小数。小数点位置和单位一起变看起来更专业。注意lcd_printf是自己封装的LCD打印函数不是标准库的printf避免引入浮点打印的巨大开销。4.4 LCD1602驱动与刷新策略LCD1602用4位或8位并口模式8位占用IO多但速度快4位省IO但驱动复杂一点。仿真里我推荐8位模式因为Proteus的LCD1602模型对时序要求不严8位模式写起来简单。刷新策略是每200ms更新一次显示内容不要每次ADC转换都刷否则屏幕会闪。// LCD1602 8位模式写命令 void lcd_write_cmd(uint8_t cmd) { LCD_RS 0; LCD_RW 0; LCD_DATA cmd; LCD_EN 1; delay_us(1); LCD_EN 0; delay_ms(2); } // 写数据 void lcd_write_data(uint8_t data) { LCD_RS 1; LCD_RW 0; LCD_DATA data; LCD_EN 1; delay_us(1); LCD_EN 0; delay_us(50); }LCD_RS是命令/数据选择LCD_RW是读写选择LCD_EN是使能脉冲。延时参数根据LCD1602手册命令延时2ms数据延时50us。仿真里可以缩短但实物上必须满足所以代码里保留标准延时方便直接移植。5. 避坑与常见问题排查仿真能跑通不代表实物能跑通5.1 ADC读数跳动大显示值不稳定现象LCD上的电压读数最后一位一直跳比如显示“1.234V”和“1.235V”来回变。原因通常是参考电压不稳或模拟输入阻抗太高。STM32F103的ADC参考电压直接取自VDDA如果VDDA和VDD之间有噪声读数就会跳。解决方法是硬件上在VDDA引脚加100nF和10uF电容软件上增加滤波次数。仿真里可以把参考电压源设成理想3.3V但实物上必须处理。5.2 量程切换后读数错误超量程不显示OL现象从30V档切到3V档读数还是按30V档的分压比算导致显示值偏小。原因是量程切换后没有同步更新换算系数。解决方法是把分压比、采样电阻、参考电阻这些参数做成数组量程切换时同时切换参数索引。代码里用一个range_index变量换算函数根据索引查表。5.3 运放输出饱和电流档始终显示满量程现象电流测量时无论实际电流多大ADC读数都接近4095。原因是运放增益太高输入失调电压被放大后饱和。解决方法是降低增益或者在运放输入端加调零电路。仿真里可以先把增益降到10倍看是否正常再逐步调高。实物上LM358的失调电压最大7mV30倍增益就是210mV接近ADC量程的6%必须考虑。5.4 Proteus仿真速度慢ADC采样卡顿现象仿真运行时LCD刷新很慢按键响应迟钝。原因是Proteus对STM32的指令级仿真速度有限浮点运算和频繁中断会拖慢仿真。解决方法是减少浮点运算把换算改成定点数降低ADC采样频率从1kHz降到100Hz关闭不用的外设时钟。仿真阶段优先保证逻辑正确速度可以妥协。5.5 通断判断阈值设得太死蜂鸣器时响时不响现象测通断时电阻在几十欧姆附近蜂鸣器断断续续。原因是阈值设成固定值没有迟滞。解决方法是设两个阈值低于10Ω判定为通高于20Ω判定为断中间保持上一次状态。这样电阻在阈值附近波动时蜂鸣器不会频繁切换。提示通断判断的响应速度比精度更重要所以通断通道不要经过滑动平均滤波直接读原始值判断响应时间控制在50ms以内。6. 验收与答辩怎么证明你的万用表“测得准”验收分三步功能验收、精度验收、稳定性验收。功能验收看四项测量是否都能正常显示量程切换是否顺畅通断蜂鸣器是否响应。精度验收用Proteus里的理想源做基准比如给一个10.00V电压看显示值是否在9.95~10.05V之间给一个100Ω电阻看显示是否在99~101Ω之间。稳定性验收连续运行30分钟看读数是否漂移LCD是否花屏。答辩时老师最常问三个问题分压电阻怎么选的ADC精度怎么保证的量程切换会不会引入误差第一个问题答“根据满量程和ADC参考电压算分压比留10%余量”第二个答“12位ADC理论分辨率0.8mV加中值滤波和滑动平均后有效位数约10位误差在1%以内”第三个答“CD4051导通电阻100Ω分压电阻选kΩ级影响小于1%切换后延时1ms再采样”。我一般会在答辩前做一张误差对照表把每个量程的实测值和理论值列出来误差超过2%的档位重点解释原因。这张表比任何PPT都管用老师一看就知道你真的调过。// 误差计算示例 float error_percent(float measured, float reference) { return (measured - reference) / reference * 100.0f; }measured是显示值reference是标准源的值返回值是百分比误差。正数表示偏大负数表示偏小。答辩时把每个量程的误差算出来列成表格一目了然。从那以后我每次做仿真项目都会在验收前把每个量程的误差表跑一遍不跑完不写报告。这个习惯帮我省了很多返工的时间。希望帮到你。本文还有配套的精品资源点击获取