这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【let'sdo|2026年第2期】简易超声波测距仪实践【过程-任务2:超声波数

共1条 1/1 1 跳转至

【let'sdo|2026年第2期】简易超声波测距仪实践【过程-任务2:超声波数据显示】

助工
2026-09-12 22:03:23     打赏


一、硬件介绍

1、产品特点

FRDM-MCXA153是一款NXP推出的基于Arm Cortex-M33内核(96MHz)开发板,搭载128KB带ECC纠错Flash与32KB SRAM,板载MCU-Link高速调试器,双USB‑C分别用于调试通信与设备功能,集成RGB指示灯、PMOD接口、用户按键、温度传感器等资源;




主要特性

内核:Arm Cortex-M33(96MHz),无FPU / TrustZone

Flash:128KB(ECC 校验,1 位纠错、2 位检错)

SRAM:32KB,其中8KB 支持 ECC


芯片运行功耗:59μA/MHz

掉电模式(SRAM 全保留):6.5μA

深度掉电休眠:0.39μA(394nA)


集成 MCU-Link 片上调试器(主控 LPC55S69)

RGB三色LED

3个用户按键(Reset、WakeUp、ISP)

I3C/I2C 数字温度传感器(P3T1755)


系统框图



2、引脚示意图



3、超声波测距模块

Unit Ultrasonic-IO 是一款GPIO接口的超声波测距传感器;

硬件采用RCWL-9620超声波测距单芯片搭配16mm探头,能够实现2cm-450 cm范围内的精准测距;



主要特性


二、环境搭建

详见【快速环境搭建



三、功能实现

1、硬件搭建

将超声波测距模块连接到开发板的PMOD接口的对应引脚上;



实物搭建效果:


image.png




2、功能效果

效果:MCU读取超声波模块检测到的数据,并通过板载的MCU-Link串口,发送至串口助手上进行实时显示;


超声波模块工作原理

通过外部MCU给模块Trig脚一个大于10uS的高电平脉冲;

模块会给出一个与距离等比的高电平脉冲信号,可根据脉宽时间“T”算出当前距离;


距离 = T * C / 2 (C为声速)


声速温度公式:c ≈ 331.5 + 0.61 * t

例:25℃:

c ≈ 331.5 + 0.61 * 25 = 346.75 m/s


时序图




四、代码编写

1、导入SDK中的 led blinky 模板;


2、使用 Config Tools 图形化工具,配置相关引脚功能;



导入当前工程文件目录下的 led_blinky.mex文件 进行配置;


3、引脚功能配置

GPIO3_12:LED_RED

GPIO3_27:ECHO_PIN (开启 双边沿触发)

GPIO3_28:TRIG_PIN


4、时钟配置

使用内部RC时钟源

系统主频 96Mhz

FRO_HF_clock / LPUART0_clock:96Mhz


5、外设功能配置

GPIO3_IRQn:ECHO引脚中断优先级配置;


板载串口功能配置:串口打印



Sys定时计数器:延时


主要相关代码

主要运行流程:引脚/外设/串口等初始化 → SysTick计数器 → 发11us脉冲触发 → 等ECHO边沿中断记录时间 → 根据脉宽换算距离 → 串口打印;


在原有基础上 led blinky.c 中进行代码修改;

将TRIG (P3_28)设置为输出,将ECHO (P3_27)设置为输入;

将TRIGPin设定为高电平状态,持续11微秒;

读取ECHOPin,返回以微秒为单位的声波移动时间 T;


最后 根据公式 距离 = T * C / 2 进行计算

(声速C采用:340m/s)

对距离值,使用中值滤波(3次取中值)


#include "fsl_device_registers.h"
#include "fsl_debug_console.h"
#include "board.h"
#include "peripherals.h"
#include "clock_config.h"
#include "fsl_adapter_gpio.h"

// TRIG = P3_28
#define HC_SR04_TRIG_HANDLE BOARD_INITPINS_TRIG_PIN_handle
// ECHO = P3_27
#define HC_SR04_ECHO_HANDLE BOARD_INITPINS_ECHO_PIN_handle

volatile uint32_t echo_start_tick = 0U;
volatile uint32_t echo_end_tick = 0U;
volatile uint8_t echo_capture_done = 0U;

void Systick_FreeCounter_Init(void)
{
    SysTick->LOAD = 0xFFFFFFU;
    SysTick->VAL = 0U;
    SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
}

/*
 * ECHO 引脚中断回调
 * 由 GPIO3_IRQHandler 自动分发并自动清中断标志
 * 读引脚电平判断上升/下降沿
 */
static void HC_SR04_Echo_Callback(void *param)
{
    uint8_t level;
    (void)param;
    (void)HAL_GpioGetInput(HC_SR04_ECHO_HANDLE, &level);
    if (level != 0U)
    {
        echo_start_tick = SysTick->VAL;
        echo_capture_done = 0U;
    }
    else
    {
        echo_end_tick = SysTick->VAL;
        echo_capture_done = 1U;
    }
}

void HC_SR04_Gpio_Init(void)
{
    /* 注册 ECHO 中断回调 */
    (void)HAL_GpioInstallCallback(HC_SR04_ECHO_HANDLE, HC_SR04_Echo_Callback, NULL);
    /* 双边沿中断触发 */
    (void)HAL_GpioSetTriggerMode(HC_SR04_ECHO_HANDLE, kHAL_GpioInterruptEitherEdge);
}

/*
 * 基于 SysTick 的延时
 * 1us = 96 ticks;SysTick->VAL 递减计数
 */
static void delay_us(uint32_t us)
{
    uint32_t start = SysTick->VAL;
    uint32_t ticks = us * 96U;
    while (((start - SysTick->VAL) & 0xFFFFFFU) < ticks)
    {
    }
}

static void delay_ms(uint32_t ms)
{
    while (ms > 0U)
    {
        delay_us(1000U);
        ms--;
    }
}

void HC_SR04_Trigger(void)
{
    (void)HAL_GpioSetOutput(HC_SR04_TRIG_HANDLE, 1U);
    delay_us(11); /* TRIG ≥10us 精准延时 */
    (void)HAL_GpioSetOutput(HC_SR04_TRIG_HANDLE, 0U);
}

float HC_SR04_ReadDistance(void)
{
    uint32_t delta_tick;
    uint32_t pulse_us;
    uint32_t timeout = 0U;
    echo_capture_done = 0U;
    HC_SR04_Trigger();
    while ((echo_capture_done == 0U) && (timeout < 300000U))
    {
        timeout++;
    }

    if (echo_capture_done == 0U)
    {
        return 0.0f;
    }

    if (echo_end_tick > echo_start_tick)
    {
        delta_tick = (0xFFFFFFU - echo_start_tick) + echo_end_tick;
    }
    else
    {
        delta_tick = echo_start_tick - echo_end_tick;
    }

    pulse_us = delta_tick / 96U;
    float distance_cm = ((float)pulse_us * 0.034f) / 2.0f;
    return distance_cm;
}

/*
 * 3点中值滤波
 */
static float Median_Filter_3(float a, float b, float c)
{
    if (a > b)
    {
        float t = a;
        a = b;
        b = t;
    }
    if (b > c)
    {
        float t = b;
        b = c;
        c = t;
    }
    if (a > b)
    {
        float t = a;
        a = b;
        b = t;
    }
    return b;
}

int main(void)
{
    float dist;
    BOARD_InitBootClocks();      // 96MHz
    BOARD_InitPins();            // 引脚功能初始化
    BOARD_InitBootPeripherals(); // 外设功能初始化
    BOARD_InitDebugConsole();    // 板载串口功能初始化

    HC_SR04_Gpio_Init();        // 超声波模块初始化
    Systick_FreeCounter_Init(); // SysTick 计数器初始化

    while (1)
    {
        /* 3点中值滤波 */
        dist = Median_Filter_3(HC_SR04_ReadDistance(),
                               HC_SR04_ReadDistance(),
                               HC_SR04_ReadDistance());

        /* 有效量程 2cm ~ 450cm */
        if ((dist >= 2.0f) && (dist <= 450.0f))
        {
            PRINTF("Distance = %.2f cm\r\n", dist);
        }
        else
        {
            PRINTF("No echo(timeout)\r\n");
        }
        delay_ms(200);
    }
}



五、程序烧录

1、连接USB数据线至开发板MUC-LINK端口;

2、右键当前工程项目;

3、点击 Flash the Selected Target 烧录程序到开发板上;




六、效果演示

















共1条 1/1 1 跳转至

回复

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