[其他ST产品] 一个定时器 四个channel复用映射 实现超声波四路测距

[复制链接]
 楼主| 欢乐家园 发表于 2023-8-27 12:59 | 显示全部楼层 |阅读模式
闲来无事,转眼就要开学了,学长说超声波测距用多个定时器太low了,而且还不让用定时器计时高电平时间的方法,对此学长的建议,我虚心接受,并在他的帮助教学下,完成了一个定时器四个channal复用映射 实现超声波四路测距,极大的优化了超声波测距的方法。鉴于超声波模块的测距原理网上很多,在此不再赘述,网上关于超声波测距的方法也很多,建议阅读此文章。下面进入本篇正片。

本超声波测距方式基于hal库,参考了正点原子的滴答定时器延时函数(非阻塞型延时),进行1ms一次的超声波测距发送触发trig函数(拉高拉低某一I/O电平 时间间隔为40us)

  1. void SysTick_Handler(void)
  2. {
  3.   /* USER CODE BEGIN SysTick_IRQn 0 */

  4.   /* USER CODE END SysTick_IRQn 0 */
  5.   HAL_IncTick();
  6.   /* USER CODE BEGIN SysTick_IRQn 1 */
  7.     hcsr04_send();
  8.   /* USER CODE END SysTick_IRQn 1 */
  9. }//1ms 进一次


  10. void hcsr04_send()
  11. {
  12.     //GPIOB->ODR|=1<<5;      //PB.5 Êä³ö¸ß
  13.     //GPIOB->ODR=0x00000010||GPIOB->IDR;
  14.     HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);

  15.     delay_us(40);

  16.     HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET);
  17.    
  18. }


 楼主| 欢乐家园 发表于 2023-8-27 12:59 | 显示全部楼层
至此,单片机已经能触发超声波模块的trig口,echo口已经能发送回波,我们需要测量超声波模块echo口的回波持续高电平时间。那么我们先完成一路超声波测回波时间,首先我们对于定时器3进行初始化,选择上升沿捕获,配置通道1,开启TIM3捕获通道1,使能中断更新,设置中断优先级,开启ITM3中断通道,使能TIM3时钟,复用推挽输入此channel对应的I/O,下拉,高速模式。打开定时器3中断服务函数。后来发现此通道的定时器捕获通道被LCD屏幕占用,果断选择I/O复用功能,查询数据手册得知STM32F103ZET6     TIM3四个捕获通道可全部复用到PC6至PC9。初始化至此完成。代码为配置四路复用I/O后的。
 楼主| 欢乐家园 发表于 2023-8-27 13:00 | 显示全部楼层
  1. TIM_HandleTypeDef TIM3_Handler;      //¶¨Ê±Æ÷¾ä±ú
  2. //TIM_HandleTypeDef TIM4_Handler;      //¶¨Ê±Æ÷¾ä±ú
  3. //ͨÓö¨Ê±Æ÷3Öжϳõʼ»¯
  4. //arr£º×Ô¶¯ÖØ×°Öµ¡£
  5. //psc£ºÊ±ÖÓÔ¤·ÖƵÊý
  6. //¶¨Ê±Æ÷Òç³öʱ¼ä¼ÆËã·½·¨:Tout=((arr+1)*(psc+1))/Ft us.
  7. //Ft=¶¨Ê±Æ÷¹¤×÷ƵÂÊ,µ¥Î»:Mhz
  8. //ÕâÀïʹÓõÄÊǶ¨Ê±Æ÷3!
  9. void TIM3_Init(u16 arr,u16 psc)
 楼主| 欢乐家园 发表于 2023-8-27 13:00 | 显示全部楼层
  1. {  
  2.         TIM_IC_InitTypeDef TIM3_CH1Config;  
  3.    
  4.     TIM3_Handler.Instance=TIM3;                          //ͨÓö¨Ê±Æ÷3
  5.     TIM3_Handler.Init.Prescaler=psc;                     //·ÖƵϵÊý
  6.     TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;    //ÏòÉϼÆÊýÆ÷
  7.     TIM3_Handler.Init.Period=arr;                        //×Ô¶¯×°ÔØÖµ
  8.     TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//ʱÖÓ·ÖÆµÒò×Ó
  9.     HAL_TIM_IC_Init(&TIM3_Handler);                        //³õʼ»¯ÊäÈë²¶»ñʱ»ù²ÎÊý
  10.    
  11.     TIM3_CH1Config.ICPolarity=TIM_ICPOLARITY_RISING;    //ÉÏÉýÑØ²¶»ñ
  12.     TIM3_CH1Config.ICSelection=TIM_ICSELECTION_DIRECTTI;//Ó³Éäµ½TI1ÉÏ
  13.     TIM3_CH1Config.ICPrescaler=TIM_ICPSC_DIV1;          //ÅäÖÃÊäÈë·ÖƵ£¬²»·ÖƵ
  14.     TIM3_CH1Config.ICFilter=0;                          //ÅäÖÃÊäÈëÂ˲¨Æ÷£¬²»Â˲¨
  15.     HAL_TIM_IC_ConfigChannel(&TIM3_Handler,&TIM3_CH1Config,TIM_CHANNEL_1);//ÅäÖÃTIM3ͨµÀ1
  16.       HAL_TIM_IC_ConfigChannel(&TIM3_Handler,&TIM3_CH1Config,TIM_CHANNEL_2);//ÅäÖÃTIM3ͨµÀ2
  17.       HAL_TIM_IC_ConfigChannel(&TIM3_Handler,&TIM3_CH1Config,TIM_CHANNEL_3);//ÅäÖÃTIM3ͨµÀ3
  18.       HAL_TIM_IC_ConfigChannel(&TIM3_Handler,&TIM3_CH1Config,TIM_CHANNEL_4);//ÅäÖÃTIM3ͨµÀ4
  19.    
  20.     HAL_TIM_IC_Start_IT(&TIM3_Handler,TIM_CHANNEL_1);   //¿ªÆôTIM3µÄ²¶»ñͨµÀ1£¬²¢ÇÒ¿ªÆô²¶»ñÖжÏ
  21.     HAL_TIM_IC_Start_IT(&TIM3_Handler,TIM_CHANNEL_2);   //¿ªÆôTIM3µÄ²¶»ñͨµÀ2£¬²¢ÇÒ¿ªÆô²¶»ñÖжϠ  
  22.     HAL_TIM_IC_Start_IT(&TIM3_Handler,TIM_CHANNEL_3);   //¿ªÆôTIM3µÄ²¶»ñͨµÀ3£¬²¢ÇÒ¿ªÆô²¶»ñÖжÏ
  23.         HAL_TIM_IC_Start_IT(&TIM3_Handler,TIM_CHANNEL_4);   //¿ªÆôTIM3µÄ²¶»ñͨµÀ4£¬²¢ÇÒ¿ªÆô²¶»ñÖжÏ


  24.     __HAL_TIM_ENABLE_IT(&TIM3_Handler,TIM_IT_UPDATE);   //ʹÄܸüÐÂÖжÏ
  25.    
  26.         HAL_NVIC_SetPriority(TIM3_IRQn,2,0);    //ÉèÖÃÖжÏÓÅÏȼ¶£¬ÇÀÕ¼ÓÅÏȼ¶2£¬×ÓÓÅÏȼ¶0
  27.     HAL_NVIC_EnableIRQ(TIM3_IRQn);          //¿ªÆôITM3ÖжÏͨµÀ  
  28.     __HAL_RCC_TIM3_CLK_ENABLE();            //ʹÄÜTIM3ʱÖÓ

  29.   TIM3_Init(65535,72-1);           //¶¨Ê±Æ÷3³õʼ»¯

  30.     HAL_TIM_IC_Start_IT(&TIM3_Handler,TIM_CHANNEL_1);   
  31.     __HAL_TIM_ENABLE_IT(&TIM3_Handler,TIM_IT_UPDATE);   
  32. }
 楼主| 欢乐家园 发表于 2023-8-27 13:00 | 显示全部楼层
  1. //¶¨Ê±Æ3µ×²ãÇý¶¯£¬Ê±ÖÓʹÄÜ£¬Òý½ÅÅäÖÃ
  2. //´Ëº¯Êý»á±»HAL_TIM_IC_Init()µ÷ÓÃ
  3. //htim:¶¨Ê±Æ÷3¾ä±ú
  4. void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
  5. {
  6.     GPIO_InitTypeDef GPIO_Initure;
  7.     __HAL_RCC_TIM3_CLK_ENABLE();            //ʹÄÜTIM5ʱÖÓ
  8.     __HAL_AFIO_REMAP_TIM3_ENABLE(); //TIM3 ???????????
  9.         __HAL_RCC_GPIOC_CLK_ENABLE();                  //¿ªÆôGPIOBʱÖÓ
  10.         //__HAL_RCC_AFIO_CLK_ENABLE(); //?????? IO ??
  11.    
  12.     GPIO_Initure.Pin=GPIO_PIN_6 | GPIO_PIN_7| GPIO_PIN_8| GPIO_PIN_9;           //PA0
  13.     GPIO_Initure.Mode=GPIO_MODE_AF_INPUT;     //¸´ÓÃÍÆÍìÊäÈë
  14.     GPIO_Initure.Pull=GPIO_PULLDOWN;        //ÏÂÀ­
  15.     GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//¸ßËÙ
  16.     HAL_GPIO_Init(GPIOC,&GPIO_Initure);
  17.    
  18.    
  19.     HAL_NVIC_SetPriority(TIM3_IRQn,2,0);    //ÉèÖÃÖжÏÓÅÏȼ¶£¬ÇÀÕ¼ÓÅÏȼ¶2£¬×ÓÓÅÏȼ¶0
  20.     HAL_NVIC_EnableIRQ(TIM3_IRQn);          //¿ªÆôITM5ÖжÏͨµÀ  
  21. }

 楼主| 欢乐家园 发表于 2023-8-27 13:01 | 显示全部楼层
  1. //¶¨Ê±Æ÷3ÖжϷþÎñº¯Êý
  2. void TIM3_IRQHandler(void)
  3. {
  4.     HAL_TIM_IRQHandler(&TIM3_Handler);                //¶¨Ê±Æ÷¹²Óô¦Àíº¯Êý
  5. }
 楼主| 欢乐家园 发表于 2023-8-27 13:01 | 显示全部楼层
定义四个变量,分别为pre_tim3_count[1],sec_tim3_count[1],flag[1],scr04_count[1],注意,此方法的核心是通过捕获上升沿与下降沿所触发的时刻计数值,记录这两个值,得到高电平时间,也就完成了测距。在初始化中,将捕获定时器的定时触发时间设置为65.5ms溢出,注意,由超声波模块的使用手册可以得知这个捕获时间也就是在trig收到高低电平时间后的时间至下一次trig收到高低电平的时间间隔,理想的一次超声波测距应该是在第一个if判断标志位里的操作,此时测量超声波模块返回高电平的时间恰好在我们定时器计数的65.5ms之内,注意,若在测量超声波模块高电平中的某一时刻定时器发生了溢出,计数清零,那么会出现这个if后的else情况此时我们将定时器捕获方式改为下降沿捕获,此时才能得到回波信号的转换为低电平的时间计数点。
 楼主| 欢乐家园 发表于 2023-8-27 13:02 | 显示全部楼层
  1. void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//²¶»ñÖжϷ¢ÉúʱִÐÐ
  2. {
  3.     if(htim == &TIM3_Handler)
  4.     {
  5.             
  6.         /*****************³¬Éù²¨Í¨µÀ1 PC6********************************************/
  7.         
  8.         if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
  9.         {
  10.             if(!flag[1])
  11.             {
  12.                 //HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET);
  13.                 pre_tim3_count[1] = __HAL_TIM_GetCounter(&TIM3_Handler);
  14.                 __HAL_TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_FALLING);
  15.                 flag[1] = !flag[1];
  16.             }
  17.             else
  18.                 {
  19.                     sec_tim3_count[1] = __HAL_TIM_GetCounter(&TIM3_Handler);
  20.                     __HAL_TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);
  21.                     
  22.                     if(pre_tim3_count[1] > pre_tim3_count[1])
  23.                     {
  24.                         scr04_count[1] = sec_tim3_count[1] - pre_tim3_count[1];
  25.                     }
  26.                     else
  27.                     {
  28.                         scr04_count[1] = 65535 - pre_tim3_count[1] + sec_tim3_count[1]+1;
  29.                     }
  30.                     flag[1] = !flag[1];
  31.                 }   
  32.             }
  33.         /*****************³¬Éù²¨Í¨µÀ1 PC6********************************************/        


  34.             
  35.             
  36.         /*****************³¬Éù²¨Í¨µÀ2 PC7********************************************/            
  37.         if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
  38.         {
  39.             
  40.             if(!flag[2])
  41.             {

  42.                 pre_tim3_count[2] = __HAL_TIM_GetCounter(&TIM3_Handler);
  43.                 __HAL_TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_FALLING);
  44.                 flag[2] = !flag[2];
  45.             }
  46.             else
  47.             {
  48.                 sec_tim3_count[2] = __HAL_TIM_GetCounter(&TIM3_Handler);
  49.                 __HAL_TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_RISING);
  50.                
  51.                 if(pre_tim3_count[2] > pre_tim3_count[2])
  52.                 {
  53.                     scr04_count[2] = sec_tim3_count[2] - pre_tim3_count[2];
  54.                 }
  55.                 else
  56.                 {
  57.                     scr04_count[2] = 65535 - pre_tim3_count[2] + sec_tim3_count[2]+1;
  58.                 }
  59.                 flag[2] = !flag[2];
  60.             }   
  61.         }        
  62.         
 楼主| 欢乐家园 发表于 2023-8-27 13:02 | 显示全部楼层
  1.   if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3)
  2.         {   
  3.             if(!flag[3])
  4.             {
  5.                 pre_tim3_count[3] = __HAL_TIM_GetCounter(&TIM3_Handler);
  6.                 __HAL_TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_3,TIM_INPUTCHANNELPOLARITY_FALLING);
  7.                 flag[3] = !flag[3];
  8.             }
  9.             else
  10.             {
  11.                 sec_tim3_count[3] = __HAL_TIM_GetCounter(&TIM3_Handler);
  12.                 __HAL_TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_3,TIM_INPUTCHANNELPOLARITY_RISING);
  13.                
  14.                 if(pre_tim3_count[3] > pre_tim3_count[3])
  15.                 {
  16.                     scr04_count[3] = sec_tim3_count[3] - pre_tim3_count[3];
  17.                 }
  18.                 else
  19.                 {
  20.                     scr04_count[3] = 65535 - pre_tim3_count[3] + sec_tim3_count[3]+1;
  21.                 }
  22.                 flag[3] = !flag[3];
  23.             }   
  24.             }        
 楼主| 欢乐家园 发表于 2023-8-27 13:02 | 显示全部楼层
  1.      
  2.         if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4)
  3.         {   
  4.             if(!flag[4])
  5.             {
  6.                 pre_tim3_count[4] = __HAL_TIM_GetCounter(&TIM3_Handler);
  7.                 __HAL_TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_4,TIM_INPUTCHANNELPOLARITY_FALLING);
  8.                 flag[4] = !flag[4];
  9.             }
  10.             else
  11.             {
  12.                 sec_tim3_count[4] = __HAL_TIM_GetCounter(&TIM3_Handler);
  13.                 __HAL_TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_4,TIM_INPUTCHANNELPOLARITY_RISING);
  14.                
  15.                 if(pre_tim3_count[4] > pre_tim3_count[4])
  16.                 {
  17.                     scr04_count[4] = sec_tim3_count[4] - pre_tim3_count[4];
  18.                 }
  19.                 else
  20.                 {
  21.                     scr04_count[4] = 65535 - pre_tim3_count[4] + sec_tim3_count[4]+1;
  22.                 }
  23.                 flag[4] = !flag[4];
  24.             }   
  25.             }        
  26.         }
  27.     }
 楼主| 欢乐家园 发表于 2023-8-27 13:03 | 显示全部楼层
  1. READ一下就完成啦。

  2. void hcsr04_read()
  3. {
  4. //    if(TIM3CH1_CAPTURE_STA & 0x80)    //
  5. //    {
  6. //        time = TIM3CH1_CAPTURE_STA & 0x3F;    //
  7. //        time *= 65536;        //
  8. //        time += TIM3CH1_CAPTURE_VAL;    //
  9. //        distance = time * 342.62*100/2000000;
  10. //        LCD_ShowxNum(20, 250, distance, 20, 16, 0);
  11. //        TIM3CH1_CAPTURE_STA = 0;
  12. //    }
  13.    
  14.     distance[1] = (uint16_t)((scr04_count[1] * 342.62 * 100.0)/2000000.0);
  15. //    LCD_ShowString(0, 235, 20, 20, 16, "ONE");
  16. //    LCD_ShowxNum(40, 235, distance[1], 6, 16, 0);
  17.    
  18.     distance[2] = (uint16_t)((scr04_count[2] * 342.62 * 100.0)/2000000.0);
  19. //    LCD_ShowString(0, 255, 20, 20, 16, "TWO");
  20. //    LCD_ShowxNum(40, 255, distance[2], 6, 16, 0);   
  21.    
  22.     distance[3] = (uint16_t)((scr04_count[3] * 342.62 * 100.0)/2000000.0);
  23. //    LCD_ShowString(0, 275, 20, 20, 16, "TRE");
  24. //    LCD_ShowxNum(40, 275, distance[3], 6, 16, 0);   
  25.    
  26.     distance[4] = (uint16_t)((scr04_count[4] * 342.62 * 100.0)/2000000.0);
  27. //    LCD_ShowString(0, 295, 20, 20, 16, "FOU");
  28. //    LCD_ShowxNum(40, 295, distance[4], 6, 16, 0);   
  29. }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

113

主题

1029

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部

113

主题

1029

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部