×

STM32F103C8T6------定时器输入捕获模式(有别于外部中断)

zxjy辉 zxjy辉 发表于2022-10-14 16:08:48 浏览264 评论0

抢沙发发表评论

秋天唯美清新高清风景桌.jpeg

需要明确需要什么资源、是否复用、是否重映射

  1. 定时器的输入捕获模式

    1. 同样的只有基本定时器没有这个功能,通用定时器和高级定时器是有这个功能的

    2. 定时器的输入捕获模式,也就是检测外部的一个波形,检测的触发方式,是边沿检测,和外部中断一样的,但是看似差不多的功能,实际上差别还是挺大的

    3. 外部中断进行的边沿检测是没有滤波功能的,而采用定时器的输入捕获是有滤波功能,并且还可以对输入的波,进行分频,对(定时器产生的)采样信号也可以进行分频

    4. 而且在中断中,捕获也是对应了一个中断(TIM_IT_CC),溢出(更新)也同样也对应一个中断(TIM_IT_UpDate);外部中断对应的标志位则是对应的中断线(例如:EXTI_Line11)

  2. 作用

    1. 可以对外部信号进行较为精确的采集输出,可以用来作为采集心率、脉搏等等,某一动作的出发时间等等 ;例如检测按键按下了3s开始复位

  3. 实现流程

    1. 明确需要的资源(定时器、输入的引脚、是否复用、是否映射)

    2. 开启对应的时钟

    3. 引脚初始化

    4. 定时器初始化

    5. 定时器输入捕获模式初始化

    6. 定时器中断初始化

    7. 定时器的中断服务程序,要注意输入捕获的标志位是TIM_IT_CCX ( X代表通道几 )

  4. 代码

    1. #include "catch_channel.h"
      //这是一个用来测试定时器输入捕获的
      //目的:检测到按键按下的时间,并且再传口中打印出具体的时间
      //已知:按键K1是 PA11
      //需要用到的资源是:定时器1的通道4,这个是PA11的复用功能、定时器1的中断
      u16 Catch_Time = 0;    //这个是记录捕获时间的,每进一次中断就++,一次中断时0.1ms
      u16 Catch_Flag = 0;
      u16 Old_Catch_Time = 0;    //旧的捕获时间
      u16 New_Catch_Time = 0;    //新的捕获时间
      ///引脚初始化
      void Catch_GPIO_Init(){
          GPIO_InitTypeDef GPIO_InitStructrue;
          RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
          RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO, ENABLE );
          
        GPIO_InitStructrue.GPIO_Pin = GPIO_Pin_11;
          GPIO_InitStructrue.GPIO_Mode = GPIO_Mode_IPD;
          GPIO_InitStructrue.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_Init( GPIOA, &GPIO_InitStructrue );
          
          GPIO_SetBits( GPIOA, GPIO_Pin_11 );
          
      
          
      }
      ///定时器1初始化
      void Catch_TIM1_Init(){
        TIM_TimeBaseInitTypeDef TIM1_TimeBaseInitStructure;
          RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM1, ENABLE );
          
          TIM1_TimeBaseInitStructure.TIM_Period = 3599;  //APB1上的时钟最大是36M,此时一个脉冲也就是3600/36000000=0.0001s=0.1ms
          TIM1_TimeBaseInitStructure.TIM_Prescaler = 0;
          TIM1_TimeBaseInitStructure.TIM_ClockDivision =0;
          TIM1_TimeBaseInitStructure.TIM_CounterMode =TIM_CounterMode_Up;
          TIM_TimeBaseInit( TIM1, &TIM1_TimeBaseInitStructure );
              
      }
      ///定时器1模式初始化
      void Catch_TIM1_Mod_Init(){
          TIM_ICInitTypeDef TIM1_ICInitStructure;
          TIM1_ICInitStructure.TIM_Channel = TIM_Channel_4;
          TIM1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;     //设置输入捕获方式 下降沿捕获
          TIM1_ICInitStructure.TIM_ICPrescaler = 0;                         //设置输入捕获的分频系数
          TIM1_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;  //将捕获通道映射在定时器的通道上
          TIM1_ICInitStructure.TIM_ICFilter = 0x00;                         //配置滤波器,此时不配置滤波器
          TIM_ICInit( TIM1, &TIM1_ICInitStructure );
          
      
      }
      ///定时器1的中断
      void TIM1_NVIC_Init(){
        NVIC_InitTypeDef TIM1_NVIC_InitStructure;
          
          //NVIC_PriorityGroupConfig( NVIC_PriorityGroup_0 );
          TIM1_NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
          TIM1_NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
          TIM1_NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
          TIM1_NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
          NVIC_Init(&TIM1_NVIC_InitStructure);
          
          TIM_ITConfig( TIM1,TIM_IT_Update|TIM_IT_CC4, ENABLE );  //开启对应的中断
          TIM_Cmd( TIM1, ENABLE );
      }
      
      ///硬件初始化
      void Catch_Channel_Hard_Init(){
          
        Catch_GPIO_Init();
          Catch_TIM1_Init();
          Catch_TIM1_Mod_Init();
          TIM1_NVIC_Init();
      }
      
      ///定时器1的更新中断 ,在此中断中,实现了查看按键按下的时间
      void TIM1_UP_IRQHandler(){
          
        if(TIM_GetFlagStatus( TIM1, TIM_IT_CC4 ) == SET ){ //被置位了 ,第一次的时候,说明捕获到了(边沿)下降沿,也就是说按键按下了
              Catch_Flag = ~Catch_Flag;
              if( Catch_Flag == 0){
                  if( Catch_Time < 0xFFFF ){  //小于变量(16位)的最大值
                      New_Catch_Time = Catch_Time;  //记录下松开按键的时间
                  }else{
                  printf("太大了\r\n");
                  }
              
                  //将通道4的输入捕获方式重新设置为下降沿捕获,以便下一次的使用
                  TIM_OC4PolarityConfig( TIM1, TIM_ICPolarity_Falling );//
                  //清除标志
                  TIM_ClearFlag( TIM1,TIM_IT_Update|TIM_IT_CC4 );
                  //计算一下时间,打印出来
                  printf("时间:%d ms\r\n",(int)((New_Catch_Time - Old_Catch_Time)*0.1) );  //进入一次中断就是0.1ms
              }else{
                  printf("%d\r\n",Catch_Flag);
                  //记录下按键按下的时间
                  Catch_Time = 0;
                  Old_Catch_Time = Catch_Time;
                  
                  //设置上升沿触发,等待松开按键
                  TIM_OC4PolarityConfig( TIM1, TIM_ICPolarity_Rising);  //将通道4的输入捕获设置为上升沿捕获
                  //清除标志
                  TIM_ClearITPendingBit( TIM1,TIM_IT_Update|TIM_IT_CC4);
              }
              
              
              
              printf("kkk");
          TIM_ClearITPendingBit( TIM1,TIM_IT_CC4);
          }
          Catch_Time++;
      TIM_ClearITPendingBit( TIM1, TIM_IT_Update);
      
      }
#好好学习!

群贤毕至

访客