基于STM32和HC-SR04的超声波测距实验

1.HC-SR04原理介绍

HC-SR04是一款广泛使用的超声波测距模块,它能够通过发射和接收超声波来测量距离。HC-SR04主要包括三个模块
发射器:一个可以发射超声波的压电陶瓷片。
接收器:一个可以接收超声波的压电陶瓷片。
控制电路:包括一个控制芯片,用于控制发射和接收超声波的时序。
四个接口
VCC:电源输入,通常为5V。
Trig:触发信号输入。
Echo:回声信号输出。
GND:地线。
具体的工作原理是当Trig接口接到一个触发信号时(高电平>=10us)发射器发出一个以40kHz为频率的超声波信号,遇到障碍物反射后被接收器接收,接收器输出高电平,所以大概的的测距公式可以得出为
S=(接收器输出高电平时间*340m/s/2)mm

2.功能实现

2.1 实验准备

硬件:STM32F103C8T6系统板,HC-SR04超声波测距模块,OLED显示屏,蜂鸣器,STlinK
软件:keil5
接线图
在这里插入图片描述

2.2 代码撰写

核心代码
HC-SR04.h

#ifndef __HCSR04_H
#define __HCSR04_H

extern u32 g_cap_distance;	//超声波测量距离
void timer4_cap_init(u16 timer_arr, u16 timer_psc);
void hcsr04_read_distance(void);
void TIM4_IRQHandler(void);

#endif

HC-SR04.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

TIM_ICInitTypeDef  tim_ic_init;
u16 g_cap_state, g_cap_val;
u32 g_cap_distance;	//超声波测量距离
//g_cap_state:捕获状态标志(bit7:完成捕获; bit6:捕获高电平;bit5-bit0:捕获高电平溢出次数)

//---------------------------------------------------------------------------------------------------------------------------------------------
//	函 数 名: timer4_cap_init
//	功能说明: TIM4初始化
//	形    参: timer_arr:自动重装值; timer_psc:时钟分频系数
//	返 回 值: 无
//	日    期: 
//	作    者: 
//  备    注: 
//---------------------------------------------------------------------------------------------------------------------------------------------
void timer4_cap_init(u16 timer_arr, u16 timer_psc)
{
	GPIO_InitTypeDef gp_init;
	TIM_TimeBaseInitTypeDef  tim_base_init;
	NVIC_InitTypeDef nvic_init_config;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);	//使能TIM2时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  //使能GPIOB时钟

	gp_init.GPIO_Pin  	= GPIO_Pin_8; 
	gp_init.GPIO_Mode 	= GPIO_Mode_IPD; //PB8 输入 (ECHO) 
	GPIO_Init(GPIOB, &gp_init);

	gp_init.GPIO_Pin  	= GPIO_Pin_9;     
	gp_init.GPIO_Mode 	= GPIO_Mode_Out_PP;     //PB9 输出 (TRIG)
	gp_init.GPIO_Speed 	= GPIO_Speed_2MHz;     //2M
	GPIO_Init(GPIOB, &gp_init);

	//初始化定时器4 TIM4	 
	tim_base_init.TIM_Period 		= timer_arr; //设定计数器自动重装值 
	tim_base_init.TIM_Prescaler 	= timer_psc; 	//预分频器   
	tim_base_init.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	tim_base_init.TIM_CounterMode 	= TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM4, &tim_base_init); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

	//初始化TIM4输入捕获参数
	tim_ic_init.TIM_Channel 	= TIM_Channel_3; //CC1S=03 	选择输入端 IC3映射到TI1上
	tim_ic_init.TIM_ICPolarity 	= TIM_ICPolarity_Rising;	//上升沿捕获
	tim_ic_init.TIM_ICSelection = TIM_ICSelection_DirectTI;
	tim_ic_init.TIM_ICPrescaler = TIM_ICPSC_DIV1;	 //配置输入分频,不分频 
	tim_ic_init.TIM_ICFilter 	= 0x00;//配置输入滤波器 不滤波
	TIM_ICInit(TIM4, &tim_ic_init);

	//中断分组初始化
	nvic_init_config.NVIC_IRQChannel 					= TIM4_IRQn;  //TIM4中断
	nvic_init_config.NVIC_IRQChannelPreemptionPriority 	= 3;  //先占优先级2级
	nvic_init_config.NVIC_IRQChannelSubPriority 		= 3;  //从优先级0级
	nvic_init_config.NVIC_IRQChannelCmd 				= ENABLE; //IRQ通道被使能
	NVIC_Init(&nvic_init_config);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 	
	
	TIM_ITConfig(TIM4, TIM_IT_Update|TIM_IT_CC3, ENABLE);//允许更新中断 ,允许CC3IE捕获中断	
	TIM_Cmd(TIM4, ENABLE); 	//使能定时器3
}

//---------------------------------------------------------------------------------------------------------------------------------------------
//	函 数 名: hcsr04_read_distance
//	功能说明: 超声波测量距离
//	形    参: 无
//	返 回 值: 无
//	日    期: 
//	作    者: 
//  备    注: 
//---------------------------------------------------------------------------------------------------------------------------------------------
void hcsr04_read_distance(void)
{
	GPIO_SetBits(GPIOB, GPIO_Pin_9);	//启动超声波测量
	Delay_us(15);
	GPIO_ResetBits(GPIOB, GPIO_Pin_9);
	
	if (g_cap_state & 0X80)	//捕获一次高电平
	{
		g_cap_distance = g_cap_state & 0X3f;
		g_cap_distance *= 65535;
		g_cap_distance += g_cap_val;
		g_cap_distance = g_cap_distance * 170 / 1000;	//计算距离(mm)
		g_cap_state = 0X00;
	}
}

void TIM4_IRQHandler(void)
{
	u16 sta_val;
	
	sta_val = TIM4->SR;
	if ((g_cap_state & 0X80) == 0X00)	//未捕获
	{
		if (sta_val & 0X01)	//溢出
		{
			if (g_cap_state & 0X40)	//捕获到高电平
			{
				if ((g_cap_state & 0X3f) == 0X3f)	//高电平时间过长
				{
					g_cap_state |= 0X80;	//记录一次捕获
					g_cap_val = 0Xffff;	//溢出时间
				}
				else 
				{
					g_cap_state++;	//继续捕获
				}
			}
		}
		
		if (sta_val & 0X08) //捕获3(通道3)发生捕获事件
		{
			if (g_cap_state & 0X40)	//捕获下降沿
			{
				g_cap_state |= 0X80;	//标记成功捕获一次高电平
				g_cap_val = TIM4->CCR3;	//获取当前捕获值
				TIM4->CCER &= ~(1<<9);	//CC1P=0 设置为上升沿捕获
			}
			else 
			{
				g_cap_state = 0;
				g_cap_val = 0;
				g_cap_state |= 0X40;	//标记捕获到上升沿
				TIM4->CNT = 0;	//清空计数器
				TIM4->CCER |= (1<<9);	//CC1P=1 设置为下降沿捕获
			}
		}
	}
	
	TIM4->SR = 0;	//清除中断标志位
}


main .c


#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "hcsr04.h"
#include "usart.h"
#include "OLED.h"
#include "beep.h"
//超声波测试函数
int main(void)
{ 
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
	uart1_init(115200 * 8);	 //串口初始化为961200
	
	timer4_cap_init(0Xffff, 72 - 1);
	OLED_Init();
	beep_init();
	while (1)
	{
		OLED_Clear();
		hcsr04_read_distance();
		printf("g_cap_distance = %d \r\n", g_cap_distance);	//用串口1打印输出
		
		if(g_cap_distance<100&&(g_cap_distance>50)){
			beep_on_1();
		}
		if(g_cap_distance<50&&(g_cap_distance>30)){
			beep_on_2();
		}
		if(g_cap_distance<30){
			beep_on_3();
		}
		OLED_ShowNum(2,2,g_cap_distance,5);
		OLED_ShowString(2,8,"mm");
		Delay_ms(200);
	}
	
}



3.效果展示

在这里插入图片描述

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值