基於stm32的HC-SR04超聲波測距模塊使用

1 工作原理

使用超聲波模塊之前,先了解其IO口和工作原理:

1.1 IO說明

VCC: 供5V電源
GND: 爲地線
TRIG: 觸發控制信號輸入
ECHO: 迴響信號輸出
在這裏在這裏插入圖片描述插入圖片描述

1.2 基本工作原理:

認真看好以下工作原理,後面的代碼就是基於工作原理來實現的。
(1)採用IO口TRIG觸發測距,給最少10us的高電平信號。
(2)模塊自動發送8個40khz的方波,自動檢測是否有信號返回;
(3)有信號返回, 通過IO口ECHO輸出一個高電平,高電平持續的時間就是超聲波從發射到返回的時間。 測試距離=(高電平時間*聲速(340M/S))/2
時序圖:
在這裏插入圖片描述

2 程序編寫

2.1 外設配置

根據兩個信號引腳來配置兩個單片機的IO口
trig: 需要產生一個10us高電平, 配置爲推輓輸出;
echo: 等待高電平脈衝並測量其脈衝寬度, 配置爲下拉輸入
測量echo的高電平持續的時間,需要用到定時器, 因此配置一個定時器,用來計時

void UltrasonicWave_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//開啓GPIOB時鐘
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //開啓TIM2時鐘	
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;	 // 對應trig引腳
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推輓輸出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
 	GPIO_ResetBits(GPIOB,GPIO_Pin_1);	
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;	 // 對應echo引腳
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; 	//下拉輸入
 	GPIO_Init(GPIOB, &GPIO_InitStructure);	  
 	
   //定時器初始化,分頻係數爲71,則頻率爲1MHZ,每個計數爲1us,(頻率越高越精確)
   //重裝載值爲65535,溢出時間爲1us*65536=	65.536ms=0.065536s
   //一個計數週期可以測距 0.065536s * 340m/s / 2  = 11.14112m
	TIM_TimeBaseStructure.TIM_Period = 65535; 
	TIM_TimeBaseStructure.TIM_Prescaler = 71; 
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; 
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //	
}

2.2 測距函數

根據工作原理 :
(1)採用IO口TRIG觸發測距,給最少10us的高電平信號。

/***** 啓動超聲波 *****/
void UltrasonicWave_StartMeasure(void)
{
	GPIO_SetBits(GPIOB, GPIO_Pin_1);   //拉高PB1電平
	delay_us(20);            //持續20us
	GPIO_ResetBits(GPIOB, GPIO_Pin_1); //拉低PB1電平
}

(2)有信號返回, 通過IO口ECHO輸出一個高電平,高電平持續的時間就是超聲波從發射到返回的時間。 測試距離=(高電平時間*聲速(340M/S))/2

/***** 測距 *****/
float UltrasonicWave_Measure(void)   //
{
    while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==1);//echo爲高電平時,則等待至低電平,才啓動超聲波
	UltrasonicWave_StartMeasure(); //啓動超聲波			
	while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10) == 0);//等待echo的高電平到來	
	TIM_SetCounter(TIM2,0); //清零計數器
	TIM_Cmd(TIM2, ENABLE);  //使能定時器2,開始計數
	while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10) == 1);//等待echo的高電平結束
    TIM_Cmd(TIM52, DISABLE);	//失能定時器2,截止計數	
	return (TIM_GetCounter(TIM2))/1000000*340/2 *100;	//此處單位轉換爲cm
}

2.3 測距

int main()
{
		float distance;
		UltrasonicWave_Init(void);//初始化
		delay_init();
		while(1)
		{
		    distance = UltrasonicWave_Measure(void); //完成測距
		    delay_ms(60);//建議測量週期爲 60ms以上, 以防止發射信號對迴響信號的影響。
		    printf("distance:%5.2f ",distance);//打印到串口
        }	
}

還可以使用中斷方式進行測距, 大致框架如下, 有興趣自行研究

  //先開啓對應引腳雙邊沿觸發中斷, 中斷服務函數大致如下
  float Distance;
  void EXTI15_10_IRQHandler(void)
  {		 		
	if(//發生中斷)
	{   
		if(//上升沿)   
		{
			TIM_SetCounter(TIM2,0); //清零計數器
			TIM_Cmd(TIM2, ENABLE);  //使能定時器2,開始計數
 		}
	    if(//下降沿)
	    {
		    TIM_Cmd(TIM52, DISABLE);	//失能定時器2,截止計數
			Distance=(TIM_GetCounter(TIM2))/1000000*340/2 *100;//此處單位轉換爲cm
		}
	}
	EXTI_ClearITPendingBit(EXTI_Line10);  //清除中斷標誌					  
 } 
  //主函數
  
```c
extern float Distance;
int main()
{
		UltrasonicWave_Init(void);//初始化
		while(1)
		{
			UltrasonicWave_StartMeasure();//啓動超聲波
		    delay_ms(60);//建議測量週期爲 60ms以上, 以防止發射信號對迴響信號的影響。
		    //Distance 在中斷服務函數中被重新賦值
		    printf("Distance:%5.2f ",Distance);//打印到串口
        }	
}

以上超聲波模塊的使用一次記錄,歡迎一起討論

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章