模塊:HC-SR04
感應角度:不大于15度?
探測距離:2cm-450cm??????
高精度:可達0.3cm
Trig:觸發信號,接收MCU發送的控制脈沖,MCU對應GPIO 設置為輸出
Echo:反饋信號,向MCU發送數據脈沖,?MCU對應GPIO 設置為輸入
VCC:3.3V~5V
超聲波測距原理:
- 超聲波發射裝置向某一方向發出超聲波,并開始計時
- 超聲波在空氣中傳播,途中碰到障礙物就立即返回來
- 接收器接收到超聲波的時間差,就停止計時
- 根據超聲波在空氣中傳播速度(340m/s),再根據計時器記錄的時間t,可以算出距離(s)
似乎有多種模式,本文只使用GPIO模式:
單片機操作步驟:
(1)采用IO口TRIG觸發測距,給最少10us的高電平信號。
(2)模塊自動發送8個40khz的方波,自動檢測是否有信號返回;
(3)有信號返回, 超聲波模塊通過ECHO引腳輸出一個高電平(ECHO輸出的高電平持續時間,就是處理的結果), 高電平持續的時間就是超聲波從發射到返回的時間。
代碼
UltraSonic_Init()
- 配置 GPIOG 的 14 腳為 Trig 輸出,15 腳為 Echo 輸入
- 配置 TIM4 定時器為 1MHz 計數頻率 (1us / 計數)
- 設置最大測量時間為 50ms (50000 計數)
void UltraSonic_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;// UlatrSonic-->PG14,PG15RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE); //使能PG端口時鐘GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; // TrigGPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽輸出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度為50MHzGPIO_Init(GPIOG, &GPIO_InitStructure); //根據設定參數初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; // EchoGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //設置成上拉輸入GPIO_Init(GPIOG, &GPIO_InitStructure); //推挽輸出 ,IO口速度為50MHz// 設置一個定時器,1us計數1個數,不用中斷,且開始時不使能定時器//1、能定時器時鐘。RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);TIM_TimeBaseInitStruct.TIM_Prescaler = 84-1; //84MHZ/8400 = 10000HZ Prescaler范圍1~65536 TIM_TimeBaseInitStruct.TIM_Period = 50000-1; //在10000HZ時鐘頻率下,用時1ms 自動重裝載寄存器值TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上計數TIM_TimeBaseInitStruct.TIM_ClockDivision= TIM_CKD_DIV1; //分頻因子//2、初始化定時器TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStruct);//【不使能定時器】TIM_Cmd(TIM4, DISABLE);
}
UltraSonic_GetDistance()
- 發送 15us 的高電平觸發信號,然后拉低引腳
- 等待模塊返回的 Echo 信號(高電平)
- 高電平來了,開始定時器計時,目的是測量 Echo 高電平持續時間
- 低電平來了,停止定時器計時,得到 Echo 高電平持續時間
- 根據超聲波在空氣中的傳播速度 (340m/s) 計算距離
float UltraSonic_GetDistance()
{float distance_cm = 0;u32 time_us = 0;//**************************************//啟動超聲波模塊 也就是要發送啟動信號GPIO_ResetBits(GPIOG, GPIO_Pin_14);delay_us(5);//高電平需要10us以上---【啟動信號】GPIO_SetBits(GPIOG, GPIO_Pin_14);delay_us(15);GPIO_ResetBits(GPIOG, GPIO_Pin_14);//*********************************//設置定時器的CNT值為0,設置初值TIM_SetCounter(TIM4,0);//等待ECHO的高電平到來while(GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_15)==Bit_RESET);//**************************//【高電平來了】-------啟動定時器TIM_Cmd(TIM4,ENABLE);//等待ECHO的低電平到來while(GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_15)==Bit_SET);//****************************//【低電平來了】------讀時間數據,關定時器//取出CNT的值-----定時器的當前值time_us = TIM_GetCounter(TIM4); // 微秒 (μs)。//關閉定時器TIM_Cmd(TIM4, DISABLE);//**************************************//【通過公式】: // distance (m) * 2 = time * 10(-6) * 340m/s// distance (m) = time * 10(-6) * 340m/s / 2// distance (cm) = time * 10(-6) * 340m/s / 2 * 100 = time * 10(-3) * 17distance_cm = time_us * 0.017; // distance = time / 58;return distance_cm;
}
調用程序:
void ULTRA_SONIC_task(void *pvParameters)
{float distance_cm = 0;while(1){printf("ULTRA_SONIC_task \r\n");distance_cm = UltraSonic_GetDistance();printf("distance = %f (cm) \r\n",distance_cm);delay_ms(3000);}
}
輸出結果: