
简介基于单片机金属探测器设计通常从电磁感应原理出发涉及传感器选型、信号调理电路与单片机控制多个环节而 Proteus 仿真能够在实物焊接前验证电路和程序逻辑有效减少重复打板成本。资源包内含完整的 Proteus 仿真工程DSN、C 语言源码 main.c、Hex 烧录文件、RZ-51V2.8 开发板原理图 PDF 与实际运行截图共 17 个文件压缩包约 173KB同时保留了 Keil 工程文件、编译中间文件obj、lst、m51和 bak 备份方便直接打开工程查看电路连接、传感器接口与代码结构。对电子类课程设计、毕业设计或单片机入门者可借助仿真观察金属靠近时输出指示与报警的响应过程理解灵敏度调节、滤波处理和抗干扰设计的具体实现。设计资料将硬件原理图、程序源码和仿真验证集中在一起既适合快速学习也可作为二次开发的参考模板。目前已有 171 人学习下载体积小巧便于随时获取并快速复现。1. 基于单片机金属探测器Proteus仿真程序到底在解决什么拿到“基于单片机金属探测器Proteus仿真程序”这个标题先别急着找能吸起硬币的电磁铁。工程上的金属探测器往往在低功耗下工作探头只是一个空心线圈金属靠近时线圈的电感量或高频损耗发生变化单片机通过检测这个变化来判断有没有金属。你没有硬件探头时最难的不是写代码而是怎么在Proteus里把“金属靠近”这件事重演出来。最常见的做法是用NE555搭一个可调频率发生器来代替真实LC振荡器运行时转动电位器模拟金属接近再用51单片机的定时器测频率、做报警和显示。这个标题没有限定单片机型号但最容易在Proteus 8 Professional里完整复现的是AT89C51下面按这个组合展开。2. 金属探测器检测原理与单片机接口选型2.1 频率式与幅度式为什么选测频率金属探测器的前端电路可以输出两类可判读信号一类是振荡频率变化另一类是振荡幅度变化。频率式把探头线圈放进LC振荡回路金属靠近时等效电感变小、频率升高幅度式则利用金属在交变磁场中产生涡流消耗能量让振荡幅度回落。两种方式都能用但51单片机做频率式最顺定时器本身就是数字计数硬件把正弦波整形后方波接进T0即可不需要额外ADC芯片。为什么不用ADC检测幅度幅度式需要峰值检波、RC滤波和运放在Proteus里仿真这些模拟环节很容易因时间常数设置不当而出现纹波。更麻烦的是AT89C51没有内置ADC加ADC0832又要多画几根接线、多写一套SPI时序。频率式只关心方波的跳变沿计数结果稳定程序判据也干净。因此在课程设计里绝大多数Proteus金属探测器工程都采用“LC振荡器 LM393整形 单片机测频”的结构。本文后面统一按频率式处理。2.2 从LC振荡到单片机可读的方波LC振荡器输出的通常是正弦波幅度只有几百毫伏到几伏不能直接接51的I/O口。中间必须加一级比较器常见用LM393同相输入端接探头信号反相输入端接VCC/2参考电压输出端加上拉电阻到VCC。这样LM393输出就是与振荡信号同频的0~5V方波可以直接驱动P3.4引脚。实际硬件里比较器参考电压的高低会影响方波占空比但单片机外部计数只认下降沿占空比稍微偏离50%不会影响计数结果。Proteus里能不能直接画一个LC振荡器来当探头能但运行后你无法在屏幕上“放一块金属”让它自动反应。Proteus的SPICE模型不会把屏幕上的金属物体耦合到线圈里。这里我一般用NE555搭一个张弛振荡器替代探头频率公式为f1.44/((RA2RB)C)把RB的一部分换成电位器POT运行时用鼠标滚轮调节电位器阻值频率就会连续变化。这个频率变化的方向和幅度与实际金属靠近时的表现一致正好用来验证单片机程序。2.3 定时器分配与测频精度边界测频需要两个定时器配合T0作为外部计数器接收P3.4上的脉冲T1作为定时器产生50ms基准闸门。每50ms读一次T0计数寄存器20次累加后得到1秒内的总脉冲数也就是频率值分辨率1Hz。TMOD设置为0x15含义是T0方式1计数、T1方式1定时两者互不干扰。参数数值说明晶振12MHzT1定时基准TMOD0x15T0计数T1定时均方式1T1初值0x3CB0对应50ms中断闸门周期50ms中断内读T0增量软件闸门20次累计1秒得到频率频率上限约1.3MHz50ms内T0最大65535个脉冲报警阈值1000~5000Hz按静态频率1%~2%选择这个方案的好处是T0计数时可以完全不用中断只在T1中断里读TH0和TL0配合“差分计数”写法即使T0发生溢出用无符号减法自动回绕也能得到正确结果。需要优先保障的信号是P3.4的方波质量NE555输出本身是推挽结构不需要再整形。2.4 为什么Proteus适合先验证这套链路Proteus的优势在于模拟波形和数字逻辑在同一工程里实时可见。把虚拟示波器挂在NE555输出脚把频率计挂在P3.4LCD和蜂鸣器的动作随时同步。这样调试时能分清问题出在“前端没有起振”还是“后端计数程序没跑到”。另外程序在Keil中编译生成HexProteus直接加载后就能跑不用买开发板也不用反复烧Flash。这套验证流程对一个需要提交仿真工程或做实物前的风险评估来说都是低成本高反馈的路径。3. 在Proteus 8 Professional里搭建金属探测器仿真电路3.1 元件清单与参数表新建工程时模板选择Schematic Design单片机选AT89C51。元件选好后按下面表逐一放置注意NE555和POT的库名称在Proteus中可能有多个变体用POT-LIN最稳妥。Proteus库名称参数数量作用AT89C5112MHz晶振1主控NE555-1替代探头产生可调频率RES1kΩ2NE555振荡电阻POT-LIN10kΩ1调节频率模拟金属靠近CAP1nF1振荡电容CAP0.01μF1NE555控制端滤波RESPACK-8上拉排阻1P0口上拉LCD1602字符型1显示频率与阈值BUTTON轻触按键2基准频率、灵敏度设置LED-RED-1报警指示BUZZER直流蜂鸣器1报警输出放置LCD1602后把数据口D0~D7接到P0.0~P0.7控制口RS、RW、EN依次接P2.5、P2.6、P2.7。P0是开漏引脚不接上拉排阻会白屏或乱码这是仿真中最容易出现的问题。3.2 NE555振荡器连接与频率范围计算NE555按无稳态多谐振荡器接法8脚和4脚接VCC1脚接地5脚经0.01μF电容接地。7脚与VCC之间接1kΩ电阻RA7脚再串1kΩ固定电阻和10kΩ电位器接到2脚和6脚2脚与6脚短接对地接1nF电容。3脚是输出端直接接到AT89C51的P3.4。频率范围计算RA1kΩRB1kΩ0~10kΩC1nF。电位器阻值从最大调到最小时频率从约62.6kHz升到约480kHz。这个范围在T0的50ms计数上限之内又远高于50Hz工频干扰适合观察。实际运行时把鼠标移到POT上方按键盘上下箭头或滚动滚轮阻值变化后频率会立即改变。如果调了很久频率没反应检查电位器是否串在了7脚到2/6脚的充电通路上很多工程把POT滑动端悬空只焊了两个固定端导致RB恒为0。3.2.1 用虚拟示波器确认前端工作正常在主界面点击Virtual Instruments选择Oscilloscope把通道A探头接到NE555的3脚。运行仿真后应看到清晰的方波频率稳定在几十到几百kHz。若波形频率为0多半是NE555的5脚没有接地电容或电位器接线错误。虚拟示波器只是验证仪器不需要接入单片机电路不影响信号逻辑。3.3 单片机侧接线映射与调试连完振荡源后把所有外围器件接到单片机映射关系见下表信号源单片机引脚说明NE555 3脚P3.4/T0方波计数输入按键1P1.0 到GND按下记录当前频率为基准按键2P1.1 到GND循环调节灵敏度阈值LEDP2.0 通过1kΩ电阻到GND报警指示BUZZERP2.1 到GND报警输出LCD RSP2.5寄存器选择LCD RWP2.6读写选择接地只写LCD ENP2.7使能信号上拉排阻P0到VCC必须接否则LCD异常LCD的RW可以直接接地不用接P2.6但为了保持代码通用性这里仍用P2.6控制。蜂鸣器使用Proteus里的BUZZER元件不要用SOUNDER因为SOUNDER需要交流驱动信号直流电平不会响。3.4 加载Hex并运行仿真在Keil中编译上一篇代码生成Hex文件然后在Proteus里双击AT89C51在Program File属性中浏览选择该HexCrystal Frequency改成12MHz。回到原理图点击左下角运行按钮LCD应显示NE555当前频率。把电位器从中间位置向两端调节频率偏离基准值超过阈值后LED亮起、蜂鸣器鸣叫。若LCD显示空白先按暂停双击LCD1602确认它连接到了VCC和GND再检查P0口上拉排阻是否放置。整个过程不需要额外下载线Proteus会在每次运行前重新加载Hex文件。4. Keil C51程序实现定时器测频与阈值报警4.1 TMOD与定时器初值计算测频的核心是把T0配成外部计数模式T1配成定时中断。TMOD0x15二进制为0001 0101其中低四位0x01设置T0为方式1计数高四位0x10设置T1为方式1定时。T1在12MHz晶振下一个机器周期1μs要产生50ms中断初值为65536-5000015536即0x3CB0。每次T1中断读取T0的16位计数值与上次读取值做差得到一个50ms内的脉冲增量。用无符号减法做差分即使T0溢出回绕差值依然正确。累积20次增量后乘以20得到1秒频率值。频率计算式不是“读两次相减”这么简单要点在于把读值动作放在固定中断里而不是用while循环去等电平。4.2 完整C51代码LCD1602显示测频报警#include reg52.h #include stdio.h sbit RS P2^5; sbit RW P2^6; sbit EN P2^7; sbit LED P2^0; sbit BEEP P2^1; sbit KEY_F0 P1^0; sbit KEY_BIAS P1^1; unsigned long freq 0; unsigned long base_freq 0; unsigned int bias 2000; bit alarm 0; unsigned int last_count 0; unsigned long total 0; unsigned char gate 0; void delay_ms(unsigned int ms) { unsigned int i, j; for(i 0; i ms; i) for(j 0; j 120; j); } void lcd_cmd(unsigned char c) { P0 c; RS 0; RW 0; EN 1; delay_ms(1); EN 0; } void lcd_data(unsigned char c) { P0 c; RS 1; RW 0; EN 1; delay_ms(1); EN 0; } void lcd_str(char *s) { while(*s) lcd_data(*s); } void lcd_init(void) { delay_ms(15); lcd_cmd(0x38); /* 8位数据双行显示5x7点阵 */ lcd_cmd(0x0C); /* 显示开光标关 */ lcd_cmd(0x01); /* 清屏 */ lcd_cmd(0x06); /* 光标右移地址自动加1 */ } void timer1_isr(void) interrupt 3 { unsigned int now; TH1 0x3C; TL1 0xB0; now (TH0 8) | TL0; /* 读当前T0计数值 */ total (unsigned long)(now - last_count); last_count now; gate; if(gate 20) /* 软件闸门到1秒 */ { gate 0; freq total * 20UL; total 0; last_count 0; } } unsigned long abs_diff(unsigned long a, unsigned long b) { return (a b) ? (a - b) : (b - a); } void calc_detect(void) { unsigned long diff abs_diff(freq, base_freq); if(alarm 0) { if(diff bias) /* 超阈值进入报警 */ { alarm 1; LED 0; BEEP 0; } } else { if(diff (bias 300 ? bias - 300 : 0)) /* 回差300Hz */ { alarm 0; LED 1; BEEP 1; } } } void display(void) { char line[17]; lcd_cmd(0x80); sprintf(line, F:%luHz, freq); lcd_str(line); lcd_cmd(0xC0); sprintf(line, B:%lu S:%u, base_freq, bias); lcd_str(line); } void main(void) { TMOD 0x15; /* T1定时T0外部计数均方式1 */ TH0 0; TL0 0; TH1 0x3C; TL1 0xB0; TR0 1; TR1 1; ET1 1; EA 1; LED 1; BEEP 1; P1 0xFF; lcd_init(); while(1) { if(KEY_F0 0) /* 按下按键1记录基准频率 */ { delay_ms(20); if(KEY_F0 0) { base_freq freq; while(KEY_F0 0); } } if(KEY_BIAS 0) /* 按下按键2切换灵敏度 */ { delay_ms(20); if(KEY_BIAS 0) { bias 500; if(bias 5000) bias 500; while(KEY_BIAS 0); } } calc_detect(); display(); } }这段代码可以直接在Keil中新建工程编译Target Device选择Atmel AT89C51Options for Target里的晶振频率填12MHz并勾选Create HEX File。P1口在上电后默认是高电平按键接低电平触发按下时引脚被拉低。base_freq初始为0因此上电后第一次看到报警属于正常现象需要先按一次KEY_F0记录当前静态频率。4.3 阈值判定中的回差处理金属探测器最怕临界状态抖动金属靠近边缘时频率差在阈值附近反复穿越LED一闪一闪、蜂鸣器忽响忽停。这里在报警解除条件上引入了300Hz回差。比如bias设为2000进入报警条件是偏差超过2000Hz解除条件是偏差低于1700Hz。这样中间留出300Hz缓冲避免因为频率轻微波动导致状态频繁翻转。abs_diff函数用无符号比较后相减避免了有符号数减出负数的问题。freq和base_freq都是unsigned long基频可能高于当前频率也可能低于当前频率探测效果只关心差值绝对值不关心方向。若你的探头是“金属靠近导致频率降低”类型程序同样适用因为detect只判断偏差大小。5. 用虚拟频率计验证探头基准与灵敏度标定5.1 三分钟校准流程仿真连好后不要急着转电位器先执行一轮校准。第一步把电位器POT调到中间位置LCD上的F值稳定后按下KEY_F0此时base_freq等于当前静态频率。第二步按下KEY_BIASbias从2000以500为单位递增到5000再回退到500选择合适的灵敏度。一般建议取静态频率的1%~2%例如静态频率约250kHz时bias取2000~5000Hz太大会漏检太小会误报。第三步滚动电位器让频率偏离基频观察报警指示灯是否在阈值处触发。5.2 虚拟频率计和示波器双重验证在Proteus的Virtual Instruments里放一个COUNTER TIMER把输入端接到NE555的3脚它会直接显示信号频率。把它的读数和LCD上F值对比误差应小于2Hz。如果差距很大先检查TMOD是否0x15、T1初值是否0x3CB0再看P3.4是否被其他网络占用。虚拟示波器主要用来看波形形状NE555输出应该是上升沿陡峭的方波如果看到缓慢的三角波说明电容充电回路参数不对需要减小C值。5.3 从NE555替换到真实探头的接口变化调试通过后把NE555及其外围电阻、电位器从原理图中删除换上真实的LC谐振探头和LM393整形电路。LM393的输出端接P3.4其他单片机程序不用改动。真实探头静态频率由线圈电感和并联电容决定可能不在62.6kHz~480kHz范围内因此硬件的径向尺寸改变后需要重新按一次KEY_F0标定。如果静态频率超过1.3MHz需要把T1中断周期缩短到20ms软件闸门次数改成50次初值和计数器上限随之调整测频公式不变。将NE555输出断开把LM393整形后的方波接回P3.4重新运行仿真即可验证真实前端逻辑。本文还有配套的精品资源点击获取