一、HC_SR04简述
HC-SR04超声波测距模块可提供 2cm-400cm的非接触式距离感测功能,测距精度可达高到 3mm;模块包括超声波发射器、接收器与控制电路。
基本工作原理:
(1)采用IO 口TRIG 触发测距,给最少10us 的高电平信呈。
(2)模块自动发送8 个40khz 的方波,自动检测是否有信号返回;
(3)有信号返回,通过IO 口ECHO 输出一个高电平,高电平持续的时间就是超声
波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2;
注意:当测距时间大于38ms时,便超时了,这是无论如何,ECHO都会被拉低
二、代码编写
通过定时器定时测量测距时间再通过上述公式计算对应的距离,这里定时器可以通过定时中断计时。
1.定时器基本配置
#include "Timer.h"void Timer_Init(uint16_t ARR,uint16_t PSC)
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);TIM_TimeBaseInitTypeDef Tim4_InitStructure;Tim4_InitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//不分频Tim4_InitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数Tim4_InitStructure.TIM_Period=ARR;Tim4_InitStructure.TIM_Prescaler=PSC;Tim4_InitStructure.TIM_RepetitionCounter=0x00;TIM_TimeBaseInit(TIM4,&Tim4_InitStructure);TIM_ClearFlag(TIM4, TIM_FLAG_Update); //清除由于初始化而置的标志位TIM_Cmd(TIM4,DISABLE);TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);/***************初始化定时器,开启更新中断****************/NVIC_InitTypeDef TIM4_IT_InitStructure;TIM4_IT_InitStructure.NVIC_IRQChannel=TIM4_IRQn;TIM4_IT_InitStructure.NVIC_IRQChannelCmd=ENABLE;TIM4_IT_InitStructure.NVIC_IRQChannelPreemptionPriority=4;TIM4_IT_InitStructure.NVIC_IRQChannelSubPriority=4;NVIC_Init(&TIM4_IT_InitStructure);
}
2.传感器函数编写
1.基本配置
#include "HC_SR04.h"#define Trigo GPIO_Pin_14
#define Echo GPIO_Pin_15
static uint16_t count;
/*内部调用*/
/**********Trigo为输出引脚************/
void Trigo_Write(uint8_t val)
{GPIO_WriteBit(GPIOE,Trigo,(BitAction)val);
}
/**********Echo为输入引脚************/
/*内部调用*/
uint8_t Echo_Read(void)
{return GPIO_ReadInputDataBit(GPIOE,Echo);
}
2.初始化
void HCSR04_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin=Trigo;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOE,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin=Echo;GPIO_Init(GPIOE,&GPIO_InitStructure);Trigo_Write(0);
}
3.距离测量
完整的时间=产生更新中断的次数*产生一次中断需要的时间+TIM->CNT里的时间
/*CNT f=1000 000HZ */
/*ARR 1000*/
/*PSC 72 */
/*假设返回单位为cm distance=340*100*time/2/1000 000 */
float HCSR04_GetDistance(void)
{
/****************先将Trigo拉高*******************/Trigo_Write(1);
/****************延迟20us确保脉冲足够触发测距*******************/delay_us(20);
/****************再拉低脉冲使其开始测距*******************/Trigo_Write(0);
/****************当Echo变高时便说明其开始测距*******************/while(Echo_Read()==0);
/****************开启定时器,开始计数*******************/TIM_Cmd(TIM4,ENABLE);
/****************测距结束的时候便是Echo再次变低*******************/while(Echo_Read()==1);
/****************计算时间,即为完整的产生中断的时间加上CNT上的时间*******************/float time=count*1000+TIM4->CNT;printf("time:%f\r\n",time);
/****************超时判断*******************/if(time/1000>38)//如果大于38ms则不能测距{return 0;}
/****************再次清零,回到开始状态等待下一次的测距指令*******************/count=0;TIM4->CNT=0;
/****************失能定时器*******************/TIM_Cmd(TIM4,DISABLE);
/****************返回距离*******************/float distance;distance=time*340/2/10000;return distance;
}
/****************中断函数用于计时*******************/
void TIM4_IRQHandler(void)
{if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET){count++;TIM_ClearITPendingBit(TIM4,TIM_IT_Update);}
}
4.主函数
#include "main.h"
float distance;
int main(void)
{delay_init();uart_init(115200);Timer_Init(1000,72);NVIC_PriorityGroupConfig (NVIC_PriorityGroup_2 );HCSR04_Init();while(1){distance=HCSR04_GetDistance();if(distance) printf("distance :%f\r\n",distance);else printf("distance erro\r\n");delay_ms(500);}}
三、最终现象
实际距离约18-20cm,通过串口观察现象可知符合现象
超时检测
以上便是本次学习的记录