STM32学习笔记9:TIM输入捕获

芯片型号:STM32F103RC

软件开发包:标准外设库

一、输入捕获简介

  • IC(Input Capture)输入捕获
  • 输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前 CNT 的值将被锁存到 CCR 中,可用于测量 PWM 波形的频率、占空比、脉冲间隔、电平持续时间等参数
  • 每个高级定时器和通用定时器都拥有 4 个输入捕获通道
  • 可配置为 PWMI 模式,同时测量频率和占空比
  • 可配合主从触发模式,实现硬件全自动测量

输入捕获框图

从引脚进来,有一个三输入的异或门连接在通道 1、2、3 端口。异或门的执行逻辑是当三个输入引脚中的任何一个电平翻转时,输出引脚就发生一次电平翻转。之后输出通过数据选择器,到达输入捕获通道 1 ,数据选择器如果选择上面的,那么输入捕获通道 1 的输入,就是 3 个引脚的异或值;如果选择下面的,那异或门就没有作用,4 个通道各用各的引脚。

设计这个异或门主要是为三项无刷电机服务的,无刷电机有三个霍尔传感器检测转子的位置,可以根据转子的位置进行换相,有了这个异或门,就可以在前 3 个通道上接上无刷电机的霍尔传感器,然后这人定时器就作为无刷电机的接口定时器,去驱动换相电路工作。

输入信号继续,来到了输入滤波器和边沿检测器。输入滤波器可以对信号进行滤波,避免一些高频的毛刺信号误触发。边沿检测其可以选择高电平触发或者低电平出触发,当出现指定的电平时,边沿检测电路就会触发后续电路执行动作。

另外这里,其实设计了两套滤波和边沿检测电路。第一套电路,经过滤波和极性选择,得到 TI1FP1(TI1 Filter Polarity 1),输入给通道 1 的后续电路;第二套电路,经过另一个滤波和极性选择,得到 TI1FP2(TI1 Filter Polarity 2),输入个下面通道 2 的后续电路。

同理,下面 TI2 信号进来,也经过两套滤波和极性选择,得到 TI2FP1 和 TI2FP2 。其中, TI2FP1 输入给上面通道 1 的后续电路,TI2FP2 输入给通道 2 的后续电路。所以,对于 TI1 和 TI2 信号,经过输入滤波器和边沿检测器后,可以各走各的,也可以交叉。进行交叉连接的目的主要有两个:第一,可以灵活切换后续捕获电路的输入;第二,可以把一个引脚的输入同时映射到两个捕获单元,这也是PWMI 模式的经典结构。

输入信号进行滤波和极性选择后,就来到了预分频器。预分频器,每个通道各有一个,可以选择对前面的信号进行分频,分频后的触发信号就可以触发捕获电路进行工作了。每来一个触发信号,CNT 的值,就会向 CCR 转运一次,转运的同时会发生一个捕获事件,这个事件会在状态寄存器置标志位,同时也可以产生中断。如果需要在捕获的瞬间处理一些事情的话,就可以开启这个捕获中断。

二、频率测量

频率测量

2.1 测频法

在闸门时间 T 内,对上升沿计次,得到 N ,则频率
f x = N / T f_x=N / T fx=N/T
频率简单理解就是 1s 内出现多少个重复的周期,单位为 Hz 。所以在 1s 的闸门时间内对上升沿计次,计次多少,频率就是多少 Hz 。

特点:适用于高频信号,测量结果更新较慢,数值相对稳定。测频法测量的是在闸门时间内的多个周期,所以它自带一个均值滤波,如果再闸门时间内波形频率有变化,得到的其实是这段时间的平均频率。如果闸门时间选为 1s ,那么每隔 1s 才能得到一次结果,所以测频法结果更新慢,测量结果是一段时间的平均值,值比较平滑。

测频法具体实现方法:每来一个上升沿计次 +1 ,同时再用一个定时器定时 1s 中断,在中段里,每隔 1s 取一次计次值,同时清零计次,为下一次做准备。每次读取的计次值就是频率。

2.2 测周法

两个上升沿内,以标准频率 fc 计次,得到 N ,则频率
f x = f c / N f_x=f_c / N fx=fc/N
测周法就是根据周期的倒数就是频率,测出一个周期的时间,再取个倒数,得到频率。

实际操作中,通过捕获心信号的两个上升沿,然后测量一下两者持续的时间来实现。但实际上,并没有一个精度足够的秒表来测量时间,所以依然是使用定时器计次的方式。使用一个已知的标准频率 f c f_c fc 的计次时钟来驱动计数器,从一个上升沿开始计,计数器从 0 开始,一直计到下一个上升沿为止,计一个数的时间是 1 / f c 1/f_c 1/fc ,计 N 个数,时间就是 N / f c N/f_c N/fc ,再取个倒数就得到了频率。

特点:适用于低频信号,测量结果更新较快,数据跳变也非常快。测周法只测量一个周期,就能出一次结果,所以出结果的速度取决于待测信号的频率。一般而言,待测信号都是几百几千 Hz ,所以测周法结果更新更快。但是测周法只测量一个周期,所以结果会受噪声的影响,波动比较大。

2.3 中界频率

测频法与测周法误差相等的频率点
f m = ( f c / T ) f_m=\sqrt{(f_c / T)} fm=(fc/T)
为了确定是使用测频法还是测周法,引入了中界频率的概念。

在使用测频法和测周法时,计次数量 N 越大,相对误差越小。因为在这些方法中,计次可能存在正负 1 误差。

测频法:在闸门时间内,并不是每个周期信号都是完整的。比如在最后时间里,可能就有一个周期刚出现一半,闸门时间就到了,那这只有半个周期。因为计次只有整数,只能舍弃掉或者当作一整个周期来看,那么就会导致多计一个数或少计一个数。

测周法:标准频率 f c f_c fc 计次,在最后时刻,有可能一个数刚数到一半,计数就结束了,那这半个数也只能舍弃或者按一整个数来算了。

所以,正负 1 误差是这两中方法固有的误差,要想减少正负 1 误差的影响,就要尽量多计一些数。

当有一个频率,测频法和测周法计数的 N 相同,就说明误差相同,这个频率就是中界频率。当待测频率小于中界频率时,测周法误差更小,选用测周法更合适;当待测频率大于中界频率时,测频法误差更小,选用测频法更合适。

三、输入捕获通道

输入捕获通道

引脚进来,先经过一个滤波器。滤波器的输入是 TI1 ,输出的 TI1F 就是滤波后的信号, f D T S f_{DTS} fDTS 是滤波器的采样时钟来源,CCMR1 寄存器的 ICF 位可以控制滤波器参数。滤波之后的信号通过边沿检测器捕获上升沿或者下降沿,用 CCER 寄存器里的 CC1P 位,就可以选择极性了。最终得到 TI1FP1 触发信号,通过数据选择器进入通道 1 后续的捕获电路,CCMR1 寄存器的 CC1S 位可以对数据进行选择,ICPS 位可以配置分频器的分频系数。最后 CC1E 位控制输出使能或失能,如果使能了输出,输入端产生指定边沿信号,经过层层电路得到 IC1PS 信号,就可以让 CNT 的值转运到 CCR 中。

每捕获一次 CCR 的值都要把 CNT 清零一下,以便下一次的捕获,在这里硬件电路就可以在捕获之后自动完成 CNT 的清零工作。TI1FP1 信号和 TI1 的边沿信号 TI1F_ED 都可以通向从模式控制器,而从模式电路里面就有电路可以自动完成 CNT 的清零。

四、输入捕获基本结构(测周法)

输入捕获基本结构

在这个结构里只使用了一个通道,所以只能测量频率。

先配置时基单元,启动定时器,CNT 就会在预分频之后的时钟驱动下不断自增。其中,CNT 就是测周法中用于计数计时的东西,经过预分频之后的用于驱动 CNT 的时钟的频率就是标准频率 f c f_c fc

然后下面输入捕获通道 1 的 GPIO 口,输入一个如左上角的方波信号,经过滤波器和边沿检测,选择 TI1FP1 为上升沿触发,之后输入选择直连的通道,分频器选择不分频。当 TI1FP1 出现上升沿之后,CNT 的当前计数值转运到 CCR1 里。同时触发源选择,选中 TI1FP1 为触发信号,从模式选择复位操作,这样 TI1FP1 的上升沿也可以触发 CNT 的清零。

注意:

  1. CNT 的值是有上限的,最大为65535,如果信号频率太低,CNT 的值可能会溢出;
  2. 从模式的触发源选择,只有 TI1FP1 和 TI2FP2 ,没有 TI3 和 TI4 的信号,所以只有通道 1 和通道 2 可以使用从模式自动清零 CNT。对于通道 3 和 通道 4 就只能开启捕获中断,在中断中进行清零操作,这样做会导致程序频繁进入中断,比较消耗软件资源。

五、PWMI 基本结构

PWMI基本结构

PWMI 模式使用两个通道同时捕获一个引脚,可以同时测量 PWM 的频率和占空比。

基本原理同普通模式,首先,TI1FP1 配置上升沿触发,触发捕获和清零 CNT。同时,再来一个 TI1FP2 ,配置为下降沿触发,通过交叉通道去触发通道 2 的捕获单元。

根据左上角的图,最开始上升沿触发 CCR1 捕获,同时清零 CNT,之后 CNT 一直 ++ 。然后,在下降沿触发 CCR2 捕获,这时的 CCR2 的值高电平的计数值。CCR2 捕获并不触发 CNT 清零,所以 CNT 继续 ++,直到下一次上升沿,触发 CCR1 捕获,清零 CNT。这样,在一整个周期中,CCR1 就是一整个周期的计数值,CCR2 就是高电平的计数值,CCR2/CCR1 就是占空比。

六、输入捕获结构体详解

输入捕获结构体 TIM_ICInitTypeDef 用于输入捕获模式,与 TIM_ICInit 函数配合使用完成定时器输入通道初始化配置。如果使用 PWM 输入模式需要与 TIM_PWMIConfig 函数配合使用完成定时器输入通道初始化配置 。

typedef struct {
    uint16_t TIM_Channel; 		// 输入通道选择
    uint16_t TIM_ICPolarity; 	// 输入捕获触发选择
    uint16_t TIM_ICSelection; 	// 输入捕获选择
    uint16_t TIM_ICPrescaler; 	// 输入捕获预分频器
    uint16_t TIM_ICFilter; 		// 输入捕获滤波器
} TIM_ICInitTypeDef;
  1. TIM_Channel:捕获通道 ICx 选择,可选 TIM_Channel_1、 TIM_Channel_2、 TIM_Channel_3 或TIM_Channel_4 四个通道。它设定 CCMRx 寄存器 CCxS 位的值。
  2. TIM_ICPolarity:输入捕获边沿触发选择,可选上升沿触发、下降沿触发或边沿跳变触发。它设定 CCER 寄存器 CCxP 位和 CCxNP 位的值。
  3. TIM_ICSelection:输入通道选择,捕获通道 ICx 的信号可来自三个输入通道,分别为TIM_ICSelection_DirectTI、 TIM_ICSelection_IndirectTI 或 TIM_ICSelection_TRC。它设定 CCRMx 寄存器的 CCxS[1:0] 位的值。
  4. TIM_ICPrescaler:输入捕获通道预分频器,可设置 1、 2、 4、 8 分频,它设定 CCMRx 寄存器的 ICxPSC[1:0] 位的值。
  5. TIM_ICFilter:输入捕获滤波器设置,可选设置 0x0 至 0x0F。它设定 CCMRx 寄存器 ICxF[3:0]位的值。一般我们不使用滤波器,即设置为 0。

七、编程要点

7.1 测周法测频率

  1. 定时器用到的 GPIO 初始化,把 GPIO 配置为输入模式,一般选择上拉输入或浮空输入模式;
  2. 定时器时基结构体初始化;
  3. 定时器输入捕获结构体初始化;
  4. 选择从模式的触发源;
    使用函数TIM_SelectInputTrigger
  5. 选择触发之后执行 Reset 操作;
    使用函数TIM_SelectSlaveMode
  6. 使能定时器。

7.2 PWMI 模式测频率和占空比

和测周法测频率相比,定时器输入捕获结构体初始化稍有不同。

在初始化输入捕获结构体时,不再使用TIM_ICInit,而是使用 TIM_PWMIConfig

使用这个函数,只需要传入一个通道的参数就行了,在函数里,会自动把剩下的一个通道初始化成相反的配置。比如,如果传入的是通道1 直连、上升沿,那函数里就将通道 2 配置为交叉、下降沿;反之,亦然。

注意:这个函数只支持通道 1 和 通道 2。

八、举例

8.1 测周法测频率

选择内部时钟为 TIM3 的时钟源,预分频值设为 71,则计数器的驱动时钟的频率为72M/72=1MHz,即标准频率为1MHz。

  1. 配置 GPIO
void IC_CPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    // 配置GPIOA0为上拉输入
    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);
}
  1. 配置 TIM
void IC_TIM_Config(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_ICInitTypeDef TIM_ICInitStructure;

    // 使能TIM3时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    // 配置TIM3时基单元
    TIM_TimeBaseStructure.TIM_Period = 65536 - 1;               // 满量程计数
    TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1;               // 标准频率为72M/72=1MHz
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;     // 不分频
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;                // 选择通道1
    TIM_ICInitStructure.TIM_ICFilter = 0;                           // 不滤波
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;     // 上升沿触发
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;           // 不分频
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; // 选择直连通道
    TIM_ICInit(TIM3, &TIM_ICInitStructure);							

    TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);        // 选择从模式触发源为TI1FP1
    TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);     // 选择从模式为Reset

    TIM_Cmd(TIM3, ENABLE);
}
  1. 测量频率

为了得到待测信号的频率,我们需要取得 TIM3 的 CCR1 的值,用到函数TIM_GetCapture1

uint32_t IC_GetFreq(void)
{
    return 1000000 / TIM_GetCapture1(TIM3);
}

8.2 PWMI 模式测频率和占空比

在测周法测频率的基础上,只需要将 TIM_ICInit(TIM3, &TIM_ICInitStructure) 改为 TIM_PWMIConfig(TIM3, &TIM_ICInitStructure)

测量占空比

uint32_t PWMI_GetDuty(void)
{
    return 100 * TIM_GetCapture2(TIM3) / (TIM_GetCapture1(TIM3);
}

参考视频源于B站up主: 野火科技、江协科技
参考文档:《STM32库开发实战指南——基于野火MINI开发板》

  • 36
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值