打印
[STM32F1]

【转】STM32的超声波测距程序

[复制链接]
4818|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
不会发光的LED|  楼主 | 2016-12-22 13:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我所使用的测距模块是HC-SR04,C-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能,测

距精度可达高到3mm;模块包括超声波发射器、接收器与控制电路。

HC-SR04基本工作原理:
(1)采用IO口TRIG触发测距,给最少10us的高电平信呈。
(2)模块自动发送8个40khz的方波,自动检测是否有信号返回;
(3)有信号返回, 通过IO口ECHO输出一个高电平, 高电平持续的时间就是超声波从发射到返回的时间。 测试距离=(高电平时间*声速(340M/S))/2。


程序编写思路是:1、配置好使用到的GPIO以及定时器;
2、给模块TRIG端口发送大于10us的高电平信号,当收、收到ECHO回响信号是,打开定时器开始定时;
3、当回响信号消失,关闭定时器;
4、通过定时器定时时间来确定距离。

上时序图表明你只需要提供一个 10uS以上脉冲触发信号,该模块内部将发出8个 40kHz周期电平并检测回波。一旦检测到有回波信号则输出回响信号。回响信号的脉冲宽度与所测的距离成正比。 由此通过发射信号到收到的回响信号时间间隔可以计算得到距离。 公式: uS/58=厘米或者uS/148=英寸; 或是: 距离=高电平时间*声速( 340M/S) /2; 建议测量周期为 60ms以上, 以防止发射信号对。
回响信号的影响


具体程序如下:
#include "cs.h"
#include "stm32f10x.h"
#include "delay.h"
#include "usart.h"

/*记录定时器溢出次数*/
uint overcount=0;


/*设置中断优先级*/
void NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructer;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

NVIC_InitStructer.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStructer.NVIC_IRQChannelSubPriority=0;
NVIC_InitStructer.NVIC_IRQChannel=TIM2_IRQn;
NVIC_InitStructer.NVIC_IRQChannelCmd=ENABLE;

NVIC_Init(&NVIC_InitStructer);
}

/*初始化模块的GPIO以及初始化定时器TIM2*/
void CH_SR04_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructer;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructer;

RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

/*TRIG触发信号*/
GPIO_InitStructer.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructer.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructer.GPIO_Pin=GPIO_Pin_8;
GPIO_Init(GPIOB, &GPIO_InitStructer);

/*ECOH回响信号*/
GPIO_InitStructer.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStructer.GPIO_Pin=GPIO_Pin_9;
GPIO_Init(GPIOB, & GPIO_InitStructer);

/*定时器TIM2初始化*/
TIM_DeInit(TIM2);
TIM_TimeBaseInitStructer.TIM_Period=999;//定时周期为1000
TIM_TimeBaseInitStructer.TIM_Prescaler=71; //分频系数72
TIM_TimeBaseInitStructer.TIM_ClockDivision=TIM_CKD_DIV1;//不分频
TIM_TimeBaseInitStructer.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructer);

TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//开启更新中断
NVIC_Config();
TIM_Cmd(TIM2,DISABLE);//关闭定时器使能

}



float Senor_Using(void)
{
float length=0,sum=0;
u16 tim;
uint i=0;
/*测5次数据计算一次平均值*/
while(i!=5)
{
PBout(8)=1;  //拉高信号,作为触发信号
delay_us(20);  //高电平信号超过10us
PBout(8)=0;
/*等待回响信号*/
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_9)==RESET);
TIM_Cmd(TIM2,ENABLE);//回响信号到来,开启定时器计数

i+=1; //每收到一次回响信号+1,收到5次就计算均值
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_9)==SET);//回响信号消失
TIM_Cmd(TIM2,DISABLE);//关闭定时器

tim=TIM_GetCounter(TIM2);//获取计TIM2数寄存器中的计数值,一边计算回响信号时间

length=(tim+overcount*1000)/58.0;//通过回响信号计算距离

sum=length+sum;
TIM2->CNT=0;  //将TIM2计数寄存器的计数值清零
overcount=0;  //中断溢出次数清零
delay_ms(100);
}
length=sum/5;
return length;//距离作为函数返回值
}



void TIM2_IRQHandler(void) //中断,当回响信号很长是,计数值溢出后重复计数,用中断来保存溢出次数
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)
  {
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除中断标志
overcount++;

  }
}


沙发
mmuuss586| | 2016-12-22 14:03 | 只看该作者
谢谢分享;

使用特权

评论回复
板凳
过去的故事| | 2016-12-28 14:20 | 只看该作者
楼主我把你的程序改了下用不了,我用的是神舟的开发板,PB9对应TIM4,把你的TIM2改成TIM4,然后用液晶显示,没反应!!!!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

61

主题

102

帖子

1

粉丝