STM32F103驱动超声波HC-SR04

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=T340(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);

	}
}

这是在串口调试助手中获取的数据

在这里插入图片描述

单位是CM,可能是我测得太远了,数据有一些小波动,近距离测试还是比较稳的,我就不测了。

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值