超聲波用於避障,測距之類的,是比較簡單的傳感器
datasheet下載地址
外觀
HC-SR04超聲波測距模塊可提供約2cm400釐米的非接觸式距離感測功能,測距精度可達高到3毫米;模塊包括超聲波發射器,接收器與控制電路像智能小車的測距以及轉向,或是一些項目中,常常會用到。智能小車測距可以及時發現前方的障礙物,使智能小車可以及時轉向,避開障礙物。
HC-SR04有4個引腳:VCC,GND,TRIG和ECHO。
- VCC是5v電源。這應該來自微控制器
- GND是接地引腳。在微控制器上接地。
- TRIG應連接到可設置爲HIGH的GPIO引腳
ECHO有點困難。HC-SR04輸出5v,可能會破壞許多微控制器GPIO引腳(最大允許電壓變化)。爲了降壓,使用單個電阻器或分壓器電路。這又取決於您使用的特定微控制器,您需要找出其GPIO最大電壓並確保低於該值。(只限於FT引腳),也就是ECHO對於stm32只能連在FT引腳上!!
基本原理
TRIG引腳負責發送超聲波脈衝串。此引腳應設置爲高電平10μs,此時HC-SR04將以40 kHZ發出8個週期的聲波脈衝。發出聲波爆發後,ECHO引腳將變爲高電平。 ECHO引腳是數據引腳 - 用於進行距離測量。發送超聲波脈衝串後, ECHO引腳將變爲高電平,它將保持高電平,直到檢測到超聲波脈衝串爲止,此時它將變爲低電平。
就是TRIG引腳給一個持續10us的高電平,觸發超聲波模塊自動發送8個40khz的方波,發出聲波後,ECHO引腳會被拉高,待接收到之後,ECHO引腳拉低,我們只要測出ECHO引腳從拉高到拉低的時間就可以知道距離了
計算公式
我們知道聲速是340m/s
根據x=vt
因爲超聲波發送出去和回來是測量距離的兩倍,所以假設距離是L
2L=344xt
t我們用定時器測出來
一般都是us
所以就是tx172x10的-6次方=L,L單位爲cm
最終的出 L= t(us) * 0.0172(cm/us)
0.0172=1/58
所以 L= t(us)/58(cm)
對於51單片機,12mhz的週期時間爲1us
所以11.059200mzh的計算公式爲
L = 計數 x(12/11.0592) x (1/58)
= 計數 x 0.0187
= (計數 x 1.87)/100(cm)
測試代碼
51&15
//#include <reg52.h>
#include "stc15.h"
#include <intrins.h>
#include <stdio.h>
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
sbit Echo=P3^2;//超聲波模塊echo腳定義
sbit Trig=P3^3;//超聲波模塊trig腳定義
u16 time=0;
float Distance=0;
bit flag=0;//定時器0溢出標誌位
void Config_UARTimer(u16 Baud);//配置串口,定時器
void Delay10us_15(void);//15延時10us程序
void Delay10us_51(void);//51延時10us程序
void delayms(u16 ms);//ms延時程序
void StartModule();//打開超聲波測距
void Count_Distance();//計算距離
void main()
{
Config_UARTimer(9600);
while(1)
{
StartModule();
while(!Echo);
TR0=1;
while(Echo);
TR0=0;
Count_Distance();
delayms(100);
}
}
//15延時10us程序
void Delay10us_15(void)
{
u8 i=30;
_nop_();
while(--i);
}
//51延時10us程序
void Delay10us_51(void)
{
u8 i=15;
_nop_();
while(--i);
}
//ms延時程序
void delayms(unsigned int ms)
{
unsigned char i=100,j;
for(;ms;ms--)
{
while(--i)
{
j=10;
while(--j);
}
}
}
//打開超聲波測距
void StartModule()
{
Trig=1;
Delay10us_51();
Trig=0;
}
void Count_Distance()
{
time=TH0*256+TL0;
TH0=0;
TL0=0;
Distance = (time*1.87)/100;
if(flag==1) //超出測量
{
flag=0;
printf("-----\n");
}
else
{
printf("Distance = %f CM\n",Distance);
}
}
void Config_UARTimer(u16 Baud)
{
//需要配置串口,定時器0,定時器1
// //15單片機配置
// PCON &= 0x7F; //不倍速
// SCON = 0x50; //工作方式1,8位異步
// AUXR &= 0xBF; //定時器1時鐘爲Fosc/12,即12T
// AUXR &= 0xFE; //串口1選擇定時器1爲波特率發生器
// TMOD &= 0x0F;
// TMOD|=0X21;//定時器1工作方式2(8位定時器),定時器0工作方式1(16位定時器)
//
// TH0=0;
// TL0=0;//定時器0初值賦值
//
// TH1=256-(11059200/12/32)/Baud;
// TL1=TH1;//定時器1初值賦值
//
// ET0=1;//定時中斷0打開
// ET1=0;//定時中斷1禁止
// TR0=1;//定時器0打開
// TR1=1;//定時器1打開
// TI=1;
//51單片機配置程序
PCON&=0X7F;//不倍速
SCON=0X50;//工作方式1,8位異步
TMOD=0X21;//定時器1工作方式2(8位定時器),定時器0工作方式1(16位定時器)
TH0=0;
TL0=0;//定時器0初值賦值
TH1=256-(11059200/12/32)/Baud;
TL1=TH1;//定時器1初值賦值
ET0=1;//定時中斷0打開
ET1=0;//定時中斷1禁止
TR0=1;//定時器0關閉
TR1=1;//定時器1打開
TI=1;
EA=1;//打開總中斷
}
void timer0()interrupt 1
{
flag=1;
}
stm32
hcsr04.c
#include "hcsr04.h"
#include "delay.h"
u16 overcount=0;//溢出計數
//中斷配置
void NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStruct;
//設置中斷優先級
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//中斷初始化
NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
NVIC_Init(&NVIC_InitStruct);
}
//超聲波初始化
void HCSR04_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
//時鐘使能
RCC_APB2PeriphClockCmd(HCSR04,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
//trig腳-推輓輸出
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=HCSR04_TRIG;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(HCSR04_PORT,&GPIO_InitStruct);
GPIO_ResetBits(HCSR04_PORT,HCSR04_TRIG);
//echo腳-浮空輸入
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin=HCSR04_ECHO;
GPIO_Init(HCSR04_PORT,&GPIO_InitStruct);
GPIO_ResetBits(HCSR04_PORT,HCSR04_ECHO);
//定時器TIM2初始化
TIM_DeInit(TIM2);
TIM_TimeBaseInitStruct.TIM_Period=1000-1;
TIM_TimeBaseInitStruct.TIM_Prescaler=72-1;
TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
//定時器中斷配置_更新中斷
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
//中斷配置
NVIC_Config();
//關閉定時器使能
TIM_Cmd(TIM2,DISABLE);
}
//打開定時器
void OpenTimeForHc(void)
{
//計數器清空
TIM_SetCounter(TIM2,0);
overcount=0;
TIM_Cmd(TIM2,ENABLE);
}
//關閉定時器
void CloseTimeForHc(void)
{
TIM_Cmd(TIM2,DISABLE);
}
//獲取定時器時間
u32 GetEchoTimer(void)
{
u32 t=0;
t=overcount*1000;
t+=TIM_GetCounter(TIM2);
//計數器清0
TIM2->CNT=0;
delay_ms(50);
return t;
}
//超聲波測距
float Hcsr04GetLength(void)
{
u32 t=0;
int i=0;
float lengthTemp=0;
float sum=0;
while(i!=5)
{
TRIG_Send=1;
delay_ms(20);
TRIG_Send=0;
while(ECHO_Reci==0);
OpenTimeForHc();
i=i+1;
while(ECHO_Reci==1);
CloseTimeForHc();
t=GetEchoTimer();
lengthTemp=((float)t/58.0);
sum+=lengthTemp;
}
lengthTemp=sum/5;
return lengthTemp;
}
//定時器2中斷
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)
{
//清除中斷標誌位
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
overcount++;
}
}
hcsr04.h
#ifndef __HCSR04_H
#define __HCSR04_H
#include "sys.h"
#define HCSR04_PORT GPIOB
#define HCSR04 RCC_APB2Periph_GPIOB
#define HCSR04_TRIG GPIO_Pin_5
#define HCSR04_ECHO GPIO_Pin_6
#define TRIG_Send PBout(5)
#define ECHO_Reci PBin(6)
void NVIC_Config(void);//中斷配置
void HCSR04_Init(void);//超聲波初始化
float Hcsr04GetLength(void);//超聲波測距
#endif