HCSR04超聲波傳感器驅動

HC_SR04是一款使用較爲普遍的超聲波測距模塊,模塊圖以下測試


該模塊具備四個引腳,分別爲VCC GND TRIG ECHO,其中VCC GND爲供電腳spa

TRIG爲測距觸發引腳,ECHO爲測距輸入引腳code

該模塊的驅動模式爲事件

控制口發一個 10US 以上的高電平,就能夠在接收口等待高電平輸出.一有輸出就能夠開定時器計時,當此口變爲低電平時就能夠讀定時器的值,此時就爲這次測距的時間,方可算出距離.如此不斷的週期測,就能夠達到你移動測量的值了ip

 

模塊工做原理以下ci

(1)採用 IO 觸發測距,給至少 10us 的高電平信號;rem

(2)模塊自動發送 8 40khz 的方波,自動檢測是否有信號返回;it

(3)有信號返回,經過 IO 輸出一高電平,高電平持續的時間就是超聲波從發射到返回的時間io

(4計算測試距離測試距離=(高電平時間*聲速(340M/S))/2;class

 

根據工做原理,咱們能夠選擇兩種模式驅動

1.       採用中斷+定時器方式,ECHO定義爲上升沿降低沿都能觸發中斷,trig觸發以後,echo高電平進中斷打開定時器,echo低電平關閉定時器並統計定時器計數值

2.       採用普通IO+定時器模式,觸發以後等待echo響應,響應時打開定時器,直到echo恢復低關閉定時器,獲取時間

 

1:此模塊不宜帶電鏈接,若是要帶電鏈接,則先讓模塊的 Gnd 端先鏈接。不然會影響

模塊工做。

2:測距時,被測物體的面積很多於0.5平方米且要儘可能平整。不然會影響測試結果。

 

詳細驅動代碼以下所示

Hcsr04.c

#include "hcsr04.h"


#define HCSR04_PORT     GPIOB
#define HCSR04_CLK      RCC_APB2Periph_GPIOB
#define HCSR04_TRIG     GPIO_Pin_5
#define HCSR04_ECHO     GPIO_Pin_6

#define TRIG_Send  PBout(5)
#define ECHO_Reci  PBin(6)

u16 msHcCount = 0;//ms計數

void Hcsr04Init(u32 NVIC_PriorityGroup,u32 PreemptionPriority,u32 SubPriority)
{
	u32 NVICtemp    = 0;        //用於NVIC控制器的變量
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;     //生成用於定時器設置的結構體
	GPIO_InitTypeDef GPIO_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);                     //使能對應中斷
	
}
static void OpenTimerForHc()	//打開定時器
{
	TIM_SetCounter(TIM6,0);//清除計數
	msHcCount = 0;
	TIM_Cmd(TIM6, ENABLE);  //使能TIMx外設
}

static void CloseTimerForHc()	//關閉定時器
{
	TIM_Cmd(TIM6, DISABLE);  //使能TIMx外設
}


//定時器6中斷服務程序
void TIM6_IRQHandler(void)   //TIM3中斷
{
	if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET)  //檢查TIM3更新中斷髮生與否
	{
		TIM_ClearITPendingBit(TIM6, TIM_IT_Update  );  //清除TIMx更新中斷標誌 
		msHcCount++;
	}
}

u32 GetEchoTimer(void)
{
	u32 t = 0;
	t = msHcCount*1000;//獲得MS
	t += TIM_GetCounter(TIM6);//獲得US
	return t;
}

//一次獲取超聲波測距數據 兩次測距之間須要相隔一段時間,隔斷迴響信號
void Hcsr04GetLength(u32* length)
{
    u32 t = 0;
    float lengthTemp;
    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"





//超聲波模塊初始化
void Hcsr04Init(u32 NVIC_PriorityGroup,u32 PreemptionPriority,u32 SubPriority);

//超聲波模塊一次距離獲取
//返回0 成功
//返回1 失敗
void Hcsr04GetLength(u32* length);

#endif



相關文章
相關標籤/搜索