目錄
0、SR-04基本原理
1、準(zhǔn)備工作
2、連線
?3、STM32CUBEMX設(shè)置
3.1新建工程
3.2芯片通用設(shè)置
3.3定時(shí)器捕獲設(shè)置
?3.4其他設(shè)置
3.5生成工程
?4、程序完善
4.1完善打印輸出函數(shù)
?4.2完善tim.c
4.3完善gpio.c?
4.4完善main函數(shù)?
?5、總結(jié)
0、SR-04基本原理
聲波遇到障礙物會(huì)反射,而聲波的速度已知,所以只需要知道發(fā)射到接收的時(shí)間差,就能輕松計(jì)算出測(cè)量距離,再結(jié)合發(fā)射器和接收器的距離,就能算出障礙物的實(shí)際距離。
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-619511.html
?
以HC-SR04硬件為例,端口為VCC、Trig、Echo、GND。
VCC–接STM32板子+5V;
GND–接STM32板子GND;
Trig–為觸發(fā)控制信號(hào)輸入,觸發(fā)測(cè)距,給至少10us的高電平信號(hào),模塊自動(dòng)發(fā)射8個(gè)40KHz的方波,自動(dòng)檢測(cè)是否有信號(hào)返回;
Echo–回響信號(hào)輸出,有信號(hào)返回,通過(guò)IO口ECHO輸出一個(gè)高電平,高電平持續(xù)時(shí)間就是超聲波從發(fā)射到返回的時(shí)間。
那用STM32怎么給端口信號(hào)呢?又是怎么獲取信號(hào)呢?
Trig端口為超聲波模塊的輸入信號(hào),也就是通過(guò)STM23一個(gè)端口推挽輸出一個(gè)至少10us的高電平信號(hào)即可,利用delay_ms(20)實(shí)現(xiàn);
Echo端口為超聲波模塊的輸出信號(hào),也就是利用STM32端口捕獲高電平時(shí)間,那么這個(gè)端口肯定是可以用做定時(shí)器的端口。
通過(guò)以上分析,這里采用以下STM32端口
?
1、準(zhǔn)備工作
開(kāi)發(fā)板:STM32F1精英版
軟件:STM32CubeMx軟件
IDE: MDK-Keil軟件
傳感器:HC-SR04
2、連線
選擇TIM5的CH1即PA0作為輸入捕獲引腳(Echo),選擇PA5作為觸發(fā)腳Trig。具體連接線如下:
紅線連接精英版的5V與SR04的VCC腳
白線連接精英板的GND與SR04的GND腳
橙色線連接精英板的PA5與Trig腳
黑色線連接精英板的PA0與Echo腳
?3、STM32CUBEMX設(shè)置
3.1新建工程
1)新建工程
2)選擇芯片
3.2芯片通用設(shè)置
1)時(shí)鐘芯片設(shè)置
2)時(shí)鐘設(shè)置
3)系統(tǒng)調(diào)試設(shè)置
3.3定時(shí)器捕獲設(shè)置
由于前文連線中,我們將TIMER5CH1作為輸入捕獲引腳,所以對(duì)TIMER5進(jìn)行設(shè)置:
Channel 1選擇:Input Capture direct mode
與分頻系數(shù)填寫(xiě):72-1(則每次計(jì)數(shù)為1us)
Polarity Selection選擇:Rising Edge(上升沿)
其他保持不變。
NVIC settings選擇TIM5 global interrupt
3.4其他設(shè)置
1)USART1設(shè)置
為了方便調(diào)試,將測(cè)量所得數(shù)據(jù)通過(guò)串口傳遞到電腦上進(jìn)行顯示,此處使用串口1通過(guò)printf將輸出發(fā)送至電腦。
?2)GPIO配置
?此處選擇PA5作為Trig腳,具體配置如下:
3.5生成工程
?4、程序完善
4.1完善打印輸出函數(shù)
在main函數(shù)中加入下面語(yǔ)句:
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "string.h"
/* USER CODE END Includes */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/* USER CODE END 0 */
加入此語(yǔ)句之后可以在main函數(shù)中加入printf語(yǔ)句測(cè)試是否成功。
將精英板USB232口通過(guò)USB數(shù)據(jù)線與電腦連接,并在電腦上打開(kāi)串口調(diào)試軟件:?
?
?4.2完善tim.c
在tim.c中加入以下程序:
定義變量:
/* USER CODE BEGIN 0 */
//捕獲狀態(tài)
//[7]:0,沒(méi)有成功的捕獲;1,成功捕獲到一次.
//[6]:0,還沒(méi)捕獲到低電平;1,已經(jīng)捕獲到低電平了.
//[5:0]:捕獲低電平后溢出的次數(shù)
uint8_t TIM5CH2_CAPTURE_STA=0; //輸入捕獲狀態(tài)
uint16_t TIM5CH2_CAPTURE_VAL; //輸入捕獲值(TIM2是16位)
/* USER CODE END 0 */
?在底部加入溢出回調(diào)函數(shù)和輸入捕獲回調(diào)函數(shù)。其中參考了正點(diǎn)原子官方的的輸入 捕獲回調(diào)函數(shù)。
/* USER CODE BEGIN 1 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//更新中斷(溢出)發(fā)生時(shí)執(zhí)行
{
if((TIM5CH2_CAPTURE_STA&0X80) ==0) //還未捕獲成功
{
if(TIM5CH2_CAPTURE_STA&0X40) //捕獲到一個(gè)下降沿
{
if((TIM5CH2_CAPTURE_STA&0X3F)==0X3F) //高電平時(shí)間太長(zhǎng)了
{
TIM5CH2_CAPTURE_STA |= 0X80; //標(biāo)記成功捕獲一次
TIM5CH2_CAPTURE_VAL = 0XFFFF; //
}
else
TIM5CH2_CAPTURE_STA++; //否則標(biāo)記溢出數(shù)加一
}
}
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//捕獲中斷發(fā)生時(shí)執(zhí)行
{
if((TIM5CH2_CAPTURE_STA&0x80)==0) //還未捕獲成功
{
if(TIM5CH2_CAPTURE_STA&0x40) //成功捕獲到一個(gè)下降沿
{
TIM5CH2_CAPTURE_STA |= 0X80; //標(biāo)記成功,捕獲到一次高電平完成
TIM5CH2_CAPTURE_VAL = HAL_TIM_ReadCapturedValue(&htim5, TIM_CHANNEL_1); //獲取當(dāng)前捕獲值
TIM_RESET_CAPTUREPOLARITY(&htim5, TIM_CHANNEL_1); //清除原來(lái)設(shè)置
TIM_SET_CAPTUREPOLARITY(&htim5, TIM_CHANNEL_1, TIM_ICPOLARITY_RISING); //捕獲到下降沿后,將捕獲復(fù)位到捕獲上升沿
}
else //捕獲到一個(gè)上升沿
{
TIM5CH2_CAPTURE_STA = 0;
TIM5CH2_CAPTURE_VAL = 0;
TIM5CH2_CAPTURE_STA |= 0x40; //第六位標(biāo)記為捕獲到上升沿
__HAL_TIM_DISABLE(&htim5); //關(guān)閉定時(shí)器
__HAL_TIM_SET_COUNTER(&htim5, 0); //定時(shí)器初始值設(shè)置為0
TIM_RESET_CAPTUREPOLARITY(&htim5, TIM_CHANNEL_1);
TIM_SET_CAPTUREPOLARITY(&htim5, TIM_CHANNEL_1, TIM_ICPOLARITY_FALLING); //捕獲到上升沿之后,將捕獲設(shè)置為下降沿
__HAL_TIM_ENABLE(&htim5);
}
}
}
/* USER CODE END 1 */
4.3完善gpio.c?
模擬Trig腳,先置位,過(guò)40us后,復(fù)位。
/* USER CODE BEGIN 2 */
void CHL_capture(void)
{
uint32_t i;
HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_SET);
for(i=0;i<72*40;i++)
__NOP();
HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET);
}
/* USER CODE END 2 */
4.4完善main函數(shù)?
int main(void)
{
/* USER CODE BEGIN 1 */
float len = 0;
uint32_t time= 0;
uint8_t count = 0;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM5_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
printf("Hello World!\r\n");
HAL_TIM_IC_Start_IT(&htim5,TIM_CHANNEL_1); //開(kāi)啟TIM2的捕獲通道2,并且開(kāi)啟捕獲中斷
__HAL_TIM_ENABLE_IT(&htim5,TIM_IT_UPDATE); //使能更新中斷
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_Delay(100);
CHL_capture();
if(TIM5CH2_CAPTURE_STA & 0x80) //成功捕獲一個(gè)脈寬
{
time = TIM5CH2_CAPTURE_STA & 0x3F; //獲取溢出次數(shù)
time *= 65536; //獲得溢出的時(shí)間值
time += TIM5CH2_CAPTURE_VAL; //加上最后一次取得的值
len = time * 342.62*100/2000000;
TIM5CH2_CAPTURE_STA = 0;
}
printf("LENGTH: %f CM\r\n", len);
}
/* USER CODE END 3 */
}
?5、總結(jié)
本文介紹了通過(guò)HAL庫(kù)完成SR-04超聲波傳感器距離的測(cè)量。包括了,超聲波傳感器的原理、STM32CUBEMX的配置,以及程序的完善。最終的結(jié)果如下:
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-619511.html
?
到了這里,關(guān)于手把手教你,通過(guò)HAL庫(kù)實(shí)現(xiàn)STM32的超聲波測(cè)距--以SR-04為例的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!