STM32超声波测距及OLED显示距离原理解析

一、超声波简介

超声波原理:

利用声音测距,声音在空气中的速度是340m/s(15℃)
当声音传播时,若遇到障碍物时,就会被反弹回来,通过计时反弹回来的时间就可以计算出从发射端到障碍物的距离

引脚定义:

工作电压:3V-5.5V宽电压供电

测距盲区:2cm最小盲区

接口定义如图

序号

接口定义

说明

1

Vcc

供电电源

2

Trig/Rx/SCL

GPIO模式:   Trig   触发信号

UART模式:   Rx     接收信号

IIC 模式:   SCL    时钟信号

3

Echo/Tx/SDA

GPIO模式为   Echo   反馈信号

UART模式:   Tx     发射信号

ICC 模式:   SCL    数据信号

4

Gnd

GPIO模式测量原理:

 

外部MCU给模块Trig脚一个大于10uS的高电平脉冲;模块会给出一个与距离等比的高电平脉冲信号,可根据脉宽时间“T”算出:距离=T*C/2  (C为声速)

即本文中使用的距离 = t / 58 cm

声速温度公式:c=(331.45+0.61t/℃)m•s-1 (其中330.45是在0℃)

     0℃声速:   330.45M/S

     20℃声速:  342.62M/S

     40℃声速:  354.85M/S

0℃-40℃声速误差7%左右。实际应用,如果需要精确距离值,必需要考虑温度影响,做温度补偿。

二、代码解析

HCSR04.c

初始化部分

void Sr04_Init()
{
/*GPIO初始化*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//设置发生电平引脚trig
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);	
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//接受电平引脚echo
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOB, &GPIO_InitStructure); 
GPIO_ResetBits(GPIOB,GPIO_Pin_11);//默认低电平	
GPIO_ResetBits(GPIOB,GPIO_Pin_10);//默认低电平

/*定时器TIM2初始化*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_InternalClockConfig(TIM2);
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 1000-1;//ARR
TIM_TimeBaseStructure.TIM_Prescaler = 72-1;//PSC
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;	
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除标志位
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//使能更新中断->NVIC

/*NVIC初始化*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStructure);
}

开、关定时器

/*打开定时器*/
void OpenTimer()
{
	TIM_SetCounter(TIM2,0);
	count=0;//计数为零
	TIM_Cmd(TIM2,ENABLE);
}

/*关闭定时器*/
void CloseTimer()
{
	TIM_Cmd(TIM2,DISABLE);
}

定时器中断

void TIM2_IRQHandler(void)	
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update)== SET)
	{
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
		count++;// 72M/(PSC+1)/(ARR+1)即72M/72/1000=1ms
	}
}

获取计数值

u32 GetEchoTimer()
{
u32 t=0;
t = count*1000;
t +=TIM_GetCounter(TIM2);
TIM2->CNT = 0;
Delay_ms(50);
return t;
}

计算距离

float Sr04GetLength()
{
u32 t = 0;
int i = 0;
float length = 0;
float sum = 0;
while(i!=5)
	{
      GPIO_SetBits(GPIOB,GPIO_Pin_11);//trig发出高电平
      Delay_us(20);
      GPIO_ResetBits(GPIOB,GPIO_Pin_11);
      while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10) == 0);//echo等待回响
      OpenTimer();//´打开定时器       
      i = i + 1;//每收到一次,回响信号+1,计算收到5次的平均值
      while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10) == 1);
      CloseTimer();//关闭定时器    
      t = GetEchoTimer();        
      length = ((float)t/58.0);//cm
      sum = length + sum ;        
   }
    length = sum/5.0;
    return length;
}

LED.c

我这里LED接的是高电平,所以STM32给低电平点亮

/*LED初始化*/
void LED_Init()
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
}

void LED_ON()
{
	GPIO_ResetBits(GPIOA,GPIO_Pin_0);
}

void LED_OFF()
{
	GPIO_SetBits(GPIOA,GPIO_Pin_0);
}

main.c

OLED显示距离。

当距离小于10cm时,LED点亮;大于10cm时,LED熄灭。

a=Sr04GetLength();//距离变量a

int main(void)
{
	LED_Init();
	OLED_Init();
	Sr04_Init();
	OLED_ShowString(1,1,"length:");
	
	while(1)
	{
		a=Sr04GetLength();
		OLED_ShowNum(2,1,a,4);
		if(a<10)
		{
			LED_ON();
		}
		else
		{
			LED_OFF();
		}
	}
}

物联沃分享整理
物联沃-IOTWORD物联网 » STM32超声波测距及OLED显示距离原理解析

发表评论