1.HC-SR04介绍
(1)该模块一共四个引脚,VCC、GND、TRIG、ECHO。该模块的典型工作电压为5V,精度为0.3cm,盲区为2cm。
1.TRIG引脚:控制端引脚。
2.ECHO引脚:接收端引脚。
(2)工作原理
1.首先控制端引脚需要提供一个至少10us以上的高电平触发信号。
2.模块内部在接收到该信号后,自动发送出8个40KHz的脉冲。
3.接收端引脚接收到回响信号则会输出高电平,高电平的持续时间与所测的距离成正比。
总的来说,就是给trig一个10us以上的脉冲信号,然后去获取echo引脚持续高电平的时间即可。然后就得到了声波从发出到接触到物体在反射到接收端的时间。
其计算距离的公式为:
S
=
T
∗
340
(
M
/
S
)
/
2.
S= T*340(M/S)/2.
S=T∗340(M/S)/2.
其中340(M/S)为声速。
2.利用定时器来计算声波传输的时间(TIM7)
这个方法是使用定时器7来记录ECHO引脚接收到高电平的时间。先介绍下tim7.h文件
#ifndef _TIME7_H
#define _TIME7_H
#include "stm32f10x.h"
#define BASIC_TIM7 TIM7
#define BASIC_TIM7_CLK RCC_APB1Periph_TIM7
#define BASIC_TIM7_Relod (1000 - 1) // 1ms定时
#define BASIC_TIM7_PSC 72 // 72 / PSC + 1 = 1us
#define BASIC_TIM7_IRQ TIM7_IRQn
#define BASIC_TIM7_IRQHandler TIM7_IRQHandler
void BASIC_TIM7_Init(void);
uint32_t BASIC_TIM7_GetTime(void);
void BASIC_TIM7_Stop(void);
void BASIC_TIM7_Start(void);
#endif
/* _TIME7_H */
接下来是tim7.c文件中的程序。
#include "time7.h"
extern uint16_t time7;
void BASIC_TIM7_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitTypeDefine;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitTypeDefine.NVIC_IRQChannel = BASIC_TIM7_IRQ;
NVIC_InitTypeDefine.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitTypeDefine.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitTypeDefine.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitTypeDefine);
}
void BASIC_TIM7_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitTypeDefine;
RCC_APB1PeriphClockCmd(BASIC_TIM7_CLK, ENABLE);
TIM_TimeBaseInitTypeDefine.TIM_Period = BASIC_TIM7_Relod;
TIM_TimeBaseInitTypeDefine.TIM_Prescaler = BASIC_TIM7_PSC;
//初始化结构体
TIM_TimeBaseInit(BASIC_TIM7, &TIM_TimeBaseInitTypeDefine);
//清除计时器更新标志位
TIM_ClearFlag(BASIC_TIM7, TIM_FLAG_Update);
//开启计时器中断
TIM_ITConfig(BASIC_TIM7, TIM_FLAG_Update, ENABLE);
TIM_Cmd(BASIC_TIM7, DISABLE);
}
void BASIC_TIM7_Init(void)
{
BASIC_TIM7_NVIC_Config();
BASIC_TIM7_Config();
}
void BASIC_TIM7_Start(void)
{
TIM_SetCounter(TIM7,0);
time7 = 0;
TIM_Cmd(BASIC_TIM7, ENABLE);
}
void BASIC_TIM7_Stop(void)
{
TIM_Cmd(BASIC_TIM7, DISABLE);
}
uint32_t BASIC_TIM7_GetTime(void)
{
uint32_t time_count = 0;
time_count = time7 * 1000; //将ms转为us
time_count += TIM_GetCounter(TIM7); //取出计时器中不到一的中断周期的数,相加即为总时间
TIM_SetCounter(TIM7,0); //再将计数器清零
return time_count; //返回值为传输时间
}
HCSR04.h
#ifndef _HCSR04_H
#define _HCSR04_H
#include "stm32f10x.h"
#include "time7.h"
#include "SysTick.h"
#define HCSR04_PORT GPIOC
#define HCSR04_Trig GPIO_Pin_6
#define HCSR04_Echo GPIO_Pin_7
#define HCSRO4_CLK RCC_APB2Periph_GPIOC
#define Trig_Send(n) do{if(n == 0) GPIO_ResetBits(HCSR04_PORT,HCSR04_Trig);else if(n == 1)GPIO_SetBits(HCSR04_PORT,HCSR04_Trig); }while(0)
#define HCSR04_EchoState GPIO_ReadInputDataBit(HCSR04_PORT, HCSR04_Echo)
float HCSR04_GetLength(void);
void HCSR04_GPIO_Config(void);
#endif /* _HCSR04_H */
HCSR04.c
#include "hcsr04.h"
void HCSR04_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(HCSRO4_CLK, ENABLE);
//Trig 控制端
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = HCSR04_Trig;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
//Echo 接收端
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = HCSR04_Echo;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
}
float HCSR04_GetLength(void)
{
uint8_t i = 0;
float sum = 0;
uint32_t time = 0;
float length_temp = 0;
float length = 0;
while(i != 10)
{
Trig_Send(1);
Delay_us(20);
Trig_Send(0);
while(HCSR04_EchoState == 0);
BASIC_TIM7_Start();
while(HCSR04_EchoState == 1);
BASIC_TIM7_Stop();
time = BASIC_TIM7_GetTime();
length_temp = (float)time * 34/2000.0 ;
sum += length_temp;
Delay_ms(70); //延时60ms以上,防止发射信号对回波影响。
i++;
}
length = sum / 10.0;
return length;
}
最后一定要记得在stm32f10x_it.c中加入下面这段程序
uint16_t time7 = 0;
void BASIC_TIM7_IRQHandler(void)
{
if (TIM_GetFlagStatus(BASIC_TIM7, TIM_FLAG_Update) != RESET)
{
time7++;
TIM_ClearITPendingBit(BASIC_TIM7, TIM_FLAG_Update);
}
}
在main函数中调用HCSR04_GetLength()这个函数就可以得到测量得出的距离啦!
举个例子
int main(void)
{
float height;
HCSR04_GPIO_Config();
USART1_Init();
SysTick_Init();
BASIC_TIM7_Init();
while(1)
{
Delay_ms(1000);
height = HCSR04_GetLength();
printf("高度:%.2f\n",height);
}
}