2.1超声波测距(附带源码)

引言

我们上一讲说到了有两种思路来初始化我们的超声波测距模块!

1使用从模式   2使用捕获通道

但其实他们的初始化结构基本相似,所以我们只使用第二种方法初始化。

我们使用的是TIM4定时器。

补充

上节课我们遗漏了一个知识点,传进定时器的ETR信号是什么!理解这个十分重要!

我在这里补充一下。

ETR

ETR(External Trigger Input)外部/触发/输入(是一个输入端引脚)

外部时钟源:ETR引脚可以作为定时器的外部时钟源输入,允许定时器根据外部信号的频率进行计数。这对于需要与外部事件同步的定时器应用尤为重要。

触发信号输入:除了作为时钟源外,ETR引脚还可以接收外部触发信号,用于在特定条件下启动或重置定时器的计数。

应用实例

  1. 脉冲计数:ETR引脚可以用于计数外部输入的脉冲个数,实现频率测量等功能。
  2. 同步控制:在多个定时器或外部设备需要同步工作的场景中,ETR引脚可以用于接收同步信号,确保各设备按照相同的节奏工作。
  3. 位置控制:在电机控制等应用中,ETR引脚可以接收编码器的信号,实现精确的位置控制。

捕获模式

我们使用的是TIM4定时器的一通道。

所以引脚对应关系为:trrig——PA0(产生TTL电平信号)    echo——PB6与PE0(一个是接收ETR信号,一个是TIM4的一通道)那我们直接开写了:

TRIG引脚初始化

我们需要使PA0初始化完处于低电平状态,当我们需要测距时,产生一个TTL脉冲,脉冲的时间大于10us。根据此思路可以写出一个初始化代码和触发测距代码。

#include "echo.h"
#include "Delay.h"
void TRIG_Init(void)
{
GPIO_InitTypeDef triggpio;
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, ENABLE);
triggpio.GPIO_Mode=GPIO_Mode_Out_PP;
triggpio.GPIO_Pin=GPIO_Pin_0;
triggpio.GPIO_Speed=GPIO_Speed_50MHz;	
GPIO_Init(GPIOA, &triggpio);	
GPIO_WriteBit(GPIOA, GPIO_Pin_0,  Bit_RESET);
}
void TRIG(void)
{

GPIO_WriteBit(GPIOA, GPIO_Pin_0,  Bit_SET);
Delay_us(11);
GPIO_WriteBit(GPIOA, GPIO_Pin_0,  Bit_RESET);	
}

ECHO引脚初始化

这里就不多讲了,需要的直接拿走即可。接线方式,PE0与PB6同时接入echo引脚。

void echo_Init(void)
{
GPIO_InitTypeDef echogpio;
TIM_TimeBaseInitTypeDef time4;
TIM_ICInitTypeDef ic1;
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, ENABLE);	
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, ENABLE);	
echogpio.GPIO_Mode=GPIO_Mode_IN_FLOATING;
echogpio.GPIO_Pin=GPIO_Pin_6;
echogpio.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &echogpio);
TIM_TimeBaseStructInit(&time4);
time4.TIM_CounterMode=TIM_CounterMode_Up;
time4.TIM_Period=71;
time4.TIM_Prescaler=65535;
TIM_TimeBaseInit(TIM4, &time4);	
TIM_ICStructInit(&ic1);
	ic1.TIM_Channel=TIM_Channel_1;
	ic1.TIM_ICPolarity=TIM_ICPolarity_Falling;//从定时器开始到捕获到下降沿结束
    ic1.TIM_ICSelection = TIM_ICSelection_DirectTI;
	TIM_ICInit(TIM4, &ic1);
	//           DMA/中断操作(计数和捕获)
	TIM_ClearFlag(TIM4,TIM_FLAG_CC1|TIM_FLAG_Update);
	TIM_ITConfig(TIM4, TIM_IT_CC1,ENABLE);
	TIM_CCxNCmd(TIM4, TIM_Channel_1, TIM_CCxN_Enable);
	TIM_Cmd(TIM4, DISENABLE);
	//           计数涉及到了加减所以需要清零
	TIM4->CNT=0x00;

}

那么什么时候才打开定时器呢,这就涉及到了PE0引脚的作用。(我们的捕获指的是从定时器打开到定时器接收到电平变低的脉冲,所以我们需要一个能够控制定时器打开的功能)因此还需要一个函数。

void echo(void)
{
GPIO_InitTypeDef ping;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
	ping.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	ping.GPIO_Pin=GPIO_Pin_0;
	ping.GPIO_Speed=GPIO_Speed_50MHz;
  GPIO_Init(GPIOE, &ping);	
	TIM_ETRConfig(TIM4, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted,0x00);
	TIM_SelectInputTrigger(TIM4, TIM_TS_ETRF);
	TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Trigger);
	TIM4->CNT =0x0;
  TIM_Cmd(TIM4, DISABLE);
	
}

 模块初始化

void ECHO(void)
{
TRIG_Init();
TRIG();
echo_Init();
echo();
}

echo.h 

#ifndef   __ECHO_H
#define		__ECHO_H

#include  "stm32f10x.h"


void TRIG_Init(void);
void TRIG(void);
void echo_Init(void);
void echo(void);

#endif

中断函数计算距离

在初始化完成,我们就实现了当测距开始时打开时钟,拉成高电平,当我们测距完成时拉低电平,进行捕获。那么我们的终极目标是测距,所以必须有一个中断服务函数。

#include "echo.h"
float  Distance =0;
void TIM4_IRQChannel(void)
{
	__IO uint16_t  cnt;
	cnt=TIM4->CCR1;//(us计时)
if(TIM_GetITStatus(TIM4,TIM_IT_CC1)==SET)
{	
	Distance=cnt/58.82;//(当时间单位为微秒距离单位为厘米时:时间*1/2*340m/s就近似等于58.82)
TIM_ClearFlag(TIM4, TIM_FLAG_CC1);
TIM_Cmd(TIM4, DISABLE);	
TIM4->CNT = 0;
}

}

主函数使用

优先级配置

有了模块有了中断必不可少的就是配置中断优先级。我们尽量配置的高一些,因为就靠中断来完成我们的功能!!!

#include "stm32f10x.h"
#include "echo.h"
#include "myIT.h"



int main(void)
{
	NVIC_InitTypeDef   nvic;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	nvic.NVIC_IRQChannel=TIM4_IRQn  ;
  nvic.NVIC_IRQChannelPreemptionPriority=1;
	nvic.NVIC_IRQChannelSubPriority=1;
	nvic.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&nvic);
	while(1)
	{
	ECHO();  //触发超声波测距
	Delay_ms(10);

	}
}

下一节课我们就涉及到了如何完成超声波测距避障!并且如何将模块装载到我们的小车上! 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值