HC_SR04是一款使用較為廣泛的超聲波測距模塊,模塊圖如下
該模塊具有四個引腳,分別為VCC GND TRIG ECHO,其中VCC GND為供電腳
TRIG為測距觸發(fā)引腳,ECHO為測距輸入引腳
該模塊的驅(qū)動模式為
控制口發(fā)一個10US以上的高電平,就可以在接收口等待高電平輸出.一有輸出就可以開定時器計時,當此口變?yōu)榈碗娖綍r就可以讀定時器的值,此時就為此次測距的時間,方可算出距離.如此不斷的周期測,就可以達到你移動測量的值了
模塊工作原理如下
(1)采用IO觸發(fā)測距,給至少10us的高電平信號;
(2)模塊自動發(fā)送8個40khz的方波,自動檢測是否有信號返回;
(3)有信號返回,通過IO輸出一高電平,高電平持續(xù)的時間就是超聲波從發(fā)射到返回的時間
(4計算測試距離測試距離=(高電平時間*聲速(340M/S))/2;
根據(jù)工作原理,我們可以選擇兩種模式驅(qū)動
1.采用中斷+定時器方式,將ECHO定義為上升沿下降沿都能觸發(fā)中斷,trig觸發(fā)之后,echo高電平進中斷打開定時器,echo低電平關(guān)閉定時器并統(tǒng)計定時器計數(shù)值
2.采用普通IO+定時器模式,觸發(fā)之后等待echo響應(yīng),響應(yīng)時打開定時器,直到echo恢復(fù)低關(guān)閉定時器,獲取時間
1:此模塊不宜帶電連接,如果要帶電連接,則先讓模塊的Gnd端先連接。否則會影響
模塊工作。
2:測距時,被測物體的面積不少于0.5平方米且要盡量平整。否則會影響測試結(jié)果。
詳細驅(qū)動代碼如下所示
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計數(shù)
voidHcsr04Init(u32NVIC_PriorityGroup,u32PreemptionPriority,u32SubPriority)
{
u32NVICtemp=0;//用于NVIC控制器的變量
TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;//生成用于定時器設(shè)置的結(jié)構(gòu)體
GPIO_InitTypeDefGPIO_InitStructure;
RCC_APB2PeriphClockCmd(HCSR04_CLK,ENABLE);
NVICtemp=NVIC_EncodePriority(NVIC_PriorityGroup,PreemptionPriority,SubPriority);//中斷優(yōu)先級變量解碼
//IO初始化
GPIO_InitStructure.GPIO_Pin=HCSR04_TRIG;//發(fā)送電平引腳
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);//使能對應(yīng)RCC時鐘
//配置定時器基礎(chǔ)結(jié)構(gòu)體
TIM_TimeBaseStructure.TIM_Period=1000;//設(shè)置在下一個更新事件裝入活動的自動重裝載寄存器周期的值計數(shù)到1000為1ms
TIM_TimeBaseStructure.TIM_Prescaler=(72-1);//設(shè)置用來作為TIMx時鐘頻率除數(shù)的預(yù)分頻值1M的計數(shù)頻率1US計數(shù)
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//TIM向上計數(shù)模式
TIM_TimeBaseInit(TIM6,&TIM_TimeBaseStructure);//根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時間基數(shù)單位
TIM_ClearFlag(TIM6,TIM_FLAG_Update);//清除更新中斷,免得一打開中斷立即產(chǎn)生中斷
TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);//打開定時器更新中斷
NVIC_SetPriority(TIM6_IRQn,NVICtemp);//設(shè)置中斷優(yōu)先級
NVIC_EnableIRQ(TIM6_IRQn);//使能對應(yīng)中斷
}
staticvoidOpenTimerForHc()//打開定時器
{
TIM_SetCounter(TIM6,0);//清除計數(shù)
msHcCount=0;
TIM_Cmd(TIM6,ENABLE);//使能TIMx外設(shè)
}
staticvoidCloseTimerForHc()//關(guān)閉定時器
{
TIM_Cmd(TIM6,DISABLE);//使能TIMx外設(shè)
}
//定時器6中斷服務(wù)程序
voidTIM6_IRQHandler(void)//TIM3中斷
{
if(TIM_GetITStatus(TIM6,TIM_IT_Update)!=RESET)//檢查TIM3更新中斷發(fā)生與否
{
TIM_ClearITPendingBit(TIM6,TIM_IT_Update);//清除TIMx更新中斷標志
msHcCount++;
}
}
u32GetEchoTimer(void)
{
u32t=0;
t=msHcCount*1000;//得到MS
t+=TIM_GetCounter(TIM6);//得到US
returnt;
}
//一次獲取超聲波測距數(shù)據(jù)兩次測距之間需要相隔一段時間,隔斷回響信號
voidHcsr04GetLength(u32*length)
{
u32t=0;
floatlengthTemp;
TRIG_Send=1;//發(fā)送口高電平輸出
DelayUs(10);
TRIG_Send=0;
while(ECHO_Reci==0);//等待接收口高電平輸出
OpenTimerForHc();//打開定時器
while(ECHO_Reci==1);
CloseTimerForHc();//關(guān)閉定時器
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