一篇文章教会你HC-SR04超声波传感器测距,附STM32代码示例

 

目录

 一、HC-SR04超声波传感器介绍:

(1)HC-SR04 (2020 版本):

(2)特点: 

(3)性能参数: 

(4)接口定义: 

(5)模式选择:

二、测量操作方法:

(1)GPIO模式:

(2)UART模式:

(3)IIC模式:

(4)注意事项:

三、STM32代码示例:

(1)GPIO模式测距:

(2)UART模式测距:

(3)IIC模式测距:

四、效果演示及代码下载: 


一、HC-SR04超声波传感器介绍:

(1)HC-SR04 (2020 版本):

b650a48b930b45f7b9634d19a4db8a11.png

f729f974afa8405da4aea51f78b4ddd0.png

        HC-SR04(2020 版本)是一款尺寸完全兼容老版本,增加 UART 和 IIC 功能的开放式超声波测距模块。默认条件下,软件与硬件完全兼容老版本HC-SR04;可以通过电阻设置成UART或 IIC 模式。2CM超小盲区,4.5M典型最远测距,2.2mA超低工作 电流。采用升级解调芯片RCWL-9206,带UART与IIC功能MCU; 使其外围更加简洁,工作电压更宽(3-5.5V),接口功能更多。 

(2)特点: 

  • 多接口支持:RCWL-9206芯片支持GPIO、UART与IIC三种模式接口,这使得它能够灵活地与不同的系统和设备进行通信,提高了其在多种应用场景中的适用性。

  • 宽电压供电与低功耗:该芯片能够在3V至5.5V的电压范围内工作,并且具有2.2mA的低工作电流,这使得它既适合于电池供电的便携设备,也适合于需要宽电压范围的工业应用。

  • 超宽测量范围与最小盲区:RCWL-9206提供了2cm至450cm的超宽测量范围,适合测量平整墙面,并且拥有2cm的最小盲区,这意味着它可以在非常近的距离内开始有效测量,提高了测量的精确性和可靠性。

  • 兼容性与外围简洁:芯片默认软件与硬件完全兼容老版本的HC-SR04,这为升级和替换提供了便利。同时,外围电路设计更简洁,有助于减少设计复杂性和成本,使得集成和部署更加容易。

  • 工作温度范围为-10℃至70℃,确保了芯片在不同环境下都能稳定工作。

(3)性能参数: 

263b0b5fc4044ab59c04c58249481545.png

(4)接口定义: 

8915cd50df5d4989b71335a5c2e4ca03.png

(5)模式选择:

5b2e374e54c94bef94d7307a0aec9ef6.png

二、测量操作方法:

(1)GPIO模式:

a637e9e419814571babadee830c78b3a.png

        工作模式同老版本HC-SR04。外部MCU给模块Trig脚一个大于10uS的高 电平脉冲;模块会给出一个与距离等比的高电平脉冲信号,可根据脉宽时间 “T” 。

计算公式:

                        距离=T*C/2 (C为声速)

声速温度公式:

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%左右。实际应用,如果需要精确距离值,必需要考虑温度影响,做温度补偿。

(2)UART模式:

UART 模式波特率设置: 9600

f04713827bde458eab99cb15f25d2675.png

连接串口,外部MCU或PC发命令0XA0,模块完成测距后发3个返回距离数据,BYTE_H,BYTE_M 与BYTE_L。

距离计算方公式(单位mm):

距离=((BYTE_H<<16)+(BYTE_M<<8)+ BYTE_L)/1000

(3)IIC模式:

IIC 地址: 0X57

IIC 传输格式:

6dc1f14ed92f488bb5726644fcc28352.png

72fc3d95770b439a8209662c48bfc76a.png 

命令格式:

fc94c2a0a3564a68abb622002350542b.png 

向模块写入0X01,模块开始测距,等待200mS(模块最大测距时间) 以上。直接读出3个距离数据。BYTE_H,BYTE_M与BYTE_L。

距离计算方式如下(单位mm):

距离=((BYTE_H<<16)+(BYTE_M<<8)+ BYTE_L)/1000

(4)注意事项:

  • 此模块不宜带电连接,如果要带电连接,则先让模块的Gnd端先连接。
  • 如果测试面不是很规则或测试远距离物体时,可采用多次测量的方法来校正。
  • 两次测试间隔要不小于200ms。

三、STM32代码示例:

(1)GPIO模式测距:

 初始化引脚:初始化GPIO口和外部中断(EXTI),以及配置超声波传感器HC-SR04的Trig(触发)和Echo(回声)引脚。

  • 首先,使能GPIOA的外设时钟,并配置PA6为推挽输出模式,用于Trig引脚的输出。
  • 然后,配置PA7为浮空输入模式,用于Echo引脚的输入。
  • 接着,使能AFIO的外设时钟,并设置AFIO映射,将外部中断线与GPIOA的Pin7关联。
  • 配置EXTI,使能EXTI_Line7(与PA7对应),并设置为中断模式,触发方式为上升沿和下降沿。
  • 最后,配置NVIC,为外部中断分配中断优先级。
void HC_SR04_Init(void) {
  
    // 初始化GPIO口, Trig使用推挽输出, Echo使用浮空输入
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);			// 使能GPIOA的外设时钟

    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      			// 选择推挽输出模式
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;           			// 选择GPIO_Pin_6
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    			// 默认选择50MHz
    GPIO_Init(GPIOA, &GPIO_InitStructure);               			// 初始化GPIOA6

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   		// 选择浮空输入模式
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;            			// 选择GPIO_Pin_7
    GPIO_Init(GPIOA, &GPIO_InitStructure);               			// 初始化GPIOA7

    // AFIO映射中断引脚
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); 			// 使能AFIO的外设时钟
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource7); 	// 选择外部中断源和中断通道

    // EXTI中断配置
    EXTI_InitTypeDef EXTI_InitStructure;
    EXTI_InitStructure.EXTI_Line = EXTI_Line7;          			// echo使用的端口7, 因此选择7号中断线
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; 	// 上升沿和下降沿都触发中断
    EXTI_Init(&EXTI_InitStructure);                     			// 初始化外部中断7

    // NVIC分配外部中断的中断优先级
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 				// 指定中断分组
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; 				// 使用的端口7, 因此选择这个参数
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; 		// 抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; 				// 响应优先级
    NVIC_Init(&NVIC_InitStructure);                    				// 初始化NVIC
}

初始化定时器:初始化STM32的定时器TIM2,用于测量Echo引脚的高电平时间。

  • 使能TIM2的外设时钟,并配置定时器的时钟分频、计数模式、周期和预分频值,以实现1ms的计时精度。
  • 使能TIM2的更新中断,并配置NVIC,为TIM2的中断分配中断优先级。
//初始化定时器,用于测量高电平时间
void Timer_Init(void){
	
    // 配置定时器
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); 				// 使能TIM2的外设时钟
	
	// 72MHz/72=1MHz, 1us计数值加1, 计数100次溢出(100us)产生中断,每次溢出number+1
    TIM_TimeBaseInitTypeDef TimeBase_InitStructure;
    TimeBase_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1; 			// 使用时钟分频1
    TimeBase_InitStructure.TIM_CounterMode = TIM_CounterMode_Up; 		// 向上计数	
    TimeBase_InitStructure.TIM_Period = 72 - 1; 						// 预分频系数
    TimeBase_InitStructure.TIM_Prescaler = 100 - 1; 					// 自动重装器
    TimeBase_InitStructure.TIM_RepetitionCounter = 0; 					// 该参数仅给高级定时器使用
    TIM_TimeBaseInit(TIM2, &TimeBase_InitStructure); 					// 初始化TIM2
	
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); 							// 使能中断输出信号
    TIM_InternalClockConfig(TIM2); 										// 选择内部时钟

    // NVIC分配定时器的中断优先级
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; 					// 指定TIM2的中断通道
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; 			// 抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 					// 响应优先级
	
    NVIC_Init(&NVIC_InitStructure); 									// 初始化NVIC
}

计算测距结果:

  • 循环10次,每次发送Trig引脚的脉冲信号,并等待Echo引脚的高电平信号,以测量距离。
  • 计算10次测距的平均值,以减少误差,并返回测得的距离。
// 计算测距结果,取10次的平均值
uint16_t range(void){
	
	int temp=0;
        distance = 0;
        for (int i = 0; i < 10; ++i) { 						// 每次取10次测距数据, 取平均值减少误差
            GPIO_SetBits(GPIOA, GPIO_Pin_6); 				// 产生脉冲信号
            Delay_us(15);									// 提供至少10us的高电平
            GPIO_ResetBits(GPIOA, GPIO_Pin_6);
            Delay_ms(65); 									// 每个周期至少需要等待60ms
            distance += (times*0.34262/2); 					// 获取单位为mm的距离 20℃声速342.62M/S(0.34262mm/us)
        }
        temp=distance /= 10; 								// 测距10次计算平均距离	
		
	return temp;
}

TIM2_IRQHandler() 函数:在每次定时器溢出时增加计数器。

// 定时器中断函数
void TIM2_IRQHandler(void) {
	
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) { 			// 检查TIM2更新中断发生与否
        number++; 												// 每次中断将次数++
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update); 			// 清除TIM2中断标志
    }
	
}

EXTI9_5_IRQHandler() 函数:处理Echo引脚的上升沿和下降沿事件。

  • 在上升沿时,重置计数器并启动定时器。
  • 在下降沿时,停止定时器,并记录高电平的持续时间。

ecfb651b1f084419b5df488227a614a8.png

// 外部中断函数
void EXTI9_5_IRQHandler(void) {
    if (EXTI_GetITStatus(EXTI_Line7) == SET) { 				// 检查外部中断7是否触发PA7
        if (flag == 0) {
															// 上升沿即回响电平开始, 打开计数器
            number = 0; flag = 1;							// 中断标志位置1
            TIM_SetCounter(TIM2, 0); 						// 重置定时器
            TIM_Cmd(TIM2, ENABLE); 							// 启动定时器
        } else {
															// 下降沿即回响电平结束, 统计高电平持续时长
            TIM_Cmd(TIM2, DISABLE); 						// 关闭定时器
            flag = 0;										// 中断标志位置0
            times = number * 100 + TIM_GetCounter(TIM2); 	// 得到回响的高电平持续的时间
        }
        EXTI_ClearITPendingBit(EXTI_Line7); 				// 清除外部中断7的中断标志位
    }
}

(2)UART模式测距:

(3)IIC模式测距:

四、效果演示及代码下载: 

d54ba64eb6784b4ca7ab679a2e2b70e8.png

通过网盘分享的文件:10- 超声波模块GPIO模式测距
链接: https://pan.baidu.com/s/1B9Lv9eDVhcQv2QP8dE5bHg?pwd=smfb 提取码: smfb

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

The_xzs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值