定时器输入捕获模式(stm32)

备注:博文仅仅是记录个人笔记,加深理解

说起定时器,我们可能都认为都是简单的定时功能.但说句实在话,想把定时器学的透彻还是需要发些时间的.
stm32f4的定时器的标准库都有3300多行,可见其实也是很复杂的.

输入捕获功能相对比较简单,一般用来计算频率.它的过程是这样的,

  • 当定时器通道捕获到预先配置的边沿,则会把当前计数器的值,锁存到对应通道的CCR寄存器中,此时锁存的值记为value1.
  • 当再次捕获到对应的边沿,此时锁存到CCR寄存器中的值记为value2.

当计数器没有发生溢出时,(value2-value1)即为外部波形一个周期中计数器增加或减少的计数器值. 如果计数器发生过溢出,则实际的value2 为 (计数器溢出次数 * 定时器时钟) - value1 + value2. 如果定时器的时钟为clk,那么 clk/(value2-value1) 即为外部信号频率.

如下图T2-T1就是一个周期的时间.
在这里插入图片描述
代码分析:
定时器时钟为60K. 从原理上这个可以用来测量编码器的脉冲数量,进而计算出瞬时速度

#define TIM1_CLK 60000

int inputCaptureMain(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    uint16_t PrescalerValue = 0;
    
   /* 这里是定时器gpio的初始化*/
  TIM_Config();

  /*base config*/
  /* Compute the prescaler value */
  /* 默认APB2时钟是84M,所以这里定时器TIM1时钟为6M*/
  PrescalerValue = (uint16_t) (SystemCoreClock / TIM1_CLK) - 1;

  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 60000; //定时器为1s发生溢出
  TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

  /*下面能看到定时器的捕获边沿为上升沿*/
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //捕获上升沿
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  TIM_ICInitStructure.TIM_ICFilter = 0x0;

  TIM_ICInit(TIM1, &TIM_ICInitStructure);
  
  /* Enable the CC1 Interrupt Request */
  TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE);
  TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
  
    /* TIM enable counter */
  TIM_Cmd(TIM1, ENABLE);
}

/*记录计数器溢出次数*/
void TIM1_UP_IRQ(void)
{ 
  if(TIM_GetITStatus(TIM1, TIM_IT_Update) == SET) 
  {
      overFlowCount++;
      TIM_ClearFlag(TIM1, TIM_FLAG_Update);
  }
}

void TIM1_CC_IRQ(void)
{ 
  if(TIM_GetITStatus(TIM1, TIM_IT_CC1) == SET) 
  {
    /* Clear TIM1 Capture compare interrupt pending bit */
    TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);
    TIM_ClearFlag(TIM1, TIM_IT_CC1);
      
    if(uhCaptureNumber == 0)
    {
      /* 捕获第一次的计数器的值 */
      uhIC3ReadValue1 = TIM_GetCapture1(TIM1);
      uhCaptureNumber = 1;
      overFlowCount = 0;
    }
    else if(uhCaptureNumber == 1)
    {
      /* 捕获第二次计数器的值 */
      uhIC3ReadValue2 = TIM_GetCapture1(TIM1); 
      
      if (overFlowCount > 0)
      {
          uhIC3ReadValue2 = (overFlowCount*TIM1_CLK) - uhIC3ReadValue1 + uhIC3ReadValue2;
      }
      /* 计算value2和value1的差值,即过去了多长时间*/
      if (uhIC3ReadValue2 > uhIC3ReadValue1)
      {
        uwCapture = (uhIC3ReadValue2 - uhIC3ReadValue1); 
      }
      else if (uhIC3ReadValue2 < uhIC3ReadValue1)
      {
        uwCapture = ((0xFFFF - uhIC3ReadValue1) + uhIC3ReadValue2); 
      }
      else
      {
        uwCapture = 0;
      }
      /* 计算外部时钟的周期*/ 
      uwTIM1Freq = (uint32_t) TIM1_CLK / uwCapture;
      uhCaptureNumber = 0;
      printf("freq:%d,val2:%d,val1:%d\n", uwTIM1Freq, uhIC3ReadValue2, uhIC3ReadValue1);
    }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值