目录

超声波模块介绍

超声波模块在电子DIY作品中实现小车避障测距等方面均应用广泛,在大学生智能车DIY爱好者中尤为显眼。

①实物图


在这里插入图片描述

点击图片购买

②产品说明

HC-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能,测距精度可达3mm,包括发射器、接收器与控制电路,它是一种压电式传感器,利用电致伸缩现象而制成。

③电气参数

电气参数HCSR04超声波模块
工作电压DC5V
工作电流15mA
工作频率40KHz
最远射程4M
最近射程2cm
测量角度15°
输入触发信号10us的TTL脉冲
输出回响信号输出TTL电平信号,与射程成比例

④超声波工作原理

首先我们可以看下面的一张超声波的时序图:
在这里插入图片描述
图中我们可以大致看出,要使用HCSR04这个超声波模组,我们必须先给超声波发送一个触发信号,引导超声波内部循环发出8个40Khz的脉冲然后输出回响信号引脚上拉为高电平,然后我们利用超声波回响信号引脚的高电平所得计数时间经过相关运算就可以得到对应的距离,具体公式如下:
测试距离 = (高电平时间声速(340M/S)/2)= ((float)t/58.0)
这个公式的具体换算过程,大家可以用以前学过的知识进行还算下,最后得到的距离单位是厘米。
下面放一张超声波的引脚功能示意图,能更好的理解HCSR04的具体使用和接线在代码中:
在这里插入图片描述

驱动代码

之前写过用51单片机驱动HCSR04在LCD1602上的驱动代码,这篇文章我使用STM32驱动HCSR04在0.96OLED(使用人数较多并且开源初始化代码方便移植)上面使用的驱动代码。

①STM32配置初始化代码

时钟和GPIO以及中断相关配置:

void HCSR04_Init(void)
{  
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;     //定义定时器结构体
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
     
    //IO 初始化
    GPIO_InitStructure.GPIO_Pin = HCSR04_TRIG;       	//发送高点平引脚
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	//推挽输出
    GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
    GPIO_ResetBits(HCSR04_PORT,HCSR04_TRIG);
     
    GPIO_InitStructure.GPIO_Pin = HCSR04_ECHO;    	 //返回电平引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;	
    GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);  
    GPIO_ResetBits(HCSR04_PORT,HCSR04_ECHO);	
	 
	//定时器初始化使用基本定时器3
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);   //打开TIM3定时器时钟

	TIM_DeInit(TIM3);
	TIM_TimeBaseStructure.TIM_Period = 65535; //(1000-1); //设置在下一个更新时间装入活动的自动重装载寄存器周期的值         计数到1000为1ms
	TIM_TimeBaseStructure.TIM_Prescaler =(72-1); //设置用来作为TIMx时钟频率除数的预分频  1M的计时频率 1US计数
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;	//不分频
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位	 
		
	TIM_ClearFlag(TIM3, TIM_FLAG_Update);   	//清除更新中断避免立即产生更新中断
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);    //启用计时器更新中断

	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;            	//设置中断服务
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  	//主优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;         	//次优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;        		//启用中断
	NVIC_Init(&NVIC_InitStructure);
	
    TIM_Cmd(TIM3,DISABLE);     
}

//定时器中断服务程序
void TIM3_IRQHandler(void)   //TIM3中斷
{
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM更新中断是否发生
    {
         TIM_ClearITPendingBit(TIM3, TIM_IT_Update);  //清除TIM更新中断标志位
         msHcCount++;
    }
}

①超声波驱动应用代码

下面展示写根据超声波时序图可以写出下面的驱动代码:

//开始计数
static void StartTimer()        //打开定时器
{
    TIM_SetCounter(TIM3,0);	//清除计数
    msHcCount = 0;
    TIM_Cmd(TIM3, ENABLE);  //启用TIM3外设
}
 
static void StopTimer() 	//关闭定时器外设
{
    TIM_Cmd(TIM3, DISABLE); //关闭TIM定时器外设
}
 
//获取计时器时间
float GetEchoTimer(void)
{
    u32 t = 0;
    t = msHcCount*1000;			//得到ms
    t += TIM_GetCounter(TIM3);	//得到us
	TIM3->CNT = 0;  			//将TIM3定时计数器的寄存器清零
	delay_ms(50);
    return t;
}

②超声波距离计算代码

//取五次数据平均值,为了使测距所得到的值更加精确可采取多次测距的平均值来使用应用中
float HCSR04GetLength(void)
{
	u32 t = 0;
	int i = 0;
	float lengthTemp = 0;  
	float sum = 0; 	
	float distance;

	for(i=0;i<5;i++){		
		
		TRIG_SEND = 1;      //发送高电平输出
		delay_us(20);
		TRIG_SEND = 0;
			
		while(ECHO_RECEIVE == 0); 	//等待接收高电平输出
		StartTimer();        	//打开计时器

		while(ECHO_RECEIVE == 1);
		StopTimer();        	//关闭计时器
		
		t = GetEchoTimer();     //获取时间,解析度为1US

		lengthTemp = ((float)t/58.2);	//cm
		sum = lengthTemp + sum ;
	}
	distance = 100*sum/5.0;
	return distance;
}

具体测试现象

本次使用OLED屏幕显示超声波所测距离并显示如下图所示:
在这里插入图片描述

总结

文章中使用的显示方式为0.96寸OLED模块显示,驱动MCU使用的为STM32F103C8T6,在使用HCSR04的过程中也可以自己根据HCSR04的驱动代码所得到的距离值去做其他的接口应用,例如做小车,或者其他测距案例均可移植使用,需要完整工程的可下方留言邮箱获取。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐