这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 简易超声波测距仪实践过程贴-测量距离并显示

共1条 1/1 1 跳转至

简易超声波测距仪实践过程贴-测量距离并显示

助工
2026-08-18 17:30:30     打赏

一、硬件连接

 FRDM-MCXA153板子上有个microBUS接口,有5V供电输出,用来给超声波模块供电。超声波模块:Trig连接P3_28;Echo连接P3_27; P3_15脚做为串口输出,连接到StickS3的G5管脚。FRDM-MCXA153板子与StickS3的GND用导线连接起来。

f7b3af68d3765dbe263811b2e0a4421e.jpg17784a9d911494bbdecfd852b18ba4b6.jpg

二、软件编程

软件编程,我使用的是官方的MCUXpresso IDE v25.6,使用例程“frdmmcxa153_gpio_input_interrupt”来进行修改。

超声波测距模块,通过拉高Trig管脚并维持20us,触发模块发出一束超声波,当超声波遇到障碍物反射回来,被接收到,会触发Echo管脚电平由高变低变换。 FRDM-MCXA153开发板通过中断获取Echo的电平变换,并计时,计算出超声波在空气中运动的时长,计算出距离信息。

image.png

超声波使用两个GPIO,一个负责触发Trig,为输出IO,一个用来检查Echo,为输入IO。

static void Ultrasonic_Init(void)
{
gpio_pin_config_t trig_config = {
kGPIO_DigitalOutput,
0,
};

gpio_pin_config_t echo_config = {
kGPIO_DigitalInput,
0,
};

GPIO_PinInit(ULTRASONIC_TRIG_GPIO, ULTRASONIC_TRIG_GPIO_PIN, &trig_config);
GPIO_PinInit(ULTRASONIC_ECHO_GPIO, ULTRASONIC_ECHO_GPIO_PIN, &echo_config);

GPIO_SetPinInterruptConfig(ULTRASONIC_ECHO_GPIO, ULTRASONIC_ECHO_GPIO_PIN, kGPIO_InterruptEitherEdge);
EnableIRQ(ULTRASONIC_ECHO_IRQ);

GPIO_PinWrite(ULTRASONIC_TRIG_GPIO, ULTRASONIC_TRIG_GPIO_PIN, 0);
}

触发Trig的代码:

static int32_t Ultrasonic_ReadDistanceMm(void)
{
uint32_t timeout_start;

g_echo_stage = ECHO_IDLE;
g_echo_valid = false;

GPIO_GpioClearInterruptFlags(ULTRASONIC_ECHO_GPIO, 1U << ULTRASONIC_ECHO_GPIO_PIN);

if (GPIO_PinRead(ULTRASONIC_ECHO_GPIO, ULTRASONIC_ECHO_GPIO_PIN) == 0U)
{
g_echo_stage = ECHO_WAIT_RISING;
}

GPIO_PinWrite(ULTRASONIC_TRIG_GPIO, ULTRASONIC_TRIG_GPIO_PIN, 1);
DelayUs(20);
GPIO_PinWrite(ULTRASONIC_TRIG_GPIO, ULTRASONIC_TRIG_GPIO_PIN, 0);

timeout_start = g_micros;
while (!g_echo_valid)
{
if ((g_micros - timeout_start) > 150000U)
{
g_echo_stage = ECHO_IDLE;
return -1;
}
}

return (int32_t)(((uint64_t)(g_echo_end_us - g_echo_start_us) * 343U) / 2000U);
}

中断接收的代码:

void ULTRASONIC_ECHO_IRQ_HANDLER(void)
{
uint32_t flags = GPIO_PortGetInterruptFlags(ULTRASONIC_ECHO_GPIO);

if (flags & (1U << ULTRASONIC_ECHO_GPIO_PIN))
{
uint32_t pin_state = GPIO_PinRead(ULTRASONIC_ECHO_GPIO, ULTRASONIC_ECHO_GPIO_PIN);

switch (g_echo_stage)
{
case ECHO_IDLE:
if (pin_state == 0U)
{
g_echo_stage = ECHO_WAIT_RISING;
}
break;

case ECHO_WAIT_RISING:
if (pin_state != 0U)
{
g_echo_start_us = g_micros;
g_echo_stage = ECHO_WAIT_FALLING;
}
break;

case ECHO_WAIT_FALLING:
if (pin_state == 0U)
{
g_echo_end_us = g_micros;
g_echo_valid = true;
g_echo_stage = ECHO_DONE;
}
break;

default:
break;
}

GPIO_GpioClearInterruptFlags(ULTRASONIC_ECHO_GPIO, 1U << ULTRASONIC_ECHO_GPIO_PIN);
}

SDK_ISR_EXIT_BARRIER;
}

主函数通过循环,不停滴触发超声波模块发出超声波测距,然后通过串口展示获得的距离信息。

int main(void)
{
uint32_t echo_state;
char buf[64];

BOARD_InitHardware();

PRINTF("\r\n====================================================\r\n");
PRINTF(" Ultrasonic Sensor (Interrupt Mode)\r\n");
PRINTF(" TRIG: P3_28, ECHO: P3_27\r\n");
PRINTF(" SystemCoreClock: %u Hz\r\n", SystemCoreClock);
PRINTF(" Secondary UART: P3_15 (LPUART2_TXD) 115200\r\n");
PRINTF("====================================================\r\n\r\n");

Secondary_UART_Init();
Secondary_UART_SendString("Ultrasonic Sensor UART Ready\r\n");

Ultrasonic_Init();

echo_state = GPIO_PinRead(ULTRASONIC_ECHO_GPIO, ULTRASONIC_ECHO_GPIO_PIN);
PRINTF("[INIT] ECHO=%u, IRQ enabled\r\n", echo_state);

SysTick_Config(SystemCoreClock / 1000000U);
PRINTF("[SYSTICK] 1us tick started\r\n\r\n");

while (1)
{
int32_t distance = Ultrasonic_ReadDistanceMm();

if (distance < 0)
{
echo_state = GPIO_PinRead(ULTRASONIC_ECHO_GPIO, ULTRASONIC_ECHO_GPIO_PIN);
PRINTF("[MEASURE] No echo! ECHO=%u\r\n", echo_state);
snprintf(buf, sizeof(buf), "ERR,ECHO=%u\r\n", echo_state);
Secondary_UART_SendString(buf);
}
else
{
PRINTF("[MEASURE] Distance: %u mm\r\n", distance);
snprintf(buf, sizeof(buf), "%u  \n", (unsigned int)distance);
Secondary_UART_SendString(buf);
}

DelayUs(500000U);
}
}

image.png

除了通过烧写口的串口读取获取到的信息外,还启动了串口2,将获得的距离信息,以字符串的方式发送给串口2。串口2为输出串口,波特率使用115200。

static void Secondary_UART_Init(void)
{
lpuart_config_t config;

CLOCK_SetClockDiv(kCLOCK_DivLPUART2, 1U);
CLOCK_AttachClk(kFRO12M_to_LPUART2);

LPUART_GetDefaultConfig(&config);
config.baudRate_Bps = 115200U;
config.enableTx = true;
config.enableRx = false;

LPUART_Init(s_secondary_uart, &config, 12000000U);
}

三、距离信息展示

StickS3是一个以ESP32S3为核心的开发板,板子自带一个彩色的显示屏,有排针引出部分GPIO。StickS3使用arduino编程,做了个简单的展示功能,从串口接收到数据,然后直接在屏幕上进行展示。

#include "M5Unified.h"

static const int RX_BUF_SIZE = 8;
static char rx_buf[RX_BUF_SIZE] = {0};
static String rx_str = "";
static bool data_updated = false;

void setup()
{
    M5.begin();
    M5.Power.setExtOutput(false);
    Serial.begin(115200);

    Serial1.begin(115200, SERIAL_8N1, GPIO_NUM_5, -1);

    M5.Lcd.setTextDatum(middle_center);
    M5.Lcd.setTextFont(&fonts::FreeMonoBold9pt7b);
    M5.Lcd.setTextSize(2);
    M5.Lcd.setRotation(1);
}

void loop()
{
    M5.Lcd.clear();
    while (Serial1.available() > 0)
    {
        int len = Serial1.available();
        if (len >= RX_BUF_SIZE) len = RX_BUF_SIZE - 1;
        int read = Serial1.read((uint8_t*)rx_buf, len);
        if (read >= 5)
        {
            rx_buf[read] = '\0';
            rx_str = String(rx_buf);
            rx_str.trim();
            data_updated = true;
            Serial.printf("RX[%d]: %s\n", read, rx_buf);
        }
    }

    M5.Lcd.setCursor(0, 20);
    M5.Lcd.println("Distance:");

    if (data_updated)
    {
        M5.Lcd.setCursor(30, 90);
        M5.Lcd.printf("%s mm", rx_str.c_str());
    }
    else
    {
        M5.Lcd.setCursor(30, 90);
        M5.Lcd.println("Waiting...");
    }

    delay(1000);
}

、效果展示

超声波模块放在桌上,测量到屋顶天花的距离。可以看见屏幕显示2米的距离。

1cb612e1475ccecb92dc48ce386534e8.jpg用手靠近超声波测距仪。

aaf210bbebe5132cce9eb8ff09934b22.jpg、项目源码

frdmmcxa153_gpio_input_interrupt.zip


共1条 1/1 1 跳转至

回复

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