赞
踩
一、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);
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。