STM32CubeIDE 利用LL库 SysTick简单实现hcsr04超声波测距

一、超声波测距模块简介(网络摘取)

HC-sr04是一款典型的超声波测距模块,升级版的程序和04的差别不大,只是测量范围和精度有所不同。

它是如何工作的?

超声波传感器使用声纳来确定到物体的距离。以下是其工作过程:

1.    发射器(触发引脚)发送信号:一段高频声音。

2.    当信号遇到一个物体时,它会被反射;

3.    然后发射器(回声引脚)接收该信号。

信号发送和接收之间的时间可以告知我们到物体的距离。这个是可以实现的,因为我们知道声音在空气中传播的速度。

传感器引脚图

●    VCC:+ 5VDC

●    Trig:触发(输入)

●    Echo:回声(输出)

●    GND:GND

二、CubeMX配置

任选两个GPIO,一个作为输入,一个作为输出。

在Project Manager -- Advanced Settings选项栏内,GPIO后面选择LL库。(忽略其他配置)

三、自动生成的代码

void MX_GPIO_Init(void)
{
  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);

  /**/
  LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_12);

  /**/
  GPIO_InitStruct.Pin = LL_GPIO_PIN_12;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /**/
  GPIO_InitStruct.Pin = LL_GPIO_PIN_13;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_FLOATING;
  LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

四、用户代码

1. <hcsr04.h>

/*
 * hcsr04.h
 *
 *  Created on: 2020年4月29日
 *      Author: zateper
 */

#ifndef INC_HCSR04_H_
#define INC_HCSR04_H_

float HCSR04_GetLength(void);

#endif /* INC_HCSR04_H_ */

2. <hcsr04.c>

#include "hcsr04.h"
#include "gpio.h"
#include "delay.h"
#include "usart.h"

#define HCSR04_PORT     GPIOB
#define HCSR04_TRIG     LL_GPIO_PIN_12
#define ECHO_Reci  LL_GPIO_IsInputPinSet(HCSR04_PORT,LL_GPIO_PIN_13)


void TRIG_pulse()
{
    LL_GPIO_SetOutputPin(HCSR04_PORT,HCSR04_TRIG);
    Delay_us(30);
    LL_GPIO_ResetOutputPin(HCSR04_PORT,HCSR04_TRIG);
}

float HCSR04_GetLength(void)
{
	uint32_t startval,endval,tickn,ticknend,delayt;
	double delays;
	uint32_t timeout = 23530;//uS
	int i = 0;
	float lengthTemp = 0;
	float sum = 0;
	delays = 0;

	while(i!=5)
	{
		TRIG_pulse();
		startval = SysTick->VAL;
		tickn = HAL_GetTick();
		while(ECHO_Reci == 0)      //等待接收口高电平输出
		{
			endval = SysTick->VAL;//读取系统滴答值
			ticknend = HAL_GetTick();
			if(ticknend == tickn)
			{
				if(startval > endval)
				{
					delayt = (startval - endval);
				}
				else//系统滴答进入下一毫秒
				{
					delayt = (startval +72000 - endval);
				}
			}
			else
			{
				delayt = ((ticknend - tickn) * 72000 + startval - endval);
			}

			if(delayt > 360000)//时间超时
			{
				printf("s%d,e%d;t%d,d%d\r\n",startval,endval,tickn,ticknend);
				return delayt;
			}

		}

		startval = SysTick->VAL;//跳出上一循环意味着Echo来了上升沿,读取此时滴答(时间)
		tickn = HAL_GetTick();

			i = i + 1;

		while(ECHO_Reci == 1)
			{
				endval = SysTick->VAL;
				ticknend = HAL_GetTick();
				if(ticknend == tickn)
				{
					if(startval > endval)
					{
						delays = (startval - endval)/72.0;
					}
					else
					{
						delays = (startval +72000 - endval)/72.0;
					}
				}

				else
				{
					delays = ((ticknend - tickn) * 72000 + startval - endval)/72.0;
				}

				if(delays > timeout)//超时时间
				{
					printf("s%d,e%d;t%d,d%d\r\n",startval,endval,tickn,ticknend);
					return delays;
				}

			}
		endval = SysTick->VAL;//跳出上一循环意味着Echo来了下降沿,读取此时滴答(时间)
		ticknend = HAL_GetTick();
		delays = ((ticknend - tickn) * 72000 + startval - endval)/72;//计算时间差

		lengthTemp = ((float)delays/58.0);//单位cm
		sum = lengthTemp + sum ;
	}

	lengthTemp = sum/5.0;
	return lengthTemp;
}

此方法利用现成的SysTick计算时间差而没有使用硬件定时器,精度一样很高,适用于没有中断或者中断响应处理比较快的场景。同时加入了超时处理,避免while()死循环。

3. delay_us()

见:HAL库微秒us的延时Delay实现

4. 使用

float length;

length = HCSR04_GetLength();
printf("距离为:%.3f\r\n",length);

 

 

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于使用HCSR04超声波测距,可以按照以下步骤进行: 1. 将HCSR04的Trig引脚连接到STM32的任意一个GPIO输出引脚,将Echo引脚连接到STM32的任意一个GPIO输入引脚。 2. 在STM32中配置GPIO引脚的模式为输出模式和输入模式。 3. 在STM32中使用定时器来生成10us的触发信号,并将Trig引脚拉高至少10us。 4. 等待Echo引脚变高,并开始计时,直到Echo引脚变低,停止计时。 5. 根据计时结果计算出距离。 以下是示例代码: ```c #include "stm32f4xx.h" #define TRIG_PIN GPIO_Pin_0 #define ECHO_PIN GPIO_Pin_1 #define TRIG_PORT GPIOA #define ECHO_PORT GPIOA void delay_us(uint32_t us) { uint32_t ticks = us * (SystemCoreClock / 1000000); while (ticks--); } float measure_distance(void) { GPIO_ResetBits(TRIG_PORT, TRIG_PIN); delay_us(2); GPIO_SetBits(TRIG_PORT, TRIG_PIN); delay_us(10); GPIO_ResetBits(TRIG_PORT, TRIG_PIN); while (!GPIO_ReadInputDataBit(ECHO_PORT, ECHO_PIN)); uint32_t start = SysTick->VAL; while (GPIO_ReadInputDataBit(ECHO_PORT, ECHO_PIN)); uint32_t end = SysTick->VAL; float distance = (start - end) * 0.017; return distance; } int main(void) { GPIO_InitTypeDef GPIO_InitStruct; TIM_TimeBaseInitTypeDef TIM_InitStruct; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); GPIO_InitStruct.GPIO_Pin = TRIG_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(TRIG_PORT, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = ECHO_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(ECHO_PORT, &GPIO_InitStruct); TIM_InitStruct.TIM_Period = 0xFFFFFFFF; TIM_InitStruct.TIM_Prescaler = SystemCoreClock / 1000000 - 1; TIM_TimeBaseInit(TIM2, &TIM_InitStruct); TIM_Cmd(TIM2, ENABLE); SysTick_Config(SystemCoreClock / 1000000); while (1) { float distance = measure_distance(); // do something with distance } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值