目录
一、HC-SR04超声波传感器介绍:
(1)HC-SR04 (2020 版本):
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)性能参数:
(4)接口定义:
(5)模式选择:
二、测量操作方法:
(1)GPIO模式:
工作模式同老版本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
连接串口,外部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 传输格式:
命令格式:
向模块写入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引脚的上升沿和下降沿事件。
- 在上升沿时,重置计数器并启动定时器。
- 在下降沿时,停止定时器,并记录高电平的持续时间。
// 外部中断函数
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模式测距:
四、效果演示及代码下载:
通过网盘分享的文件:10- 超声波模块GPIO模式测距
链接: https://pan.baidu.com/s/1B9Lv9eDVhcQv2QP8dE5bHg?pwd=smfb 提取码: smfb