简介:一套基于单片机金属探测器Proteus仿真与程序的完整资料包,面向电子信息类学生、嵌入式初学者及课程设计开发者,旨在帮助理解金属探测的电磁感应原理、传感器选型、信号调理与单片机控制逻辑。压缩包共包含17个文件,涵盖Proteus仿真电路(DSN/DBK)、Keil工程源码(C/HEX/Uvproj)、开发板原理图PDF及运行截图等,文件体积仅173KB,便于快速下载与本地运行。配套的RZ-51开发板原理图可辅助对照硬件设计,main.c与hex文件则展示了包括数据采集、滤波处理、阈值判断和结果输出在内的完整程序实现流程。仿真工程已集成必要的环境配置,可直接打开运行并观察金属靠近时的响应变化。已有171人学习下载,适合作为单片机综合实训、毕业设计参考或金属探测类项目入门模板;通过调整线圈参数与滤波算法可直观测试探测灵敏度与抗干扰能力,有效降低实物调试门槛。
1. 单片机金属探测器仿真,为什么值得先做在 Proteus 里
金属探测器不是"一个线圈加蜂鸣器"那么简单:探头线圈靠近金属时,涡流会让振荡回路的等效电感量和 Q 值发生变化,这个变化只有几百赫兹到几千赫兹,靠耳朵听不靠谱。如果直接搭实物,线圈绕制、信号整形、探头屏蔽三件事就能消耗掉一个周末。更现实的做法是用 Proteus 仿真 51 单片机金属探测器:先把振荡、整形、测频、报警这一整条链路跑通,再决定是不是值得打板。这个项目对单片机入门到进阶的人都合适,你会用到定时器计数器、溢出中断、上电校准和阈值判决,Proteus 里能随时停下来看计数器寄存器变化,也能用虚拟示波器直接看频率偏移,调参成本比实物低一个量级。
这个标题的核心其实是一套可以复用的思路:把"物理量的变化"变成"脉冲频率的变化",再用单片机数脉冲做判决。掌握之后,光照传感器、接近开关、电机测速的仿真程序都能按同一套逻辑写,Proteus 只是把这套逻辑压缩到一台电脑上验证。
2. 从涡流效应到频率检测:金属探测器仿真方案的原理与选型
2.1 涡流效应与线圈参数变化:为什么频率能反映金属
金属探测器检测对象是金属导体。当探头线圈中有高频交流电流时,线圈周围产生交变磁场,金属物体进入该磁场后,表面会感应出涡流,涡流又产生反向磁场削弱原磁场。从电路上看,相当于探头线圈的等效电感量变化,同时涡流损耗使线圈的等效串联电阻变大,回路的 Q 值下降。
如果把探头线圈接成一个谐振回路并参与振荡,这些参数变化就会直接落到振荡频率上。绕制工艺和电路结构不同,频率漂移方向可能不同:有的方案金属靠近频率升高,有的方案频率降低,但无论哪个方向,频率一定偏离原来的中心值。单片机不需要关心物理过程,只需稳定地测量当前频率,并与无金属时的基准频率比较,偏差超过一定阈值就报警。
2.2 三种常见探测体制及选型
从事金属探测器设计的常见路线有三种:
| 体制 | 英文缩写 | 基本原理 | 单片机参与度 |
|---|---|---|---|
| 拍频振荡 | BFO | 两个振荡器差频,金属改变探测振荡器频率,差频变化经耳机或仪表指示 | 低,可只做提示 |
| 感应平衡 | IB | 双线圈平衡电桥,金属破坏平衡产生信号 | 需要高精度 ADC 采样 |
| 脉冲感应 | PI | 线圈通断电流,金属涡流延长放电时间 | 需要高速 ADC 与时间门控 |
对 Proteus 仿真而言,BFO 和直接测频方案的电路最简单,仿真收敛性最好。IB 需要搭建模拟前端,PI 需要微秒级时间测量,在 Proteus 中参数调节繁琐且很容易跑不出理想的信噪比。所以常见做法是用"振荡器 + 整形 + 单片机计数器"测频,这也是最容易在一晚上跑通,且能讲清楚原理的方案。这个方案里,单片机的定时器负责生成时间窗口,计数器负责数脉冲,核心逻辑与项目标题里的"程序"完全对应。
2.3 本设计的信号链路:振荡-整形-计数-判决
2.3.1 用 NE555 模拟 LC 振荡器的可复现性取舍
真实探头一般用分立三极管或施密特反相器搭 LC 振荡器。这类电路在仿真软件中受模型参数影响大,可能出现启动困难、波形畸变,跑不起来会让初学者误以为是程序问题。为了把重点放在单片机程序上,我一般会在 Proteus 仿真阶段先把探头部分用 NE555 多谐振荡器代替:它输出标准的 0-5V 方波,无需额外整形,能直接接到 51 单片机的 T1 计数器引脚。
NE555 振荡频率由 R1、R2、C 决定,周期 T ≈ 0.693 × (R1 + 2×R2) × C。当取 R1=R2=4.7kΩ、C=1nF 时,f≈102.4kHz,这个频率落在常用金属探测器的工作区间。仿真时"金属靠近"用开关并入一个 220pF 电容模拟:电容变大,振荡频率下降,T1 在固定窗口里的脉冲数减少,单片机据此判断有金属。实际硬件做出来时,只需要把 NE555 这一级换成 LC 振荡并保证输出同频率的方波,程序无需修改。
2.3.2 100ms 测量窗口与计数器溢出问题
测频最常见的方式是固定一个时间窗口,数窗口内来了多少个脉冲,再用"脉冲数 / 窗口时间"得到频率。窗口选长一些,频率分辨率高,但响应慢;窗口选短,响应快,分辨率和抗抖动能力会变差。综合权衡后,取 100ms 窗口:在 102.4kHz 的输入频率下,窗口内约 10240 个脉冲,16 位计数器远没有溢出,频率分辨率约 10Hz。
这里要特别处理 T1 计数器的溢出。T1 工作在 8 位自动重装计数模式时,每计数 256 个脉冲溢出一次并触发中断,中断里累加 overflow_count,窗口结束时计算 pulse_count = overflow_count × 256 + TL1。如果直接把 16 位计数器用于 100kHz 信号,1 秒内就会溢出多次,会造成计数丢失,这也是很多人仿真"数据跳变"的主要原因。
3. 51 单片机金属探测器程序:100ms 窗口测频与报警输出
3.1 定时器0做时基,定时器1做脉冲计数器
程序只用单片机自带的资源:T0 工作在 16 位定时器模式,产生 10ms 中断;T1 工作在 8 位自动重装计数器模式,对外部脉冲计数。TMOD 设为 0x26,其中高 4 位给 T1,低 4 位给 T0。T0 在 12MHz 晶振下初值为 0xD8F0,每个机器周期 1μs,10ms 需要 10000 个计数。T1 的 TH1 和 TL1 初始化为 0,每 256 个脉冲溢出一次,溢出中断给 overflow_count 加 1。
之所以不让 T1 直接用 16 位模式,是因为 16 位计数器一次溢出对应 65536 个脉冲,在 100kHz 频率下约 0.65 秒就会溢出一次,中断服务程序里需要拼接两个字节,读取时的瞬间溢出问题很难处理。8 位自动重装模式配合溢出次数累加,窗口结束时一次性拼接,读写都非常稳定。
3.2 代码:初始化、中断与主循环
#include <reg51.h> #define TH0_INIT 0xD8 // 12MHz 晶振下 10ms 定时初值 #define TL0_INIT 0xF0 #define WINDOW_TIMES 10 // 10ms * 10 = 100ms 测量窗口 #define CALIB_SAMPLES 5 // 上电基准校准采样次数 #define THRESHOLD 100 // 偏差阈值,单位:窗口内脉冲数 sbit BEEP = P1^0; // 蜂鸣器 sbit LED_ALARM = P1^1; // 报警指示灯 sbit LED_NORMAL = P1^2; // 正常指示灯 unsigned char time_count = 0; unsigned char overflow_count = 0; unsigned int pulse_count = 0; // 当前窗口计数值 unsigned int base_count = 0; // 上电校准基准值 unsigned char window_done = 0; // 100ms 窗口结束标志 bit alarm_on = 0; unsigned char buzz_timer = 0; void timer0_isr(void) interrupt 1 { TH0 = TH0_INIT; TL0 = TL0_INIT; time_count++; if (time_count >= WINDOW_TIMES) { time_count = 0; TR1 = 0; // 暂停 T1,稳定读取计数值 pulse_count = ((unsigned int)overflow_count << 8) | TL1; overflow_count = 0; TL1 = 0; TR1 = 1; // 开启下一个窗口 window_done = 1; } } void timer1_isr(void) interrupt 3 { overflow_count++; // T1 每计满 256 个脉冲触发一次 }这里的关键参数有三个。WINDOW_TIMES 是 10ms 时基累加次数,设为 10 就是 100ms 窗口;THRESHOLD 是脉冲数阈值,100 表示与基准值相差 100 个脉冲时才报警,换算到频率就是 1000Hz;CALIB_SAMPLES 是上电校准取平均的次数,5 次平均能滤掉个别窗口的抖动。
T0 中断服务程序里先重装初值再判断窗口是否到点。到点后先把 TR1 清零,读取 overflow_count 与 TL1,拼接成 pulse_count,再清零并重启 T1。拼接时把 overflow_count 左移 8 位后与 TL1 按位或,等价于 overflow_count × 256 + TL1。先停后读的顺序很重要,若在读 TL1 时不暂停,恰好发生溢出会让结果多出 256 个脉冲,这是计数器类程序最容易踩的坑。
3.3 主循环:校准、绝对偏差判决与报警输出
void main(void) { unsigned char i; unsigned long sum = 0; TMOD = 0x26; // T0 定时器模式1,T1 计数器模式2 TH0 = TH0_INIT; TL0 = TL0_INIT; TH1 = 0x00; // 计数器自动重装值为 0 TL1 = 0x00; ET0 = 1; ET1 = 1; EA = 1; TR0 = 1; TR1 = 1; // 上电校准:连续取 5 个窗口计数的平均作为基准 for (i = 0; i < CALIB_SAMPLES; i++) { window_done = 0; while (!window_done); sum += pulse_count; } base_count = (unsigned int)(sum / CALIB_SAMPLES); LED_NORMAL = 0; while (1) { if (window_done) { window_done = 0; // 无论频率升高还是降低,只要偏离阈值就报警 if (pulse_count > base_count) alarm_on = (pulse_count - base_count) > THRESHOLD; else alarm_on = (base_count - pulse_count) > THRESHOLD; if (alarm_on) { LED_ALARM = 0; LED_NORMAL = 1; buzz_timer++; if (buzz_timer >= 50) buzz_timer = 0; BEEP = (buzz_timer < 25) ? 0 : 1; } else { LED_ALARM = 1; LED_NORMAL = 0; BEEP = 1; buzz_timer = 0; } } } }上电校准必须在主循环中等待窗口完成,而不是在中断里做,因为校准需要连续采样多个完整窗口,中间若被大段关中断的操作打断,窗口就会拉长,计数值不再对应 100ms。主循环中 window_done 置位后,先算出 pulse_count,再在下一次窗口内做判决,延迟不超过一个窗口周期。这个程序的结构是"中断只产生数据,主循环负责决策",延时抖动不会影响测量结果。
阈值比较用绝对偏差而非固定"频率升高"或"频率降低",因为 NE555 换成真实 LC 探头后,频率漂移方向取决于电路是感抗变化主导还是涡流损耗主导。用绝对偏差,程序在实物移植阶段能少改一行逻辑。
4. Proteus 仿真 51 单片机金属探测器:电路搭建与运行步骤
4.1 Proteus 8 professional 中的元件清单与参数
打开 Proteus 后新建工程,先在元件模式中放置下表对应元件:
| 元件 | 型号/参数 | 数量 | 电路中的作用 |
|---|---|---|---|
| AT89C51 | AT89C51 | 1 | 程序主控,完成测频与判决 |
| NE555 | NE555 | 1 | 产生约 102kHz 方波,模拟探头振荡 |
| RES | 4.7kΩ | 2 | NE555 定时电阻 R1、R2 |
| CAP | 1nF | 1 | NE555 定时电容 |
| CAP | 220pF | 1 | 并入定时电容,模拟金属靠近 |
| SW-SPST | 按键 | 1 | 模拟金属靠近的开关 |
| CRYSTAL | 12MHz | 1 | 单片机时钟 |
| CAP-ELEC | 10μF | 1 | 复位电容 |
| RES | 10kΩ | 1 | 复位电阻 |
| RES | 1kΩ | 3 | LED、蜂鸣器限流 |
| LED-RED | 红色 | 1 | 报警指示 |
| LED-GREEN | 绿色 | 1 | 正常指示 |
| BUZZER | 有源蜂鸣器 | 1 | 报警提示 |
| POT-HG | 10kΩ | 1 | 调整振荡频率起点(可选) |
注意 NE555 的 R1 接 VCC 与 DISCH(第 7 脚),R2 接 DISCH 与 THRES(第 6 脚),C 接 THRES 到 GND,OUT(第 3 脚)就是输出方波。若电位器串接在 R1 的供电端,它可以把中心频率从 80kHz 调到 120kHz,仿真时能直接观察频率对计数的影响。
4.2 NE555 振荡器接线与"金属靠近"的仿真方式
NE555 的接线按数据手册典型多谐振荡器连接:第 2 脚 TRIG 与第 6 脚 THRES 短接,第 4 脚 RST 接 VCC,第 5 脚通过 0.01μF 电容接地,第 1 脚接地,第 8 脚接 VCC。220pF 电容用 SW-SPST 跨接在 1nF 定时电容两端。SW1 断开时,频率约 102kHz;按下 SW1 时,220pF 并入,总电容变成 1.22nF,频率降到约 84kHz。
这个开关模拟的实际物理过程是:金属靠近探头线圈导致振荡回路等效参数变化,从而引起频率偏移。在 Proteus 里直接拖动电感值不太方便,运行期间改动参数也很难还原"从远到近"的过程,用开关并入电抗元件是 Proteus 仿真金属探测器最常见的变化模拟形式。
4.3 单片机最小系统与信号连接
AT89C51 的晶振电路用 12MHz 晶振加两个 30pF 负载电容,复位电路用 10μF 电解电容与 10kΩ 电阻构成上电复位,第 31 脚 EA 接 VCC 使单片机从内部 ROM 启动。NE555 的第 3 脚直接接 AT89C51 的 P3.5(T1)。这个引脚是定时器 1 的外部计数输入端,下降沿有效,NE555 输出标准方波,不需要再加电平转换或整形。
输出部分:P1.0 接蜂鸣器,由于 51 单片机 I/O 口驱动能力有限,仿真中直接用 1kΩ 限流电阻接有源蜂鸣器,工作正常;做实物时建议用三极管或 ULN2003 驱动。P1.1 接红色 LED,P1.2 接绿色 LED,均通过 1kΩ 电阻接 VCC,低电平点亮。
4.4 用 Keil 生成 HEX 文件并装载
在 Keil C51 中新建工程,单片机型号选 AT89C51,把第 3 章代码粘贴到 main.c。工程选项中勾选 Output 页的 Create HEX File,晶振频率保持 12MHz 与仿真一致。编译无误后,在 Proteus 中双击 AT89C51,在 Program File 一栏选择 Keil 生成的 .hex 文件,点击运行。
运行时,绿色 LED 应该保持点亮。按下 SW1,红色 LED 点亮,P1.0 输出变为 500ms 周期的间歇低电平,蜂鸣器驱动生效;Proteus 仿真中蜂鸣器是否发声取决于元件模型,看引脚逻辑即可。松开开关后 100ms 内状态恢复。如果按下开关没有反应,先检查 NE555 输出是否在示波器上有波形,再检查 THRESHOLD 是否设得过大。
5. 仿真调试技巧:示波器核对频率与阈值设定
5.1 先把NE555频率测准,再谈单片机
最容易犯的错误是一上来就调程序。建议在放置完 NE555 后,先不接单片机,用虚拟示波器 A 通道接 OUT 引脚,观察波形周期是否接近 9.8μs。若有偏差,按频率公式反推 R1、R2、C,优先调 C 而不是调 R,因为电容值在仿真里可以精确到 pF 级,而电位器拖动很难稳到固定值。确认稳定后,再接 P3.5。
5.2 阈值 THRESHOLD 和窗口时间的配合
| 窗口时间 | 基频脉冲数(约102kHz) | 频率分辨率 | 推荐THRESHOLD |
|---|---|---|---|
| 10ms | 1024 | 100Hz | 20 ~ 30 |
| 100ms | 10240 | 10Hz | 80 ~ 150 |
| 1s | 102400 | 1Hz | 800 ~ 1500 |
100ms 窗口下,THRESHOLD 设 100 对应频偏 1000Hz,够区分常见开关模拟扰动;如果换成真实探头,信号源频率稳定度通常优于正负 0.1%,可以把阈值降到 30~50,提高灵敏度。阈值设太小,上电基准值本身有抖动,会出现误报警;建议先用 100 跑通,再逐步减小。
5.3 实物移植时最值得保留的技巧
NE555 换成真实 LC 振荡器后,程序不用改,但要做三件事: LC 输出先经过施密特触发器整形再接 T1;在基准校准期间禁止人靠近线圈,否则基准确错;探头线圈要屏蔽并固定好,轻微移动造成的频率漂移会在低频端放大。实物样机如果出现"按下开关才报警、靠近铁罐没反应",多半不是程序问题,而是整形电路不满足 T1 对下降沿幅值的要求。把这套仿真里的计数窗口、绝对偏差判决和上电校准逻辑原样保留,再针对电平做适配,是这套方案从 Proteus 走向实物的最短路径。
本文还有配套的精品资源,点击获取