网上的资料太杂太乱,调这个东西的时候走了不少弯路,现在分享出来,亲测管用!
基本工作原理:
(1)采用IO口TRIG触发测距,给至少10us的高电平信号;
(2)模块自动发送8个40khz的方波,自动检测是否有信号返回;
(3)有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间声速(340M/S))/2;
(4)本模块使用方法简单,一个控制口发一个10US以上的高电平,就可以在接收口等待高电平输出.一有输出就可以开定时器计时,当此口变为低电平时就可以读定时器的值,此时就为此次测距的时间,方可算出距离.如此不断的周期测,即可以达到你移动测量的值*
5、 操作:初始化时将trig和echo端口都置低,首先向给 trig 发送至少10 us的高电平脉冲(模块自动向外发送8个40K的方波),然后等待,捕捉 echo 端输出上升沿,捕捉到上升沿的同时,打开定时器开始计时,再次等待捕捉echo的下降沿,当捕捉到下降沿,读出计时器的时间,这就是超声波在空气中运行的时间,按照 测试距离=(高电平时间声速(340M/S))/2 就可以算出超声波到障碍物的距离。
程序:
超声波端口初始化:
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);//使能GPIO时钟
//trig
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOG, &GPIO_InitStructure);//
//echo
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOG, &GPIO_InitStructure);//¯
定时器初始化:
TIM4_Int_Init(250-1,8400-1);//定时器时钟84M,分频系数8400,所以84M/8400=10KHZ的技术频率,记一次数0.1ms,计数250次为25ms。
/超声波测距最大4米,按声速340M/s计算,超声波测量最大距离4m时所用时间为42/340=23.6ms,这里取中断时间为25ms,完全够用!*/
定时器中断程序:
void TIM4_IRQHandler(void)
{
if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET) //溢出中断
{
flag=1;//·发生中断代表测量范围超出,使flag为1.
}
TIM_ClearITPendingBit(TIM4,TIM_IT_Update); //清除中断标志位
}
测距程序:
double s=0;
double l;
double p[5];
int i;
for(i=1;i<=5;i++)
{
//发出方波
trig=1;
delay_us(20);
trig=0;
//等待echo接收高电平
while(echo==0);
//开启定时器计时
TIM_Cmd(TIM4, ENABLE); //
TIM4->CNT=0;
while(echo==1);//等待接收完成
TIM_Cmd(TIM4, DISABLE);//完全接收后关闭定时器
//检验接收时是否发生了定时器中断,若发生中断,则超出测量范围,一般这种情况不会发生,空气中杂质粒子会影响声波,超声波测量范围也就1米以内。
if(flag==1)
{
p[i]=400;
flag=0;
}
else
{
l=TIM_GetCounter(TIM4);//
p[i]=l*17/10;//cm 0.1/1000*340/2*100*l
}
s+=p[i];
delay_ms(24);
/* 延时必须要加,否则容易出现声波发生碰撞的问题,产生较大误差,延时根据声波在空气中运行的最大时间计算即可,这里按4米计算,延时24ms.
*/
}
s=s/5;//取平均。
return s;
}
主程序:
while(1)
{
sum=ceju();
printf("%lf \n",sum);
}