基于STM32的超声波测距

一、HC-SR04模块介绍

HC-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能,测距精度可高达3mm;模块包括超声波发射器、接收器、与控制电路。

模块的基本工作原理为:

(1)采用 IO口 TRIG触发测距,给最少 10us的高电平信呈。

(2)模块自动发送 8个 40khz的方波,自动检测是否有信号返回;

(3)有信号返回,通过 IO口 ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。

测试距离=(高电平时间*声速(340M/S))/2;

具体的电气参数如下:

作为一个传感器模块,它本身与单片机的数据传输也就尤为重要,超声波的时序图如下:

HC-SR04的时序图只有这一个,而且看着比较简单,也是比较容易理解的,但是当时自己去写程序去调试的时候确是花费了不少时间,这里我们主要是要理解一点模块内部发出的8个40kHz脉冲并不通多端口输出,只存在与模块内部,我们在设计程序的时候是不需要去管这个内部信号的。从时序图来看程序的设计思路还是比较简单的,我们只需要提供一个10us以上的脉冲触发信号,模块内部将发出8个40kHz周期电平并检测回波。一旦检测到又回波信号则输出回响信号。回响信号的脉冲宽度与所测的距离成正比。由此通过发射信号到收到的回响信号时间间隔可以计算得到距离。建议测量周期为60ms以上,以防止发射信号对回响信号的影响。

这里还有两点需要注意的:

1、模块不宜带电连接,若要带电连接,则需要先让模块的GND端先连接,否则会影响模块的正常工作。

2、测距时,被测物体的面积不少于0.5平方米且平面尽量要求平整,否则影响测量的结果。(如果对测量结果的精度要求不高的情况之下,这个点还是可以忽略的,话说如果对精度要求高估计也不会用到这个传感器)

二、与单片机的连接

上图时HC-SR04的接线端口的说明,TRIG输入端口我们只需要随便接一个普通io口就可以了,我们只需要通过这个io口向模块发送出发信号,然后等待接收就行。ECHO输出口,因为我们我要检测输出高点平的持续时间,所以我们就需要将他接到具有输入捕获的io口上。我们整个程序设计的为:

TRIG---------PA1

ECHO--------PA0

这是STM32F103ZET6数据手册的一部分,可以看到PA0为TIM5_CH1的接口,

三、程序设计

主程序:

int main()

{

u8 i=0;

float distance;

SysTick_Init(72);

LED_Init();

USART1_Init(115200);

HC_SR04_Init();

while(1)

{

distance=HC_SR04_Measure();

printf("障碍物距离为:%.2f cm\r\n",distance);

i++;

if(i%20==0)

{

led1=!led1;

}

delay_ms(10);

}

}

定时器初始化程序

//**定时器初始化,分频系数为71则频率为1Mhz,每个计数为1us**//

//**自动重装载值为65535,一个计数周期1*65536=0.65536 s **//

TIM_TimeBaseInitStructure.TIM_Period=65535; //自动装载值 定时器定时时间计算公式

TIM_TimeBaseInitStructure.TIM_Prescaler=71; //分频系数 ((per)*(psc+1))/Tclk

TIM_TimeBaseInitStructure.TIM_ClockDivision=0;//时钟分频

TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //计数模式(向上计数模式)

TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);

/****输入捕获设置***/

TIM_ICInitStructure.TIM_Channel=TIM_Channel_1; //通道设置 通道1

TIM_ICInitStructure.TIM_ICFilter=0x00; //滤波器长度 无滤波

TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising; //捕获极性 上升沿捕获

TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1; //分频系数 1

TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI; //直接映射到TI1

TIM_ICInit(TIM5,&TIM_ICInitStructure);

TIM_ITConfig(TIM5,TIM_IT_CC1,ENABLE); //使能中断

NVIC_InitStructure.NVIC_IRQChannel=TIM5_IRQn; //中断通道

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2; //抢占优先级

NVIC_InitStructure.NVIC_IRQChannelSubPriority=0; //子优先级

NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //IRQ通道使能

NVIC_Init(&NVIC_InitStructure);

TIM_Cmd(TIM5,ENABLE);

读取距离程序:

float HC_SR04_Measure()

{ \\这个函数只是将高电平持续的时间转化为输出的距离

float distance;

GPIO_SetBits(GPIOA,GPIO_Pin_1);

delay_us(20);

GPIO_ResetBits(GPIOA,GPIO_Pin_1);

if(TIM5_CH1_CAPTURE_STA&0X80)

{

distance=TIM5_CH1_CAPTURE_VAL*0.000001*340*100*0.5;

TIM5_CH1_CAPTURE_STA=0;

delay_ms(50);

return distance;

}

return 0;

}

中断服务函数

void TIM5_IRQHandler(void) //中断服务函数 \\ 高电平时间的读取是在中断服务函数中完成的,

{ \\这样只要模块输出端口输出高电平,单片机就会第一时间去处理

\\从而完成对持续时间的读取

if(TIM_GetITStatus(TIM5,TIM_IT_CC1))

{

if(TIM5_CH1_CAPTURE_STA&0x40) //0100 0000 //发生捕获中断

{

TIM5_CH1_CAPTURE_STA|=0X80; //成功捕获一次高电平

TIM5_CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);

TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //设置上升沿捕获

}

else

{

TIM5_CH1_CAPTURE_STA=0;

TIM5_CH1_CAPTURE_VAL=0;

TIM5_CH1_CAPTURE_STA|=0X40; //捕获到高电平 标志

TIM_Cmd(TIM5,DISABLE);

TIM_SetCounter(TIM5,0); //定时器初值为0

TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //设置下降沿捕获

TIM_Cmd(TIM5,ENABLE);

}

}

TIM_ClearITPendingBit(TIM5,TIM_IT_CC1);

}

  • 6
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搞机佬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值