stm32学习之HC_SR04超声波测距

文章内容仅个人的理解,如有错误还请各位多多包涵

参考:http://t.csdnimg.cn/iZ1qn

硬件

单片机:stm32f103c8t6,HC_SR04超声波测距

一、硬件介绍

注意不是3.3V电压(不过我接了用也能返回数据)

Trlg:接入单片机GPIO输出端

Echo:接入单片机GPIO输入端

二、超声波测距工作原理

有两个口,一个发送超声波,然后超声波碰到障碍物,反弹,另一个口就接收到回波。

怎么得到距离呢?

在一个口发出超声波时,同时间打开定时器计

超声波碰到障碍物,产生回波

等到另一个口接收到回波

就关闭定时器

此时定时器里的计数时间,是不是就是超声波传出的时间和传回的时间之和?

对,有了时间。距离就好算了,速度是声速

s=v *(t / 2),这样就明了

超声波模块是一上电就开始测量,发送超声波吗?

不,需要单片机给他发送触发信号(开始信号)

关于送触发信号

看代码理解,B11引脚我们设为输出

先从低拉到高,持续15us,再拉低,这一个过程就是单片机  发送开始信号

发送开始信号后 

等待超声波模块 响应(也就是超声波模块接收到回波时)给单片机发送个提醒信号

我们这里用B10引脚接收,b10为输入

三、全代码

.h

#ifndef _HC_SR04_H
#define _HC_SR04_H
#include "stm32f10x.h"                  // Device header
#include "delay.h"                  // Device header

#define	Trig_Send_Open GPIO_SetBits(GPIOB, GPIO_Pin_11)
#define	Trig_Send_Close GPIO_ResetBits(GPIOB, GPIO_Pin_11) 
#define Echo_Receive GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_10)


void HC_SR04_Init(void);
float Get_Length(void);
void Timer_On(void);
void Timer_Off(void);
int Get_Echo_TIM(void);



#endif

.c

#include "hc_sr04.h"                  // Device header
#include "stm32f10x.h"


 unsigned int Y_Out_Counter;//溢出时间增量(也就是计数器溢出的次数

void HC_SR04_Init(void)
{	
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIO时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使能TIMx时钟

	//GPIO初始化 Trig(STM32发送触发信号给HC-SR04)
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出(高低电平均有驱动能力)
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);

	//GPIO初始化 Echo(STM32接收回波信号,计算距离)
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);

	//定时中断配置
	//选择时钟源
	TIM_InternalClockConfig(TIM2);

	//配置时基单元
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 100-1;//ARR 定时时间0.1ms
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72-1;//PSC 1MHz(150HZ以上最好)
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//高级定时器采用,给0
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);

	//TIM_ClearFlag(TIM2,TIM_FLAG_Update);//解除初始化就进入中断(避免数据出错)

	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能定时中断

	//配置NVIC 分配和管理中断
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组

	
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//响应优先级
	NVIC_Init(&NVIC_InitStructure);

	//失能定时
	TIM_Cmd(TIM2,DISABLE);
}

//定时器开
void Timer_On(void)
{
	TIM_SetCounter(TIM2,0);//计数值清零(解除干扰)
	Y_Out_Counter = 0;//定时器还没使能,溢出值始终为0
	TIM_Cmd(TIM2,ENABLE);
}

//定时器关
void Timer_Off(void)
{
	TIM_Cmd(TIM2,DISABLE);//关闭定时器
}


void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)//中断标志判断
	{
		Y_Out_Counter++;//自增
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除中断标志
	}
}

int Timer_Get_Counter(void)
{
	unsigned int T;
	T=Y_Out_Counter*100;//重装值100,每溢出一次,进入定时中断一次,因此,溢出计数值=溢出次数*重装值
	T=T+TIM_GetCounter(TIM2);//总的计数值=溢出次数*重装值+最后一次没有到溢出值的计数
	TIM_SetCounter(TIM2,0);//计数值清零
	delay_ms(50);
	return T;
}


float Get_Length(void)
{
			//求解距离,采用平均值最好
	int i=0;//次数变量
	unsigned int t=0;
	float Length=0;
	float Sum=0;

	for(i=0;i<3;i++)//计算3次
	{	
		
		//触发信号(触发超声波模块工作)
		GPIO_ResetBits(GPIOB,GPIO_Pin_11);
		GPIO_SetBits(GPIOB,GPIO_Pin_11);//设B11引脚为高电平
		delay_us(15);//10US以上
		GPIO_ResetBits(GPIOB,GPIO_Pin_11);//设B11引脚为低电平
		//---------------------------------------
		
		//获取Echo引脚的电平状态
		while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==0);//低电平就执行空操作
		
		//读取到高电平
		Timer_On();//打开定时器
		
		while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==1);//高电平就执行空操作(直到读取完成)
		
		//低电平(接收结束)
		Timer_Off();//关闭定时器

		t=Timer_Get_Counter();//获取时间
		
		Length=((float)t/58.0);//计算距离
		
		Sum=Sum+Length;//3次计算的总距离
	}

	//计算距离的均值
	Length=Sum/3.0;
	return Length;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值