超声波测距的公式怎么理解 ?(语言-c语言)

stm32的超声波公式怎么理解,网上都说是接收到高电平的持续时间就是声音传播时间,再用时间乘以声速就是距离的两倍,但是这不是声波的宽度吗?不应该是trig发送高电平开始,就打开定时器计时,直到echo接收到高电平结束计时,或者是trig发送高电平,直到echo接收到高电平开始计时,最后echo变成低电平结束计时吗?

网上都是发送10微妙的高电平,然后关闭trig,等到echo接收到高电平才开始计时,到高电平结束,超声波58微妙才走1厘米,10微妙1厘米都走不到,如果我要测的距离是10厘米,这样计时最终得到的时间不还是10微妙吗?

以下内容仅个人理解

  1. 实际超声波测距的原理就是题主理解的,记录的时间是从超声波发出到回波被接收的时间,然后这个时间除以2,再乘超声波的传播速度得到距离。超声波测距模块实际也是这么做的。模块内部会记录超声波发出的时刻,在接收到回波后会立刻以高电平的形式从Echo引脚输出高电平,高电平的持续时间就是超声波从发出到被接收到的时间间隔。这么做是模块为了方便单片机处理,快速得到超声波从发出到被接收到的时间间隔。
  2. 实际题主可以自己测试一下,初始化一个定时器,从给Trig引脚10us高电平结束时刻开启定时器,到Echo引脚接收到高电平的时刻停止计时,用这个时间来计算距离,实际和用高电平持续时间来计算距离得到的结果基本是相同的。
  3. 另外,给Trig引脚10us高电平并不是说只发送10us的超声波。10us的高电平是为了触发模块工作。10us高电平结束后,模块会发送一个8个40KHz的方波。

最后,如果回答对您有帮助,请采纳!

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 以下回答来自chatgpt:

    首先来解答一些你的困惑。

    关于测距原理,超声波传感器通常由触发器(trig)和回波接收器(echo)组成。当触发器发送一个高电平脉冲信号时,超声波传感器开始发射超声波。当超声波碰到障碍物并被反射回传感器时,回波接收器会接收到一个高电平信号。我们通过测量触发脉冲到接收到回波信号之间的时间差来计算物体与传感器之间的距离。

    现在我们来优化问题,提出具体的解决方案。

    问题标题: 如何正确理解超声波测距公式(使用C语言)?

    优化后的问题内容: 我正在尝试理解stm32中超声波测距的公式,对于现有的解释感到困惑。根据网上的说法,声波的传播时间可以通过接收到高电平的持续时间来计算,然后乘以声速即可得到距离的两倍。然而,我对于这种解释的正确性有所疑问,因为这看起来更像是在计算声波的宽度。我原本认为操作步骤应该是这样的:trig发送高电平开始计时,直到echo接收到高电平结束计时;或者trig发送高电平开始计时,直到echo接收到高电平开始计时,最后在echo变为低电平时结束计时。此外,我还注意到网上通常使用发送10微秒的高电平并关闭trig,等待echo接收到高电平后才开始计时。另外,据说超声波每走1厘米需要58微秒的时间,然而10微秒的高电平连1厘米都走不到。因此,如果我想测量的距离是10厘米,那么最终得到的时间是否仍然是10微秒呢?我希望能够得到一个清晰的解释来帮助我正确理解超声波测距公式。

    解决方案如下:

    1. 首先,我们要明确一点,声波的传播距离是由回波信号的时间差决定的,而不是高电平的持续时间。

    2. 为了测量距离,我们需要使用定时器来测量回波信号的时间差。首先,设置一个触发脉冲信号的输出引脚(trig)。当需要发送触发信号时,将此引脚设置为高电平,持续一段时间(例如10微秒),然后将其设置为低电平。这将触发传感器发送超声波。

    3. 启动一个定时器以记录触发脉冲和接收到回波脉冲之间的时间差。当回波信号被接收到时,定时器的值会被记录下来。

    4. 计算时间差。根据定时器的配置和测量时间差的单位(如微秒或毫秒),可以使用以下公式计算距离: 距离 = 时间差 * 声速 / 2

    例如,如果声速为340米/秒,时间差为10微秒,则距离 = 10 * 340 / 2 = 1700微米。

    下面是一个使用C语言的简单示例代码,用于测量超声波传感器的距离:

    #include <stdio.h>
    #include <stdint.h>
    #include "stm32f4xx_hal.h"
    
    // 定义触发脉冲引脚和定时器
    #define TRIG_PIN GPIO_PIN_0
    #define TRIG_GPIO_PORT GPIOA
    #define ECHO_PIN GPIO_PIN_1
    #define ECHO_GPIO_PORT GPIOA
    #define TIMx TIM2
    
    // 定义声速(单位:米/秒)
    #define SOUND_SPEED 340
    
    // 定义测量结果变量
    volatile uint32_t timerValue = 0;
    
    // 初始化触发脉冲引脚和定时器
    void init(void) {
        GPIO_InitTypeDef GPIO_InitStruct;
        TIM_HandleTypeDef TIM_InitStruct;
    
        // 启用GPIOA和TIM2时钟
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_TIM2_CLK_ENABLE();
    
        // 配置触发脉冲引脚
        GPIO_InitStruct.Pin = TRIG_PIN;
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
        HAL_GPIO_Init(TRIG_GPIO_PORT, &GPIO_InitStruct);
    
        // 配置回波脉冲引脚
        GPIO_InitStruct.Pin = ECHO_PIN;
        GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
        HAL_GPIO_Init(ECHO_GPIO_PORT, &GPIO_InitStruct);
    
        // 配置定时器
        TIM_InitStruct.Instance = TIMx;
        TIM_InitStruct.Init.Period = 0xFFFFFFFF;
        TIM_InitStruct.Init.Prescaler = 83; // 1微秒为一个计数单位
        TIM_InitStruct.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
        TIM_InitStruct.Init.CounterMode = TIM_COUNTERMODE_UP;
        HAL_TIM_Base_Init(&TIM_InitStruct);
    
        // 启动回波脉冲的中断
        HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(EXTI0_IRQn);
    }
    
    // 发送触发脉冲
    void sendTriggerPulse(void) {
        HAL_GPIO_WritePin(TRIG_GPIO_PORT, TRIG_PIN, GPIO_PIN_SET);
        // 稍微延时一段时间
        for (int i = 0; i < 10; i++) {
            __NOP();
        }
        HAL_GPIO_WritePin(TRIG_GPIO_PORT, TRIG_PIN, GPIO_PIN_RESET);
    }
    
    // 中断处理程序,记录定时器值
    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
        if (GPIO_Pin == ECHO_PIN) {
            timerValue = HAL_TIM_ReadCounter(&TIM_InitStruct);
        }
    }
    
    int main(void) {
        HAL_Init();
        init();
    
        while (1) {
            sendTriggerPulse();
    
            // 等待回波脉冲的中断
            while (timerValue == 0);
    
            // 计算距离
            float distance = (timerValue * SOUND_SPEED) / 2000000.0; // 时间单位:微秒,距离单位:米
            printf("Distance: %.2f meters\n", distance);
    
            // 重置定时器值
            timerValue = 0;
        }
    }
    
    // 回波脉冲的中断处理程序
    void EXTI0_IRQHandler(void) {
        HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
    }
    

    这是一个简单的示例代码,用于测量超声波传感器的距离。代码通过配置GPIO引脚和定时器来实现触发脉冲的发送和回波脉冲的接收。在主循环中,我们发送触发脉冲并等待回波信号的中断。一旦接收到回波脉冲,我们就计算距离并打印出来。然后重置计时器的值,准备下一个测量。

    要注意的是,示例代码中的一些参数(如GPIO引脚和定时器)应根据您的实际硬件配置做相应修改。

    希望以上解答能够帮助您更好地理解和使用超声波测距公式。如果您还有任何疑问,请随时提出。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^