STM32
直播中

CDCNKA

8年用户 1228经验值
擅长:385288
私信 关注
[问答]

如何利用现成的SysTick去实现HC-sr04超声波测距呢

什么是HC-sr04超声波测距模块呢?

HC-sr04超声波测距模块它是如何工作的?
如何利用现成的Systick去实现HC-sr04超声波测距呢?

回帖(1)

陈小鸥

2021-12-2 09:12:27
一、超声波测距模块简介(网络摘取)

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
*
*  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%drn",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%drn",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()

4. 使用

float length;
length = HCSR04_GetLength();
printf("距离为:%.3frn",length);
举报

更多回帖

发帖
×
20
完善资料,
赚取积分