当前位置:   article > 正文

超声波测距模块(HC-SR04)---外部中断+定时器计时_超声波模块外部中断

超声波模块外部中断

超声波测距模块介绍

实物图

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

引脚定义

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

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

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

模块工作原理

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

超声波时序图

在这里插入图片描述

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

模块实现

思路

运用定时器计时 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();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

代码示例

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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81

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);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/479326
推荐阅读
相关标签
  

闽ICP备14008679号