超声波测距模块(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以上。防止回响信号没有测量完,就再一次发送触发信号。

模块实现

思路

运用定时器计时 CNT*(CNT计数一次的时间)*速率=距离

运用功能

1.GPIO引脚输出高电平,置为1;
2.外部中断:在输入引脚收到高电平时,触发中断,开启定时器,计数器CNT置0;
3.定时器计时:

配置流程

 1. 开启时钟(定时器、GPIO)
 2. 配置GPIO引脚结构体(Trig,Echo):GPIO_Init();
 3. 配置NVIC、和外部中断EXTI:NVIC_Init() / EXTI_Init()

 4. 配置定时器结构体初始化:TIM_TimeBaseInit();
 5. 配置定时器中断结构体(更新中断)NVIC_Init / TIM_ITConfig
 6. 使能定时器:TIM_Cmd
 7. 编写外部中断服务函数:打开定时器,计时器CNT清0
 8. 编写定时器中断服务函数:清除中断
 
 9. Trig引脚输出高电平(10us以上),然后关闭
 10. 等待Echo引脚输出高电平开始(EXTI外部中断触发),定时器打开->开启计数器计数
 11. 等待Echo引脚输出高电平结束(EXTI外部中断结束),定时器关闭->停止计数器计数
(注意在主函数配置NVIC分组):NVIC_PriorityGroupConfig();

代码示例

UltrasonicWave.c

#include "stm32f10x.h"
#include <stdio.h>
#include "delay.h"
#include "time.h"
#include "Bluetooth.h"
#include "string.h"

int count;

void UltrasonicWave_Init(void)
{
	GPIO_InitTypeDef GPIOInitDef;
	NVIC_InitTypeDef  NVICInitDef;
	EXTI_InitTypeDef EXTIInitDef;
//-----------------------------------------------------
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
//-----------------------------------------------------	
	GPIOInitDef.GPIO_Pin=GPIO_Pin_0;				//PB0
	GPIOInitDef.GPIO_Mode=GPIO_Mode_Out_PP;				//通用推挽
	GPIOInitDef.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIOInitDef);
	
	GPIOInitDef.GPIO_Pin=GPIO_Pin_1;				//PB1
	GPIOInitDef.GPIO_Mode=GPIO_Mode_IPD;		//上拉输入,接收高电平
	GPIOInitDef.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIOInitDef);
//-----------------------------------------------------	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);	
	
	NVICInitDef.NVIC_IRQChannel=EXTI1_IRQn;						//设置中断线1
	NVICInitDef.NVIC_IRQChannelCmd=ENABLE;
	NVICInitDef.NVIC_IRQChannelPreemptionPriority=0;
	NVICInitDef.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVICInitDef);
	
	EXTIInitDef.EXTI_Line=EXTI_Line1;						//设置外设中断源
	EXTIInitDef.EXTI_LineCmd=ENABLE;
	EXTIInitDef.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTIInitDef.EXTI_Trigger=EXTI_Trigger_Rising_Falling;//上升沿
	EXTI_Init(&EXTIInitDef);

}

void EXTI1_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line1) != RESET)
	{
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1))//up
		{
			TIM_SetCounter(TIM1,0);
			TIM_Cmd(TIM1, ENABLE);   //开启时钟	Tim1
		}
		else
		{
			TIM_Cmd(TIM1, DISABLE);
		}
			EXTI_ClearITPendingBit(EXTI_Line1);  //清除EXTI1线路挂起位
	}	
}

void put_high(void)		//输出10us以上的高电平
{
	GPIO_SetBits(GPIOB,GPIO_Pin_0);
	delay_us(12);											
	GPIO_ResetBits(GPIOB,GPIO_Pin_0);
//	l=lcont*34/20.0;
//	return l;
}

//**************************************************************************************************	
float Distance;
char a[200];

void juli(void)				
{
	Distance=TIM_GetCounter(TIM1)*340/200.0;
	
	delay_ms(1000);
}

time.c

#include "stm32f10x.h"
#include <stdio.h>

void  Time1_Init()
{
		TIM_TimeBaseInitTypeDef TIMBaseInitDef;
		NVIC_InitTypeDef  NVICInitDef;
	//-----------------------------------------------------开时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);			//PA8
//-----------------------------------------------------		配置定时器
	TIMBaseInitDef.TIM_ClockDivision=TIM_CKD_DIV1;			
	TIMBaseInitDef.TIM_CounterMode=TIM_CounterMode_Up;//配置向上计数
	TIMBaseInitDef.TIM_Period=1000-1;											//每1ms一个周期,999个,  计数1000个为1ms
	TIMBaseInitDef.TIM_Prescaler=7200-1;//10khz  t=100us  0.1ms
	TIM_TimeBaseInit(TIM1,&TIMBaseInitDef);
//-----------------------------------------------------	设置中断
	NVICInitDef.NVIC_IRQChannel=TIM1_UP_IRQn;				//设置更新中断
	NVICInitDef.NVIC_IRQChannelCmd=ENABLE;
	NVICInitDef.NVIC_IRQChannelPreemptionPriority=0;
	NVICInitDef.NVIC_IRQChannelSubPriority=2;
	NVIC_Init(&NVICInitDef);

	TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);//更新中断***
	
	TIM_Cmd(TIM1,ENABLE);				//使能定时器
}


void TIM1_UP_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM1,TIM_IT_Update)==SET)
	{
		TIM_ClearITPendingBit(TIM1,TIM_IT_Update);
	}
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

好好睡觉好好吃饭

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

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

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

打赏作者

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

抵扣说明:

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

余额充值