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(TIM2, 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(TIM2, DISABLE); //失能定時器2,截止計數 Distance=(TIM_GetCounter(TIM2))/1000000*340/2 *100;//此處單位轉換為cm } } EXTI_ClearITPendingBit(EXTI_Line10); //清除中斷標志 } //主函數 extern float Distance; int main() { UltrasonicWave_Init(void);//初始化 while(1) { UltrasonicWave_StartMeasure();//啟動超聲波 delay_ms(60);//建議測量周期為 60ms以上, 以防止發射信號對回響信號的影響。 //Distance 在中斷服務函數中被重新賦值 printf("Distance:%5.2f ",Distance);//打印到串口 } }
以上超聲波模塊的使用一次記錄,歡迎一起討論
版權聲明:本文為CSDN博主「hhh_little_hu」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_40134414/article/details/105290644