一、HC-SR04工作原理
1)采用IO触发测距,给至少10us的高电平信号。
2)模块自动发送8个40KHz的方波,自动检测是否有信号返回。
3)有信号返回,通过IO输出一高电平,高电平持续时间就是超声波从发射到返回的时间声波从发
射到返回的时间。
4)HC-SR04超声波测距模块提供2cm~400cm的测距功能,精度达3mm。
二、实物介绍
以下图片截取自深圳市捷深科技有限公司的《HC-SR04超声波测距模块说明书》:
VCC 3.3-5V供电(推荐5V供电)
GND 接地
Trig 外部触发信号输入,输入一个高于10μs的高电平即可触发模块测距
Echo 回响信号输出,测距结束时此管脚输出一个低电平,电平宽度反映超声波往返时间之和
三、工作说明
1、触发信号Trig直接通过IO输出和延时给一个大于10us的高电平即可触发。
2、Echo引脚需要接收并记录高电平的持续时间。
3、在发送触发信号后,Echo响应后(上升沿)触发外部中断,开启定时器计时直到Echo变为低电
平,关闭定时器记录下计时时间。
4、实际应用,如果需要精确距离值,必需要考虑温度影响,做温度补偿。
distance = time * 0.017
距离=T*C/2(C 为声速)
声速温度公式:c=(330.45+0.61t/℃)m/s-1 (其中330.45是在0℃)
0℃声速:330.45m/s 20℃声速:342. 62m/s 40℃声速:354.85M/S
四、标准库工作代码
我一般使用标准库较少,使用代码时请注意检查
使用OLED显示,OLED使用可以看:
- uint32_t distance;
- while(1)
- {
- 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(70); //每个周期至少需要等待60ms
- distance+=(times/5.8); //获取单位为mm的距离
- }
- distance/=10;
- OLED_ShowNum(2,1,distance,4); //使用OLED显示
- }
-
- //定时器中断函数
- //72MHz/72/100=1000,每秒定时器计数1000个,因此每个计数为100us
- void TIM2_IRQHandler(void)
- {
- if(SET==TIM_GetITStatus(TIM2,TIM_FLAG_Update))
- {
- number++; //每次中断将次数++
- TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update);
- }
- }
-
- //外部中断函数,利用外部中断检测高低电平变化来控制定时器开关
- void EXTI9_5_IRQHandler(void)
- {
- if(SET==EXTI_GetITStatus(EXTI_Line7))
- {
- if(flag==0)
- {
- //上升沿即回响电平开始,打开计数器
- number=0;flag=1;
- TIM_SetCounter(TIM2,0);
- TIM_Cmd(TIM2,ENABLE);
- }
- else
- {
- //下降沿即回响电平结束,统计高电平持续时长
- TIM_Cmd(TIM2,DISABLE);
- flag=0;
- times=number*100+TIM_GetCounter(TIM2); //得到回响的高电平持续的us
- }
- EXTI_ClearITPendingBit(EXTI_Line7);
- }
- }
五(1)、HAL--CubeMX配置
GPIO配置(Trig端口):设置PA1为触发端(可更改为其他GPIO口)。单击芯片的PA1引脚会跳
出选择项,选择GPIO_Output,即为GPIO输出。
定时器配置(Echo端口):为方便计算定时器的分频系数和定时周期,将APB1设置为50MHz。
先设置TIM2的通道1位直接模式输入捕获,在参数设置中设置预分频为71,通过计算分频器输出的
时钟信号频率为1000kHz,通过换算得到1us,极性为上升沿触发。设置完成后自动引出PA0引
脚,即为接收端引脚Echo,使能NVIC中断。
USART1配置:串口输出显示结果,设置为异步模式,波特率为115200Bits/s,
RX--PA10//TX--PA9
五(2)、HAL库工作代码
1、HCSR04.h
- #ifndef __HCSR04_H
- #define __HCSR04_H
-
- #include "main.h"
- //#include "tim.h"
- #include "stdio.h"
-
- #define TRIG_H HAL_GPIO_WritePin(Trig_GPIO_Port,Trig_Pin,GPIO_PIN_SET)
- #define TRIG_L HAL_GPIO_WritePin(Trig_GPIO_Port,Trig_Pin,GPIO_PIN_RESET)
-
- void delay_us(uint32_t us);
- void HCSR04_GetData(void);
-
- #endif
2、HCSR04.c
- #include "HCSR04.h"
-
- float distance; //测量距离
- uint32_t Buf[3] = {0}; //存放定时器计数值的数组
- uint8_t Cnt = 0; //状态标志位
- uint32_t high_time; //超声波模块返回的高电平时间
-
- //读取距离
- void HCSR04_GetData(void)
- {
- switch(Cnt)
- {
- case 0:
- TRIG_H; //发送信号
- delay_us(30);
- TRIG_L;
-
- Cnt++; //标志位为1
- __HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
- HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); //开启TIM2
- //启动输入捕获或者:__HAL_TIM_ENABLE(&htim5);
- break;
- case 3:
- high_time = Buf[1]- Buf[0]; //计算高电平时间
- printf("\r\n----高电平时间-%d-us----\r\n",high_time); //串口打印时间
- distance=(high_time*0.034)/2; //计算距离单位cm
- printf("\r\n-检测距离为-%.2f-cm-\r\n",distance); //串口打印距离
- Cnt = 0; //清空标志位
- TIM2->CNT=0; //清空计时器计数
- break;
- }
- }
-
- //中断回调函数
- void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
- {
- if(TIM2 == htim->Instance)// 判断触发的中断的定时器为TIM2
- {
- switch(Cnt)
- {
- case 1:
- //获取当前的捕获值
- Buf[0] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);
- //设置为下降沿捕获!!!
- __HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);
- Cnt++;
- break;
- case 2:
- //获取当前的捕获值
- Buf[1] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);
- HAL_TIM_IC_Stop_IT(&htim2,TIM_CHANNEL_1);
- //停止捕获或者: __HAL_TIM_DISABLE(&htim5);
- Cnt++; //此时标志位为3
- break;
- }
- }
- }
评论记录:
回复评论: