大伙早上好啊,这一期给大伙带来一个外设模块 —— HC-SR04超声波模块。
代码例程放在文末,建议大家还是先学一下模块的原理,再学代码。
文章目录
模块介绍
工作原理
通过Trig引脚触发超声波发射,Echo引脚接收反射信号,测量时间差计算距离。
引脚
VCC:接5V电源
GND:接地
Trig:触发信号输入(接数字引脚)
Echo:回响信号输出(接数字引脚)
电气参数
电气参数 | HCSR04超声波模块 |
---|---|
工作电压 | DC5V |
工作电流 | 15mA |
工作频率 | 40KHz |
最远射程 | 4M |
最近射程 | 2cm |
测量角度 | 15° |
输入触发信号 | 10us的TTL脉冲 |
输出回响信号 | 输出TTL电平信号,与射程成比例 |
关键电路与信号处理
Trig触发电路:
外部控制器(如Arduino)发送高电平脉冲后,模块内部振荡器生成40kHz方波驱动发射器。
Echo信号生成电路:
接收器信号经过放大、滤波后,通过比较器生成高电平脉冲,宽度直接对应往返时间。
抗干扰设计:
模块内置滤波电路,减少环境噪声对接收信号的干扰。
工作流程(时序解析)
步骤1:触发超声波发射
Trig引脚输入信号:
向Trig引脚发送一个至少10µs的高电平脉冲(如Arduino代码中的digitalWrite(Trig, HIGH))。
触发后,模块内部电路启动,发射8个周期的40kHz超声波脉冲(约持续200µs)。
步骤2:超声波传播与反射
超声波发射:
发射器发出超声波,声波在空气中以340m/s(常温下)的速度传播。
遇到障碍物:
超声波遇到障碍物后反射,返回接收器。
步骤3:接收反射信号
接收器检测信号:
接收器捕获反射的超声波,内部电路将其转换为电信号。
生成Echo信号:
Echo引脚输出一个高电平脉冲,脉冲宽度与超声波往返时间成正比。
步骤4:测量时间差
使用pulseIn()函数:
通过Arduino的pulseIn(Echo, HIGH)测量Echo引脚高电平的持续时间(单位为µs)。
该时间对应超声波从发射到反射接收的总时间(即往返时间)。
步骤5:计算距离
公式推导:
距离
=
时间差
×
声速
2
距离 = \frac{\text{时间差} \times \text{声速}}{2}
距离=2时间差×声速
时间差:Echo引脚高电平持续时间(µs)。
声速:340m/s = 0.034cm/µs(常温下)。
除以2:超声波往返时间需折半,得到单程距离。
代码例程
- 采用 IO 口 TRIG 触发测距,给最少 10us 的高电平
- 模块自动发送 8 个 40khz 的方波,自动检测是否有信号返回
- 有信号返回,通过 IO 口 ECHO 输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。
距离 = 时间差 × 声速 2 距离 = \frac{\text{时间差} \times \text{声速}}{2} 距离=2时间差×声速
注意:测量周期应为60ms以上,以防止发射信号对回响信号的影响,被测物体的面积应不小于0.5平方米且尽量要求平整,否则会影响结果。
HCSR04.c
#include "stm32f10x.h" // Device header
#include "HCSR04.h"
#include "Timer.h"
#include "Delay.h"
void HCSR04_Init(void)
{
RCC_APB2PeriphClockCmd(HCSR04_CLK, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
//IO 初始化
GPIO_InitStructure.GPIO_Pin = HCSR04_TRIG; //发送高点平引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
GPIO_ResetBits(HCSR04_PORT,HCSR04_TRIG);
GPIO_InitStructure.GPIO_Pin = HCSR04_ECHO; //返回电平引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
GPIO_ResetBits(HCSR04_PORT,HCSR04_ECHO);
Timer_Init(72, 100);
}
static void OpenTimerForHc(void)
{
TIM_SetCounter(TIM2,0);
msHcCount = 0;
TIM_Cmd(TIM2, ENABLE);
}
//关闭定时器4
static void CloseTimerForHc(void)
{
TIM_Cmd(TIM2, DISABLE);
}
float GetEchoTimer(void)
{
u32 t = 0;
t = msHcCount*1000; //得到ms
t += TIM_GetCounter(TIM3); //得到us
TIM3->CNT = 0; //将TIM3定时计数器的寄存器清零
Delay_ms(50);
return t;
}
float HCSR04_GetLength(void)
{
u32 t = 0;
int i = 0;
float lengthTemp = 0;
float sum = 0;
while(i!=5)
{
GPIO_SetBits(HCSR04_PORT, HCSR04_TRIG);//trig发出高电平
Delay_us(20);
GPIO_ResetBits(HCSR04_PORT, HCSR04_TRIG);//trig发出低电平
while(GPIO_ReadInputDataBit(HCSR04_PORT, HCSR04_ECHO) == 0);//echo等待回响
OpenTimerForHc();
i = i + 1;//每收到一次,回响信号+1,计算收到5次的平均值
while(GPIO_ReadInputDataBit(HCSR04_PORT, HCSR04_ECHO) == 1);//echo等待回响
CloseTimerForHc();
t = GetEchoTimer();
lengthTemp = ((float)t/58.0);//cm
sum = lengthTemp + sum ;
}
lengthTemp = sum/5.0;
return lengthTemp;
}
HCSR04.h
#ifndef __HCSR04_H
#define __HCSR04_H
#define HCSR04_CLK RCC_APB2Periph_GPIOA
#define HCSR04_PORT GPIOA
#define HCSR04_TRIG GPIO_Pin_0
#define HCSR04_ECHO GPIO_Pin_1
void HCSR04_Init(void);
static void OpenTimerForHc(void);
static void CloseTimerForHc(void);
float GetEchoTimer(void);
float HCSR04_GetLength(void);
#endif
main.c
#include "stm32f10x.h" // Device header
#include "OLED.h"
#include "Delay.h"
#include "Timer.h"
#include "HCSR04.h"
float dis = 0;
int main()
{
OLED_Init();//函数定义初始化
HCSR04_Init();
OLED_ShowString(0, 0, "dis:", OLED_8X16);
OLED_Update();
while(1)
{
dis = HCSR04_GetLength();
Delay_ms(500);
OLED_ShowFloatNum(0, 16, dis, 4, 4, OLED_8X16);
OLED_Update();
}
}
代码效果
代码例程
链接:小白兔的礼物——HC-SR04超声波模块
提取码:hxgM
结语
这一期,我们从HCSR04的原理讲到了代码的编写,如果大伙有什么疑惑也可以在评论区里提出。或者大伙有什么需要的外设模块的需要,也可以在评论区里提出来。