HCSR04超声波传感器驱动
扫描二维码
随时随地手机看文章
HC_SR04是一款使用较为广泛的超声波测距模块,模块图如下
该模块具有四个引脚,分别为VCC GND TRIG ECHO,其中VCC GND为供电脚
TRIG为测距触发引脚,ECHO为测距输入引脚
该模块的驱动模式为
控制口发一个10US以上的高电平,就可以在接收口等待高电平输出.一有输出就可以开定时器计时,当此口变为低电平时就可以读定时器的值,此时就为此次测距的时间,方可算出距离.如此不断的周期测,就可以达到你移动测量的值了
模块工作原理如下
(1)采用IO触发测距,给至少10us的高电平信号;
(2)模块自动发送8个40khz的方波,自动检测是否有信号返回;
(3)有信号返回,通过IO输出一高电平,高电平持续的时间就是超声波从发射到返回的时间
(4计算测试距离测试距离=(高电平时间*声速(340M/S))/2;
根据工作原理,我们可以选择两种模式驱动
1.采用中断+定时器方式,将ECHO定义为上升沿下降沿都能触发中断,trig触发之后,echo高电平进中断打开定时器,echo低电平关闭定时器并统计定时器计数值
2.采用普通IO+定时器模式,触发之后等待echo响应,响应时打开定时器,直到echo恢复低关闭定时器,获取时间
1:此模块不宜带电连接,如果要带电连接,则先让模块的Gnd端先连接。否则会影响
模块工作。
2:测距时,被测物体的面积不少于0.5平方米且要尽量平整。否则会影响测试结果。
详细驱动代码如下所示
Hcsr04.c
#include"hcsr04.h"
#defineHCSR04_PORTGPIOB
#defineHCSR04_CLKRCC_APB2Periph_GPIOB
#defineHCSR04_TRIGGPIO_Pin_5
#defineHCSR04_ECHOGPIO_Pin_6
#defineTRIG_SendPBout(5)
#defineECHO_ReciPBin(6)
u16msHcCount=0;//ms计数
voidHcsr04Init(u32NVIC_PriorityGroup,u32PreemptionPriority,u32SubPriority)
{
u32NVICtemp=0;//用于NVIC控制器的变量
TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;//生成用于定时器设置的结构体
GPIO_InitTypeDefGPIO_InitStructure;
RCC_APB2PeriphClockCmd(HCSR04_CLK,ENABLE);
NVICtemp=NVIC_EncodePriority(NVIC_PriorityGroup,PreemptionPriority,SubPriority);//中断优先级变量解码
//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_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;//下拉输入
GPIO_Init(HCSR04_PORT,&GPIO_InitStructure);
//定时器初始化使用基本定时器TIM6
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);//使能对应RCC时钟
//配置定时器基础结构体
TIM_TimeBaseStructure.TIM_Period=1000;//设置在下一个更新事件装入活动的自动重装载寄存器周期的值计数到1000为1ms
TIM_TimeBaseStructure.TIM_Prescaler=(72-1);//设置用来作为TIMx时钟频率除数的预分频值1M的计数频率1US计数
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//TIM向上计数模式
TIM_TimeBaseInit(TIM6,&TIM_TimeBaseStructure);//根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_ClearFlag(TIM6,TIM_FLAG_Update);//清除更新中断,免得一打开中断立即产生中断
TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);//打开定时器更新中断
NVIC_SetPriority(TIM6_IRQn,NVICtemp);//设置中断优先级
NVIC_EnableIRQ(TIM6_IRQn);//使能对应中断
}
staticvoidOpenTimerForHc()//打开定时器
{
TIM_SetCounter(TIM6,0);//清除计数
msHcCount=0;
TIM_Cmd(TIM6,ENABLE);//使能TIMx外设
}
staticvoidCloseTimerForHc()//关闭定时器
{
TIM_Cmd(TIM6,DISABLE);//使能TIMx外设
}
//定时器6中断服务程序
voidTIM6_IRQHandler(void)//TIM3中断
{
if(TIM_GetITStatus(TIM6,TIM_IT_Update)!=RESET)//检查TIM3更新中断发生与否
{
TIM_ClearITPendingBit(TIM6,TIM_IT_Update);//清除TIMx更新中断标志
msHcCount++;
}
}
u32GetEchoTimer(void)
{
u32t=0;
t=msHcCount*1000;//得到MS
t+=TIM_GetCounter(TIM6);//得到US
returnt;
}
//一次获取超声波测距数据两次测距之间需要相隔一段时间,隔断回响信号
voidHcsr04GetLength(u32*length)
{
u32t=0;
floatlengthTemp;
TRIG_Send=1;//发送口高电平输出
DelayUs(10);
TRIG_Send=0;
while(ECHO_Reci==0);//等待接收口高电平输出
OpenTimerForHc();//打开定时器
while(ECHO_Reci==1);
CloseTimerForHc();//关闭定时器
t=GetEchoTimer();//获取时间,分辨率为1US
lengthTemp=((float)t/58);//cm
*length=(u32)lengthTemp;
}
Hcsr04.h
#ifndef__HCSR04_H
#define__HCSR04_H
#include"stm32f10x.h"
#include"delay.h"
#include"ioremap.h"
#include"common.h"
//超声波模块初始化
voidHcsr04Init(u32NVIC_PriorityGroup,u32PreemptionPriority,u32SubPriority);
//超声波模块一次距离获取
//返回0成功
//返回1失败
voidHcsr04GetLength(u32*length);
#endif