STM32- drive module HC-SR04 Ultrasonic Ranging

Ultrasonic ranging principle

HC-SR04 using ultrasonic ranging module can achieve more precise linear distance, which distance measurement principle is as follows:
Here Insert Picture Description
one end of the ultrasonic waves emitted HC-SR04, after exposure to the reflective reflector, is received by another port, so long as we know emission and the time difference received directly from the HC-SR04 and the reflector can be calculated according to the rate of propagation of acoustic waves.
So we need to achieve Ultrasonic Ranging two conditions:

  • The time difference between transmission and reception
  • Ultrasonic wave transmission rate

HC-SR04 works

Electrical parameters Module HC-SR04 as shown:
Here Insert Picture Description
physical map Module HC-SR04 as shown:
Here Insert Picture Description
four pins:

  • Vcc: + 5V power supply
  • Trig: trigger signal (Ranging may trigger)
  • Echo: Outgoing echo signal (time difference can be returned)
  • Gnd: Ground

Trig achieved with pins and Echo ranging process:
1. a period of at least 10us Trig output level (pulse) trigger a distance, during the transmission of the ultrasonic wave has been Echo output high.
2. After the pulse output Trig, Echo detection level immediately pin, high Echo measured duration t, t is the time required for a round trip in the ultrasonic distance measurements.
Ranging timing chart as shown:
Here Insert Picture Description

STM32 drive to achieve

Using the STM32 drive HC-SR04 need to make a few key points:

  • Pin Configuration
  • Timing of control
  • Time difference measurement

To achieve several key points separately below

1. Configure pin

HC-SR04 four pins, Vcc, and Gnd directly connected to the power from the board can be, and is mainly configured Trig Echo pins, I chose Trig connector pins PB1, PB2 Echo pin connector.
Because the output level to control the Trig, the pin pattern PB1 is a push-pull output GPIO_Mode_Out_PP
Echo duration of the high level to be detected, so PB2 pin floating input mode is GPIO_Mode_IN_FLOATING
associated configuration code is as follows:

void SR04_GPIO_Init( void )
{
	GPIO_InitTypeDef GPIO_InitStruct;
	RCC_APB2PeriphClockCmd( Trig_Clock  |Echo_Clock , ENABLE );
	
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin = Trig_PIN;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(Trig_PORT, &GPIO_InitStruct);
	
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStruct.GPIO_Pin = Echo_PIN;
	GPIO_Init(Echo_PORT, &GPIO_InitStruct);
}

2. Timing Control

HC-SR04的时序是:先来一段10us的Trig高电平,接着接收一段Echo的高电平,伪代码如下:

#define Trig_H  GPIO_SetBits(GPIOB, GPIO_Pin_1)
#define Trig_L  GPIO_ResetBits(GPIOB, GPIO_Pin_1)

/* Trig给一个至少10us的高电平,超声波进行一次测距 */
	Trig_H;
	Delay_us( 10 );
	Trig_L;
/* 等待Echo高电平 */

3.时间差测量

这个是最重要的一步,要测量Echo高电平持续的时间,因为光传播的速率是340m/s,而测距的范围大多是cm级别,所以相应Echo高电平持续的时间也就是us级别的。
所以,测量时间差的条件就比较苛刻,我是利用SysTick(系统计数器)的原理实现计时的。SysTick计数器原理是对通过SysTick_Config()函数配置每俩次中断之间的节拍数,也就是俩次中断之间的机器周期,我大概算出了,测出0.1cm距离的Echo高电平时间约为6um,而系统时钟的频率是72MHz,所以配置每俩次中断之间的节拍为432的时候,进入一次中断就代表0.1cm的距离,所以只需要记录进入中断的次数就可以算出距离。通过一个全局变量在中断函数中自增来记录中断次数。SysTick_Config函数源代码如下:

static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ 
	/* 判断ticks 是否超出装填值和重装值的最大值 */
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            
  
  /* 配置 装载寄存器 */	
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;     
	/* 配置 内核中断的优先级,也是在NVIC中 */
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); 
	/* 加载计数器的值 */
	/* SysTick->VAL是当前数值寄存器的值 */
  SysTick->VAL   = 0;      
 
	/* CTRL是SysTick控制及状态寄存器:
		CLKSOURCE:位段2 时钟源选择,0=APB/8;1=APB  APB即72MHz
	  TICKINT:   位段1 当置为1时,计数器递减到0时会产生中断请求;当置为0时无动作
	  ENABLE:   位段0 使能位,可以启动SysTick定时器*/
	SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                   SysTick_CTRL_TICKINT_Msk   | 
                   SysTick_CTRL_ENABLE_Msk;                  
  return (0);                                              
}

SysTick的具体原理可以参考一下我之前的博客:SysTick原理

注意:SysTick_Config()函数执行完就开启了中断,所以必须在Echo为低电平后及时关闭中断,并且将记录中断的变量清零。
中断函数如示:

/* 用extern和volatile关键字修饰的 全局变量n */
extern volatile uint32_t n;

void SysTick_Handler(void)
{
	n++;
}

关闭中断及清零n的代码如下:

/* 本来的使能位取反 */
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;

SysTick->CTRL寄存器的0位控制着中断的使能,具体情况在之前SysTick的博客中已做详细说明。

4.如何将距离测出来

我在main函数中实现了距离的测量,并且通过串口打印函数将距离传到上位机,具体代码如示:

int main(void)
{

	int i=1,q;
	float p;
	/* HC-SR04模块引脚初始化 */
	SR04_GPIO_Init();
	/* 串口相关配置 */
	GQ_UART_Config();
	/* 打印调试信息 */
	printf("慢漫的测距实验\n ");
	
	
	while( 1 )
	{
		/* 每0.5s测一次距离 */
		Delay_ms( 500 );
	
		/* Trig给一个至少10us的高电平,超声波进行一次测距 */
		Trig_H;
		Delay_us( 10 );
		Trig_L;
		/* 等待Echo高电平 */
		while( Echo_Value != 1 );
		/* 打开中断,对Echo高电平时间计时 */
		/* 配置计数器的装载值是72*6=432,即一次中断6um,正好是超声波的0.1cm,所以中断次数n对应着n*0.1cm */
		/* SysTick_Config()中已经使能计数器了,所以无需再开启	*/
		SysTick_Config( 432 );
		/* 等待直到Echo为低电平 */
		while(Echo_Value == 1);
		/* 关闭中断,通过参数n来取得距离参数 */
		/* 本来的使能位取反 */
		SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
		/* p、q分别是距离的整数部分和小数部分 */
		p=n/10;
		q=n%10;
		/* 打印距离信息 */
		/* p-50时经过调试的,因为测量的距离和诸多因素有关,这个操作减小了误差 */
		printf("第%d次测量为:%.0f.%dcm\n",i,p-50,q);
		i++;
		/* 清零中断记录变量n */
		n=0;
	}
	
}

主要的代码就是这些,有什么问题可以和博主交流,大家一起进步!
q:2723808286

Published 62 original articles · won praise 188 · views 10000 +

Guess you like

Origin blog.csdn.net/qq_43743762/article/details/103217402