STM32超声波测距(OLED显示距离)

文章介绍了超声波测距的基本原理,包括声音在不同温度下的速度以及如何通过测量回波时间计算距离。同时,详细解析了使用STM32进行超声波模块(HCSR04)的GPIO初始化、定时器配置和中断处理的代码,以及如何进行温度补偿以提高精度。此外,文中还展示了LED灯根据测距结果亮灭的实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、超声波简介

超声波原理:

利用声音测距,声音在空气中的速度是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();
		}
	}
}

### 解决 IntelliJ IDEA 中 `@Autowired` 注解导致的红色波浪线错误 在使用 Spring 框架时,如果遇到 `@Autowired` 注解下的依赖注入对象显示为红色波浪线错误或者黄色警告的情况,通常是由以下几个原因引起的: #### 1. **Spring 插件未启用** 如果 Spring 支持插件未被激活,则可能导致 IDE 无法识别 `@Autowired` 或其他 Spring 特定的功能。可以通过以下方式解决问题: - 打开设置菜单:`File -> Settings -> Plugins`。 - 确认已安装并启用了名为 “Spring Framework Support” 的官方插件[^1]。 #### 2. **项目配置文件缺失或不正确** Spring 需要通过 XML 文件、Java Config 类或其他形式来定义 Bean 定义。如果没有正确加载这些配置文件,可能会导致 `@Autowired` 报错。 - 确保项目的 `applicationContext.xml` 或者基于 Java 的配置类(带有 `@Configuration` 和 `@Bean` 注解)已被正确定义和引入。 - 对于 Spring Boot 项目,确认是否存在 `spring.factories` 文件以及是否包含了必要的组件扫描路径[^3]。 #### 3. **模块依赖关系问题** 当前模块可能缺少对 Spring Core 或 Context 组件库的有效引用。这可能是由于 Maven/Gradle 构建工具中的依赖项声明不足造成的。 - 检查 `pom.xml` (Maven) 或 `build.gradle` (Gradle),确保包含如下核心依赖之一: ```xml <!-- For Maven --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> ``` ```gradle // For Gradle implementation 'org.springframework:spring-context:${springVersion}' ``` - 更新项目依赖树以应用更改:右键点击项目根目录 -> `Maven -> Reload Project` 或运行命令 `./gradlew build --refresh-dependencies`。 #### 4. **IDE 缓存损坏** Intellij IDEA 的缓存机制有时会因各种因素而失效,从而引发误报错误。清除缓存可以有效缓解此类情况。 - 使用快捷组合键 `Ctrl + Alt + Shift + S` 进入项目结构对话框;也可以尝试执行操作序列:`File -> Invalidate Caches / Restart... -> Invalidate and Restart`. #### 5. **启动异常影响正常解析** 若之前存在类似 `com.intellij.diagnostic.PluginException` 的严重初始化失败日志记录,则表明某些关键服务未能成功加载,进而干扰到后续功能表现[^2]。建议重新下载最新稳定版本的 IDEA 并按照标准流程完成初次部署工作。 ```java // 示例代码片段展示如何正确运用 @Autowired 注解实现自动装配 @Service public class StudentService { private final Repository repository; public StudentService(@Qualifier("specificRepository") Repository repo){ this.repository = repo; } } @Component class SpecificComponent{ @Autowired private transient StudentService studentService; // 此处应无任何编译期告警现象发生 } ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值