简介:基于STM32单片机设计的超声波测厚仪完整解决方案,面向嵌入式开发者、电子竞赛参赛者及测控类课程设计人员,解决在1.2mm~225mm范围内对物体厚度的非接触式精准测量问题,设计误差控制在(±1%H+0.1)mm以内。资源共44个文件,压缩包约95.83MB,包含完整的AD原理图、PCB设计文件、可编译的STM32源程序、演示视频以及BOM表等,另附PCB工程预览与日志文件,便于快速检索与二次开发。核心代码涵盖超声波发射接收时序控制、厚度数值显示和按键交互功能,配合视频演示可直观核对硬件调测效果。包内还整理了stm核心板资料与原理图/PCB压缩包,为理解传感器选型、反射回波处理及整机装配提供闭环参考。目前已有101人学习下载,适合需要从零搭建超声波测厚仪并完成实物调试的工程师参考。
1. STM32 超声波测厚仪,为什么不是“拿个探头就能量”
钢板从生产现场到复验台,超声测厚是设备维护里上手最快的一项,但现场经常出现“同一个人、同一块试块,读数隔两分钟就差 0.3mm”的情况。这不是探头没放平,而是换能器激励、回波放大、比较器整形到 MCU 计时这条完整信号链上,每个环节都在贡献误差。基于 STM32 单片机设计的超声波测厚仪,核心是用一颗 STM32F103 级芯片把高压激励、飞行时间采集、声速校准和数值显示全部接管,而配套的原理图、PCB、源程序、演示视频和 BOM 表,本质上都是围绕这个信号链展开的。
这套方案之所以常见,是因为它把硬件和软件切成了三条线索:发射端解决“怎么激励探头”,接收端解决“怎么从噪声里捞回波”,固件解决“捞回来的边沿怎么算成厚度”。拿到资料后最忌讳直接开 Keil 编译,因为原理图里一个阻尼电阻的取值、PCB 上一段敏感走线的位置、源程序里的检测门限,彼此都会互相牵连。下文按一个完整落地顺序展开:先把测厚公式和探头选型算清楚,再对照原理图画出发射/接收链路,接着讲 PCB 走线和晶振参数,然后进源程序的定时器捕获与滤波,最后一章给出现场调试和演示视频里该录的验证流程。
2. 测厚原理先行:脉冲回波模型、声速表和换能器选型
2.1 脉冲回波测厚的核心公式与分辨力边界
超声波测厚仪基本都沿用脉冲回波原理:探头贴在被测件一侧,压电晶片发出超声波,声波穿过材料后在底面反射回到晶片,测厚仪测量从发射到接收的时间差。厚度等于声程除以“往返时间”的一半,源程序里最常见的写法是这个公式:
float thickness_mm = sound_speed_mps * time_us / 2000.0f;这里的 2000.0f 来自量纲换算:time_us 是往返时间,先乘声速得到回路声程,除以 2 才是单程厚度,再除以 1000 把米换算成毫米。以钢为例,纵波声速约 5920m/s,1mm 钢板的往返时间只有约 0.338μs,这也就是为什么测厚设备里最怕的不是算术,而是那零点几微秒的时间测量误差。
分辨力也不能只看定时器位数。一套 5MHz 探头的接收信号带宽约在 3~7MHz,回波前沿受探头阻尼影响,上升时间通常有几十到上百纳秒。STM32F103 的定时器工作在 72MHz,一个计数脉冲约 13.9ns,换算到钢材料上相当于 0.041mm,这是“数值分辨力”,不是系统精度。系统精度还取决于晶振偏差、声速随温度变化、耦合剂状态以及比较器阈值,因此验收时要用标准试块复测,而不是只看屏上小数位数。
2.2 换能器频率、晶片直径和单晶/双晶的取舍
探头是整套解决方案里最不该省的部分。频率决定衰减和分辨率的平衡:低频探头穿透深但回波宽,高频探头分辨细但不耐衰减。工程上常用的选型区间可以按表和被测材料来定。
| 探头频率 | 钢中适用厚度范围 | 典型应用场景 |
|---|---|---|
| 1MHz ~ 2.25MHz | 20mm ~ 200mm 以上 | 大锻件、铸铁、厚壁管道 |
| 5MHz | 1mm ~ 50mm | 钢结构和压力容器常规测厚 |
| 10MHz | 0.5mm ~ 10mm | 薄壁管、板材分层检测 |
晶片直径影响声束指向性和近场长度。5MHz、直径 10mm 的探头在钢中波长约 1.18mm,能兼顾耦合面积和小曲率表面的贴合,是测厚方案里出现最多的配置。如果被测表面是小管径的曲面,直径 6mm 的小晶片更合适。
单晶探头用一个压电晶片既发又收,电路简单,但发射后的余振会拖长表面回波,薄工件底波容易被表面余振掩盖;双晶探头把发射晶片和接收晶片分开,各自带声延迟块,接收通道在发射时基本听不到自己的余振,盲区可以做得很小。DIY 测厚仪通常选 5MHz 双晶探头,源程序里的最小测厚门槛也要按照探头的盲区来设。
2.3 STM32F103 定时器测量飞行时间的实际分辨力
把探头回波整形后的脉冲接到 STM32 的定时器输入捕获,是最直接的“时间到数字”转换办法。STM32F103C8T6 的 TIM2 在 72MHz 时钟下,捕获值单位是 13.9ns。对 15mm 钢板,往返时间约为 5.07μs,对应约 365 个计数;对 2mm 薄板,往返约 0.676μs,对应约 49 个计数。这说明即便是资源最普通的 F103,也能覆盖常规测厚范围。
不过“计数够密”不等于“测得到”。回波经过 60dB 放大后,噪声基底同样会被放大,比较器在噪声上的抖动范围往往远大于一个定时器计数,所以固件里要加中值滤波和回波窗口,也就是后面章节会写的 MIN_GATE_US 与 MAX_GATE_US。若项目要求 0.01mm 级别的重复精度,常见做法是外接 TDC7200 或 GP22 这类时间数字转换芯片,再将测量结果返给 STM32;但这就不再是纯粹“STM32 解决计时”的轻量路线,成本和复杂度都会上升。
3. 从原理图到源程序:发射、接收与回波检测电路设计
3.1 发射驱动:STM32 怎样送出 5MHz 脉冲串激励探头
压电换能器需要一个短促的激励信号。常见做法有两种:一种是产生单极性高压尖峰脉冲,用几百纳秒的窄脉冲去敲晶片,适合供电简单的便携表;另一种是由 MCU 产生 5MHz 附近的脉冲串,再用 MOSFET 和脉冲变压器把幅度抬升到几十伏以上,对回波带宽更友好。这套方案里通常采用后一种链路:TIM1 输出 PWM → 逻辑电平 MOSFET 栅极 → 脉冲变压器初级 → 次级并联后接探头。
void send_ultrasound_burst(uint8_t cycles) { TIM1->ARR = 13; // 计数值 13+1=14,72MHz/14 ≈ 5.14MHz TIM1->CCR1 = 7; // 占空比接近 50% __HAL_TIM_SET_COUNTER(&htim1, 0); HAL_TIM_PWM_Start_IT(&htim1, TIM_CHANNEL_1); HAL_DelayUs(2); // 约 10 个周期,足够让探头起振 HAL_TIM_PWM_Stop_IT(&htim1, TIM_CHANNEL_1); }代码里 ARR 写 13,是因为定时器输出周期是 ARR+1 个时钟计数。注释里的 5.14MHz 与探头标称频率略有偏差,但探头本身有一定带宽,这个误差通常可以接受;如果源程序里做编码激励或相关运算,则要让定时器时钟与探头频率精确对齐。
发射级一定要有阻尼设计。脉冲变压器次级并联一个电阻,常在几百欧到 2kΩ 之间,用来吸收探头自由振荡,缩短表面余振;电阻太小会吃掉发射能量,太大则回波拖尾变长。这个值是电路调试中反复试出来的,BOM 表里该电阻的功率和封装也要留余量,不能只看阻值。
3.2 接收链路:限幅、放大和比较器整形
回波回到探头时通常只有数毫伏到几十毫伏,而发射端可能有上百伏高压,所以接收放大器输入端必须先做钳位保护。钳位二极管要选开关速度快的 BAT54S 或 BAS70,物理位置紧贴探头插座,让多余能量在进入放大器之前被泄放掉。
放大链路常见采用两到三级结构:第一级低噪声固定增益,后续用可变增益实现对不同深度回波的补偿。比较器把模拟回波变成数字边沿,再送到 STM32 定时器输入捕获。下面是简化后的 BOM 参考,具体数值要以实际原理图为准。
| 位号 | 器件 | 参考型号/参数 | 作用 |
|---|---|---|---|
| U4 | 低噪声放大器 | AD8331 或 THS4304 | 第一级固定增益 |
| U5 | 对数放大器 | AD8310 | 压缩回波动态范围,辅助阈值判断 |
| U6 | 比较器 | TLV3501 | 回波过阈值输出上升沿 |
| D1/D2 | 钳位二极管 | BAT54S | 发射高压限幅 |
| R11 | 阻尼电阻 | 500Ω~2kΩ | 抑制探头余振 |
接收链路里最容易忽略的是自动增益或阈值自适应。固定阈值只能在一个很小的测厚深度内有效;深度大时回波衰减,需要更高增益,而近表面回波强,又容易造成比较器提前触发。因此很多源程序会实时统计一段时间的噪声峰值,动态给比较器一个略高于噪声的阈值,或者在模拟端用 AGC 引脚控制增益。
3.3 把回波时间送进 STM32:输入捕获与检测窗口
比较器输出的上升沿接到 STM32 的捕获输入脚,例如 TIM2_CH2 对应的 PA1。发射脉冲发出瞬间把定时器清零,回波边沿到达时,捕获寄存器自动记录当前计数值。关键点是在中断里判断“这个回波是不是本次发射产生的”,避免把上一次发射的余振或电源噪声当成有效回波。
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM2 && htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) { uint32_t ticks = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_2); float time_us = ticks * (1.0f / 72.0f); if ((time_us > MIN_GATE_US) && (time_us < MAX_GATE_US)) { g_valid_echo = 1; g_last_us = time_us; __HAL_TIM_SET_COUNTER(&htim2, 0); } } }MIN_GATE_US 和 MAX_GATE_US 就是测厚仪里的“检测闸门”。MIN 由探头盲区决定,比这更小的时间差来自表面串扰或探头延迟块耦合,不是底波;MAX 对应系统能测的最大厚度。软件窗口比硬件门控更灵活,是源程序里第一个值得反复调试的参数。
4. PCB 布局与走线:把回波干扰压到比较器能抗住的程度
4.1 高压发射区与微弱回波区怎么分区
原理图能跑通往往只代表电路及格,真正决定回波稳定性的常常是 PCB。超声波测厚仪里同时存在高压小电流的发射支路、毫伏级回波和数字逻辑,三类信号如果混在同一块地上,回波很容易被电源和数字开关噪声淹没。
常见做法是把 PCB 划成三个区:高压发射区、模拟接收区、数字控制区。发射区放在板边,靠近探头插座;模拟接收区与发射区之间保持至少 2~3 毫米间距;STM32 和显示、按键电路离两个区最远。整套方案通常带 LCD 和按键,这个分区要在布局阶段就确定,不要等布线时才发现运放和 PWM 输出挤在一起,最后只能靠飞线救火。
4.2 回波通道的 PCB 走线要求与板层设置
模拟接收通道的走线要求可以概括成三个词:短、直、包地。比较器输出之前的所有信号都属于敏感信号,走线尽量不超过 20mm,避免穿过数字区域;需要转弯时用 45° 或圆弧,不用直角。接收通道两侧加接地过孔栅栏,能把板内噪声耦合压低。下面的自查表可以直接在打样前逐条核对。
| 检查项 | 要求 | 原因 |
|---|---|---|
| 回波输入走线 | 距发射级 ≥ 5mm,不足则包地 | 防止高压脉冲串入接收通道 |
| 比较器输出 | 靠近 STM32 引脚,线宽不小于 0.2mm | 数字边沿不需要阻抗控制,但要短 |
| 电源退耦 | 每个运放电源脚 100nF 紧靠引脚 | 高频退耦路径越短越有效 |
| 晶振区域 | 下方禁止布敏感信号 | 晶振走线和回波放大线会互相干扰 |
| 探头插座 | 尽可能靠近模拟前端 | 探头引线越长,等效天线效应越明显 |
至于板层设置,四层板可以直接采用 TOP-GND-POWER-BOTTOM 叠构,信号参考面完整,回波走线放在 TOP 层,底层只放少量器件;若用双层板降成本,则 TOP 层走信号,BOTTOM 层做完整地平面,并尽量减少过孔数量,因为每个过孔都会打断回流路径。用 Cadence PCB Editor 设置层叠时,要注意 GND 层网络必须铺完整,不能只靠几根宽线当代替;导出 Gerber 前再做一次 AD20 或对应工具的 DRC 检查,重点看不连接网络和丝印压盘。
4.3 最小系统的晶振电容计算与供电滤波
STM32 最小系统不止是“芯片能跑”,还要保证串口和 SWD 稳定。外部晶振的负载电容会直接影响起振余量和频率精度,电容不是随意取的。晶振两侧对地电容和寄生电容的关系如下:
CL = (C1 * C2) / (C1 + C2) + Cstray假设晶振规格标称 CL=12pF,PCB 走线寄生电容 Cstray 取 3pF,则 C1、C2 各取 18pF 时,并联后约 9pF,加上寄生 3pF 正好约 12pF。如果手头只有 20pF 标称值电容,实际 CL 会被推到 13pF 左右,差异不大,可以起振;但晶振标称 CL=20pF 而板子上只放了 10pF,实际负载就明显偏低,可能起振慢甚至不起振。
供电方面,模拟前端建议用 LDO 单独供一路 3.3V,数字电源经磁珠或小电阻把高频噪声隔开;比较器电源脚要放 100nF 加 10μF 双电容,并且紧靠引脚。STM32 的 BOOT0 下拉和复位电容不要省,否则现场烧录时会遇到“error: no STM32 target found”一类问题,排查方向就会从“程序写错了”变成“硬件根本没进入调试状态”。
5. 源程序测量骨架:定时器捕获、厚度计算、滤波和校准
5.1 STM32CubeMX 里的输入捕获配置与引脚分配
源程序里最核心的流程是“发射脉冲 → 定时器清零 → 等待捕获 → 处理回波”。用 STM32CubeMX 配置时,TIM2 选择 Input Capture direct mode,通道 2 映射到 PA1,时钟不分频,捕获极性是上升沿。这样才能保持 13.9ns 一个计数的原生分辨力,而不是随手把 prescaler 拉到 71 变成 1μs 分辨率。
TIM_IC_InitTypeDef ic = {0}; ic.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; ic.ICSelection = TIM_ICSELECTION_DIRECTTI; ic.ICPrescaler = TIM_ICPSC_DIV1; ic.ICFilter = 0x0F; HAL_TIM_IC_ConfigChannel(&htim2, &ic, TIM_CHANNEL_2); HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);ICFilter 设为 0x0F,表示捕获引脚上做 8 个时钟周期的数字滤波,能滤掉比较器输出边沿附近的高频毛刺。副作用是让边沿延迟几个周期,这个固定延迟会被声速校准覆盖掉;如果回波幅度小、边沿很钝,滤波可以调小,否则真实回波可能被当成毛刺丢掉。打开工程前还要确认 Keil5 里安装对应的 STM32F1xx 芯片包;如果电脑里同时装了 C51 和 STM32 两个环境,安装路径要分开,否则工程打开后看不到芯片型号,编译和烧录都会出问题。
5.2 厚度计算、中值滤波和坏回波剔除
把捕获回调里的时间值转成厚度,公式就是第二章那个量纲换算。实际源程序里通常封装成一个函数,避免主循环里到处写魔法数。
#define SOUND_SPEED_STEEL 5920.0f static float echo_time_to_thickness(float time_us, float sound_speed) { return sound_speed * time_us / 2000.0f; }单次回波不稳定是正常的,最常见做法是连续采集 5 次,取中位数而不是平均值。中位滤波器对耦合剂偶发气泡造成的单次短回波免疫力强,平均值则会被一个大的毛刺直接拉偏。如果连续 5 次测量里最大值和最小值之差超过 0.3mm,通常认为本次结果不可信,继续保留上一次显示值,并在串口打一个不确定标记。这个坏回波剔除逻辑在薄壁件上尤其重要,因为薄板底波和表面波之间的间隔本来就小。
5.3 声速校准与 LCD/UART 输出
不同批次钢材的声速可能有 1%~3% 偏差,而测厚仪的绝对误差里,声速误差往往比定时器分辨力大得多。因此源程序必须有校准入口:在一块已知厚度 D_std 的试块上测出飞行时间 t_cal,反推当前探头与材料的声速。常见材料可以先用默认值,实际测量以校准结果为准。
| 材料 | 纵波声速(m/s) | 备注 |
|---|---|---|
| 碳钢 | 5850 ~ 5950 | 以标准试块校准后使用 |
| 铸铁 | 4500 ~ 4600 | 灰口铁差异较大 |
| 铝 | 6250 ~ 6350 | 轻金属中声速较快 |
| 铜 | 4650 ~ 4750 | 声速受合金成分影响 |
| 亚克力/塑料 | 2300 ~ 2700 | 衰减较大,适合低频探头 |
校准的要点是试块厚度尽可能接近被测厚度。只做单点校准,近区回波和远区回波的时间基准仍可能有差异;如果手头有两块标准试块,比如 5mm 和 40mm,可以实现两点线性校准,把声速曲线斜率一起修正。温度修正一般按线性系数折算,但 0~50°C 范围内的工业测厚,声速温漂往往小于耦合状态带来的误差,可以先不做复杂补偿。
输出方式对演示效果影响很大。最直观的是 UART 按 CSV 格式打印,例如:
uint16_t d10 = (uint16_t)(thickness_mm * 10.0f); printf("d:%u.%u mm\r\n", d10 / 10, d10 % 10);先乘 10 再拆成整数和小数,是为了避免浮点格式化占用太多开销,也符合常见嵌入式串口库的能力。如果串口用 USB 转 TTL 接到电脑,在 Windows 设备管理器里看到“STM32 Virtual COM Port 叹号”,要先查驱动,而不是反复改源程序;驱动装好后还要确认串口号被占用,否则演示视频里抓不到实时数据。
6. 现场验证与排错:演示视频里该录的流程和检查单
6.1 验证流程:试块、耦合剂和重复性
拿到打样回来的板子和烧录好的源程序,先不要急着拍视频。验证顺序可以固定为:先准备已知厚度试块,再用砂纸或锉刀处理被测面,让表面尽量平整,接着涂耦合剂,常用的是甘油或超声耦合凝胶,把探头轻轻放上去,不要用力压,等读数稳定后连续记录 5 次,看最大值和最小值的差。只有这个差值小于 0.1mm 到 0.2mm 时,才说明整条信号链是可信的。
演示视频也应该按这个顺序拍:先展示标准试块,再显示屏幕上经过校准的厚度值,接着换第二块厚度不同的试块,重新测一遍。如果视频里能同时拍到探头、试块、液晶屏或串口助手,说服力会明显强于只对着屏幕拍。录制过程中如果数值跳动,先检查耦合剂是否涂满探头底面,再检查探头是否倾斜,而不是马上动代码。
6.2 常见故障现象对应的检查路径
现场最容易遇到的不是代码编译失败,而是“能烧录但测不到数”。下面这几个现象和排查顺序可以做成检查单。
| 现象 | 可能原因 | 排查顺序 |
|---|---|---|
| 完全无回波 | 高压没建立、探头断线、比较器阈值过高 | 示波器看发射极波形,再看运放输出 |
| 读数每次都不一样 | 耦合不良、表面粗糙、比较器阈值太低 | 重新涂耦合剂,增大 IC Filter |
| 数值偏大或带毛刺 | 把表面回波当成底波,或窗口起点太小 | 调大 MIN_GATE_US,确认探头双晶特性 |
| 数值缓慢漂移 | 探头发热、声速温度漂移、晶振不稳定 | 校准时连续测 30 分钟,观察极差 |
| ST-Link 连不上目标 | 接线反了、芯片锁死、BOOT0 悬空 | 用 ST-LINK Utility 全擦除,再查 SWD 三线 |
比较器阈值是最容易被忽视的一项。阈值低,噪声会频繁触发捕获;阈值高,小回波直接丢失。用示波器同时看比较器输入和输出,能快速判断是模拟端回波太小,还是数字端滤波过度。
6.3 Gerber 导出与 BOM 一致性检查
源程序调试稳定后,打样前要把原理图和 PCB 再对照一遍:每条信号网络的位号是否在 BOM 表里出现,封装和实际元件能不能对上。导出 Gerber 时要确认钻孔文件已包含,板厂默认会做全部贯穿孔,未设置的盲孔或埋孔不会自动生成。用 Gerber 查看器转成图形后,重点检查探头插座、比较器、晶振三处器件是否有丝印压盘或过孔打在焊盘上。
最后一个实用技巧是:录制演示视频之前,用一个高频示波器探头夹在接收放大器输出端,观察是否有稳定的底波回波包络。只要这一步看到波形,再去看屏幕数值就有底气;如果示波器上已经是一团噪声,就别急着拍视频,回头先查发射级阻尼电阻和接收通道钳位二极管是否装反。把这一步当作每次改板后的固定动作,测厚仪的排错效率会高很多。
本文还有配套的精品资源,点击获取