1. 程式人生 > >STM32F4-超聲波測距模組學習筆記(HC-SR04)

STM32F4-超聲波測距模組學習筆記(HC-SR04)

(1)基本的工作原理:
a、IO口 --TRIG觸發測距,最少給10us的高電平
b、模組自己發出8個40KHz的方波,檢測是否有訊號返回
c、ECHO迴向訊號輸出一個高電平,高電平持續輸出的時間就是超聲波一個來回的時間
d、距離=(高電平持續時間*340m/s)/2
(2)IO口選擇:
由於資料輸出使用TTl串列埠資料輸出,所以借用了STM32預留的CAMERA介面,選用了DCMI_D5(TRIG)、DCMI_D7(ECHO),電源5V和地線
在這裡插入圖片描述

(3)時序圖解讀:
在這裡插入圖片描述
以上時序圖表示,需要提供一個持續10us的高電平觸發脈衝訊號,這樣模組會自己檢測回波訊號,這樣根據通過從發射訊號到回收到訊號的時間間隔可以算出距離;us公式 --》us/58=釐米
us/148=英寸。

(4)部分關鍵程式碼:
//開啟AHB1 B組ER組時鐘 選用CAMERA DCMI_D5 DCMI_D7引腳 對應PB6 PE6這些引腳的初始化便不都寫上;

標頭檔案:
#ifndef __HC_SRC_H
#define __HC_SRC_H

//標頭檔案
#include “stm32f4xx.h” //這個標頭檔案一定要留
#include “sysTick.h” //滴答定時器

#define TRIG(a); if(a)
GPIO_SetBits(GPIOB,GPIO_Pin_6);
else
GPIO_ResetBits(GPIOB, GPIO_Pin_6);

#define EHCO GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_6)

//函式宣告
void HC_SRC04_Init(void);//GPIO口初始化
uint16_t Get_Dist(void);//獲取距離

#endif
獲取距離方法:
uint16_t Get_Dist(void)
{
uint16_t dis = 0;

//1、使用TRIG引腳發初始訊號
TRIG(1);
Time_us(15);
TRIG(0);

//2、利用EHCO 獲取接收回波時間
while(EHCO==0);//等待高電平
TIM3->CNT = 0; //計時器置0
TIM_Cmd(TIM3,ENABLE);//開始計時
while(EHCO==1);      //收到回波
TIM_Cmd(TIM3,DISABLE);//關閉計時

//3、計算距離
dis = (count*1000+TIM3->CNT)/58;
count=0;
return dis;

}

串列埠的初始化:
void UART1_Init(uint32_t BaudRate)
{
GPIO_InitTypeDef GPIO_InitStructrue;
USART_InitTypeDef USART_InitStructrue;
NVIC_InitTypeDef NVIC_InitStructrue;

//1、開啟   串列埠1  相關GPIO時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

//2、將 PA9 PA10 引腳複用為 USART1 的特殊功能引腳
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10, GPIO_AF_USART1);

//3、配置以及初始化 PA9 PA10 為複用模式
GPIO_InitStructrue.GPIO_Mode  = GPIO_Mode_AF;   //複用模式
GPIO_InitStructrue.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructrue.GPIO_Pin   = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructrue.GPIO_PuPd  = GPIO_PuPd_UP;
GPIO_InitStructrue.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructrue);

//4、配置以及初始化 串列埠模式
USART_InitStructrue.USART_BaudRate = BaudRate;   //波特率 115200 9600 ...
USART_InitStructrue.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//關閉硬體流控
USART_InitStructrue.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  //能夠接收 也 能夠傳送
USART_InitStructrue.USART_Parity = USART_Parity_No;  //無校驗
USART_InitStructrue.USART_StopBits =USART_StopBits_1;   //1位停止位
USART_InitStructrue.USART_WordLength = USART_WordLength_8b; //8位資料位
USART_Init(USART1,&USART_InitStructrue);

//5、開啟接收中斷  USART_IT_RXNE  --->接收資料暫存器不為空時觸發中斷。表示有資料到來
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);

//6、初始化 NVIC
NVIC_InitStructrue.NVIC_IRQChannel = USART1_IRQn;   //串列埠1中斷
NVIC_InitStructrue.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructrue.NVIC_IRQChannelPreemptionPriority = 1;   //搶佔優先順序
NVIC_InitStructrue.NVIC_IRQChannelSubPriority = 0;          //響應優先順序
NVIC_Init(&NVIC_InitStructrue); 

//7、使能 串列埠1
USART_Cmd(USART1, ENABLE);

}

!!!當使用printf函庫數時,記得新增標頭檔案“string.h”並重寫fputc()
int fputc(int ch, FILE *f)
{
//等待當前資料傳送完成
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {}
//傳送一個位元組資料
USART_SendData(USART1, (uint8_t) ch);
return ch;
}

附:
在此專案中實現過程需要用到滴答定時器、TIM計時器等見我其他篇幅的學習筆記,在我部落格中可以搜尋到。(串列埠輸出使用stc-isp中的串列埠助手)