开箱帖认了板,过程帖打完了黑块那场仗,这一篇是收官:把整台测距仪的框图、接线、关键代码和实测效果一次摆全。
一、项目概述
本项目以 NXP FRDM-MCXA153 开发板(MCXA153,Cortex-M33,主频 96 MHz)为核心,搭配 HC-SR04 超声波模块和 NHD-0116AZ-FL-YBW 1×16 字符 LCD,实现一台裸机简易超声波测距仪:周期约 10 Hz 测量前方距离,LCD 实时显示 `Dist: xxx.x cm`,同时经 LPUART0(115200)打印到串口,便于对照。无 RTOS,逻辑全部在主循环 + 一个定时器中断里完成。
二、系统框图

测距链路:Trig 发 10 µs 高电平 → 模块发 40 kHz 超声 → Echo 拉高,脉宽正比距离 → CTIMER 捕获上升/下降沿算出脉宽 → 换算距离 → LCD 与串口输出。
三、电路原理图(接线表)
供电:HC-SR04、LCD 逻辑与背光均接 **J3-10 SYS_5V0(5V)**,地接 **J3-12 GND**,三者共地。
| 信号 | 器件脚 | MCU 脚 | 板座 | 说明 |
| Trig | HC-SR04 Trig | P1_9 | J2-20 | GPIO 输出 |
| Echo | HC-SR04 Echo | P1_8 | J2-18 | 经 10k/15k 分压到约 3.0V,接 CTIMER0 CAP0 |
| RS | LCD pin4 | P3_15 | J2-2 | GPIO 输出 |
| R/W | LCD pin5 | GND | J3-12 | 硬件接地,只写 |
| E | LCD pin6 | P3_14 | J2-4 | GPIO 输出,下降沿锁存 |
| DB0~DB7 | LCD pin7~14 | P1_4/P1_5/P2_4/P3_0/P2_5/P3_12/P3_13/P3_1 | J1 | 8 位数据 |
| V0 | LCD pin3 | 10kΩ/1kΩ 固定分压 | — | 对比度 ≈0.45V(落在 0.3~0.8V 窗口即可;有电位器也可) |
| LED+/LED- | LCD pin15/16 | 5V / GND | J3-10/J3-12 | 背光约 110 mA |
Echo 分压:`Echo(5V) ─ 10kΩ ─┬─ P1_8(≈3.0V)`,再经 `15kΩ` 到 GND。
V0 说明:V0 是模拟偏置脚不是逻辑电平脚,必须落在 **0.3~0.8 V**(对应 VLCD 4.2~4.7 V)。手头没有电位器,用 10kΩ+1kΩ 固定分压得到 0.45 V,一次到位;接 GND(VLCD 超上限)或接 3.3 V(VLCD 低于下限)都会看不到东西。
四、如何开启运行
1. 编译:工程基于 CMake + MCUXpresso SDK。引脚与 CTIMER 由 Config Tools(`hello_world.mex`)生成,编译入口 `CMakeLists.txt`,产物为 `.bin`。
2. 烧录:通过板载 MCU-Link,USB 连接 J15,下载固件。
3. 运行:上电后 `BOARD_InitHardware()` 完成引脚/时钟/外设初始化,`HCSR04_Init()` 启动定时器,`LCD_Init()` 初始化屏并显示 `HC-SR04 ready`,随后进入测距主循环。
4. 观察:打开串口助手(115200),开机打印 banner `HC-SR04 + LCD. Echo must be divided to ~3.0 V on P1_8.`,随后测距行格式为 `dist=x.x cm (raw y.y) echo=xxx us`(raw 是滤波前单次值,便于对照);LCD 同步显示滤波后的距离。
五、主要参数情况
| 参数 | 数值 |
| 量程 | 2~400 cm(最佳 10~250 cm) |
| 显示分辨率 | 0.1 cm(1 mm) |
| 刷新率 | 约 10 Hz(测量间隔 100 ms) |
| 软件滤波 | 3 点中值(有效帧入窗;连续无效保持 2 帧后刷 `--.-`) |
| 单次测量超时 | 30 ms(Match0) |
| 时基 | CTIMER0 96 MHz ÷ 95 = 1 µs/tick |
| 距离公式 | `d_cm = t_us / 58`,`mm = (t_us×10 + 29) / 58`(四舍五入) |
| 供电 | 器件 5V,MCU IO 3.3V |
六、实现步骤与关键代码
软件分层:芯片层(mex 生成的 `pin_mux.c`/`peripherals.c`)负责"脚是什么功能",驱动层(`hcsr04.c`/`lcd_st7066u.c`)负责"按协议说话"。
① 超声状态机(`Idle→WaitRise→WaitFall→Done`),CTIMER 回调里只记时间、置标志:
void HCSR04_CtimerCallback(uint32_t flags)
{
if (((flags & (uint32_t)kCTIMER_Capture0Flag) != 0U) &&
((s_state == kHcsr04_WaitRise) || (s_state == kHcsr04_WaitFall)))
{
uint32_t cap = CTIMER_GetCaptureValue(HCSR04_CTIMER, HCSR04_CAPTURE);
if (s_state == kHcsr04_WaitRise) {
s_riseTicks = cap;
s_state = kHcsr04_WaitFall;
} else {
s_echoUs = cap - s_riseTicks; /* 无符号减,脉宽 */
s_valid = (s_echoUs >= 116U) && (s_echoUs <= 30000U);
s_state = kHcsr04_Done;
}
}
if (((flags & (uint32_t)kCTIMER_Match0Flag) != 0U) &&
((s_state == kHcsr04_WaitRise) || (s_state == kHcsr04_WaitFall))) {
s_echoUs = 0U; s_valid = false; s_state = kHcsr04_Done; /* 超时 */
}
}② 主循环:发 Trig → 等完成 → 读距离 → 中值滤波 → 刷屏 + 打印:
while (1) {
HCSR04_Start();
while (!HCSR04_IsDone()) { }
mm = HCSR04_GetDistanceMm(); /* 无效返回 -1 */
shown = DistanceFilter(mm); /* 3 点中值,飞点剔除 */
LCD_ShowDistance(shown);
PRINTF("dist=%d.%d cm (raw %d.%d) echo=%u us\r\n", ...);
SDK_DelayAtLeastUs(100000U, CLOCK_GetCoreSysClkFreq());
}③ LCD 处理 DDRAM 断点:写到第 9 字跳地址到 `0x40`,并用固定 16 字符覆盖写避免清屏闪烁。
④ 3 点中值滤波(`DistanceFilter()`):有效帧进 3 深环形缓冲取中值,孤立飞点被直接顶掉;偶发无效帧在 2 帧内沿用上次显示值防闪屏,连续第 3 帧无效则清缓冲、刷 `--.-`;缓冲未满(上电/清空后)单帧直出,行为与未滤波一致。
七、软件调试心得
这一路从超声调到 LCD、再从黑块里杀出来,攒下几条实打实的心得:
用 CTIMER 输入捕获而非 `while` 轮询读 GPIO,时间戳由硬件打,近距一百多微秒也测得准,不受写屏、打印的抖动影响。
超时靠 Match0 兜底:无目标时 Echo 可能一直为低,不能死等下降沿。
ISR 里绝不写 LCD、不打印,只更新状态变量(均 `volatile`),避免拖死捕获。
先启动定时器再发 Trig,防止近距目标 Echo 来得太快丢上升沿。
板载 RGB LED 是免费的总线监视器:DB3/DB5/DB6 与 RGB 共脚,写屏正常时灯呈青白色(总线静态停在空格 0x20 → 蓝灯+绿灯亮);若常亮纯白,说明引脚停在初始低电平、写屏代码根本没在跑——这次排查旧固件就是靠灯色发现的。
黑块排障首选"总线自检:加一个编译期开关,让十根线逐根单独拉高、串口实时报"该去 LCD 第几脚量",万用表一轮量完通断+线序+电平,比肉眼对线可靠得多。DB6 断线就是靠"pin13 量到 4.66 V"暴露的——3.3 V 推挽输出物理上给不出 4.66 V,只能是悬空泄漏电平。
八、效果演示
代码全部落地,来验货。上电后 LCD 显示 `HC-SR04 ready`,随即进入测距。对准静止目标(约 58 cm),单次测量在 58.0~59.3 cm 之间抖动(±0.7 cm,HC-SR04 典型水平),经 3 点中值滤波后 LCD 锁定单一读数,只有目标真实移动才跳变;串口同步输出 `dist=58.4 cm (raw 59.3) echo=3387 us`,滤波前后值同屏可对照。目标拉远到约 2 m,回波变间歇(约每 5 帧一次有效),滤波的保持/超时序列正确接管,LCD 不闪 `--.-`;目标完全移出量程后 3 帧内刷为 `Dist: --.- cm` 并打印超时。用尺子在 10/30/100 cm 标定,误差在可接受范围内。



九、总结
这次用 MCXA153 的 CTIMER 捕获 + GPIO 模拟并口,把"超声波测距仪"完整跑通。三篇帖子从开箱、踩坑到收官,收获集中在两块:
电平边界的账要提前算。 Echo 分压、LCD R/W 接地只写、DDRAM 断点、V0 对比度窗口(0.3~0.8 V,固定电阻分压即可,没电位器也能玩)——3.3V MCU 与 5V 器件混接的每一处边界,方案阶段算清楚,比现场翻手册快得多。
黑盒排障有三板斧。板载 RGB LED 当总线活动指示(灯色即静态电平指纹)、编译期总线自检逐根扫线、用"悬空 4.66 V 不可能出自 3.3 V 推挽"这类物理判据锁定断线——DB6 断线就是这么揪出来的。
这颗 MCU 的家底还没摸完,后续还有不少可玩的:温度补偿声速(`d=t/58` 固定按 340 m/s 算,室温偏差能到 ±2%)、串口协议帧对接上位机、低功耗间歇测量,看时间慢慢填坑。感谢活动方提供的机会,代码与文档已整理,欢迎评论区交流。
我要赚赏金
