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

Posted 小材大用

tags:

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

超声波工作原理可参考博客:

(2条消息) HAL库实现定时器实现多个超声波(HC-SR04)测距_XiaoCaiDaYong的博客-CSDN博客

环境:

1.STM32 CUBEMX

2.超声波模块HC-SR04

3.STM32F103C8T6最小系统板

实现功能:

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

思路:使用定时器2实现输入捕获测距。

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

CUBEMX配置:

 

功能实现:

void ch1_capture(void)
{   
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET); 
			delay_us(20);
      //HAL_Delay(1);
			HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
}


void ch3_capture(void)
{   
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET); 
			delay_us(20);
      //HAL_Delay(1);
			HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
}

定时器中断回调:

/* USER CODE BEGIN 4 */


//定时器更新中断(计数溢出)中断处理回调函数, 该函数在HAL_TIM_IRQHandler中会被调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//更新中断(溢出)发生时执行
{
	if(htim->Instance == htim2.Instance)
  {
    if((TIM2CH1_CAPTURE_STA&0X80)==0)				//还未成功捕获上升沿
    {
      if(TIM2CH1_CAPTURE_STA&0X40)				//已经捕获到高电平了
      {
        if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)	//高电平太长了
        {
          TIM2CH1_CAPTURE_STA|=0X80;			//标记成功捕获了一次
          TIM2CH1_CAPTURE_VAL=0XFFFF;
        }else TIM2CH1_CAPTURE_STA++;
      }	 
    }	
  }

  if(htim->Instance == htim3.Instance)
  {
    if((TIM3CH1_CAPTURE_STA&0X80)==0)				//还未成功捕获上升沿
    {
      if(TIM3CH1_CAPTURE_STA&0X40)				//已经捕获到高电平了
      {
        if((TIM3CH1_CAPTURE_STA&0X3F)==0X3F)	//高电平太长了
        {
          TIM3CH1_CAPTURE_STA|=0X80;			//标记成功捕获了一次
          TIM3CH1_CAPTURE_VAL=0XFFFF;
        }else TIM3CH1_CAPTURE_STA++;
      }	 
    }	
  }
}


//定时器输入捕获中断处理回调函数,该函数在HAL_TIM_IRQHandler中会被调用
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//捕获中断发生时执行
{
  if(htim->Instance == htim2.Instance)
  {
    if((TIM2CH1_CAPTURE_STA&0X80)==0)				//还未成功捕获
    {
      if(TIM2CH1_CAPTURE_STA&0X40)				//捕获到一个下降沿 		
      {	  			
        TIM2CH1_CAPTURE_STA|=0X80;				//标记成功捕获到一次高电平脉宽
              TIM2CH1_CAPTURE_VAL=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);//获取当前的捕获值.
        TIM_RESET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1);   //一定要先清除原来的设置!!
              TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);//配置TIM2通道1上升沿捕获
      }else  										//还未开始,第一次捕获上升沿
      {
        TIM2CH1_CAPTURE_STA=0;					//清空 
        TIM2CH1_CAPTURE_VAL=0;
        TIM2CH1_CAPTURE_STA|=0X40;				//标记捕获到了上升沿
        __HAL_TIM_DISABLE(&htim2);      	//关闭定时器2
        __HAL_TIM_SET_COUNTER(&htim2,0);
        TIM_RESET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1);   //一定要先清除原来的设置!!
        TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);//定时器2通道1设置为下降沿捕获
        __HAL_TIM_ENABLE(&htim2);		//使能定时器2
      }		    
    }	
  }
  if(htim->Instance == htim3.Instance)
  {
    if((TIM3CH1_CAPTURE_STA&0X80)==0)				//还未成功捕获
    {
      if(TIM3CH1_CAPTURE_STA&0X40)				//捕获到一个下降沿 		
      {	  			
        TIM3CH1_CAPTURE_STA|=0X80;				//标记成功捕获到一次高电平脉宽
        TIM3CH1_CAPTURE_VAL=HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);//获取当前的捕获值.
        TIM_RESET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1);   //一定要先清除原来的设置!!
        TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);//配置TIM2通道1上升沿捕获
      }else  										//还未开始,第一次捕获上升沿
      {
        TIM3CH1_CAPTURE_STA=0;					//清空 
        TIM3CH1_CAPTURE_VAL=0;
        TIM3CH1_CAPTURE_STA|=0X40;				//标记捕获到了上升沿
        __HAL_TIM_DISABLE(&htim3);      	//关闭定时器2
        __HAL_TIM_SET_COUNTER(&htim3,0);
        TIM_RESET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1);   //一定要先清除原来的设置!!
        TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);//定时器2通道1设置为下降沿捕获
        __HAL_TIM_ENABLE(&htim3);		//使能定时器2
      }		    
    }
  }	
	
}
/* USER CODE END 4 */

主函数实现:

int main(void)
{
  /* USER CODE BEGIN 1 */
  float len=0;
  uint16_t dis = 0;
  uint32_t time=0;
  char str[20] ="";
  char str3[20] ="";
  float len3=0;
  uint16_t dis3 = 0;
  uint32_t time3=0;
  /* 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_USART1_UART_Init();
  MX_TIM2_Init();
  MX_TIM3_Init();
  /* USER CODE BEGIN 2 */
  delay_init(72);
  while(HAL_OK != HAL_UART_Transmit(&huart1, "wantin", 7, 5000));
  
  HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);   //开启TIM5的捕获通道1,并且开启捕获中断
  HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);   //开启TIM5的捕获通道1,并且开启捕获中断
  __HAL_TIM_ENABLE_IT(&htim2,TIM_IT_UPDATE);   //使能更新中断
  __HAL_TIM_ENABLE_IT(&htim3,TIM_IT_UPDATE);   //使能更新中断
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    ch1_capture();  // 
    ch3_capture();  //   
    if(TIM2CH1_CAPTURE_STA&0X80)           //成功捕获到了一次高电平
    {
      time=TIM2CH1_CAPTURE_STA&0X3F; 
      time*=65536;		 	    	        //溢出时间总和
      time+=TIM2CH1_CAPTURE_VAL; 			//得到总的高电平时间
      len=time*0.17;
      dis = (uint16_t)len;
      sprintf(str,"v1=%d\\r\\n",dis); 
      while(HAL_OK != HAL_UART_Transmit(&huart1, (uint8_t *)str, strlen(str), 5000));
      TIM2CH1_CAPTURE_STA=0;          //开启下一次捕获
      

    }
    if(TIM3CH1_CAPTURE_STA&0X80)           //成功捕获到了一次高电平
    {
      time3=TIM3CH1_CAPTURE_STA&0X3F; 
      time3*=65536;		 	    	        //溢出时间总和
      time3+=TIM3CH1_CAPTURE_VAL; 			//得到总的高电平时间
      len3=time3*0.17;
      dis3 = (uint16_t)len3;
      sprintf(str3,"v2=%d\\r\\n",dis3); 
      while(HAL_OK != HAL_UART_Transmit(&huart1, (uint8_t *)str3, strlen(str3), 5000));
      TIM3CH1_CAPTURE_STA=0;          //开启下一次捕获
      
    }
    
    HAL_Delay(100);
    
  }
  /* USER CODE END 3 */
}

实现效果:

具体代码实现可链接下载

(2条消息) HAL实现多个超声波测距(输入捕获实现)-C文档类资源-CSDN文库


 

以上是关于HAL实现多个超声波测距(输入捕获实现)的主要内容,如果未能解决你的问题,请参考以下文章

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

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

STM32学习(27)STM32实现超声波三种方法测距

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

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

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