【STM32F103C8t6】【HAL】HC-SR04超声波测距模块详解

前言:该文章主要讲解以stm32f103c8t6为主控,用HAL库来对HC-SR04超声波模块的进行代码编写。代码的主要核心思路是通过定时的输入捕获模式对Echo的信号进行捕获,这里我采用的是双通道的形式分别捕获Echo的上升沿和Echo的下降沿。通过分别读取两个通道捕获的计数值,然后做差就可以得到Echo信号的高电平时间。

1.HC-SR04实物图:

1.1HC-SR04引脚说明:

  • Vcc:+5V电源供电
  • Trig:输入触发信号(可以触发测距)
  • Echo:传出信号回响(可以传回时间差)
  • Gnd:接地

2.超声波模块的性能指标

3、超声波模块原理

       在TRIG 管脚输入一个10US 以上的高电平(一般建议50US 左右),芯片(TP,TN 管脚)便可发出8个40KHZ 的超声波脉冲,然后(RP,RN)检测回波信号。当检测到 回波信号后,通过ECHO管脚输出,如图5所示。

      根据ECHO管脚输出高电平的持续时间可以计算距离值。即距离值为:(高电平时间 *340m/s)/2。 当测量距离超过测量范围时,CS100A仍会通过ECHO管脚输出高电平的信号,高电 平的宽度约为33ms。如图6所示:

          测量周期:当芯片通过ECHO管脚输出的高电平脉冲后,便可进行下一次测量,所 以测量周期取决于测量距离,当测距很近时,ECHO 返回的脉冲宽度较窄,测量周期就 很短;当测距较远时,ECHO返回的脉冲宽度较宽,测量周期也就相应的变长。 最坏情况下,被测物体超出测量范围,此时返回的脉冲宽度最长,约为 33ms,所 以最坏情况下的测量周期大于33ms即可(比如测量周期可取50ms)。

4、代码详解

       当我们搞明白上面的原理后,就可以根据上面的原理来编写代码了

4.1 Trig 的初始化

        根据原理可明白超声波模块的触发是要给Trig一个不低于10us的一个高电平信号。

Trig引脚初始化

Trig发出起始信号

4.2 Echo的初始化

        Echo是用来接收Trig传过来的信号的,通过计算传过的信号中高电平的时间就可以计算出距离了。这里我采用的是双通道的形式分别捕获Echo的上升沿和Echo的下降沿。通过分别读取两个通道被捕获的计数值,然后做差就可以得到Echo信号的高电平时间。

定时器输入捕获初始化,

打开IC_IT中断和事件中断(需要注意的是:stm32f103c8t6的定时器2,3,4的中断源都是一样的,(如定时器2的中断源都是TIM2_IRQn)。而定时器1的中断源是详细的分开的)

        这里打开事件中断的目的是记录每次计数器溢出的次数,防止在第2个通道捕获计数器的值时与第一个通道捕获时不在一个计数周期内,这样获取Echo高电平时间在做差时可能出现负数。(注意:每次都有清除事件中断产生的标志位)

4.3计算距离

        根据Echo管脚输出高电平的持续时间可以计算距离值。即距离值为:(高电平时间 *340m/s)/2。(这里再除以2 是因为Frig发出超声波到Echo接收超声波一来一回,所以要除以2)

        高电平时间  =  ECHO_Time2 -ECHO_Time1 (两个通道捕获的计数值做差)(注意该获取的时间单位是微妙)

        ECHO_Time=ECHO_Time2-ECHO_Time1;           ECHO_Time高电平时间

5.完整代码

HC-SR04.c

HC-SR04.h

  • 24
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于STM32F103C8T6HC-SR04实现超声波测距的代码,使用的是STM32CubeMX和Keil IDE进行开发: 1. 首先在STM32CubeMX中配置GPIO和定时器: GPIOA_Pin0:超声波传感器的Trig引脚 GPIOA_Pin1:超声波传感器的Echo引脚 TIM2_CH2:用于捕获超声波回波信号的定时器通道 2. 在Keil IDE中编写代码: #include "main.h" TIM_HandleTypeDef htim2; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_TIM2_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM2_Init(); while (1) { uint32_t pulse_width = 0; uint32_t distance = 0; // 发送超声波信号 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); HAL_Delay(10); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); // 等待回波信号 while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET); uint32_t start_time = HAL_GetTick(); // 捕获回波信号 while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_SET); uint32_t end_time = HAL_GetTick(); pulse_width = end_time - start_time; distance = pulse_width * 17 / 1000; // 声速340m/s,除以2得到往返时间,乘以17得到距离(单位:毫米) } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } } static void MX_TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_IC_InitTypeDef sConfigIC = {0}; htim2.Instance = TIM2; htim2.Init.Prescaler = 72 - 1; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 0xFFFF; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; if (HAL_TIM_Base_Init(&htim2) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } if (HAL_TIM_IC_Init(&htim2) != HAL_OK) { Error_Handler(); } sConfigIC.ICPolarity = TIM_ICPOLARITY_RISING; sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; sConfigIC.ICFilter = 0; if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLDOWN; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } void Error_Handler(void) { __disable_irq(); while (1) { } } 3. 在main函数中,首先发送超声波信号,等待回波信号,然后捕获回波信号,计算出距离。最后通过distance变量获取距离值。 注意事项: 1. 超声波传感器回波信号的宽度与距离成正比,需要使用定时器捕获回波信号的上升沿和下降沿,计算出回波信号的脉宽。 2. 超声波传感器的Trig引脚需要在发送超声波信号前置为高电平,发送完毕后置为低电平。 3. 超声波传感器的Echo引脚需要设置为输入模式,使用下拉电阻。 4. 定时器的时钟频率需要根据具体的系统时钟频率进行调整。 5. 超声波传感器的测量范围一般为2cm-4m,超出范围会出现误差。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值