文章目录
- 大家好哇!我是小光,嵌入式爱好者,一个想要成为系统架构师的普通大学生。
- 进入正题,最近在做小车,目前已经加入红外避障、超声波测距、红外遥控三个传感器,分别实现遥控切换模式、超声波控制距离、避障功能。
- 本次文章说说超声波测距的实现。
- 非常感谢大家的阅读,如果有不对的地方欢迎指正
一、原理讲解
1.实物图
这种呢是五线的,还有一种是四线的hysrf04,不过都是一样的,就多了一个OUT口(开关量输出)。
HY-SRF05超声波测距模块可测量距离为2cm-450cm,测量精度3mm,模块包括超声波发射器、接收器与控制电路。
2.工作原理:
- 采用IO口TRIG触发测距,给至少10us的高电平信号;
- 模块自动发送8个40kHZ的方波,自动检测是否有信号返回;
- 有信号返回,通过IO口ECHO输出一个高电平,高电平的持续时间就是超声波从发射到返回的时间。测量距离=(高电平时间*声速)/2;
计算距离:uS/58 = cm
uS/148 = 英寸
3.接线:
VCC————5v
GND————板子GND
Trig————PA6(TIM3_CH1)
Echo————PA7(TIM3_CH2)
注意:1.VCC一定要接5V,不然数据一直都是0.045
2.Trig和Echo可以接其他的定时器,不过初始化得自己改
二、软件驱动代码
1.接口定义
#define ECHO_Reci PAin(7)
#define TRIG_Send PAout(6)
//超声波硬件接口定义
//超声波硬件接口定义
//超声波硬件接口定义
#define HCSR04_PORT GPIOA
#define HCSR04_CLK RCC_APB2Periph_GPIOA
#define HCSR04_TRIG GPIO_Pin_6
#define HCSR04_ECHO GPIO_Pin_7
2.驱动函数
//超声波计数
u16 msHcCount = 0;
//定时器3设置
void hcsr04_NVIC()
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;//TIM3定时器中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//IO口初始化 及其他初始化
void Hcsr04Init()
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(HCSR04_CLK, ENABLE);
//GPIO初始化
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_IN_FLOATING;
GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
GPIO_ResetBits(HCSR04_PORT,HCSR04_ECHO);
//TIM3时钟使能
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
//设置定时器预分频系数和周期
TIM_TimeBaseStructure.TIM_Period = (1000-1);
TIM_TimeBaseStructure.TIM_Prescaler =(72-1);
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
//清除TIM3的待处理标志位
TIM_ClearFlag(TIM3, TIM_FLAG_Update);
//TIM3中断使能
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
//定时器中断初始化
hcsr04_NVIC();
//TIM3使能
TIM_Cmd(TIM3,DISABLE);
}
//打开定时器3
static void OpenTimerForHc()
{
TIM_SetCounter(TIM3,0);//定时器从0开始计数
msHcCount = 0;//计数归零
TIM_Cmd(TIM3, ENABLE); //使能
}
//关闭定时器3
static void CloseTimerForHc()
{
TIM_Cmd(TIM3, DISABLE);
}
//定时器3终中断
void TIM3_IRQHandler(void)
{
//记录返回信号高电平持续的时间
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update );
msHcCount++;//定时器计数
}
}
//获取定时器3计数器值
u32 GetEchoTimer(void)
{
u32 t = 0;
t = msHcCount*1000;//将定时器计数转换成时间
t += TIM_GetCounter(TIM3);//定时器输入捕获
TIM3->CNT = 0; //清空定时器计数
delay_ms(50);//每次测量间隔
return t;
}
//通过定时器3计数器值推算距离
float Hcsr04GetLength(void )
{
u32 t = 0;
int i = 0;
float lengthTemp = 0;
float sum = 0;
while(i!=5)//测量五次
{
TRIG_Send = 1; //给TRIG口输出一个高电平,延时20us
delay_us(20);
TRIG_Send = 0;
while(ECHO_Reci == 0); //等待ECHO口返回高电平信号
OpenTimerForHc(); //ECHO输出高电平之后打开定时器
i = i + 1;
while(ECHO_Reci == 1);//用中断接收8个40khz的方波
CloseTimerForHc(); //接收完成后关闭定时器
t = GetEchoTimer(); //t就是高电平持续的时间
lengthTemp = ((float)t/58.0);//lengthTemp = 58*t;
sum = lengthTemp + sum ;
}
lengthTemp = sum/5.0;//测量五次取平均值
return lengthTemp;
}
有了驱动代码,我们就可以直接调用float Hcsr04GetLength(void )
来获取超声波测距模块测量的距离了,然后调整电机的转动就可以实现控制距离了。
总结
最终效果
稍后奉上视频(狗头保命)
本文仅仅简单介绍了超声波测距的原理和驱动代码的编写,这样就完成了智能小车的控制距离功能,后面还会有手势识别传感器、红外遥控等等,去实现更多的功能,感谢阅读,如果觉得我的文章对你有帮助的话,就点个赞吧!爱了爱了