TIM IC(定时器输入捕获)

输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中。
可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数。
每个高级定时器和通用定时器都拥有4个输入捕获通道。

  1. 可配置为PWMI模式,同时测量频率和占空比。
  2. 可配合主从触发模式,实现硬件全自动测量。

实现硬件全自动测量可避免频繁进入中断函数,节省CPU资源。
测频法:

  1. 计次:待测信号在闸门时间内经过的周期数。—— 闸门时间内捕获波形上升沿个数,较简单。
  2. 适用于高频信号,在闸门时间内越多周期经过,精度越高。
  3. 更新慢,更新时间取决于闸门时间。测出的是闸门时间内的平均频率。相当于自带滤波。\、

测周法:

  1. 计次:在待测信号一个周期内经过的标准周期个数。—— 下面主要讨论这个方法。
  2. 适用于低频信号,在待测波形一个周期内经过的标准周期越多,精度越高。
  3. 更新快,更新时间取决于待测波形周期。

“+-1误差”:对于测频法,闸门时间已到,最后一个波形没走完;对于测周法,周期已到,标准波形没走完;这都会产生正负一误差。
通用定时器ch1、ch2结构图:

例程 - 测PWM频率和占空比

采用TIM2生成PWM信号,TIM3输入捕获,用PWMI模式测定PWM的频率和占空比。此处不列出生成PWM信号的代码,可以参考:PWM控制SG90舵机,生成频率1kHz,占空比千分之500的PWM信号。

// main.c

#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "Delay.h"
#include "PWM.h"
#include "InputCapture.h"

int main(void)
{
    OLED_Init();
    PWM_Init();
    InputCapture_Init();
    
    PWM_Set_PSC(72-1); // Freq = 72M / (PSC + 1) / 1000,PSC=72-1,Freq = 1KHz
    PWM_Set_CCR1(500); // Duty = CCR / 1000
    OLED_ShowString(1, 1, "Freq:00000Hz");
    OLED_ShowString(2, 1, "Duty:0000/1000");
    
    while(1)
    {
        OLED_ShowNum(1, 6, InputCapture_Get_Freq(), 5);
        OLED_ShowNum(2, 6, InputCapture_Get_Duty(), 4);
        Delay_ms(200);
    }
}
// InputCapture.c

#include "stm32f10x.h"                  // Device header

void InputCapture_Init(void)
{
    // 时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    TIM_InternalClockConfig(TIM3);
    // GPIO - TIM3 CH1 - PA6
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    // 时基单元
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStrucure;
    TIM_TimeBaseInitStrucure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStrucure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStrucure.TIM_Period = 65535; // ARR
    TIM_TimeBaseInitStrucure.TIM_Prescaler = 72 - 1; // PSC 决定测周法的标准频率f。PSC=72-1, f=1M
    // 关于测频率上下限和修改,看江科大视频34:00处
    TIM_TimeBaseInitStrucure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStrucure);
    // 输入捕获单元
    TIM_ICInitTypeDef TIM_ICInitStructure;
    TIM_ICStructInit(&TIM_ICInitStructure);
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
    TIM_ICInitStructure.TIM_ICFilter = 0xF;
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
    TIM_PWMIConfig(TIM3, &TIM_ICInitStructure); // PWMI模式,江科大视频28:49处
    // 主从触发模式 - 触发源和从模式
    TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
    TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
    // 启动定时器
    TIM_Cmd(TIM3, ENABLE);
}

uint32_t InputCapture_Get_Freq(void) // 读取频率,单位赫兹
{
    uint32_t n = TIM_GetCapture1(TIM3);
    return 1000000 / n;
}

uint16_t InputCapture_Get_Duty(void) // 读取占空比,0-1000,单位千分之
{
    return TIM_GetCapture2(TIM3) * 1000 / TIM_GetCapture1(TIM3);
}