尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

74LS04与CX20106A构建40kHz超声波测距:原理、电路与程序实现

74LS04与CX20106A构建40kHz超声波测距:原理、电路与程序实现 简介一份基于51单片机的超声波测距软硬件工程面向电子技术学习者、课程设计与竞赛参赛者完整演示了74LS04驱动器与CX20106A接收芯片在测距系统中的应用。压缩包共16个文件、约25KB既包含C语言源码、Keil工程、启动汇编和HEX可烧写文件也附有列表、目标文件及备份配置从编辑编译到烧录调试均有覆盖。已有175人学习。工程按发射驱动、回波接收、距离计算和结果显示组织可对照74LS04六路非门的逻辑转换和CX20106A内部放大、鉴频、比较处理来理解硬件链路同时结合51单片机定时器计时、外部中断响应等编程细节掌握完整测距流程。还可借鉴多次测量取平均、滤波降噪等优化思路提升精度和抗干扰能力适合作为入门项目或课程设计的直接参考。1. 一个 74LS04 和一个 CX20106A就是这套超声波测距程序全部的秘密拿到名为 chaoshengbo.rar 的 51 工程包很多人第一反应是CX20106A 不是红外遥控接收芯片吗怎么会出现在超声波测距程序里这正是这套方案最有意思的地方。CX20106A 内部集成了前置放大、带通滤波、检波和施密特整形只要把中心频率从常用的 38kHz 拨到 40kHz它就能直接当作超声波回波解调器把微弱的反射波变成单片机认识的下降沿。而 74LS04 六反相器负责的是发射侧既能和 RC 组成 40kHz 振荡器也能给单片机输出的方波做缓冲和推挽驱动。单片机在这套系统里只干一件事记录发射到回波下降沿的时间再换成距离。无论你是要读懂例程、复刻板子还是想避开现成的超声波模块自己搭一套这个组合都值得完整啃一遍。2. 发射链路解剖74LS04 做 40kHz 方波发生器还是只做驱动缓冲2.1 为什么不能省掉 74LS04让单片机直接驱动发射头超声波发射头是一片压电陶瓷静态电容通常在 1500pF 到 2500pF 之间工作时要随着 40kHz 方波反复充放电。直接拿单片机的 P1 口去驱动不是完全不行但有三个实际麻烦。第一51 单片机复位期间所有 I/O 口输出高电平如果发射头直接挂在引脚上上电瞬间会出现一段不受控制的激励听起来像短促的“吱”一声。第二TTL 电平的单片机引脚强上拉能力有限尤其输出高电平时电流只有几百微安级别真正加到压电片上的电压摆幅不够回波幅度会明显变弱。第三发射头是感性负载吗它不是纯电感但作为容性负载在 40kHz 翻转时会产生不小的瞬态电流直接冲击引脚容易引入电源噪声这个噪声会顺着地线串进接收链路。74LS04 在这里首先是隔离和缓冲。它把 P1.0 的 40kHz 逻辑方波反相后输出压电片接在反相器输出端和地之间。复位状态 P1.0 为高74LS04 输出为低发射头两端都是低电平安静无声。等到程序启动后P1.0 开始翻转发射头才被激励。第二重作用是驱动能力74LS04 的低电平灌电流典型能达到 8mA比单片机引脚更从容。第三重作用是电平整形门电路输出的方波边沿比单片机引脚直接输出的更陡40kHz 方波的谐波成分更丰富压电片响应更好。2.2 三种常见接法单端、推挽和两路并联这一节直接对照着接线三种接法在例程包和实际板子里都出现过。单端接法是最标准的起步方案。P1.0 接 74LS04 的一个反相器输入反相器输出经过一颗 20Ω 左右的电阻接到发射头正极发射头负极接地。这里串电阻不是限流保护压电片而是抑制振铃20Ω 到 100Ω 都可以阻值太大声音会变小。上电时 P1.0 为高反相输出低发射头不响这是它最大的好处。缺点是 74LS04 输出高电平能力弱VOH 在输出负 0.4mA 时最低只有 2.7V所以给到发射头的正半周幅度偏低声音比推挽接法小。推挽接法能明显提高声压。用两个反相器输入接同一个点U1A 输出接发射头正极U1B 输出接发射头负极。无论输入是高还是低总有一个输出高、一个输出低发射头两端始终有接近电源电压的压差。74LS04 低电平侧的 8mA 灌电流是真正的驱动主力高电平侧只需要补充电压差正好避开 TTL 高电平输出能力弱的短板。代价是上电瞬间会短鸣一声这个问题不大。如果你想更响可以把两组反相器并联起来比如 U1C 和 U1D 并联后替代 U1A灌电流翻倍到 16mA发射头电压摆幅不变但驱动内阻更低。接法发射头连接方式上电状态特点单端74LS04 输出串 20Ω 接正极负极接地安静电路最简单声音偏小推挽两个反相器输出分别接发射头两脚短促鸣叫电压摆幅接近 5V声音明显更响双路并联两个反相器并联后做单端驱动安静灌电流翻倍适合发射头灵敏度低的批次如果你手里的例程包里发射头接在三极管或达林顿管上原理也一样发射信号高电平有效三极管导通把发射头负极拉到地形成一个单向脉冲。这种电路和 74LS04 的推挽接法相比少了负半周激励探测距离会短一截但省一颗芯片。标题既然点名了 74LS04优先按推挽来做。2.3 用 74LS04 和 RC 自激振荡出 40kHz 的参数思路除了给单片机方波做缓冲74LS04 也可以完全独立地产生 40kHz。经典结构是U1A 的输出端串电阻 R 回到自己的输入端输入端再对地接电容 CU1A 输出经过 U1B 整形后再去驱动发射链路。这样单片机只负责控制什么时候让振荡器工作40kHz 的产生完全不占定时器资源。很多文章会给你一个估算公式比如 f 约等于 1/(1.4RC) 或者 1/(2.2RC)但 74LS04 不是施密特触发器它的翻转阈值在 1.4V 附近且受电源电压和温度影响公式只能给个量级。我一般这样起步C 固定在 680pFR 先用 33kΩ 精密可调电阻通电后用频率计或者示波器测量 U1B 输出端慢慢调 R让频率落在 40kHz 附近。最后用固定电阻替换可调电阻再复测一次。需要知道大致方向的可以看这个表目标频率C 参考值R 调整范围说明38kHz680pF33kΩ 附近往下调红外接收常用中心频率40kHz680pF30kΩ 附近往下微调CX20106A 要配合调到 40kHz42kHz470pF33kΩ 附近避开 40kHz 环境干扰时用注意 74LS04 振荡器的输出波形边沿不算特别干净负载一变频率也会轻微漂移所以 resonate 频率不要盯死在小数点后一位38k 到 42k 之间 CX20106A 都能覆盖。关键是发射频率和接收中心频率必须一致否则回波幅度会肉眼可见地掉下去。3. 接收链路拆解CX20106A 的中心频率电阻、上拉电阻与输出波形3.1 CX20106A 为什么能兼职超声波接收前端CX20106A 的官方定位是红外遥控接收前置放大电路但它的内部结构很有意思前置放大器、限幅器、带通滤波器、检波器、积分器和施密特整形器全部做在一颗芯片里。这个链路对红外 38kHz 信号有效是因为外接电阻把带通滤波器中心频率设定在 38kHz同样的原理把中心频率挪到 40kHz它就能识别超声波发射头的回波。超声波接收头产生的信号只有毫伏级如果直接送进单片机噪声比信号还大。CX20106A 的前置放大器先把微弱信号放大带通滤波器把 40kHz 附近以外的频段滤掉限幅器保证强信号不饱和检波器把 40kHz 脉冲串变成包络积分器和施密特整形器再把包络整理成干净的数字电平。这一整套模拟处理用分立元件搭少说要七八个三极管和一堆电容用 CX20106A 一颗芯片加几个外围件就能完成。接收头接在 CX20106A 的第 1 脚和地之间。第 1 脚是前置放大器输入端内部有偏置电路一般不需要额外加偏置。如果实际灵敏度不够可以在第 1 脚到 VCC 之间并联一颗 10kΩ 左右的电阻相当于抬高输入端的直流工作点但注意不要引入电源噪声。接收头的两个引脚尽量剪短引脚过长会变成天线把 40kHz 的发射串扰直接耦合进来。3.2 关键引脚和中心频率电阻 R2 的调整方法CX20106A 一共有 8 个引脚超声波测距方案里真正要调的是第 2 脚外接电阻 R2。这颗电阻决定带通滤波器的中心频率。参考典型应用38kHz 时 R2 取 200kΩ 左右频率要提高就往小调40kHz 时通常在 150kΩ 到 180kΩ 区间。引脚功能本方案接法调参说明1前置放大输入接超声波接收头正极接收头负极接地灵敏度不足可加 10kΩ 偏置到 VCC2带通中心频率设定对地接 R2先装 200kΩR2 越大中心频率越低40kHz 往小调3检波电容通过 C3 接到第 4 脚C3 影响解调包络先照例程默认4积分电容通过 C4 接地C4 越大输出越稳但延迟越大5地直接接地尽量靠近芯片引脚接地6定时端外接 RC 到地影响内部定时一般不用调7整形输出10kΩ 上拉到 VCC接单片机 INT0平时高电平收到回波拉低8电源接 5V退耦电容 0.1uF退耦不良会引起误触发这里 R2 的方向判断有一个很实用的土办法。先装 200kΩ上电后用示波器看第 7 脚手持一张硬纸板在一米左右的位置晃动。如果第 7 脚几乎没有低电平脉冲说明中心频率偏高或偏低此时把 R2 换成 150kΩ 再试一次。两次都没有反应就往反方向找如果 150kΩ 有反应且低电平窗口更深说明频率已经靠近 40kHz。最后用精密可调电阻细调找到第 7 脚低电平脉冲最深、最稳定的点然后换固定电阻。3.3 集电极开路输出和 INT0 的接法CX20106A 的第 7 脚是集电极开路输出这意味着芯片内部只会把输出拉到低不会主动输出高电平必须外接一颗上拉电阻到 VCC。很多第一次做超声波的人栽在这里忘记上拉第 7 脚悬空INT0 输入电平不确定程序一跑起来就疯狂进中断测出来全是乱码。上拉电阻取 10kΩ 即可。电阻太小会增加静态功耗电阻太大会让上升沿变缓10kΩ 在 5V 和 TTL 输入电平下是稳妥的选择。第 7 脚直接接到 51 的 INT0 也就是 P3.2 上程序里把 IT0 置 1设置成下降沿触发。当 CX20106A 检测到连续的 40kHz 回波脉冲串时第 7 脚被拉低INT0 产生中断单片机在中断里读定时器值拿到的时间就是超声波从发射到返回的总时长。第 7 脚输出的低电平脉冲宽度不等于回波的完整时长它只是回波包络经过积分和整形后的结果。第 4 脚的积分电容 C4 会引入固定延迟这个延迟会让测距结果整体偏大几厘米但它的一致性很好可以在程序里减去一个固定偏移量来修正。C4 的取值是输出稳定性和延迟的权衡例程包里的默认值先不要动等整机精度测完再决定要不要换。4. 超声波测距程序核心定时器 0 计时、INT0 下降沿中断与温度修正4.1 测距周期的时序设计程序虽然短但时序错了整个测距都会乱。推荐的状态顺序是先发一段 40kHz 脉冲串脉冲个数控制在 8 到 12 个多了会增加余振和盲区少了回波幅度不够。发射结束后软件延时 1ms 到 2ms屏蔽掉发射头直接传过来的直达声。然后启动定时器 0 和 INT0 中断等待 CX20106A 第 7 脚的下降沿。收到下降沿就停表读计数值换算距离。为什么不在发射的同时启动定时因为 CX20106A 的增益很高发射瞬间的直达声和电源串扰几乎必然会让第 7 脚出现一个低电平毛刺这个毛刺不是反射回波。如果发射期间中断已经打开第一个下降沿会把计时停在一个非常小的值上测出来的距离只有几厘米。软件延时的 2ms 对应约 34cm 盲区这个长度对大部分测距应用是可接受的。4.2 完整可运行的主程序下面这段代码基于 STC89C52 或 AT89S52晶振 12MHz定时器 0 工作在方式 1也就是 16 位定时器。12MHz 晶振下机器周期是 1us所以定时器每计数一次正好是 1usTH0 和 TL0 组合出来的数值可以直接当作微秒用少一层换算程序在这个方案里最直观。#include REG52.H sbit TRIG P1^0; // 发射控制脚接 74LS04 输入 volatile unsigned int echo_time; // 回波时间计数值单位 us volatile bit has_echo; // 是否收到回波 void delay_us(unsigned int n) { while (n--) { _nop_(); _nop_(); // 12MHz 下接近 1us实际以示波器为准 } } void send_40k_burst(unsigned char n) { unsigned char i; for (i 0; i n; i) { TRIG 1; delay_us(12); // 半个周期约 12.5us TRIG 0; delay_us(13); // 凑满一个周期约 25us50kHz 不到一点 } } void int0_isr(void) interrupt 0 { has_echo 1; echo_time (TH0 8) | TL0; // 读到的就是微秒数 TR0 0; } void main(void) { unsigned int t; unsigned int distance_cm; int temp 25; // 可换成 DS18B20 采集值 TMOD 0x01; // 定时器 016 位模式 IT0 1; // INT0 下降沿触发 EX0 0; // 先关外部中断 TR0 0; EA 1; while (1) { has_echo 0; TH0 0; TL0 0; send_40k_burst(10); // 发射 10 个脉冲约 250us delay_us(2000); // 屏蔽盲区约 34cm TR0 1; // 发射结束才开始计时 EX0 1; // 打开 INT0等下降沿 while (!has_echo) { t (TH0 8) | TL0; // 主循环里检查超时 if (t 40000) { // 40ms 超时 has_echo 1; echo_time 40000; } } TR0 0; EX0 0; // 距离计算结果单位 cm // 声速公式v 331.4 0.607 * temp单位 m/s if (echo_time 40000) { distance_cm 9999; // 超量程标记 } else { // 除以 20000 是因为要换算成 cm 且除以 2往返 distance_cm (unsigned int)(echo_time * (331.4f 0.607f * temp) / 20000.0f 0.5f); } // 到这里把 distance_cm 送数码管、LCD1602 或串口显示 delay_us(60000); // 约 60ms 间隔等余振消失 } }这段代码的主循环里做了两件事发射完就等回波等的时候不断检查超时。这里超时检查直接读 TH0 和 TL0 是安全的因为定时器 0 不会在中断里修改这两个寄存器main 循环读到的组合值误差最多 1us。收到回波后中断会立刻停表并把 has_echo 置 1主循环退出等待进入距离换算。参数说明要特别注意三点。第一send_40k_burst 里的 delay_us 不是精确定时函数调用本身有开销实际频率可能落在 39kHz 到 41kHz 之间只要 CX20106A 的带通频率也对齐在这个范围就没问题。第二盲区屏蔽用了 2ms这是发射结束后直接等 2ms 再开定时器好处是 INT0 打开时直达声已经过去不会误触发。第三超时阈值 40ms 对应声速下约 6.9 米如果要更大量程可以改用定时器溢出中断来扩展高位计数值。4.3 距离换算的坑和温度修正常见的简化公式是距离等于时间乘以 0.017单位厘米。这个系数来自声速 340m/s0.034cm/us 是往返总距离除以 2 得到单程就是 0.017cm/us。常温下这个系数够用误差在 1% 左右但如果是户外设备冬天和夏天声速差 6%测 5 米会差 30 厘米。代码里的公式做了温度修正。声速 v 等于 331.4 加 0.607 乘以摄氏温度单位是 m/s。把 v 换算成 cm/us再乘时间再除以 2最后得到厘米。化简后的系数就是 331.4 加 0.607 乘温度除以 20000。25 摄氏度时这个系数约等于 0.01733和常用的 0.017 很接近但温度越低偏差越大。温度传感器可以用 DS18B20接到 51 后读出的温度值直接替换代码里 temp 变量的初始值 25 就行。实测精度要求不高的话还可以在程序里留一个全局变量 distance_offset先用卷尺量 1 米位置看程序显示多少比如显示 104cm就把 distance_offset 设为负 4。这个偏移量主要吸收 CX20106A 积分电容带来的固定延迟。5. 调测三步把中心频率电阻、声速系数和滤波策略一次定下来5.1 第一步示波器看 7 脚波形定 R2接通电源前先把 CX20106A 第 2 脚的 R2 装成 200kΩ第 7 脚接好 10kΩ 上拉。示波器探头接第 7 脚触发方式设成下降沿。程序烧一版连续测距的然后在一米处放一块硬纸板来回晃动。观察第 7 脚的低电平脉冲如果低电平深度不够或者干脆没有把 R2 换成 150kΩ 再试。这个过程通常两三轮就能找到 40kHz 附近的点。没有示波器的话可以在第 7 脚接一个 LED 和 1kΩ 限流电阻到 VCC有回波时 LED 会闪亮靠目测亮度变化也能大致判断频率是否对准但没法精细调整。R2 最终确定后用固定精度 1% 的金属膜电阻替代可调电阻并在 2 脚到地之间并联一颗 101 电容也就是 100pF不影响频率能滤掉高频毛刺。5.2 第二步用 1 米和 3 米两个点标定偏移量把程序里的温度补偿先关掉固定用 25 摄氏度。在平整的地面上拉一条卷尺把测距板放在 0 点障碍物放在 1 米处串口打印出 raw 的时间计数记为 t1。再把障碍物放到 3 米处打印时间计数记为 t2。用 t2 减 t1除以 200cm得到一个实测的 cm/us 系数。这个系数和理论声速的差值就是 CX20106A 内部处理引入的系统延迟来源之一。更简单的做法是直接记录 1 米处显示值算出与 100cm 的差把这个差作为固定减数写进程序。比如显示 104cm就减 4。为什么不在代码里改系数因为延迟是加法性的不是比例性的2 米距离时同样偏大 4cm 左右减固定值比改系数更稳。5.3 第三步三次测量取中值而不是平均值超声波回波有一个特点偶尔会有野值比如电机噪声、翻页声、风扇气流这些会让某一次测距突然大或突然小。平均值会被野值拉偏中值不会。连续测三次排序后取中间那个数作为最终结果。实现上只需要一个三个数的数组冒泡排序都省了中间元素就是 result。这颗 CX20106A 的核心技巧是把 2 脚电阻当作可调元件来对待而不是照抄公式。每次改完 R2 后重新上电让 CX20106A 的积分电容完全放电再观察波形。板上预留两个测试点一个接 CX20106A 的第 2 脚一个接第 7 脚后续调试不用翻板子。这套 74LS04 加 CX20106A 的超声波测距程序调完这三步距离数据就能稳定到可以拿去比对的水平。本文还有配套的精品资源点击获取
返回列表