一、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;
- 		}
- 	}
- }
 
                                    
评论记录:
回复评论: