HAL库通过一个定时器实现多个超声波(HC-SR04)测距

Posted 小材大用

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HAL库通过一个定时器实现多个超声波(HC-SR04)测距相关的知识,希望对你有一定的参考价值。

环境:

1.STM32 CUBEMX

2.超声波模块HC-SR04

3.STM32F103C8T6最小系统板

实现功能:

选用两个超声波实现实时测距,并测得的距离在串口1显示。

思路:使用定时器2实现检测,但不使用定时器中断,然后通过循环检测超声波返回脉冲的形式实现距离测量。

STM32F103C8T6最小系统板

超声波模块HC-SR04

 

超声波原理介绍:

 

接线表:

超声波模块引脚STM32最小系统板引脚设置模式
VCC+5V
GNDGND
Trig1PA1推挽输出模式
Echo1PA0输入模式
Trig2PA3推挽输出模式
Echo2PA6输入模式
-PA9USART1_TX
-PA10USART1_RX

注:这里的引脚可以随便选择都可实现超声波检测

步骤1:STM32CUBEMX配置

 

 

 TIM2设置的是1S溢出一次。

步骤2:功能实现

超声波1代码实现:

uint16_t SR04Distance(void)
{
  uint16_t Distance;
  int32_t outTime = 0;
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
	delay_us(15);
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
  
  
  while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) != 1)
  {
    outTime++;
    if(outTime > 100000)
    {
      break;
    }
  }
   htim2.Instance->CNT = 0;
  __HAL_TIM_ENABLE(&htim2);
  
  outTime = 0;
  while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) != 0)
  {
    outTime++;
    if(outTime > 100000)
    {
      break;
    }
  }
  __HAL_TIM_DISABLE(&htim2);
  Distance = (uint16_t)(htim2.Instance->CNT*340/20.0); 
  //sprintf(str,"V1=%d\\r\\n",Distance);
  //while(HAL_OK != HAL_UART_Transmit(&huart1, (uint8_t *)str, strlen(str), 5000));
  return Distance;
}

超声波2代码实现,和超声波1实现效果一致

uint16_t SR04Distance2(void)
{
  uint16_t Distance;
  int32_t outTime = 0;
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET);
	delay_us(15);
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
  
  
  while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6) != 1)
  {
    outTime++;
    if(outTime > 100000)
    {
      break;
    }
  }
   htim2.Instance->CNT = 0;
  __HAL_TIM_ENABLE(&htim2);
  
  outTime = 0;
  while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6) != 0)
  {
    outTime++;
    if(outTime > 100000)
    {
      break;
    }
  }
  __HAL_TIM_DISABLE(&htim2);
  Distance = (uint16_t)(htim2.Instance->CNT*340/20.0); 
  //sprintf(str,"V2=%d\\r\\n",Distance);
  //while(HAL_OK != HAL_UART_Transmit(&huart1, (uint8_t *)str, strlen(str), 5000));
  return Distance;
  
}

为了保证模块突发问题,我在检测高低电平的地方增加超时检测,防止程序死循环,保证程序的合理性:

while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6) != 0)
  {
    outTime++;
    if(outTime > 100000)
    {
      break;
    }
  }

接下来实现两个超声波测距:

void  UltrasonicRanging(void)
{
	uint16_t Distance[10];
	uint16_t Distance2[10];
	uint16_t max1 = 0;
	uint16_t min1 = 0;
	uint16_t max2 = 0;
	uint16_t min2 = 0;
	int i;
	SR04DistanceGlobal1 = 0;		//	超声波1测得的距离清0
	SR04DistanceGlobal2 = 0;		//	超声波2测得的距离清0
	for(i = 0;i<5;i++)
	{
		Distance[i] = SR04Distance();
    Distance2[i] = SR04Distance2();
	}
	max1 = Distance[0];
	max2 = Distance2[0];
	min1 = Distance[0];
	min2 = Distance2[0];
 	for(i = 0;i<5;i++)
 	{
 		if(max1 < Distance[i])
 		{
 			max1 = Distance[i];
 		}
		if(max2 < Distance2[i])
 		{
 			max2 = Distance2[i];
 		}
		if(min1 > Distance[i])
 		{
 			min1 = Distance[i];
 		}
		if(min2 > Distance2[i])
 		{
 			min2 = Distance2[i];
 		}
		SR04DistanceGlobal1 = SR04DistanceGlobal1 + Distance[i];
		SR04DistanceGlobal2 = SR04DistanceGlobal2 + Distance2[i];
 	}
	SR04DistanceGlobal1 = (uint16_t)((SR04DistanceGlobal1-max1-min1)/3);
	SR04DistanceGlobal2 = (uint16_t)((SR04DistanceGlobal2-max2-min2)/3);
}

这里增加了测距的稳定性,一下测量了5次,也可以测量更多次,去除最大值和最小值,目的是防止超声波突发测距不准问题,或魔鬼值问题。

主函数中代码:

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM2_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  delay_init(72);
  while(HAL_OK != HAL_UART_Transmit(&huart1, "wantin", 7, 5000));
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    UltrasonicRanging();
    sprintf(str,"V1=%d\\r\\n",SR04DistanceGlobal1);
    while(HAL_OK != HAL_UART_Transmit(&huart1, (uint8_t *)str, strlen(str), 5000));
    
    sprintf(str2,"V2=%d\\r\\n",SR04DistanceGlobal2);
    while(HAL_OK != HAL_UART_Transmit(&huart1, (uint8_t *)str2, strlen(str2), 5000));
    //HAL_Delay(20); 

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

将测量的结果在串口显示,显示效果如下:

具体代码实现可链接下载:

(2条消息) HAL库实现定时器实现多个超声波(HC-SR04)测距-C文档类资源-CSDN文库

以上是关于HAL库通过一个定时器实现多个超声波(HC-SR04)测距的主要内容,如果未能解决你的问题,请参考以下文章

HAL实现多个超声波测距(输入捕获实现)

HAL实现多个超声波测距(输入捕获实现)

基于STM32F103C8T6(HAL库)的HC-SR501红外人体传感及HC-SR04超声波测距

基于STM32F103C8T6(HAL库)的HC-SR501红外人体传感及HC-SR04超声波测距

基于STM32F103C8T6(HAL库)的HC-SR501红外人体传感及HC-SR04超声波测距

基于STM32F103C8T6(HAL库)的HC-SR501红外人体传感及HC-SR04超声波测距