主頁 >  其他 > 《嵌入式-STM32開發指南》第三部分 外設篇 - 第4章 超聲波測距

《嵌入式-STM32開發指南》第三部分 外設篇 - 第4章 超聲波測距

2021-06-10 09:40:33 其他

4.1 理論分析

4.1.1超聲波概述

人類耳朵能聽到的聲波頻率為20Hz~20000Hz,當聲波的振動頻率小于20Hz或大于20KHz時,我們便聽不見了,因此,我們把頻率高于20000赫茲的聲波稱為“超聲波”(ultrasonic),通常的超聲波頻率為1兆赫茲~5兆赫茲,它的方向性好,穿透能力強,易于獲得較集中的聲能,在水中傳播距離遠,可用于測距、測速、清洗、焊接、碎石、殺菌消毒等,在醫學、軍事、工業、農業上有很多的應用,

超聲波發生器可以分為兩大類:一類是用電氣方式產生超聲波,一類是用機械方式產生超聲波

電氣方式包括壓電型、磁致伸縮型和電動型等;機械方式有加爾統笛、液哨和氣流旋笛等,它們所產生的超聲波的頻率、功率和聲波特性各不相同,因而用途也各不相同,目前較為常用的是壓電式超聲波發生器,

壓電式超聲波發生器實際上是利用壓電晶體的諧振來作業的,其外觀結構與內部結構分別如圖所示,該傳感器有兩個壓電陶瓷(壓電晶片)和一個共鳴器(共振板), 當其兩極外加脈沖信號,且頻率等于壓電陶瓷的固有振蕩頻率時,壓電陶瓷將會發生共振,并帶動共鳴器振動產生超聲波,反之,如果兩電極間未外加電壓,當共振板接收到超聲波時,將迫使壓電陶瓷振動,將機械能轉換為電信號,這時它就成為超聲波接收器了,

圖1超聲波模塊內部結構簡圖

4.1.2超聲波測距作業原理

目前超聲波測距的方法有多種:如時間差測距法、相位測距法、聲波幅值測距法,最常用就是時間差測距法,本文的測距方法就是時間差測距法

超聲波發射器向某一方向發射超聲波,在發射的同時開始計時,超聲波在空氣中傳播,途中碰到障礙物就立即回傳,超聲波接收器收到反射波就立即停止計時,根據時間差和超聲波的速度可以估算出發射位置到障礙物位置的距離,超聲波在空氣中的傳播速度為340 m/ s,根據計時器記錄的時間t,就可以計算出發射點距障礙物的距離S ,即:S = 340t / 2,這就是所謂的時間差測距法,

圖2超聲波測距基本原理

超聲波指向性強,在介質中傳播的距離較遠,利用超聲波測距往往比較迅速、方便、計算簡單、易于做到實時控制,并且在測量精度方面能達到工業實用的要求,因此在移動機器人的研制上也得到了廣泛的應用,

超聲波測距傳感器規格很多,測驗距離也從遠到近都有,價格相差也較大,一般機器人愛好者使用的都是測量范圍在最小幾厘米到最大幾米之間,超聲波傳感器一般作用距離較短,普通的有效探測距離都在5-10m之間,精度約5毫米,但是會有一個最小探測盲區,一般在幾十毫米,因為聲波的特性,所以超聲波傳感器受環境影響比較小,使用場合比較廣泛,

圖3超聲波測距范圍

超聲波測距的優點在于測量范圍較大,且不是使用光學信號,所以被測物體的顏色對于測量結果沒有影響,但還是常常會受到外界環境的其它因素影響,依靠聲速測距,所以對于一些影響聲速的因素較敏感,比如溫度、風等,最大允許角度較小,在不同的室溫下,聲速是不同的,因而會給測距帶來誤差,所以一般的模塊測距精度都難以小于5毫米,但很自然的會想到采用溫度補償的方式,也即額外再添加一個溫度傳感器,根據不同溫度下的聲速來計算,從而可以補償溫度變化帶來的誤差,表1列出了幾種不同溫度下的聲速,在使用時,如果溫度變化不大,則可認為聲速是基本不變的,如果測距精度要求很高,則應通過溫度補償的方法加以校正

表1聲速與溫度的關系
溫度-30-20-100102030100
聲速m/s313319325323338344349386

根據以上資料可以進行線性擬合,得到如下公式:

V = 331.4 + 0.607 T ( 攝 氏 溫 度 ) V = 331.4 + 0.607 T (攝氏溫度) V=331.4+0.607T()

式中, T T T為實際溫度單位為 ℃ ℃ V V V為超聲波在介質中的傳播速度單位為 m / s m/s m/s

根據測得的實際溫度矯正環境中的真實聲速,以減小測量誤差,這樣的模塊測距精度就可以達到1~2毫米了,而且同時能當做溫度傳感器來使用,但價格也會稍高,

超聲波測距傳感器可能是機器人中運用最為廣泛的傳感器之一了,它不僅便宜,擁有豐富的庫,而且測量結果也較為可靠,我們都知道蝙蝠夜行時躲避障礙物的原理,下面以一款市面上最為成熟和常見的超聲波測距模塊HC-SR04為例來說明,

圖4超聲波模塊HC-SR04實物圖

當然啦,如果環境比較復雜,建議使用帶有溫度補償的模塊,這里推薦US-100模塊,該超聲波模塊沒有自帶溫度補償,以340m/s的室溫下聲速作為參斬訓準,同個擴展庫捕捉脈沖寬度獲得超聲波來回的時間后,通過簡單的運算獲得距離,

4.1.3 HC-SR04 測距原理

HC-SR04超聲波測距模塊可提供2cm-400cm的非接觸式距離感測功能,HC-SR04模塊性能穩定,測度距離精確,能和國外的SRF05、SRF02等超聲波測距模塊相媲美,模塊高精度,盲區(2cm)超近,測距精度可達3mm(這個是廠家介紹,一般測距要3cm以上,精度有時要到達5-6mm),包括發射器、接收器與控制電路,它是一種壓電式傳感器,利用電致伸縮現象而制成,在壓電材料切片上(如石英晶體、壓電陶瓷、鈦酸鉛鋇等)施加交變電壓,使它產生電致伸縮振動而產生超聲波,當外加交變電壓的頻率等于晶片的固有頻率而產生共振,這時產生的超聲波最強,壓電式超聲波接收器一般是利用超聲波發生器的逆效應進行作業的,其結構和超聲波發生器基本相同,有時就用同一個換能器兼作發生器和接收器兩種用途,當超聲波作用到壓電晶片上時使晶片伸縮,在晶片的兩個界面上便產生交變電荷后轉換成電壓經放大送到測量電路,最后記錄或顯示出來,

HC-SR04超聲波測距模塊的基本作業原理:

(1)采用IO口TRIG 觸發測距,給最少10us的高電平信號,
(2)模塊自動發送8個40khz的方波,自動檢測是否有信號回傳;
(3)有信號回傳,通過IO口ECHO輸出一個高電平,高電平持續的時間就是超聲波從發射到回傳的時間,測驗距離=(高電平時間*聲速(340M/S))/2,

HC-SR04測距時序圖如下:

圖5超聲波HC-SR04測距時序圖

以上時序圖表明你只需要提供一個 10uS 以上脈沖觸發信號,該模塊內部將發出 8 個 40kHz 周期電平并檢測回波,一旦檢測到有回波信號則輸出回響信號,回響信號的脈沖寬度與所測的距離成正比,由此通過發射信號到收到的回響信號時間間隔可以計算得到距離,建議測量周期為 60ms 以上,以防止發射信號對回響信號的影響

【注1】此模塊不宜帶電連接, 若要帶電連接, 則先讓模塊的 GND 端先連接, 否則會影響模塊的正常作業,

【注2】測距時,被測物體的面積不少于 0.5 平方米且平面盡量要求平整,否則影響測量的結果,

4.2 實驗詳解

4.2.1實驗目的

1.通過實驗掌握STM32 芯片定時器的配置方法
2.掌握超聲波的測距原理

4.2.2實驗設備

硬體:PC 機一臺;STM32開發板一套; 超聲波模塊一個
軟體:Windows 10系統,Keil5集成開發環境

4.2.3硬體連接

HC-SR04模塊電路圖如下圖所示:

圖6 HC-SR04模塊電路圖

TL074:四路低噪聲 JFET 輸入通用運算放大器,放大接收信號及控制,
MAX232:MAX232芯片是美信(MAXIM)公司專為RS-232標準串口設計的單電源電平轉換芯片,使用+5v單電源供電,

圖7 T1 T2輸入輸出的典型曲線

超聲波模塊利用232芯片能夠輸出正負壓信號給超聲波發生器件供電,以此來達到最大電壓差(約13~14V)給超聲波器件供電,增大超聲波發送功率,

STC11:STC單片機,處理邏輯信號,

STM32與HC-SR04模塊連接示意圖如下:

圖8 STM32與HC-SR04模塊連接圖

4.2.4 Lib_V3.5.0庫實作

根據HC-SR04 測距原理,測距流程如下:TRIG發一個10us以上的高電平,ECHO等待高電平輸出,一有輸出就可以開定時器計時,當ECHO檢測到低電平時就可以讀定時器的值,此時就為此次測距的時間,方可算出距離,具體流程圖如下:

圖9測距流程圖

距離的計算公式如下:

距 離 = ( 高 電 平 時 間 ? 聲 速 ( 340 M / S ) ) / 2 ( 單 位 : m ) 距離 = (高電平時間*聲速(340M/S))/2(單位:m) =(?(340M/S))/2(m)

接下來看看代碼是如何實作的,這里只講HC-SR04 測距相關的內容,

1.GPIO和定時器初始化

/**
 * @brief  初始化定時器3
 * @param  None
 * @retval None
 */
void HCRS04_Tim3_Config(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_ICInitTypeDef TIM3_ICInitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	
  //TIM_DeInit(TIM3);//復位TIM3定時器 
  TIM_TimeBaseStructure.TIM_Period =  7199;
  TIM_TimeBaseStructure.TIM_Prescaler = 199; 
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM3, & TIM_TimeBaseStructure);
    
	//初始化Timer3_CH1(PA6)為PWM輸出
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //選擇定時器模式:TIM脈沖寬度調制模式
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
	TIM_OCInitStructure.TIM_Pulse = 7150; //設定待裝入捕獲比較暫存器的脈沖值
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高
	TIM_OC1Init(TIM3, &TIM_OCInitStructure);  //根據TIM_OCInitStruct中指定的引數初始化外設TIMx
	TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);  //CH1預裝載使能
	
	//初始化Timer3_CH2(PA7)為脈寬捕獲
	TIM3_ICInitStructure.TIM_Channel = TIM_Channel_2; //選擇輸入端
	TIM3_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲
	TIM3_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
	TIM3_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;	  //配置輸入分頻,不分頻 
	TIM3_ICInitStructure.TIM_ICFilter = 0x00;	  //IC1F=0000 配置輸入濾波器 不濾波
	TIM_ICInit(TIM3, &TIM3_ICInitStructure);
	
}

/**
 * @brief  初始化超聲波IO口
 * @param  None
 * @retval None
 */
void HCRS04_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;			/*PA6--TRIG1*/
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	/*復用推挽輸出*/
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 
	GPIO_Init(GPIOA, &GPIO_InitStructure);	
 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;		/*PA7--ECHO3*/
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;/*浮空輸入模式*/	 
	GPIO_Init(GPIOA, &GPIO_InitStructure);

}

/**
 * @brief  初始化超聲波中斷
 * @param  None
 * @retval None
 */
void HCRS04_NVIC_Config(void)
{

	NVIC_InitTypeDef NVIC_InitStructure;
	
	//使能定時器3通道2捕獲中斷
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中斷
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占優先級1級
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //從優先級0級
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);   //根據NVIC_InitStruct中指定的引數初始化外設NVIC暫存器 
	TIM_ITConfig(TIM3, TIM_IT_CC2,ENABLE);   //不允許更新中斷,允許CC2IE捕獲中斷	
	TIM_Cmd(TIM3, ENABLE);  //使能TIM3
  TIM_ClearFlag(TIM3, TIM_FLAG_Update); 
  //TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
}

關于GPIO的初始化沒啥好說的,PA6做輸出,對應的是TRIG,用于觸發測距信號;PA7作為輸入,對應的是ECHO,需要進行輸入捕獲來獲取高電平的時間,

這里需要配置定時器3,這里使用PWM輸出來觸發測距信號,

根據前面的引數配置,我們可以算出TIM的輸出周期:

T I M = 1 / ( T c l k / ( p s c + 1 ) ) ? ( a r r + 1 ) TIM=1/(Tclk/(psc+1))*(arr+1) TIM=1/(Tclk/(psc+1))?(arr+1)

arr=7199 psc=199 Tclk=72Mhz

T I M = 1 / ( 72 M h z / ( 200 ) ) ? ( 7200 + 1 ) = 20 m s TIM=1/(72Mhz/(200))*(7200+1)=20ms TIM=1/(72Mhz/(200))?(7200+1)=20ms

占空比為 7150 / 7200 = 99 7150/7200=99% 7150/7200=99,因此完全能達到觸發的要求,

2.定時器的通道2進行脈寬捕獲,獲取高電平時間

/**
  * @brief  This function handles TIM3 interrupt request.
  * @param  None
  * @retval None
  */
void TIM3_IRQHandler(void)
{
	if ((TIM3CH2_CAPTURE_STA & 0X80) == 0)		//還未成功捕獲	
	{
		if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)		//捕獲2發生捕獲事件
		{
			TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);		//清除中斷標志位
			if (TIM3CH2_CAPTURE_STA & 0X40)		//捕獲到一個下降沿
			{
				TIM3CH2_CAPTURE_DOWNVAL = TIM_GetCapture2(TIM3);//記錄下此時的定時器計數值
				if (TIM3CH2_CAPTURE_DOWNVAL < TIM3CH2_CAPTURE_UPVAL)
				{
					TIM3_T2 = 65535;
				}
				else
					TIM3_T2 = 0;
				tempup = TIM3CH2_CAPTURE_DOWNVAL - TIM3CH2_CAPTURE_UPVAL + TIM3_T2;		//得到總的高電平的時間
				TIM3CH2_CAPTURE_STA = 0;		//捕獲標志位清零
				TIM_OC2PolarityConfig(TIM3, TIM_ICPolarity_Rising); //設定為上升沿捕獲		  
			}
			else //發生捕獲時間但不是下降沿,第一次捕獲到上升沿,記錄此時的定時器計數值
			{
				TIM3CH2_CAPTURE_UPVAL = TIM_GetCapture2(TIM3);		//獲取上升沿資料
				TIM3CH2_CAPTURE_STA |= 0X40;		//標記已捕獲到上升沿
				TIM_OC2PolarityConfig(TIM3, TIM_ICPolarity_Falling);//設定為下降沿捕獲
			}
			//計算距離
			distance = tempup * 0.034; //標準值0.034
		}
	}
}

定時器的周期是20ms,因此最終的得到的距離是:

距 離 = ( T I M 3 的 計 數 器 ? 20 / 1000 s ? 聲 速 ( 340 m / s ) ) / 200 = T I M 3 的 計 數 器 ? 0.034 ( 單 位 : c m ) 距離 = (TIM3的計數器*20/1000s*聲速(340m/s))/200 = TIM3的計數器*0.034(單位:cm) =(TIM3?20/1000s?(340m/s))/200=TIM3?0.034cm

3.最后,給出主函式的代碼

/**
  * @brief     main
  * @param     None
  * @retval    
  */
int main(void)
{	
  /*時鐘初始化*/
	SysTick_Init();
	
  /* USART1 配置模式為 115200 8-N-1,中斷接收 */
	USART1_Config();
	
	/* 超聲波初始化*/
	HCRS04_Config();
	
	printf("超聲波測距\r\n");
	
	while(1)
  {
    Delay_ms(1000);
		printf("Distance: %f cm\r\n",distance);
  }
}

到此,HC-SR04 的測距基本就實作了,筆者在測驗的時候發現,實際測驗程序中有個別資料會例外偏小,這是由于HC-SR04 的“余震”導致的,具體解釋如下:

1.電路串擾,超聲波發射時的瞬間電流很大,例如某種工業級連續測距產品瞬間電流會有15A,通常的產品也能達到1A,瞬間這么大的電流會對電源有一定影響,并干擾接收電路,通過改善電源設計可以緩解這種情況,但在低成本設計中很難根除,所以每次發射完畢,接收電路還需要一段時間穩定作業狀態,因此,在沒穩定前,HC-SR04 的測的距離和實際的距離差別較大,

2.探頭的余震,即使是分體式的,發射頭作業完后還會繼續震一會,這是物理效應,也就是余震,這個余震信號也會向外傳播,如果你的設計是發射完畢后立刻切換為接收狀態(無盲區),那么這個余震波會通過殼體和周圍的空氣,直接到達接收頭、干擾了檢測,
注:通常的測距設計里,發射頭和接收頭的距離很近,在這么短的距離里超聲波的檢測角度是很大的,可達180度,

2.殼體的余震,就像敲鐘一樣,能量仍來自發射頭,發射結束后,殼體的余震會直接傳導到接收頭,當然這個時間很短,但已形成了干擾,另外,在不同的環境溫度下,殼體的硬度和外形會有所變化,其余震有時長、有時短、有時干擾大、有時干擾小,這是設計工業級產品時必須要考慮的問題,

總之,就是HC-SR04 的各種不穩定因素導致測量精度偏差較大,消除上述現象最常用的方法就是在檢測的時候多次回圈檢測,取平均值

重新修改定時器3的內容,代碼如下:

/**
  * @brief  This function handles TIM3 interrupt request.
  * @param  None
  * @retval None
  */
void TIM3_IRQHandler(void)
{
	if ((TIM3CH2_CAPTURE_STA & 0X80) == 0)		//還未成功捕獲	
	{
		if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)		//捕獲2發生捕獲事件
		{
			TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);		//清除中斷標志位
			if (TIM3CH2_CAPTURE_STA & 0X40)		//捕獲到一個下降沿
			{
				TIM3CH2_CAPTURE_DOWNVAL = TIM_GetCapture2(TIM3);//記錄下此時的定時器計數值
				if (TIM3CH2_CAPTURE_DOWNVAL < TIM3CH2_CAPTURE_UPVAL)
				{
					TIM3_T2 = 65535;
				}
				else
					TIM3_T2 = 0;
				tempup = TIM3CH2_CAPTURE_DOWNVAL - TIM3CH2_CAPTURE_UPVAL + TIM3_T2;		//得到總的高電平的時間

				TIM3CH2_CAPTURE_STA = 0;		//捕獲標志位清零
				TIM_OC2PolarityConfig(TIM3, TIM_ICPolarity_Rising); //設定為上升沿捕獲		  
			}
			else //發生捕獲時間但不是下降沿,第一次捕獲到上升沿,記錄此時的定時器計數值
			{
				TIM3CH2_CAPTURE_UPVAL = TIM_GetCapture2(TIM3);		//獲取上升沿資料
				TIM3CH2_CAPTURE_STA |= 0X40;		//標記已捕獲到上升沿
				TIM_OC2PolarityConfig(TIM3, TIM_ICPolarity_Falling);//設定為下降沿捕獲
			}
			//計算距離
			sum += tempup * 0.034; //標準值0.034
			
			if(count == 5)
			{
				distance = sum/5.0;
				count = 0;
				sum = 0.0;
			}
			else
			{
				count ++;
			}
		}
	}
}

當然啦,有興趣的朋友可以深入研究,還可以更精度更高的測距模塊,

4.2.5 HAL庫實作

我們在串口的例子的基礎上進行配置,

串口通信(HAL庫)

這里需要配置TIM,關于TIM的內容,請參考筆者以前的博文:

TIM

由STM32與HC-SR04模塊的硬體連接關系圖,PA6做輸出,對應HC-SR04模塊的TRIG,用于觸發測距信號;PA7作為輸入,對應HC-SR04模塊的ECHO,需要進行輸入捕獲來獲取高電平的時間,那么接下來來一一配置,

1.設定RCC

設定高速外部時鐘HSE,選擇外部時鐘源,

圖10 RCC配置

2.時鐘配置
筆者的板子使用的外部晶振為8MHz,選擇外部時鐘HSE 8MHz ,PLL鎖相環9倍頻后為72MHz,系統時鐘來源選擇為PLL,設定APB1分頻器為 /2,這時候定時器的時鐘頻率為72Mhz,本文筆者使用的定時器是TIM3,TIM3掛在APB1上,不同的定時器掛在不同總線上的,

圖11時鐘配置

【注】TIM3的時鐘源有兩個選項

選項1 :Internal Clock 內部時鐘
選項2 : ETR2 外部觸發輸入(ETR)(僅適用TIM2,3,4)

3.GPIO配置
上文使用PWM最為輸出來觸發測距信號,這里通過控制GPIO的高低電平來觸發測距信號,

圖12配置PA6為輸出

將PA6配置為輸出即可,

4.TIM3配置
本文要使用TIM3的通道2,因此需要將其使能,每個通道有很多模式,通道2選擇輸入捕獲模式,當對應的通道打開后,對應的GPIO也會被使能,

圖13使能TIM3的通道

【注】如果使能通道前通道中GPIO使用過,STM32CubeMX會自動將GPIO配置為重映射的GPIO,舉個例子,當PB0被占用了,那么四個GPIO會重映射到PC6-PC9,

TIM引數配置如下:

  • Counter setting

Prtscaler (定時器分頻系數) : 199
Counter Mode(計數模式) :Up(向上計數模式)
Counter Period(自動重裝載值) : 7199
CKD(時鐘分頻因子) : No Division 不分頻
選項: 可以選擇二分頻和四分頻
auto-reload-preload(自動重裝載) : Enable 使能

  • TRGO Output (TRGO) Parameters

Master/Slave Mode(MSM bit):Disable
TRGO:定時器的觸發信號輸出 在定時器的定時時間到達的時候輸出一個信號(如:定時器更新產生TRGO信號來觸發ADC的同步轉換,)

  • Input Capture Channel (CH2)

Polarity Selection(輸入捕獲模式): Rising Edge(上升沿捕獲)
IC Selection (映射模式):Direct(直接映射)
Prescaler Division Ratio(分頻模式):No division(不分頻)
Input Filter(配置輸入濾波器):(不濾波)

圖14 TIM3引數配置

根據前面的引數配置,arr=999 psc=0 Tclk=72Mhz ,

T I M = 1 / ( 72 M h z / ( 200 ) ) ? ( 7199 + 1 ) = 20 m s TIM=1/(72Mhz/(200))*(7199+1)=20ms TIM=1/(72Mhz/(200))?(7199+1)=20ms

和使用Lib_V3.5.0庫的計算結果是一樣的,

還需要開啟中斷,

圖15開啟TIM3中斷

好了,到這里,配置就完成了,生成工程就行了,

下面看看測距的代碼是如何實作的,

1.初始化GPIO、TIM3等
這部分是自動生成的,這里就不貼出來了

2.TRIG發一個10us以上的高電平

static void HC_SR04_Delayus ( __IO uint32_t ulCount )
{
	uint32_t i;
	for ( i = 0; i < ulCount; i ++ )
	{
		uint8_t uc = 12;     //設定值為12,大約延1微秒  	      
		while ( uc -- );     //延1微秒	
	}	
}

static void HC_SR04_Start_signal(void)
{
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);
	//延時20us
	HC_SR04_Delayus(20);

	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);
}

通過GPIO的讀寫來觸發測距信號,延時就用個簡單延時就可以,不需要太精確,

3.輸入捕獲,得到高電平的時間

/**
  * @brief  This function handles TIM3 Capture Callback.
  * @param  None
  * @retval None
  */
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	TIM_IC_InitTypeDef sConfigIC = {0};
	
  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
  sConfigIC.ICFilter = 0;
	
	if(htim->Instance == htim3.Instance)
	{
		if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
		{
			if(sCapture.ChannelEdge == 0)          //捕獲上升沿
			{
				sCapture.RisingTime = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_2);                         //獲取上升沿時間點    
				sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;//切換捕獲極性
				HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_2);
				
				HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2);     //切換捕獲極性后需重新啟動
 
				sCapture.ChannelEdge = 1;          	 //上升沿、下降沿捕獲標志位
			}
			else if(sCapture.ChannelEdge == 1)     //捕獲下降沿
			{
				sCapture.FallingTime = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_2);                       //獲取下降沿時間點
				sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;//切換捕獲極性
				HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_2);
				
				HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2);   	 //切換捕獲極性后需重新啟動
 
				sCapture.HighTime = sCapture.FallingTime < sCapture.RisingTime ? sCapture.FallingTime + 0xffff - sCapture.RisingTime + 1 : sCapture.FallingTime - sCapture.RisingTime;
				 
				//清零
				sCapture.ChannelEdge = 0;		  			
				
				sCapture.FinishFlag = 1;  
				
				//高電平持續時間 = 下降沿時間點 - 上升沿時間點
				//計算超聲波測量距離
				distance = (float)sCapture.HighTime * 0.034;

			}
		}
	}
}

4.最后在主函式中列印輸出距離資訊,

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_TIM3_Init();
  /* USER CODE BEGIN 2 */
	HAL_UART_Receive_IT(&huart1, (uint8_t *)&RxBuffer, 1);
  
	/*使能定時3*/  
	// 啟動輸入捕獲并開啟中斷
	HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);
			
	printf("超聲波測距\r\n");
		
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
		HC_SR04_Start_signal();
		
		/* 完成測量高電平脈寬 */
    if(sCapture.FinishFlag)
		{
			printf("Distance: %f cm\r\n",distance);
			
			sCapture.FinishFlag = 0;	
			HAL_Delay(1000);
		}
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

注意一定開啟輸入捕獲中斷,其他就沒事好說了,

4.2.6實驗現象

不管是使用何種庫,結果都是一樣的,





代碼獲取方法

1.長按下面二維碼,關注公眾號[嵌入式實驗樓]
2.在公眾號回復關鍵詞[STM32F1]獲取資料

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/286475.html

標籤:其他

上一篇:在物聯網中解讀投資回報(一)

下一篇:一起Talk Android吧(第二百九十八回:Android中的BLE開發:大結局)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more