这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【成果帖】基于FRDM-MCXA153的简易超声波测距仪

共1条 1/1 1 跳转至页

【成果帖】基于FRDM-MCXA153的简易超声波测距仪

菜鸟
2026-10-07 00:10:12     打赏

一、项目概述

本项目基于 NXP FRDM-MCXA153 开发板(Cortex-M33 @ 96 MHz),以 HC-SR04 兼容超声波模块 作为距离传感器,通过 SSD1306 OLED 显示屏 实时显示测距结果,最终实现一台结构完整、运行稳定的简易超声波测距仪。

实现的功能

超声波测距:4 cm ~ 400 cm 范围,厘米级显示精度

OLED 实时刷新:距离数值

串口同步回显:MCU-Link 虚拟串口 115200 波特率输出原始数据


二、系统总体框图

┌─────────────────┐      Trig (GPIO)       ┌──────────────┐
│                 │ ──────────────────────> │              │
│                 │                         │   HC-SR04    │
│                 │ <────────────────────── │  超声波模块   │
│   FRDM-MCXA153  │      Echo (CTIMER IN7)  │              │
│                 │                         └──────────────┘
│   (主控 MCU)     │
│                 │      SDA / SCL (I2C)    ┌──────────────┐
│                 │ ──────────────────────> │              │
│                 │                         │  SSD1309 OLED │
│                 │ <───────────────────── │  128×64 I2C  │
│                 │                         │   显示屏      │
│                 │                         └──────────────┘
│                 │
│                 │      USB Type-C         ┌──────────────┐
│                 │ <──────────────────────> │   电脑 / 串口  │
│                 │   (MCU-Link 虚拟串口)    │   调试终端    │
└─────────────────┘                         └──────────────┘

整个系统的信号链路非常清晰:MCU 触发超声波模块 → 定时器捕获回响脉宽 → 换算成距离值 → 分别送到 OLED 屏和串口输出


三、硬件设计与接线

3.1 物料清单

序号物料型号接口数量
1主控板NXP FRDM-MCXA153—1
2超声波模块HC-SR04 兼容GPIO + 输入捕获1
3OLED 显示屏SSD1306 驱动,128×64I2C1

3.2 接线表

功能MCU 引脚外设引脚说明
超声波触发P3_14TrigGPIO 推挽输出,10 μs 高脉冲触发
超声波回响P3_15 (CT_INP7)EchoCTIMER0 通道 7 输入捕获
I2C 数据线P3_28 (LPI2C0_SDA)OLED SDALPI2C0 数据总线
I2C 时钟线P3_27 (LPI2C0_SCL)OLED SCLLPI2C0 时钟总线

四、软件设计

4.1 软件架构分层

┌─────────────────────────────────┐
│        应用层(主循环)          │
│   测距状态机 + 显示刷新 + LED   │
├─────────────────────────────────┤
│        驱动层                    │
│  ┌─────────┐ ┌────────┐ ┌────┐│
│  │ultra_sr04│ │oled_ss1309│ │led││
│  └─────────┘ └────────┘ └────┘│
├─────────────────────────────────┤
│        MCUXpresso SDK BSP        │
│  GPIO / CTIMER / LPI2C / LPUART│
└─────────────────────────────────┘

4.2 超声波驱动(CTIMER 输入捕获)

这部分在过程帖里已经详细讲过了,核心思路就是:

  • GPIO 给 10 μs 高脉冲触发测距

  • Echo 上升沿 → CTIMER 记录时间戳 t1

  • Echo 下降沿 → CTIMER 记录时间戳 t2

  • 脉宽 = t2 - t1,距离 = 脉宽(μs) × 0.017 cm

4.3 SSD1306 OLED 驱动(LPI2C 轮询模式)

I2C 通信协议要点:

  • 器件地址:0x3C(7 位地址,R/W 位由硬件自动处理)

  • 控制字节:第 6 位(Co)= 0 表示后续全是数据,= 1 表示后面跟命令

    • 发命令:控制字节 = 0x00

    • 发显存数据:控制字节 = 0x40

  • 总线速率:400 kHz Fast Mode

OLED 驱动核心函数:

/**
  * 函    数:OLED写命令
  * 参    数:Command 要写入的命令值,范围:0x00~0xFF
  * 返 回 值:无
  */
void OLED_WriteCommand(uint8_t Command)
{
    uint8_t transferData[2] = {0x00U, Command};
    lpi2c_master_transfer_t transfer = {0};

    transfer.slaveAddress = 0x3CU;
    transfer.direction = kLPI2C_Write;
    transfer.data = transferData;
    transfer.dataSize = sizeof(transferData);
    (void)LPI2C_MasterTransferBlocking(LPI2C0_PERIPHERAL, &transfer);
}

/**
  * 函    数:OLED写数据
  * 参    数:Data 要写入数据的起始地址
  * 参    数:Count 要写入数据的数量
  * 返 回 值:无
  */
void OLED_WriteData(uint8_t *Data, uint8_t Count)
{
    uint8_t transferData[129];
    lpi2c_master_transfer_t transfer = {0};

    transferData[0] = 0x40U;
    memcpy(&transferData[1], Data, Count);
    transfer.slaveAddress = 0x3CU;
    transfer.direction = kLPI2C_Write;
    transfer.data = transferData;
    transfer.dataSize = (size_t)Count + 1U;
    (void)LPI2C_MasterTransferBlocking(LPI2C0_PERIPHERAL, &transfer);
}

字模用的是 8×16  ASCII 字库,直接从数组里查表取模,往显存里塞就行。

4.4 主循环逻辑

while (1)
    {
        HCSR04_TriggerMeasurement();

        /* Keep a 200 ms trigger period; CTIMER interrupts handle capture/timeout. */
        SDK_DelayAtLeastUs(HCSR04_MEASURE_INTERVAL_US, SystemCoreClock);

        /* Fail safe if the expected 30 ms match interrupt did not arrive. */
        if ((s_hcsr04State == kHcsr04WaitingForRise) ||
            (s_hcsr04State == kHcsr04WaitingForFall))
        {
            CTIMER_StopTimer(HCSR04_CAPTURE_TIMER);
            s_hcsr04State = kHcsr04TimedOut;
        }

        if (s_hcsr04State == kHcsr04Complete)
        {
            /* distance in tenths of a centimeter: ticks * 343 / 192,000 */
            uint32_t distanceTenthsCm = (s_pulseWidthTicks * 343U) / 192000U;
            PRINTF("Echo pulse: %u ticks, distance: %u.%u cm\r\n",
                   (unsigned int)s_pulseWidthTicks,
                   (unsigned int)(distanceTenthsCm / 10U),
                   (unsigned int)(distanceTenthsCm % 10U));
            OLED_ClearArea(0, 32, 128, 16);
            OLED_Printf(0, 32, OLED_8X16, "%u.%u cm",
                        (unsigned int)(distanceTenthsCm / 10U),
                        (unsigned int)(distanceTenthsCm % 10U));
        }
        else
        {
            PRINTF("HCSR04 timeout (>30 ms)\r\n");
            OLED_ClearArea(0, 32, 128, 16);
            OLED_ShowString(0, 32, "No echo", OLED_8X16);
        }

        OLED_UpdateArea(0, 32, 128, 16);

    }

五 运行效果

微信图片_20261006232348_357_4.jpg

▲ 近距离(约 4 cm)

微信图片_20261006232349_358_4.jpg▲ 中距离(约 40 cm)




共1条 1/1 1 跳转至页

回复

匿名不能发帖!请先 [ 登陆 注册 ]