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


二、软件编程
软件编程,我使用的是官方的MCUXpresso IDE v25.6,使用例程“frdmmcxa153_gpio_input_interrupt”来进行修改。
超声波测距模块,通过拉高Trig管脚并维持20us,触发模块发出一束超声波,当超声波遇到障碍物反射回来,被接收到,会触发Echo管脚电平由高变低变换。 FRDM-MCXA153开发板通过中断获取Echo的电平变换,并计时,计算出超声波在空气中运动的时长,计算出距离信息。

超声波使用两个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);
}
}
除了通过烧写口的串口读取获取到的信息外,还启动了串口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米的距离。
用手靠近超声波测距仪。
五、项目源码
我要赚赏金
