STM32F103VET6超声波模块HC-SR04 的测试例程

版权声明:技术开源与分享,求指教,求扩散,欢迎交流与分享。 https://blog.csdn.net/tcjy1000/article/details/70170058

        近来有时间,整理一下资料,自己近十年来,业余画了不少的开发测试板,在淘宝上也买了不少的板子与器件,一直以来,都喜欢DIY,今天整理了一下超声波模块HC-SR04的程序,网上资料应该不少,自己工作中也接触过。记录一下。

        超声波如何设计的我不太关心,我只关心如何使用。这个模块可以+3.3V供电,四个引脚,使用STM32两个GPIO引脚控制即可,测试起来,简单。

        超声波模块工作的原理:首先需要触发trig,就像是打开或是使能的作用,让超声波工作起来。然后,超声波通过echo返回一段高电平,高电平的时间,就是声音到达障碍物返回的时间,声速是固定的340m/S,因此,可以求得距离。这里是2倍距离的时间,因此计算公式为:2L = Vt = 340m/S * t,这里t单位为S(秒)。


      STM32如何操作超声波模块呢?

(1)一个GPIO引脚Trig,用于触发。

(2)一个GPIO引脚接Echo,设置为外部中断,用来接收触发后返回来的高电平。

(3)一个定时器(计数器),用来测时间。

(4)可以使用另一个定时器,如Systick,隔一段时间用来触发一次超声波模块,从而不断获取当前的距离值。

(5)一个串口,用来打印输出测量的距离。



驱动代码如下:

/********************     (C) COPYRIGHT 2017      **************************
 * 文件名  :Sonic.c
 * 描述    :超声波模块 测试例程       
 * 实验平台:STM32F103VET6
 * 库版本  :ST3.5.0
 *
 * 编写日期:2017-04-10
 * 修改日期:2017-04-14
 * 作者    :
****************************************************************************/
#include "Sonic.h"


/*******************************************************************************
*	Sonic  Init
*******************************************************************************/

u32  Distance = 0;
u8   Done;
u32 __IO time_1ms = 0;

void TIM6_Init(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  //NVIC_InitTypeDef 		   NVIC_InitStructure;
  /* TIM6 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 0xFFFF; 
	TIM_TimeBaseStructure.TIM_Prescaler = 142;          //144分频,500K的计数器
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
  TIM_ITConfig(TIM6, TIM_IT_Update, DISABLE);	
	TIM_Cmd(TIM6, DISABLE);
}

void Sonic_Init(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	EXTI_InitTypeDef EXTI_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC| RCC_APB2Periph_AFIO,ENABLE);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;						//PC4 Trig
	GPIO_Init(GPIOC,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IPD;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;           		//PC5 Echo
	GPIO_Init(GPIOC,&GPIO_InitStructure);   
	
	GPIO_WriteBit(GPIOC,GPIO_Pin_4,(BitAction)0); 			//trig
	
	//EXTI_DeInit();
	EXTI_ClearITPendingBit(EXTI_Line5);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5);
	EXTI_InitStructure.EXTI_Line= EXTI_Line5; 
	EXTI_InitStructure.EXTI_Mode= EXTI_Mode_Interrupt; 
	EXTI_InitStructure.EXTI_Trigger= EXTI_Trigger_Rising_Falling;
	EXTI_InitStructure.EXTI_LineCmd=ENABLE;
  EXTI_Init(&EXTI_InitStructure);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0;        
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;   
	NVIC_Init(&NVIC_InitStructure);
	
	Distance = 0;
	Done = 1;
}

void Sonic_Trig(void)
{
	u16 i = 0;
	if((Done == 1)&&(time_1ms > 100))
	{
		time_1ms = 0;
		GPIO_WriteBit(GPIOC,GPIO_Pin_4,(BitAction)1);
		for(i=0;i<0xf0;i++);
		GPIO_WriteBit(GPIOC,GPIO_Pin_4,(BitAction)0); 
		Done = 0;
	}
}

void EXTI9_5_IRQHandler(void)
{
	static u8 flag_Sta = 0;
	if(EXTI_GetITStatus(EXTI_Line5) != RESET)		
	{
		EXTI_ClearITPendingBit(EXTI_Line5);  
		if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)==1)
		{
			 TIM_SetCounter(TIM6,0);	
			 flag_Sta=1;
			 TIM_Cmd(TIM6, ENABLE);     
		}
		else
		{
			TIM_Cmd(TIM6, DISABLE); 					
			if(flag_Sta)
			{		
				Distance = TIM_GetCounter(TIM6);
				Distance = Distance /29;
				if(Distance > 300)
					Distance = 300;
				Done = 1;
			}
			flag_Sta=0;
		}
	}
}

/*******************      (C) COPYRIGHT 2017       *END OF FILE************/



SysTick中断作的处理:


/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
void SysTick_Handler(void)
{
	time_1ms++;
	time_120ms++;
	if(time_120ms>=80)
	{
		Sonic_Trig();				//50ms Trig Sonic
		time_120ms=0;
	}
	TimingDelay_Decrement();
}


/* 
 * 函数名:main
 * 描述  : "主机"的主函数
 * 输入  :无
 * 输出  : 无
 */
 
int main(void)
{	 
	SysTick_Init();
 	USART1_Config(115200);						/* 初始化USART1 */
 	LED_GPIO_Config();	  						/* 运行LED初始化 */
	TIM2_Config(); 										/* 定时器TIM2初始化 */	
	TIM6_Init();			//TIM6 Init
	Sonic_Init();			//Sonic_Init 
	LED1(OFF);
	LED2(OFF);
	LED3(OFF);
	LED4(OFF);
	LEDR(OFF);
	printf("STM32F103VET6_Sonic Test!\r\n");
	printf("2017-04-14 9:00\r\n\r\n");
	while(1)
	{ 
		Delay_ms(1000);
		printf("The Distance is:%d\r\n",Distance);
	}
}


测试下来,基本符合要求,关于距离的测量,总结如下:

(1)超声波模块,如果前方没有障碍物,就可能不返回,这样程序里,需要有超时的处理,不能死等,否则会影响其他程序的正常进展,采集用的计数器会超时,重新计数,距离也不正确。

如超声波最大测距为:4米,则 2*4 = vt = 340m/s *Tm   Tm为最大的时间,约为:30ms。加上一些余量,60ms差不多可以完成一次采集任务。我这里使用:100ms一次。计数器:每个数为:2us,可以计到最大2*65535=130ms中断并重新计数。


(2)计算公式:

2* L = VT = 340m/s * n * 2us = 340*2*n/1000000(m)=34*2*n/1000(cm)

L= 34*n/1000 (cm),这里单位为厘米。

L= n/29.4 约为:L=n/30

这样,根据定时计数器的值,就可计算得到距离(单位为:cm)


(3)最大值限制:如超声波最大测距为:4米,程序里根据要求,可以限制到3.5米。如果超过,则等于3.5米,





工程如下:感兴趣的可以一起讨论。


https://git.oschina.net/fsmd/stm32f103ve


Keil5 工程下载




阅读更多

没有更多推荐了,返回首页