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

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

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

它是如何工作的?

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

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

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

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

STM32CubeIDE 利用LL库 SysTick简单实现hcsr04超声波测距_第1张图片

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

传感器引脚图

STM32CubeIDE 利用LL库 SysTick简单实现hcsr04超声波测距_第2张图片

●    VCC:+ 5VDC

●    Trig:触发(输入)

●    Echo:回声(输出)

●    GND:GND

二、CubeMX配置

STM32CubeIDE 利用LL库 SysTick简单实现hcsr04超声波测距_第3张图片

STM32CubeIDE 利用LL库 SysTick简单实现hcsr04超声波测距_第4张图片

任选两个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
 *
 *  Created on: 2020年4月29日
 *      Author: zateper
 */

#ifndef INC_HCSR04_H_
#define INC_HCSR04_H_

float HCSR04_GetLength(void);

#endif /* INC_HCSR04_H_ */

2. 

#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);

 

 

你可能感兴趣的:(STM32,嵌入式,stm32)