当前位置:   article > 正文

基于STM32的超声波测距_基于stm32的超声波测距设计

基于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);

}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/479301
推荐阅读
相关标签
  

闽ICP备14008679号