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