第12周实验---基于FPGA的超声波测距

 (简答题)

使用 DE2-115 开发板驱动 超声波检测模块(HC_SR04 ),并将所测得数据显示到开发板上的数码管上,或者通过用UART通信方式上传到笔记本串口助手上显示(可采用UART IP核)。

1. 实验原理
1.1. 理论原理

超声波原理:
HC-SR04超声波测距模块可提供 2cm-400cm的非接触式距离感测功能,测距精度可达高到 3mm;模块包括超声波发射器、接收器与控制电路。图1为HC-SR04外观,其基本工作原理为给予此超声波测距模块触发信号后模块发射超声波,当超声波投射到物体而反射回来时,模块输出回响信号,以触发信号和回响信号间的时间差,来判定物体的距离。

1.2. 硬件模块时序图

 1.3. 系统架构设计

  

2.硬件连接

1.VCC —— 5V
2.GND——GND
3.Trig ——PA0(TIM2_CH1)
4.Echo ——PA1(TIM2_CH2

 3.软件代码

hcsr04.h

#ifndef __HCSR04_H
#define __HCSR04_H

#include "sys.h"

void Hcsr04Init(void);
void TIM2_RQHandler(void);  
u32 GetEchoTimer(void);
float Hcsr04GetLength(void);


#endif

hcsr04.c

#include "hcsr04.h"
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"


#define TRIG_Send  PAout(0)
#define ECHO_Reci  PAin(1)

u16 msHcCount = 0;//ms计数

/*  对应IO口初始化  */
void Hcsr04Init(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;     
    GPIO_InitTypeDef GPIO_InitStructure;
	  NVIC_InitTypeDef NVIC_InitStructure;
	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);   //使能对应RCC时钟
	
    //PA0_CH1  Trig
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;       	  	 //发送电平引脚
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_ResetBits(GPIOA,GPIO_Pin_0);
	
		//PA1_CH2  Echo	
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;    		 			 //返回电平引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);  
    GPIO_ResetBits(GPIOA,GPIO_Pin_1);    
    
		TIM_DeInit(TIM2);
		TIM_TimeBaseStructure.TIM_Period = (1000-1); 									//设置在下一个更新事件装入活动的自动重装载寄存器周期的值,计数到1000为1ms
		TIM_TimeBaseStructure.TIM_Prescaler =(72-1);								  //设置用来作为TIMx时钟频率除数的预分频值  1M的计数频率 1US计数
		TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;					//不分频
		TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  	//TIM向上计数模式
		TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); 				       
		
		TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);   									  //打开定时器更新中断
		
		NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;           	  //选择串口1中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;     //抢占式中断优先级设置为1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;            //响应式中断优先级设置为1
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;               //使能中断
    NVIC_Init(&NVIC_InitStructure);

    TIM_Cmd(TIM2,DISABLE);     
}


static void OpenTimerForHc()        //打开定时器
{
        TIM_SetCounter(TIM2,0);			//清除计数
        msHcCount = 0;
        TIM_Cmd(TIM2, ENABLE);  		//使能TIM2外设
}
 
static void CloseTimerForHc()        //关闭定时器
{
        TIM_Cmd(TIM2, DISABLE);  //使能TIM2外设
}
 
 

//定时器1中断服务程序
void TIM2_IRQHandler(void)   //TIM2中断
{
        if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)  //检查TIM2更新中断发生与否
        {
                TIM_ClearITPendingBit(TIM2, TIM_IT_Update  );  //清除TIM2更新中断标志 
                msHcCount++;
        }
}
 

//获取定时器时间
u32 GetEchoTimer(void)
{
        u32 t = 0;
        t = msHcCount*1000;					//得到us
        t += TIM_GetCounter(TIM2);  //得到us
        TIM2->CNT = 0;  					  //将TIM2计数寄存器的计数值清零
        delay_ms(50);
        return t;
}
 

//一次获取超声波测距数据 两次测距之间需要相隔一段时间,隔断回响信号
//为了消除余震的影响,取五次数据的平均值进行加权滤波。
float Hcsr04GetLength(void)
{
        u32 t = 0;
        int i = 0;
        float lengthTemp = 0;
        float sum = 0;
        while(i!=5)
        {
					TRIG_Send = 1;      					//发送口高电平输出
					delay_us(20);									//20us脉冲
					TRIG_Send = 0;								//脉冲发送完成
					/*等待接收口高电平输出*/
					while(ECHO_Reci == 0);      	
					OpenTimerForHc();        			//打开定时器
					i = i + 1;
					/*等待高电平输出结束*/
					while(ECHO_Reci == 1);
					CloseTimerForHc();        		//关闭定时器
					t = GetEchoTimer();        		//获取时间,分辨率为1US
					lengthTemp = ((float)t/58.0);	//cm
					sum = lengthTemp + sum ;	
				}
        lengthTemp = sum/5.0; 				  //平均滤波
        return lengthTemp;
}

main.c

#include "stm32f10x.h"
#include "uart.h"
#include "delay.h"
#include "hcsr04.h"
#include "usart.h"
#include "stdio.h"


int main()
{
	  float length = 0;
		NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
		
	  delay_init();
		uart_init(115200);
		printf("串口初始化成功!\r\n");
		Hcsr04Init();
		printf("HcSr04初始化成功!\r\n");
		while(1)
		{
			length = Hcsr04GetLength();
			printf("距离为 %f cm\r\n",length);
		}
	
}

4.效果展示

模块测距工作原理:

(1) 主控设备给 Trig 脚提供一个 10us 的脉冲信号。

(2) HC-SR04 接收到信号,开始发送超声波,并把 Echo置为高电平,然后准备接收返回的超声波。

(3) HC-SR04 接收到返回的超声波,把 Echo 置为低电平。

(4) Echo 高电平持续的时间就是超声波从发射到返回的时间间隔。

如果超声波模块前方没有障碍物,约4米之内,那当Trig引脚被提供10μs以上脉冲触发信号后,该模块内部发射(transmit)8个40kHz的超声波脉冲并检测回波,Echo引脚收到一个高电平并持续38毫秒,之后就会处于低电平状态,所以当得到38ms这个值时,我们就知道前方没有检测到障碍物了。

如果前方有障碍物,那在发射超声波脉冲后,信号就会反射回来,Echo引脚就会在接收到信号时立即切换到低电平状态,此时Echo引脚在高电平状态保持的时间就是信号发射并返回的所花的时间。

我们知道距离=速度 * 时间,要求出超声波模块到障碍物之间的距离,我们就需要知道速度和时间。速度就是340m/s,也就是声音在空气中传播的速度,转换城cm/μs单位就是0.034 cm/μs。时间的话,由于我们得到的是信号从发射到返回的时间值,所以需要除以2。最终得到的计算公式为:距离 =  0.034 cm/μs * 时间(μs) / 2

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值