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);//打印到串口
}
}
以上超聲波模塊的使用一次記錄,歡迎一起討論