超声波测距模块(HC-SR04)---定时器输入捕获

超声波测距模块介绍

实物图

在这里插入图片描述
超声波传感器模块上面通常有两个超声波元器件,一个用于发射,一个用于接收。

引脚定义

电路板上有四个引脚:VCC、GND、Trig(控制端)、Echo(接收端)。

1.单片机在控制口发一个 10US 以上的高电平, 
2.就可以在接收口等待传感器模块高电平输出.
3.一有输出单片机就可以开定时器计时,
4.当此口变为低电平时就可以读定时器的值,此时就为此次测距的时间,
  方可算出距离.如此不断的周期测,就可以达到你移动测量的值了。

Trig(控制端):对应的GPIO引脚设置为输出模式
Echo(接收端):对应的GPIO引脚设置为输入模式

模块工作原理

(1)采用 IO 触发测距,给至少 10us 的高电平信号;
(2)模块自动发送 8 个 40khz 的方波,自动检测是否有信号返回;
(3)有信号返回,通过 IO 输出一高电平,高电平持续的时间就是此次测距的时间
(4)超声波从发射到返回的时间.测试距离=(高电平时间*声速(340M/S))/2; 

超声波时序图

在这里插入图片描述

注意:手册介绍说建议测量周期为60ms以上。防止回响信号没有测量完,就再一次发送触发信号。

模块实现

运用功能

1.位带操作,控制引脚输出高电平
2.定时器输入捕获:输入引脚设置为定时器模式,捕获引脚的高电平,
输入捕获功能参考文章:
定时器输入捕获

配置流程

1. 打开定时器和相应IO口的时钟。
2. 初始化IO口,模式为输入:GPIO_Init();
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; 
3. 初始化定时器ARR,PSC
   TIM_TimeBaseInit();
4. 初始化输入捕获通道
   TIM_ICInit();
5. 配置相应的中断
6.  NVIC_Init();
    TIM_ITConfig();
7. 使能定时器:TIM_Cmd();

8. 编写中断服务函数:TIMx_IRQHandler();

代码示例

#include "stm32f10x.h"
#include <stdio.h>
#include "sys.h"
#include "delay.h"
#include "Bluetooth.h"


float Distance1;

u16 TIM2CH2_CAPTURE_STA,TIM2CH2_CAPTURE_VAL;

void  Time12_CH2_Init()
{
	GPIO_InitTypeDef  GPIOInitDef;
	TIM_TimeBaseInitTypeDef TIMBaseInitDef;
	NVIC_InitTypeDef  NVICInitDef;
	TIM_ICInitTypeDef TIMICInitDef;
//-----------------------------------------------------开时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);			//PA1--TIM2_CH2
//-----------------------------------------------------	
	GPIOInitDef.GPIO_Pin = GPIO_Pin_1;	 //设置引脚PA1
	GPIOInitDef.GPIO_Mode = GPIO_Mode_IPD; 		 //设置下拉输入
	GPIOInitDef.GPIO_Speed = GPIO_Speed_50MHz;		 //设置传输速率为50MHZ
	GPIO_Init(GPIOA, &GPIOInitDef);					 //调用GPIO初始化函数,进行初始化
//-----------------------------------------------------		配置定时器
	TIMBaseInitDef.TIM_ClockDivision=TIM_CKD_DIV1;			
	TIMBaseInitDef.TIM_CounterMode=TIM_CounterMode_Up;//配置向上计数
	TIMBaseInitDef.TIM_Period=1000-1;											//计数周期100ms	
	TIMBaseInitDef.TIM_Prescaler=7200-1;									//10khz  CNT_t=100us  0.1ms
	TIM_TimeBaseInit(TIM2,&TIMBaseInitDef);
//-----------------------------------------------------		
	TIMICInitDef.TIM_Channel=TIM_Channel_2;
	TIMICInitDef.TIM_ICFilter=0X00;				//
	TIMICInitDef.TIM_ICPolarity=TIM_ICPolarity_Rising;		//上升沿
	TIMICInitDef.TIM_ICPrescaler=TIM_ICPSC_DIV1;					//不分频
	TIMICInitDef.TIM_ICSelection=TIM_ICSelection_DirectTI;		//影子寄存器cc2映射到捕获通道TI2
	TIM_ICInit(TIM2,&TIMICInitDef);
//-----------------------------------------------------	设置中断
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
	TIM_ITConfig(TIM2,TIM_IT_CC2,ENABLE);
	
	NVICInitDef.NVIC_IRQChannel=TIM2_IRQn;				//设置更新中断
	NVICInitDef.NVIC_IRQChannelCmd=ENABLE;
	NVICInitDef.NVIC_IRQChannelPreemptionPriority=3;
	NVICInitDef.NVIC_IRQChannelSubPriority=3;
	NVIC_Init(&NVICInitDef);
	
	TIM_Cmd(TIM2,ENABLE);				//使能定时器
}


void TIM2_IRQHandler(void)
{
	if((TIM2CH2_CAPTURE_STA&0X80)==0)//还未成功捕获	
	{
		if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)//溢出
		{	    
			if(TIM2CH2_CAPTURE_STA&0X40)//已经捕获到高电平了
			{
				if((TIM2CH2_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
				{
					TIM2CH2_CAPTURE_STA|=0X80;//标记成功捕获了一次
					TIM2CH2_CAPTURE_VAL=0XFFFF;
				}
				else 
					TIM2CH2_CAPTURE_STA++;
			}	 
		}
		if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)//发生捕获事件
		{	
			if(TIM2CH2_CAPTURE_STA&0X40)		//捕获到一个下降沿 		
			{	  			
				TIM2CH2_CAPTURE_STA|=0X80;		//标记成功捕获到一次高电平脉宽
				TIM2CH2_CAPTURE_VAL=TIM_GetCapture3(TIM3);	//获取当前的捕获值.
				TIM_OC2PolarityConfig(TIM3, TIM_ICPolarity_Rising); //设置为上升沿捕获
			}
			else  								//还未开始,第一次捕获上升沿
			{
				TIM2CH2_CAPTURE_STA=0;			//清空
				TIM2CH2_CAPTURE_VAL=0;
				TIM2CH2_CAPTURE_STA|=0X40;		//标记捕获到了上升沿
				TIM_SetCounter(TIM2, 0);		//清空计数器
				TIM_OC3PolarityConfig(TIM2, TIM_ICPolarity_Falling);//设置为下降沿捕获
			}		    
		}			     	    					   
	}
	TIM_ClearITPendingBit(TIM3, TIM_IT_Update|TIM_IT_CC3); 		//清除中断标志位
}

void Read_TIM3Distane(void)
{   
	PBout(0)=1;		//输出10us以上的高电平
	delay_us(15);  
	PBout(0)=0;	
	
	if(TIM2CH2_CAPTURE_STA&0X80)//成功捕获到了一次高电平
	{
		Distance1=TIM2CH2_CAPTURE_STA&0X3F;
		Distance1*=65536;					        //溢出时间总和
		Distance1+=TIM2CH2_CAPTURE_VAL;		//得到总的高电平时间
		Distance1=Distance1*170/1000;				//340除以2=170,计数周期为100MS,单位为340M/S,再将单位M换算为CM所以除以1000
		printf("aaa%f \r\n",Distance1);
		TIM2CH2_CAPTURE_STA=0;			//开启下一次捕获
	}				
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

好好睡觉好好吃饭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值