STM32—超声波测距仪

老小孩
原创
发布时间: 2025-06-09 22:51:23 | 阅读数 0收藏数 0评论数 0
封面
这次做一个超声波测距仪,原理是计算超声波从发射到声波从障碍物反射回来的时间差,乘以声波传播的速度(340m)除以2,从而得到测距仪到障碍物的距离。

准备工作:

材料:

  1. STM32最小系统板
  2. 超声波模块HC-SR04
  3. 面包板
  4. 0.96 OLED
  5. 导线
1

硬件连接

单片机 ---->OLED

PB14 ---->SCK

PB15 ---->SDA

V3.3 ---->VDD

GND ---->GND

单片机----->超声波模块

PBA0 -----> ECHO

PBA8 -----> TRIG

V5 -----> VCC

GND -----> GND

2

打包OLED代码为模块

在上篇文中,OLED接单片机的引脚是A0、A1,这次是B14、B15。把上次的代码修改一下,在HARDWARE文件夹下,新建文件夹OLED。在Keil中新建2个文件,取名为oled.c和oled.h,保存在刚才新建的OLED文件夹下。分别复制代码到oled.c和oled.h(定义和声明放.h别的放.c)。这样就把oled文件打包成了单独的文件模块,配置这两个文件到项目中。用同样的方法添加配置Timer模块(附件中有做好的文件)

3

建立超声波模块文件

用同样的方法,在HARDWARE文件夹下,新建文件夹HCSR04。在Keil中新建2个文件,取名为hcsr04.c和hcsr04.h,保存在刚才新建的HCST04文件夹下,并配置它。分别复制下面的代码到hcsr04.c和hcsr04.h。

hcsr04.h文件:

#ifndef __HCSR04_H

#define __HCSR04_H

#include "sys.h"

void HC_SR04_Init(void);

int16_t sonar_mm(void);

float sonar(void);

#endif

Hcsr04.c文件:

#include "sys.h"

#include "delay.h"

#include "hcsr04.h"

#define Echo GPIO_Pin_0 //HC-SR04模块的Echo脚接GPIOB6

#define Trig GPIO_Pin_8 //HC-SR04模块的Trig脚接GPIOB5

uint64_t time=0; //声明变量,用来计时

uint64_t time_end=0; //声明变量,存储回波信号时间

void HC_SR04_Init(void)

{

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //启用GPIOB的外设时钟

GPIO_InitTypeDef GPIO_InitStructure; //定义结构体

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置GPIO口为推挽输出

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //设置GPIO口5

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置GPIO口速度50Mhz

GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化GPIOB

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //设置GPIO口为下拉输入模式

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //设置GPIO口6

GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化GPIOB

GPIO_WriteBit(GPIOA,GPIO_Pin_8,0); //输出低电平

// delay_us(15); //延时15微秒

}

int16_t sonar_mm(void) //测距并返回单位为毫米的距离结果

{

uint32_t Distance,Distance_mm = 0;

GPIO_WriteBit(GPIOA,GPIO_Pin_8,1); //输出高电平

delay_us(15); //延时15微秒

GPIO_WriteBit(GPIOA,GPIO_Pin_8,0); //输出低电平

while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==0); //等待低电平结束

time=0; //计时清零

while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==1); //等待高电平结束

time_end=time; //记录结束时的时间

if(time_end/100<38) //判断是否小于38毫秒,大于38毫秒的就是超时,直接调到下面返回0

{

Distance=(time_end*346)/2; //计算距离,25°C空气中的音速为346m/s

Distance_mm=Distance/100; //因为上面的time_end的单位是10微秒,所以要得出单位为毫米的距离 //结果,还得除以100

}

return Distance_mm; //返回测距结果

}

float sonar(void) //测距并返回单位为米的距离结果

{

uint32_t Distance,Distance_mm = 0;

float Distance_m=0;

GPIO_WriteBit(GPIOA,GPIO_Pin_8,1); //输出高电平

delay_us(15);

GPIO_WriteBit(GPIOA,GPIO_Pin_8,0); //输出低电平

while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==0);

time=0;

while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==1);

time_end=time;

if(time_end/100<38)

{

Distance=(time_end*346)/2;

Distance_mm=Distance/1000;

Distance_m=Distance_mm/1000;

}

return Distance_m;

}

void TIM3_IRQHandler(void) //更新中断函数,用来计时,每10微秒变量time加1

{

if (TIM_GetITStatus(TIM3, TIM_IT_Update) == SET) //获取TIM3定时器的更新中断标志位

{

time++;

TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除更新中断标志位

}

}

4

编辑主程序代码并测试

复制下面的代码到主程序文件main.c,编译并烧录到单片机中,如果操作都对的话,屏幕上就会显示距离的数值了,用手挡在HCSR04模块的前面并调整距离,并观看屏幕结果。

#include "sys.h"

#include "delay.h"

#include "timer.h"

#include "usart.h"

#include "oled.h"

#include "hcsr04.h"

int main(void)

{

Init_OLED(); //初始化OLED屏

Timer_Init(); //初始化定时器

HC_SR04_Init(); //初始化超声波测距模块

string_8x16(20,0,"Rangefinder");//Rangefinder

OLED_diplay();

delay_init();

while (1)

{

string_8x16(0,4,"DIST: ");

string_8x16_num(40,4,sonar_mm()/10);//sonar_mm()

OLED_diplay();

delay_ms(300); //延时300毫秒

}

}

测试视频见附件:

MP4
测距仪测试视频.mp4
1.99MB
阅读记录0
点赞0
收藏0
禁止 本文未经作者允许授权,禁止转载
猜你喜欢
评论/提问(已发布 0 条)
评论 评论
收藏 收藏
分享 分享
pdf下载 下载