打印
[其他ST产品]

一个定时器 四个channel复用映射 实现超声波四路测距

[复制链接]
4249|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
欢乐家园|  楼主 | 2023-8-27 12:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
闲来无事,转眼就要开学了,学长说超声波测距用多个定时器太low了,而且还不让用定时器计时高电平时间的方法,对此学长的建议,我虚心接受,并在他的帮助教学下,完成了一个定时器四个channal复用映射 实现超声波四路测距,极大的优化了超声波测距的方法。鉴于超声波模块的测距原理网上很多,在此不再赘述,网上关于超声波测距的方法也很多,建议阅读此文章。下面进入本篇正片。

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

void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */
    hcsr04_send();
  /* USER CODE END SysTick_IRQn 1 */
}//1ms 进一次


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

    delay_us(40);

    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET);
   
}


使用特权

评论回复
沙发
欢乐家园|  楼主 | 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 | 只看该作者
TIM_HandleTypeDef TIM3_Handler;      //¶¨Ê±Æ÷¾ä±ú 
//TIM_HandleTypeDef TIM4_Handler;      //¶¨Ê±Æ÷¾ä±ú
//ͨÓö¨Ê±Æ÷3Öжϳõʼ»¯
//arr£º×Ô¶¯ÖØ×°Öµ¡£
//psc£ºÊ±ÖÓÔ¤·ÖƵÊý
//¶¨Ê±Æ÷Òç³öʱ¼ä¼ÆËã·½·¨:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=¶¨Ê±Æ÷¹¤×÷ƵÂÊ,µ¥Î»:Mhz
//ÕâÀïʹÓõÄÊǶ¨Ê±Æ÷3!
void TIM3_Init(u16 arr,u16 psc)

使用特权

评论回复
地板
欢乐家园|  楼主 | 2023-8-27 13:00 | 只看该作者
{  
        TIM_IC_InitTypeDef TIM3_CH1Config;  
   
    TIM3_Handler.Instance=TIM3;                          //ͨÓö¨Ê±Æ÷3
    TIM3_Handler.Init.Prescaler=psc;                     //·ÖƵϵÊý
    TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;    //ÏòÉϼÆÊýÆ÷
    TIM3_Handler.Init.Period=arr;                        //×Ô¶¯×°ÔØÖµ
    TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//ʱÖÓ·ÖƵÒò×Ó
    HAL_TIM_IC_Init(&TIM3_Handler);                        //³õʼ»¯ÊäÈ벶»ñʱ»ù²ÎÊý
   
    TIM3_CH1Config.ICPolarity=TIM_ICPOLARITY_RISING;    //ÉÏÉýÑز¶»ñ
    TIM3_CH1Config.ICSelection=TIM_ICSELECTION_DIRECTTI;//Ó³Éäµ½TI1ÉÏ
    TIM3_CH1Config.ICPrescaler=TIM_ICPSC_DIV1;          //ÅäÖÃÊäÈë·ÖƵ£¬²»·ÖƵ
    TIM3_CH1Config.ICFilter=0;                          //ÅäÖÃÊäÈëÂ˲¨Æ÷£¬²»Â˲¨
    HAL_TIM_IC_ConfigChannel(&TIM3_Handler,&TIM3_CH1Config,TIM_CHANNEL_1);//ÅäÖÃTIM3ͨµÀ1
      HAL_TIM_IC_ConfigChannel(&TIM3_Handler,&TIM3_CH1Config,TIM_CHANNEL_2);//ÅäÖÃTIM3ͨµÀ2
      HAL_TIM_IC_ConfigChannel(&TIM3_Handler,&TIM3_CH1Config,TIM_CHANNEL_3);//ÅäÖÃTIM3ͨµÀ3
      HAL_TIM_IC_ConfigChannel(&TIM3_Handler,&TIM3_CH1Config,TIM_CHANNEL_4);//ÅäÖÃTIM3ͨµÀ4
   
    HAL_TIM_IC_Start_IT(&TIM3_Handler,TIM_CHANNEL_1);   //¿ªÆôTIM3µÄ²¶»ñͨµÀ1£¬²¢ÇÒ¿ªÆô²¶»ñÖжÏ
    HAL_TIM_IC_Start_IT(&TIM3_Handler,TIM_CHANNEL_2);   //¿ªÆôTIM3µÄ²¶»ñͨµÀ2£¬²¢ÇÒ¿ªÆô²¶»ñÖжϠ  
    HAL_TIM_IC_Start_IT(&TIM3_Handler,TIM_CHANNEL_3);   //¿ªÆôTIM3µÄ²¶»ñͨµÀ3£¬²¢ÇÒ¿ªÆô²¶»ñÖжÏ
        HAL_TIM_IC_Start_IT(&TIM3_Handler,TIM_CHANNEL_4);   //¿ªÆôTIM3µÄ²¶»ñͨµÀ4£¬²¢ÇÒ¿ªÆô²¶»ñÖжÏ


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

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

    HAL_TIM_IC_Start_IT(&TIM3_Handler,TIM_CHANNEL_1);   
    __HAL_TIM_ENABLE_IT(&TIM3_Handler,TIM_IT_UPDATE);   
}

使用特权

评论回复
5
欢乐家园|  楼主 | 2023-8-27 13:00 | 只看该作者
//¶¨Ê±Æ3µ×²ãÇý¶¯£¬Ê±ÖÓʹÄÜ£¬Òý½ÅÅäÖÃ
//´Ëº¯Êý»á±»HAL_TIM_IC_Init()µ÷ÓÃ
//htim:¶¨Ê±Æ÷3¾ä±ú
void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
{
    GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_TIM3_CLK_ENABLE();            //ʹÄÜTIM5ʱÖÓ
    __HAL_AFIO_REMAP_TIM3_ENABLE(); //TIM3 ???????????
        __HAL_RCC_GPIOC_CLK_ENABLE();                  //¿ªÆôGPIOBʱÖÓ
        //__HAL_RCC_AFIO_CLK_ENABLE(); //?????? IO ??
   
    GPIO_Initure.Pin=GPIO_PIN_6 | GPIO_PIN_7| GPIO_PIN_8| GPIO_PIN_9;           //PA0
    GPIO_Initure.Mode=GPIO_MODE_AF_INPUT;     //¸´ÓÃÍÆÍìÊäÈë
    GPIO_Initure.Pull=GPIO_PULLDOWN;        //ÏÂÀ­
    GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//¸ßËÙ
    HAL_GPIO_Init(GPIOC,&GPIO_Initure);
   
   
    HAL_NVIC_SetPriority(TIM3_IRQn,2,0);    //ÉèÖÃÖжÏÓÅÏȼ¶£¬ÇÀÕ¼ÓÅÏȼ¶2£¬×ÓÓÅÏȼ¶0
    HAL_NVIC_EnableIRQ(TIM3_IRQn);          //¿ªÆôITM5ÖжÏͨµÀ  
}

使用特权

评论回复
6
欢乐家园|  楼主 | 2023-8-27 13:01 | 只看该作者
//¶¨Ê±Æ÷3ÖжϷþÎñº¯Êý
void TIM3_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&TIM3_Handler);                //¶¨Ê±Æ÷¹²Óô¦Àíº¯Êý
}

使用特权

评论回复
7
欢乐家园|  楼主 | 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情况此时我们将定时器捕获方式改为下降沿捕获,此时才能得到回波信号的转换为低电平的时间计数点。

使用特权

评论回复
8
欢乐家园|  楼主 | 2023-8-27 13:02 | 只看该作者
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//²¶»ñÖжϷ¢ÉúʱִÐÐ
{
    if(htim == &TIM3_Handler)
    {
            
        /*****************³¬Éù²¨Í¨µÀ1 PC6********************************************/
        
        if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
        {
            if(!flag[1])
            {
                //HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET);
                pre_tim3_count[1] = __HAL_TIM_GetCounter(&TIM3_Handler);
                __HAL_TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_FALLING);
                flag[1] = !flag[1];
            }
            else
                {
                    sec_tim3_count[1] = __HAL_TIM_GetCounter(&TIM3_Handler);
                    __HAL_TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);
                    
                    if(pre_tim3_count[1] > pre_tim3_count[1])
                    {
                        scr04_count[1] = sec_tim3_count[1] - pre_tim3_count[1];
                    }
                    else
                    {
                        scr04_count[1] = 65535 - pre_tim3_count[1] + sec_tim3_count[1]+1;
                    }
                    flag[1] = !flag[1];
                }   
            }
        /*****************³¬Éù²¨Í¨µÀ1 PC6********************************************/        


            
            
        /*****************³¬Éù²¨Í¨µÀ2 PC7********************************************/            
        if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
        {
            
            if(!flag[2])
            {

                pre_tim3_count[2] = __HAL_TIM_GetCounter(&TIM3_Handler);
                __HAL_TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_FALLING);
                flag[2] = !flag[2];
            }
            else
            {
                sec_tim3_count[2] = __HAL_TIM_GetCounter(&TIM3_Handler);
                __HAL_TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_RISING);
               
                if(pre_tim3_count[2] > pre_tim3_count[2])
                {
                    scr04_count[2] = sec_tim3_count[2] - pre_tim3_count[2];
                }
                else
                {
                    scr04_count[2] = 65535 - pre_tim3_count[2] + sec_tim3_count[2]+1;
                }
                flag[2] = !flag[2];
            }   
        }        
        

使用特权

评论回复
9
欢乐家园|  楼主 | 2023-8-27 13:02 | 只看该作者
  if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3)
        {   
            if(!flag[3])
            {
                pre_tim3_count[3] = __HAL_TIM_GetCounter(&TIM3_Handler);
                __HAL_TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_3,TIM_INPUTCHANNELPOLARITY_FALLING);
                flag[3] = !flag[3];
            }
            else
            {
                sec_tim3_count[3] = __HAL_TIM_GetCounter(&TIM3_Handler);
                __HAL_TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_3,TIM_INPUTCHANNELPOLARITY_RISING);
               
                if(pre_tim3_count[3] > pre_tim3_count[3])
                {
                    scr04_count[3] = sec_tim3_count[3] - pre_tim3_count[3];
                }
                else
                {
                    scr04_count[3] = 65535 - pre_tim3_count[3] + sec_tim3_count[3]+1;
                }
                flag[3] = !flag[3];
            }   
            }        

使用特权

评论回复
10
欢乐家园|  楼主 | 2023-8-27 13:02 | 只看该作者
     
        if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4)
        {   
            if(!flag[4])
            {
                pre_tim3_count[4] = __HAL_TIM_GetCounter(&TIM3_Handler);
                __HAL_TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_4,TIM_INPUTCHANNELPOLARITY_FALLING);
                flag[4] = !flag[4];
            }
            else
            {
                sec_tim3_count[4] = __HAL_TIM_GetCounter(&TIM3_Handler);
                __HAL_TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_4,TIM_INPUTCHANNELPOLARITY_RISING);
               
                if(pre_tim3_count[4] > pre_tim3_count[4])
                {
                    scr04_count[4] = sec_tim3_count[4] - pre_tim3_count[4];
                }
                else
                {
                    scr04_count[4] = 65535 - pre_tim3_count[4] + sec_tim3_count[4]+1;
                }
                flag[4] = !flag[4];
            }   
            }        
        }
    }

使用特权

评论回复
11
欢乐家园|  楼主 | 2023-8-27 13:03 | 只看该作者
READ一下就完成啦。

void hcsr04_read()
{
//    if(TIM3CH1_CAPTURE_STA & 0x80)    //
//    {
//        time = TIM3CH1_CAPTURE_STA & 0x3F;    //
//        time *= 65536;        //
//        time += TIM3CH1_CAPTURE_VAL;    //
//        distance = time * 342.62*100/2000000;
//        LCD_ShowxNum(20, 250, distance, 20, 16, 0);
//        TIM3CH1_CAPTURE_STA = 0;
//    }
   
    distance[1] = (uint16_t)((scr04_count[1] * 342.62 * 100.0)/2000000.0);
//    LCD_ShowString(0, 235, 20, 20, 16, "ONE");
//    LCD_ShowxNum(40, 235, distance[1], 6, 16, 0);
   
    distance[2] = (uint16_t)((scr04_count[2] * 342.62 * 100.0)/2000000.0);
//    LCD_ShowString(0, 255, 20, 20, 16, "TWO");
//    LCD_ShowxNum(40, 255, distance[2], 6, 16, 0);   
   
    distance[3] = (uint16_t)((scr04_count[3] * 342.62 * 100.0)/2000000.0);
//    LCD_ShowString(0, 275, 20, 20, 16, "TRE");
//    LCD_ShowxNum(40, 275, distance[3], 6, 16, 0);   
   
    distance[4] = (uint16_t)((scr04_count[4] * 342.62 * 100.0)/2000000.0);
//    LCD_ShowString(0, 295, 20, 20, 16, "FOU");
//    LCD_ShowxNum(40, 295, distance[4], 6, 16, 0);   
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

102

主题

918

帖子

1

粉丝