01模塊來源
資料下載鏈接:https://pan.baidu.com/s/1sSah9PvLBrmbA7So-6YcSw
資料提取碼:qq35
02 規(guī)格參數(shù)
工作電壓:3-5.5V
工作電流:5.3MA
感應(yīng)角度:小于15度
探測距離:2CM-600CM
探測精度:0.1CM+1%
輸出方式: GPIO
管腳數(shù)量:4 Pin
以上信息見廠家資料文件
03移植過程
我們的目標(biāo)是將例程移植至CW32F030C8T6開發(fā)板上【能夠判斷前方障礙物距離的功能】。首先要獲取資料,查看數(shù)據(jù)手冊應(yīng)如何實(shí)現(xiàn)讀取數(shù)據(jù),再移植至我們的工程。
3.1查看資料
只需要在 Trig 管腳(觸發(fā)信號(hào))輸入一個(gè) 10US 以上的高電平,系統(tǒng)便可發(fā)出 8 個(gè) 40KHZ 的超聲波脈沖,然后檢測回波信號(hào)。當(dāng)檢測到回波信號(hào)后,通過 Echo 管腳輸出。根據(jù) Echo 管腳輸出高電平的持續(xù)時(shí)間可以計(jì)算距離值。即距離值為:(高電平時(shí)間*340m/s)/2。
當(dāng)測量距離超過 HC-SR04 的測量范圍時(shí),仍會(huì)通過 Echo管腳輸出高電平的信號(hào),高電平的寬度約為 66ms。如圖所示:
測量周期:當(dāng)接收到 HC-SR04 通過 Echo 管腳輸出的高電平脈沖后,便可進(jìn)行下一次測量,所以測量周期取決于測量距離,當(dāng)距離被測物體很近時(shí),Echo 返回的脈沖寬度較窄,測量周期 就很短;當(dāng)距離被測物體比較遠(yuǎn)時(shí),Echo 返回的脈沖寬度較寬,測量周期也就相應(yīng)的變長。最壞情況下,被測物體超出超聲波模塊的測量范圍,此時(shí) 返回的脈沖寬度最長,約為 66ms,所以最壞情況下的測量周期稍大于 66ms 即可(取 70ms 足夠)。
3.2引腳選擇
接線表
3.3移植至工程
工程模板參考入門手冊的工程模板
移植步驟中的導(dǎo)入.c和.h文件與【CW32模塊使用】DHT11溫濕度傳感器相同,只是將.c和.h文件更改為bsp_ultrasonic.c與bsp_ultrasonic.h。這里不再過多講述,移植完成后面修改相關(guān)代碼。
在文件bsp_ultrasonic.c中,編寫如下代碼。
/*
* Change Logs:
* Date Author Notes
* 2024-06-20 LCKFB-LP first version
*/
#include "bsp_ultrasonic.h"
unsigned char msHcCount = 0;//ms計(jì)數(shù)
float distance = 0;
/******************************************************************
* 函 數(shù) 名 稱:bsp_ultrasonic
* 函 數(shù) 說 明:超聲波初始化
* 函 數(shù) 形 參:無
* 函 數(shù) 返 回:無
* 作 者:LC
* 備 注:TRIG引腳負(fù)責(zé)發(fā)送超聲波脈沖串
******************************************************************/
void Ultrasonic_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
BTIM_TimeBaseInitTypeDef BTIM_TimeBaseInitStruct; // 定時(shí)器基本初始化結(jié)構(gòu)體
RCC_SR04_ENABLE(); // 使能GPIO時(shí)鐘
RCC_TIMER_ENABLE(); // 使能定時(shí)器時(shí)鐘
// GPIO配置參數(shù)
GPIO_InitStructure.Pins = GPIO_TRIG;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; // 推挽輸出
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_Init(PORT_SR04, &GPIO_InitStructure);
GPIO_InitStructure.Pins = GPIO_ECHO;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP; // 上拉輸入
GPIO_Init(PORT_SR04, &GPIO_InitStructure);
// 禁止中斷,以安全地配置NVIC
__disable_irq();
// 開啟BTIM1中斷,并關(guān)聯(lián)到NVIC
NVIC_EnableIRQ(TIMER_IRQ);
// 允許中斷,恢復(fù)中斷狀態(tài)
__enable_irq();
// 配置定時(shí)器模式、周期和預(yù)分頻器
BTIM_TimeBaseInitStruct.BTIM_Mode = BTIM_Mode_TIMER; // 設(shè)置為定時(shí)器模式
BTIM_TimeBaseInitStruct.BTIM_Period = 1000 - 1; // 設(shè)置周期,使得定時(shí)器每1ms產(chǎn)生一次溢出中斷
BTIM_TimeBaseInitStruct.BTIM_Prescaler = BTIM_PRS_DIV64; // 預(yù)分頻器設(shè)置為64,以降低時(shí)鐘頻率
// 使用上述配置初始化定時(shí)器BTIM1
BTIM_TimeBaseInit(PORT_TIMER, &BTIM_TimeBaseInitStruct);
// 使能BTIM1的溢出中斷
BTIM_ITConfig(PORT_TIMER, BTIM_IT_OV, ENABLE);
// // 啟動(dòng)定時(shí)器BTIM1
// BTIM_Cmd(PORT_TIMER, ENABLE);
}
/******************************************************************
* 函 數(shù) 名 稱:Open_Timer
* 函 數(shù) 說 明:打開定時(shí)器
* 函 數(shù) 形 參:無
* 函 數(shù) 返 回:無
* 作 者:LC
* 備 注:
******************************************************************/
void Open_Timer(void)
{
BTIM_SetCounter(PORT_TIMER, 0); // 清除定時(shí)器計(jì)數(shù)
msHcCount = 0;
BTIM_Cmd(PORT_TIMER, ENABLE); // 使能定時(shí)器
}
/******************************************************************
* 函 數(shù) 名 稱:Get_TIMER_Count
* 函 數(shù) 說 明:獲取定時(shí)器定時(shí)時(shí)間
* 函 數(shù) 形 參:無
* 函 數(shù) 返 回:數(shù)據(jù)
* 作 者:LC
* 備 注:
******************************************************************/
uint32_t Get_TIMER_Count(void)
{
uint32_t time = 0;
time = msHcCount*1000; // 得到us
time += BTIM_GetCounter(PORT_TIMER); // 得到ms
BTIM_SetCounter(PORT_TIMER, 0); // 清除定時(shí)器計(jì)數(shù)
delay_ms(10);
return time ;
}
/******************************************************************
* 函 數(shù) 名 稱:Close_Timer
* 函 數(shù) 說 明:關(guān)閉定時(shí)器
* 函 數(shù) 形 參:無
* 函 數(shù) 返 回:無
* 作 者:LC
* 備 注:
******************************************************************/
void Close_Timer(void)
{
BTIM_Cmd(PORT_TIMER, DISABLE); // 關(guān)閉定時(shí)器
}
/******************************************************************
* 函 數(shù) 名 稱:TIMER_IRQHandler
* 函 數(shù) 說 明:定時(shí)器中斷服務(wù)函數(shù)
* 函 數(shù) 形 參:無
* 函 數(shù) 返 回:無
* 作 者:LC
* 備 注:1ms進(jìn)入一次
******************************************************************/
void TIMER_IRQHandler(void)
{
if (BTIM_GetITStatus(CW_BTIM1, BTIM_IT_OV)) // 檢查定時(shí)器中斷發(fā)生
{
msHcCount++;
BTIM_ClearITPendingBit(PORT_TIMER, BTIM_IT_OV); // 清除中斷標(biāo)志
}
}
/******************************************************************
* 函 數(shù) 名 稱:Hcsr04GetLength
* 函 數(shù) 說 明:獲取測量距離
* 函 數(shù) 形 參:無
* 函 數(shù) 返 回:測量距離
* 作 者:LC
* 備 注:無
******************************************************************/
float Hcsr04GetLength(void)
{
/*測5次數(shù)據(jù)計(jì)算一次平均值*/
float length = 0;
float t = 0;
float sum = 0;
unsigned int i = 0;
while(i != 10)
{
SR04_TRIG(1);//trig拉高信號(hào),發(fā)出高電平
delay_1us(20);//持續(xù)時(shí)間超過10us
SR04_TRIG(0);//trig拉低信號(hào),發(fā)出低電平
/*Echo發(fā)出信號(hào) 等待回響信號(hào)*/
/*輸入方波后,模塊會(huì)自動(dòng)發(fā)射8個(gè)40KHz的聲波,與此同時(shí)回波引腳(echo)端的電平會(huì)由0變?yōu)?;
(此時(shí)應(yīng)該啟動(dòng)定時(shí)器計(jì)時(shí));當(dāng)超聲波返回被模塊接收到時(shí),回波引 腳端的電平會(huì)由1變?yōu)?;
(此時(shí)應(yīng)該停止定時(shí)器計(jì)數(shù)),定時(shí)器記下的這個(gè)時(shí)間即為
超聲波由發(fā)射到返回的總時(shí)長;*/
while(SR04_ECHO() == GPIO_Pin_RESET);//echo等待回響
Open_Timer(); //打開定時(shí)器
i++;
while(SR04_ECHO() == GPIO_Pin_SET);
Close_Timer(); // 關(guān)閉定時(shí)器
t = Get_TIMER_Count(); // 獲取時(shí)間,分辨率為1us
length = (float)t / 58.0f; // cm
sum += length;
}
length = sum/10;//五次平均值
distance = length;
return length;
}
?
在文件bsp_ultrasonic.h中,編寫如下代碼。
/*
* Change Logs:
* Date Author Notes
* 2024-06-20 LCKFB-LP first version
*/
#ifndef _BSP_ULTRASONIC_H_
#define _BSP_ULTRASONIC_H_
#include "board.h"
#define RCC_SR04_ENABLE() __RCC_GPIOA_CLK_ENABLE()
#define PORT_SR04 CW_GPIOA
#define GPIO_TRIG GPIO_PIN_1
#define GPIO_ECHO GPIO_PIN_2
#define RCC_TIMER_ENABLE() __RCC_BTIM_CLK_ENABLE()
#define PORT_TIMER CW_BTIM1
#define TIMER_IRQ BTIM1_IRQn
#define TIMER_IRQHandler BTIM1_IRQHandler
#define SR04_TRIG(x) GPIO_WritePin( PORT_SR04, GPIO_TRIG, x?GPIO_Pin_SET:GPIO_Pin_RESET)
#define SR04_ECHO() GPIO_ReadPin( PORT_SR04, GPIO_ECHO )
void Ultrasonic_Init(void);//超聲波初始化
float Hcsr04GetLength(void );//獲取超聲波測距的距離
#endif
?04移植驗(yàn)證
在自己工程中的main主函數(shù)中,編寫如下。
/*
* Change Logs:
* Date Author Notes
* 2024-06-20 LCKFB-LP first version
*/
#include "board.h"
#include "stdio.h"
#include "bsp_uart.h"
#include "bsp_ultrasonic.h"
int32_t main(void)
{
board_init(); // 開發(fā)板初始化
uart1_init(115200); // 串口1波特率115200
Ultrasonic_Init();
printf("Start.......rn");
while(1)
{
printf((const char *)"距離為 = %.2fCMrn",Hcsr04GetLength() );
delay_ms(500);
}
}
移植現(xiàn)象:距離20CM處擺放障礙物,輸出換算后的實(shí)際距離。
模塊移植成功案例代碼:
鏈接:https://pan.baidu.com/s/1AwXOFbLryUoYPW-ueRZ_qA?pwd=LCKF
提取碼:LCKF