前言
在51单片机和32的标准库的时候使用过这个模块,但是到后面的时候,太久不用忘记怎末使用了
然后超声波模块测距的原理,好像也没有那么简单理解,为什么高脉冲的持续时间,就是从发送到接收的时间呢?
然后在HAL库又怎末使用呢?
本篇文章提供.c. h代码,只需要修改.h文件的TR和HC引脚,以及配置的10us的定时器中断TIM编号,就可以使用了
然后不用外部中断,只需要一个定时器中断就可以实现超声波测距的功能了
超声波测距模块简介
这个是我从产品说明书中获取的简介
超声波测距模块驱动过程
1.初始化
#define HC_TR_TRIG_PIN GPIO_PIN_0
#define HC_TR_TRIG_PORT GPIOA
#define HC_TR_ECHO_PIN GPIO_PIN_1
#define HC_TR_ECHO_PORT GPIOA
#define HC_TR_TIME htim2
只需要在Cubemx配置定时器中断,时间为10us就欧克
记得开启定时器中断,我这里是以主频为80Hz,PA0为TR,PA1为HC为例
2.脉冲发射
给TR口一个至少10us的高电平,就会开始发射8个40Hz的脉冲
因为是HAL库,HAL_Delay()是以1ms为单位的,直接给1ms就好
void TR_SEND()
{HAL_GPIO_WritePin(HC_TR_TRIG_PORT, HC_TR_TRIG_PIN, GPIO_PIN_SET);HAL_Delay(1); HAL_GPIO_WritePin(HC_TR_TRIG_PORT, HC_TR_TRIG_PIN, GPIO_PIN_RESET); GetEchoTime(2);
}
3.脉冲接收过程
根据这张图可以发现,发送完后HC还是低电平,所以我们要等到高电平
然后高电平的持续时间,就是从发送到接收的时长,我也想不明白,为什么会是这个时间
可能是发送芯片发送完后
要给接收芯片一个已发送收完的信号
接收芯片在收到发送完的信号后,才开始设置为高电平
直到接收到8个40KHz的脉冲后,才变成低电平
所以单片机在发送完后的一小段时间里面,HC还是低电平的,然后才变高,最后变低
高电平持续时间,就是发送和接收的时长
代码就在下面
其中计算的公式是
float distance = (float)GetEchoTime(0)/100000*340/2*100;
因为我定时器的时间为10us
假设期间经过了x个10us,那么就是
Time=x*10 us
=10x us
=10x /1000 ms
=10x /1000 000 s
=x/ 100 000s
然后路程等于速度乘时间
x=s*t= 340m/s * x/100 000s (m)
因为路程是距离的两倍
所以
实际测距得的距离为
L=x/2 = 340m/s * x/100 000s /2(m)
转化成cm,厘米为单位,那么就是乘100
L=x/2 = 340m/s * x/100 000s /2 *100(cm)
所以简化就是
L=x*170/1000(cm)
L=x*0.17 (cm)
历程源码-直接复制改.h文件引脚就可以使用了
记得要调用初始化函数
HC_TR.c
#include "HC_TR.h"
#include "tim.h"
#include "gpio.h"
#include "usart.h"
#include "stdio.h"
#include "string.h"void TR_SE_init()
{GPIO_InitTypeDef GPIO_InitStruct = {0};__HAL_RCC_GPIOH_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);/*Configure GPIO pin : PA0 */GPIO_InitStruct.Pin = HC_TR_TRIG_PIN ;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init( HC_TR_TRIG_PORT, &GPIO_InitStruct);GPIO_InitStruct.Pin = HC_TR_ECHO_PIN;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(HC_TR_ECHO_PORT, &GPIO_InitStruct);HAL_TIM_Base_Start_IT(&HC_TR_TIME);
}
void TR_SEND()
{HAL_GPIO_WritePin(HC_TR_TRIG_PORT, HC_TR_TRIG_PIN, GPIO_PIN_SET);HAL_Delay(1); HAL_GPIO_WritePin(HC_TR_TRIG_PORT, HC_TR_TRIG_PIN, GPIO_PIN_RESET); GetEchoTime(2);
}uint32_t GetEchoTime(uint8_t cmd)
{static uint32_t echo_time = 0;switch (cmd){case 0:return echo_time;case 1:echo_time ++;break;case 2:echo_time = 0;break;}
}// 获取距离函数
float HC_TR_GetDistance(void)
{// 发送触发信号TR_SEND();GetEchoTime(2);while(HAL_GPIO_ReadPin(HC_TR_ECHO_PORT, HC_TR_ECHO_PIN)==0){if(GetEchoTime(0) > 1000){printf("wate time \r\n");break; }}
//超时检测GetEchoTime(2);while (HAL_GPIO_ReadPin(HC_TR_ECHO_PORT, HC_TR_ECHO_PIN)){if(GetEchoTime(0) > 1000){printf("one time \r\n");break; }}//超时检测//float distance = (float)GetEchoTime(0)/100000*340/2*100; float distance = (float)GetEchoTime(0)*0.17; // printf("distance= %.1fcm\r\n",distance);return distance;
}// 定时器2中断处理函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if (htim==&HC_TR_TIME){GetEchoTime(1);}
}
HC_TR.h
#ifndef HC_TR_H
#define HC_TR_H#include "main.h"// 定义超声波传感器的引脚
#define HC_TR_TRIG_PIN GPIO_PIN_0
#define HC_TR_TRIG_PORT GPIOA
#define HC_TR_ECHO_PIN GPIO_PIN_1
#define HC_TR_ECHO_PORT GPIOA
#define HC_TR_TIME htim2
void TR_SE_init();
float HC_TR_GetDistance(void);
void TR_SEND();
uint32_t GetEchoTime(uint8_t cmd);
#endif /* HC_TR_H */