
简介51单片机作为嵌入式学习与工业控制中的经典芯片结合电流检测能有效实现过流告警、负载监测等常见功能在课程设计和毕业设计中应用广泛。这份Protues仿真实例面向单片机初学者与电子类专业学生提供了一套无需真实硬件即可运行的51单片机电流检测完整仿真工程覆盖电流采样、A/D转换、数据处理和阈值报警等关键环节。压缩包共12个文件约30KB包含Protues工程文件DSN、Keil C语言程序C、编译输出文件HEX、OBJ、LST以及工程配置文件Uv2、Opt、Plg、M51等打包了从电路搭建、源码编写到编译仿真的全部素材解压后可直接打开仿真验证。目前已有578人浏览学习说明该实例在同类资源中具备一定的参考价值。通过该实例可以直观理解霍尔效应等电流传感器将电流信号转换为电压信号再由51单片机A/D转换器读取和计算的完整链路同时也能学习到Keil工程创建、元件选型、参数设置与Protues联调等实操细节适合用来对照练习、快速复现实验或为后续扩展双路电流检测、串口上传等功能提供可移植的模板。1. 用 Proteus 跑 51 单片机电流检测先把仿真思路立起来很多人第一次看到“Protues仿真实例-51单片机-电流检测”这个文件名第一反应是打开Proteus放一个直流电流表看表头读数。但一个能交作业的电流检测仿真不是让你看表而是让单片机自己把电流大小“读”回来电流流过采样电阻产生电压这个电压被放大后送给ADC单片机读回数字量再换算成安培数显示到LCD上。Protues只是Proteus的常见笔误这在下载包里很常见不用纠结。这条链路里最难的不是程序而是“采样电阻、放大倍数和量程怎么配”。很多人把仿真跑完程序也正常就是显示值跟表头对不上原因就是电阻分压和ADC参考电压没算清楚。这里按一个最常见、最可靠的仿真方案来讲51单片机 采样电阻 LM358 ADC0832 LCD1602。适合51单片机课程设计也适合想搞明白电流检测信号链的新手工程师。2. 电流检测的采样原理与 Proteus 元件选型2.1 采样电阻法为什么最适合仿真电流检测有三条常规路线霍尔传感器、电流互感器和采样电阻。霍尔电流传感器需要磁芯和调理电路Proteus里的模型不像真实芯片那样好配电流互感器适合交流大电流低频直流根本测不了。51单片机课程设计里测的通常都是低压直流回路采样电阻法是物理上最直观、仿真里最好配的。采样电阻法就是在电流回路里串一个小电阻电流流过电阻后产生电压降这个压降和电流成正比测电压就等于测电流。如果一个0.1Ω电阻流过1A电流两端电压是0.1V这个电压太小直接送ADC分辨率不够所以要先经过运放放大到接近ADC参考电压然后交给单片机。这就是“采样电阻运放ADC”的结构。低侧检测和高侧检测的区别也要明白。低侧把采样电阻放在负载的接地端电阻对地电压接近0运放电路简单高侧把采样电阻放在电源正极端电阻两端都有较高共模电压需要差分放大器。Proteus仿真和实际电路都建议先用低侧等调通了再改高侧。2.2 Proteus 里搭电流检测电路的元件清单下面这张表是搭这个电路时常用的元件表关键词和参数都列好直接在拾取时搜就行。作用Proteus关键词参数说明主控AT89C5112MHz晶振51最小系统会自动复位采样电阻RES0.1Ω功率选大一点仿真没影响可变负载POT10k可调仿真里被当作电位器变阻运放LM358单电源5V双运放只用其中一路ADCADC08328位串行3线控制时序简单稳压源DC POWER5V主电源给单片机和运放供电显示LM016L16x2Proteus里面叫LM016L电流表DC AMMETER-用来验证仿真结果这里特别注意两个坑。第一POT在Proteus里是电位器不是固定电阻点击上下箭头能改变阻值用来模拟负载变化。第二采样电阻阻值不能拍脑袋0.1Ω适合2A级量程如果手头的例子是用1Ω电阻做小电流毫安级检测那负载和电源电压要跟着改否则电阻压降会让负载端电位直接丢一半。2.3 用 INA219 还是用 ADC采样电阻仿真里的取舍很多人在搜INA219电压电流检测想用I2C接口的电流检测芯片。这个方案在硬件上精度好但在Proteus仿真里你要写完整的I2C底层时序、读寄存器、换算数据容易把真实目的带偏。ADC0832只需要CS、CLK、DI/DO三根线逻辑简单量程也够用。仿真阶段把ADC0832跑通后面要换INA219时采样电阻和放大倍数的设计逻辑完全不变变的只是接口读写。选ADC0832还有一个原因它是8位串行ADC51单片机可以直接用普通I/O模拟时钟时序。相比并行ADC少占用8个引脚程序也好调。下面这段Python算一下采样电阻和放大倍数怎么选先解决量程问题I_max 2.0 # 要测的最大电流单位 A R_shunt 0.1 # 采样电阻单位 Ω V_ref 5.0 # ADC 参考电压单位 V s_v I_max * R_shunt # 0.2 V gain_max V_ref / s_v # 25 倍 print(f采样电压 {s_v} V) print(f最大放大倍数 {gain_max:.1f})这段代码先算出最大电流时采样电阻上的压降再用ADC参考电压除以压降得到运放最大放大倍数。比如2A配0.1ΩVref是5V最大只能放大25倍。实际工程里我会留20%余量取20倍以内这样万一电流超一点ADC也不会早早进满量程截断。如果要测200mA小电流0.1Ω压降只有0.02V放大25倍后也只有0.5VADC分辨率浪费大半这时就把采样电阻换成1Ω压降变大信噪比也好。这就是为什么采样电阻和放大倍数要成对调整。3. 在 Proteus 中搭出 51 单片机电流检测电路3.1 最小系统与仿真工程初始化Proteus画51电路最快的方式不是从零开始拖然后接一堆电阻而是先放AT89C51再放一个复位电路和一个电源终端。具体步骤新建Design在工具栏点Component Mode搜索AT89C51并放置双击芯片把Clock Frequency改成12MHz接着从Terminal Mode选择Power和Ground给40脚VCC接电源、20脚GND接地。复位电路用一个10μF电解电容和10kΩ电阻把RST引脚接到电容正极和电阻一端的交点电阻另一端接地这样上电时RST先高后低单片机才正常启动。在Proteus里做51单片机仿真P0口必须接一个排阻上拉否则P0输出高电平驱动不了LCD显示。我一般会用一个RESPACK-8排阻公共端接VCC8个引脚分别接P0.0-P0.7。这一步是Proteus和真实单片机最不一样的地方真实板子上P0默认开漏仿真里不加也会不稳定。最小系统搭完先放一个LED在P1口跑一个点灯程序确认系统活了再往后走。3.2 采样电阻 运放放大 ADC0832 的接线电流检测主回路这样接12V直流电源正极接负载用POT代替的一端负载另一端接采样电阻采样电阻下端接GND这样电流就从12V正极流经负载、采样电阻回到地。因为采用低侧检测采样电阻上端对地的电压就是我们要测的电压信号LM358的同相输入端接到采样电阻上端反相输入端直接接地运放接成同相比例放大电路。反馈电阻用20kΩ输入电阻用1kΩ放大倍数约为21倍。运放输出接到ADC0832的CH0ADC0832的CS、CLK、DI、DO分别接51单片机的P1.0-P1.3。具体引脚关系列在下表ADC0832 引脚51单片机引脚作用CSP1.0片选低电平有效CLKP1.1时钟信号由单片机产生DIP1.2配置输入DOP1.3数据输出CH0LM358 输出被测电压VCC5V供电GNDGND接地注意Proteus里ADC0832的DI和DO是分开的所以不用像网上有些图那样把两根线并在一起。如果你的模型只有一个数据脚那也可以并但这里用两引脚更省心。接到这里后先用直流电压表点一下LM358输出脚确认电位器从最小转到最大时运放输出在0V到接近5V之间变化如果超出了说明放大倍数偏大要减小反馈电阻。3.3 把电流值换算成二进制编码的公式ADC0832输出来的是一个8位二进制数范围0-255数值和电压是线性关系。假设ADC参考电压Vref5V那么读取到的电压V adc_val * 5 / 255。放大前的采样电压 V / Gain电流I 采样电压 / R_shunt。把三段合并得到完整电流公式I (adc_val * Vref / 255) / (Gain * R_shunt)写成C语言宏就是#define VREF 5.0f #define R_SHUNT 0.1f #define AMP_GAIN 21.0f #define ADC_TO_CURRENT(adc) ((adc) * VREF / 255.0f / (AMP_GAIN * R_SHUNT))有人问为什么不用乘法要连除因为这里没有可以合并的整数系数。如果用ADC0832的满量程对照一下adc255时V5V回推输入电压为5/21≈0.238V电流0.238/0.1≈2.38A说明这个方案在12V电源下可以测到2A以上。要换量程时改宏定义里的R_SHUNT和AMP_GAIN就行其他代码不用动。4. 51 单片机读取 ADC 并显示电流值的 Keil 代码4.1 主循环与 ADC 读取时序Keil工程里先定义引脚再用普通IO模拟时序读ADC0832。读函数按channel选择CH0或CH1代码里使用独立DI/DO引脚sbit ADC_CS P1^0; sbit ADC_CLK P1^1; sbit ADC_DI P1^2; sbit ADC_DO P1^3; unsigned char read_adc0832(unsigned char ch) { unsigned char i, dat 0; ADC_CS 0; ADC_CLK 0; ADC_DI 1; ADC_CLK 1; ADC_CLK 0; // 起始位 ADC_DI 1; ADC_CLK 1; ADC_CLK 0; // SGL1单端模式 ADC_DI ch; ADC_CLK 1; ADC_CLK 0; // ODDchCH0或CH1 ADC_DI 1; // 释放DI准备读DO for (i 0; i 8; i) { ADC_CLK 1; dat (dat 1) | ADC_DO; // 上升沿后读数据位 ADC_CLK 0; } ADC_CS 1; return dat; }这段时序的核心是先发送3位配置第1位启动位固定1第2位选择单端/差分模式固定1表示单端第3位选择通道ch为0则选CH0。发送完配置后ADC0832的DO开始在主时钟上升沿逐个输出8位数据最高位在前。Proteus模型对这个时序的宽容度比较高但如果你发现读出来的数一直在255或0附近抖动先查CLK线是不是连到P1.1了再查读数据的时刻有的模型需要在下降沿读。这里有几个参数值得注意ch取值只能是0或1大于1会读到错通道函数里dat初始为0每读一位向左移一次所以不要漏掉移位。返回的8位数据就是ADC原始值。4.2 电流换算与 LCD1602 显示拿到ADC值后用前面定义的宏换算成电流。因为要显示小数我用一个整型变量存储毫安值避免在单片机里频繁做浮点打印。具体做法是先扩大1000倍算成毫安再拆成整数部分和小数部分unsigned int current_mA (unsigned int)(ADC_TO_CURRENT(read_adc0832(0)) * 1000.0f); // 例如 0.63A - 630mA lcd_write_int(current_mA / 1000); lcd_write_char(.); lcd_write_int(current_mA % 1000); lcd_write_char(A);这块代码的逻辑是先用浮点位运算得到以安培为单位的电流值再乘1000转成整数毫安这样就能避开printf库和浮点格式化输出。注意current_mA % 1000如果不足3位会显示成6而不是006所以显示前要对商补零简单办法是判断小于100补0小于10补两个0。LCD1602的底层初始化函数和写数据函数用你手头现成的就行Proteus里的LM016L和真实LCD1602指令兼容。我没有在仿真里直接用%f因为C51编译器对大格式浮点支持很别扭函数库占空间不说仿真速度还会变慢。按毫安整数显示既满足课程设计的精度要求又不用动printf全家桶。如果要求显示两位小数就把倍数改成10000补零逻辑不变。4.3 仿真调试用虚拟终端观测数据LCD显示容易看出整体对不对但想精确地看转换曲线还是串口方便。在Proteus里给51单片机接一个Virtual Terminal通过P3.0和P3.1做UART输出。Keil中初始化串口后直接调用printf发送ADC值和毫安数void uart_init(void) { SCON 0x50; TMOD | 0x20; TH1 0xFD; // 9600bps 11.0592MHz TL1 0xFD; TR1 1; TI 1; } void main(void) { unsigned char adc; unsigned int ma; uart_init(); while (1) { adc read_adc0832(0); ma (unsigned int)(ADC_TO_CURRENT(adc) * 1000.0f); printf(ADC%d mA%d\r\n, adc, ma); delay_ms(200); } }这段代码里TH10xFD是针对11.0592MHz晶振的9600波特率如果前面最小系统用的是12MHz晶振串口频率会有误差虚拟终端能看到乱码。解决方法是不要把晶振改回去直接保留12MHz但把波特率重算成4800或者干脆在Proteus里把晶振改成11.0592MHz重新仿真代码不用动。P3.0和P3.1分别接虚拟终端的RXD和TXD注意交叉连接。5. 校准 Proteus 电流表与硬件实测的三点经验5.1 在 Proteus 里放置电流表验证仿真精度把DC AMMETER串到采样电阻和负载之间的支路上运行仿真旋转POT时记下电流表的安培数和LCD上显示的值对比。正常情况下误差应该来自放大倍数的小数位例如用21倍计算但实际电阻标称是20k和1k正好21倍偏差很小。如果发现测量值固定偏大或偏小优先级最高的是检查运放反馈电阻阻值其次是LCD补零逻辑是否把中间的小数位吞掉了。可以在虚拟终端同时打印ADC原始值和电流值对比电流表读数这样能快速区分是硬件接线错还是换算错。5.2 采样电阻的温漂与量程选择仿真里电阻是理想器件实际硬件里0.1Ω功率电阻温度升高后阻值会漂影响满量程精度。如果你要把仿真搬去比赛采样电阻要选低温漂的合金电阻放大倍数不要顶满计算值留20%裕量。量程也尽量往中段留电位器旋到大半时ADC值最好落在200左右不要每次都在250以上跑否则接近满量程时分辨率不够显示值会一跳一跳的。5.3 把仿真工程改造成可硬件下载的版本把Proteus里AT89C51换成STC89C52或AT89S52接线基本不变下载用STC-ISP。晶振建议换成11.0592MHz这样串口波特率才准LCD1602和ADC部分不用改。负载端要加一个功率电阻不能像仿真里那样直接用POT否则电位器会烧。烧录前把P1.0到P1.3测量一遍确认没有接反再上电看LCD第一行有没有稳定电流值如果没有先用万用表测LM358输出脚和ADC0832的CH0电压确保0到5V的变化确实送到了ADC前端。本文还有配套的精品资源点击获取