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