输入捕获可以对输入的信号的上升沿、下降沿或者双边沿进行捕获,常用的有测量输入信号的脉
宽,和测量 PWM 输入信号的频率和占空比这两种。
输入捕获的大概的原理
当捕获到信号的跳变沿的时候,把计数器 CNT 的值锁存到捕获寄 存器 CCR 中,把前后两次捕获到的 CCR 寄存器中的值相减,就可以算出脉宽或者频率。如果捕获的脉宽的时间长度超过你的捕获定时器的周期,就会发生溢出,这个我们需要做额外的处理。
输入通道
需要被测量的信号从定时器的外部引脚 TIMx_CH1/2/3/4 进入,通常叫 TI1/2/3/4 ,在后面的捕获讲解中对于要被测量的信号我们都以 TIx 为标准叫法。
输入滤波器和边沿检测器
当输入的信号存在高频干扰的时候,我们需要对输入信号进行滤波,即进行重新采样,根据采样定律,采样的频率必须大于等于两倍的输入信号。比如输入的信号为 1M ,又存在高频的信号干
扰,那么此时就很有必要进行滤波,我们可以设置采样频率为 2M ,这样可以在保证采样到有效
信号的基础上把高于 2M 的高频干扰信号过滤掉。
滤波器的配置由 CR1 寄存器的位 CKD[1:0] 和 CCMR1/2 的位 ICxF[3:0] 控制。从 ICxF 位的描述
可知,采样频率 f SAMPLE 可以由 f CK_INT 和 f DTS 分频后的时钟提供,其中是 f CK_INT 内部时钟, f DTS
是 f CK_INT 经过分频后得到的频率,分频因子由 CKD[1:0] 决定,可以是不分频, 2 分频或者是 4
分频。
边沿检测器用来设置信号在捕获的时候是什么边沿有效,可以是上升沿,下降沿,或者是双边沿,
具体的由 CCER 寄存器的位 CCxP 和 CCxNP 决定。
捕获通道
捕获通道就是图中的 IC1/2/3/4 ,每个捕获通道都有相对应的捕获寄存器 CCR1/2/3/4 ,当发生捕获
的时候,计数器 CNT 的值就会被锁存到捕获寄存器中。
这里我们要搞清楚输入通道和捕获通道的区别,输入通道是用来输入信号的,捕获通道是用来捕
获输入信号的通道,一个输入通道的信号可以同时输入给两个捕获通道。比如输入通道 TI1 的信
号经过滤波边沿检测器之后的 TI1FP1 和 TI1FP2 可以进入到捕获通道 IC1 和 IC2 ,其实这就是我
们后面要讲的 PWM 输入捕获,只有一路输入信号( TI1 )却占用了两个捕获通道( IC1 和 IC2 )。
当只需要测量输入信号的脉宽时候,用一个捕获通道即可。输入通道和捕获通道的映射关系具体
由寄存器 CCMRx 的位 CCxS[1:0] 配置。
预分频器
ICx 的输出信号会经过一个预分频器,用于决定发生多少个事件时进行一次捕获。具体的由寄存
器 CCMRx 的位 ICxPSC 配置,如果希望捕获信号的每一个边沿,则不分频。
捕获寄存器
经过预分频器的信号 ICxPS 是最终被捕获的信号,当发生捕获时(第一次),计数器 CNT 的值会
被锁存到捕获寄存器 CCR 中,还会产生 CCxI 中断,相应的中断位 CCxIF (在 SR 寄存器中)会
被置位,通过软件或者读取 CCR 中的值可以将 CCxIF 清 0 。如果发生第二次捕获(即重复捕获:
CCR 寄存器中已捕获到计数器值且 CCxIF 标志已置 1 ),则捕获溢出标志位 CCxOF (在 SR 寄存器中)会被置位,CCxOF 只能通过软件清零。
输出比较
输出比较就是通过定时器的外部引脚对外输出控制信号,有冻结、将通道 X ( x=1,2,3,4 )设置为
匹配时输出有效电平、将通道 X 设置为匹配时输出无效电平、翻转、强制变为无效电平、强制变
为有效电平、 PWM1 和 PWM2 这八种模式,具体使用哪种模式由寄存器 CCMRx 的位 OCxM[2:0]
配置。其中 PWM 模式是输出比较中的特例,使用的也最多
比较寄存器
当计数器 CNT 的值跟比较寄存器 CCR 的值相等的时候,输出参考信号 OCxREF 的信号的极性
就会改变,其中 OCxREF=1 (高电平)称之为有效电平, OCxREF=0 (低电平)称之为无效电平,
并且会产生比较中断 CCxI ,相应的标志位 CCxIF ( SR 寄存器中)会置位。然后 OCxREF 再经过
一系列的控制之后就成为真正的输出信号 OCx/OCxN
死区发生器
在生成的参考波形 OCxREF 的基础上,可以插入死区时间,用于生成两路互补的输出信号 OCx
和 OCxN ,死区时间的大小具体由 BDTR 寄存器的位 DTG[7:0] 配置。死区时间的大小必须根据与
输出信号相连接的器件及其特性来调整。下面我们简单举例说明下带死区的 PWM 信号的应用,
我们以一个板桥驱动电路为例。
在这个半桥驱动电路中, Q1 导通, Q2 截止,此时我想让 Q1 截止 Q2 导通,肯定是要先让 Q1 截
止一段时间之后,再等一段时间才让 Q2 导通,那么这段等待的时间就称为死区时间,因为 Q1
关闭需要时间(由 MOS 管的工艺决定)。如果 Q1 关闭之后,马上打开 Q2 ,那么此时一段时间
内相当于 Q1 和 Q2 都导通了,这样电路会短路。
图 带死区插入的互补输出 是针对上面的半桥驱动电路而画的带死区插入的 PWM 信号,图中的死区时间要根据 MOS 管的工艺来调节。
输入捕获应用
输入捕获一般应用在两个方面,一个方面是脉冲跳变沿时间测量,另一方面是 PWM 输入测量。
测量脉宽或者频率
测量频率
当捕获通道 TIx 上出现上升沿时,发生第一次捕获,计数器 CNT 的值会被锁存到捕获寄存器 CCR
中,而且还会进入捕获中断,在中断服务程序中记录一次捕获(可以用一个标志变量来记录),并
把捕获寄存器中的值读取到 value1 中。当出现第二次上升沿时,发生第二次捕获,计数器 CNT
的值会再次被锁存到捕获寄存器 CCR 中,并再次进入捕获中断,在捕获中断中,把捕获寄存器
的值读取到 value3 中,并清除捕获记录标志。利用 value3 和 value1 的差值我们就可以算出信号的 周期(频率)。
测量脉宽
当捕获通道 TIx 上出现上升沿时,发生第一次捕获,计数器 CNT 的值会被锁存到捕获寄存器 CCR
中,而且还会进入捕获中断,在中断服务程序中记录一次捕获(可以用一个标志变量来记录),并
把捕获寄存器中的值读取到 value1 中。然后把捕获边沿改变为下降沿捕获,目的是捕获后面的
下降沿。当下降沿到来的时候,发生第二次捕获,计数器 CNT 的值会再次被锁存到捕获寄存器
CCR 中,并再次进入捕获中断,在捕获中断中,把捕获寄存器的值读取到 value3 中,并清除捕获
记录标志。然后把捕获边沿设置为上升沿捕获。
在测量脉宽过程中需要来回的切换捕获边沿的极性,如果测量的脉宽时间比较长,定时器就会发
生溢出,溢出的时候会产生更新中断,我们可以在中断里面对溢出进行记录处理。
PWM 输入模式
测量脉宽和频率还有一个更简便的方法就是使用 PWM 输入模式,该模式是输入捕获的特例,只
能使用通道 1 和通道 2 ,通道 3 和通道 4 使用不了。与上面那种只使用一个捕获寄存器测量脉宽
和频率的方法相比, PWM 输入模式需要占用两个捕获寄存器。
当使用 PWM 输入模式的时候,因为一个输入通道 (TIx) 会占用两个捕获通道 (ICx) ,所以一个定
时器在使用 PWM 输入的时候最多只能使用两个输入通道 (TIx) 。
我们以输入通道 TI1 工作在 PWM 输入模式为例来讲解下具体的工作原理,其他通道以此类推即可。
PWM 信号由输入通道 TI1 进入,因为是 PWM 输入模式的缘故,信号会被分为两路,一路是
TI1FP1 ,另外一路是 TI2FP2 。其中一路是周期,另一路是占空比,具体哪一路信号对应周期还
是占空比,得从程序上设置哪一路信号作为触发输入,作为触发输入的哪一路信号对应的就是
周期,另一路就是对应占空比。作为触发输入的那一路信号还需要设置极性,是上升沿还是下降
沿捕获,一旦设置好触发输入的极性,另外一路硬件就会自动配置为相反的极性捕获,无需软件
配置。一句话概括就是:选定输入通道,确定触发信号,然后设置触发信号的极性即可,因为是
PWM 输入的缘故,另一路信号则由硬件配置,无需软件配置。
当使用 PWM 输入模式的时候必须将从模式控制器配置为复位模式(配置寄存器 SMCR 的位
SMS[2:0] 来实现),即当我们启动触发信号开始进行捕获的时候,同时把计数器 CNT 复位清零
下面我们以一个更加具体的时序图来分析下 PWM 输入模式。
PWM 信号由输入通道 TI1 进入,配置 TI1FP1 为触发信号,上升沿捕获。当上升沿的时候 IC1 和
IC2 同时捕获,计数器 CNT 清零,到了下降沿的时候, IC2 捕获,此时计数器 CNT 的值被锁存
到捕获寄存器 CCR2 中,到了下一个上升沿的时候, IC1 捕获,计数器 CNT 的值被锁存到捕获寄
存器 CCR1 中。其中 CCR2+1 测量的是脉宽, CCR1+1 测量的是周期。这里要注意的是 CCR2 和
CCR1 的值在计算占空比和频率的时候都必须加 1 ,因为计数器是从 0 开始计数的。
从软件上来说,用 PWM 输入模式测量脉宽和周期更容易,付出的代价是需要占用两个捕获寄存
器。
代码配置
输入捕获配置步骤
接下来我们介绍下如何使用库函数对通用定时器的输入捕获进行配置。这个
也是在编写程序中必须要了解的。其实输入捕获和前面定时器中断一样也是通用
定时器的一个功能,因此还是要用到定时器的相关配置函数,具体步骤如下:(定
时器相关库函数在 stm32f10x_tim.c 和 stm32f10x_tim.h 文件中)
(1)使能定时器及端口时钟,并设置引脚模式等
因为输入捕获也是通用定时器的一个功能,所以需要使能相应定时器时钟。
由于输入捕获通道是对应着 STM32F1 芯片的 IO 口,所以需要使能对应的端口时
钟,并将对应 IO 口设置为输入模式功能。例如本章输入捕获实验,我们是使用
TIM5 的 CH1 通道来测量输入信号的脉宽,因此需要使能 TIM5 时钟,调用的库函
数如下:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);//使能 TIM5 时
钟
而 TIM5 的 CH1 通道对应的管脚是 PA0,在 STM32F1 芯片数据手册引脚功能上
都有介绍如下:
所以需要使能 GPIOA 端口时钟。因为我们使用 PA0 来测量输入信号的高电平
时间,因此需要将 PA0 配置为下拉输入模式。GPIO 初始化如下
1. GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;//管脚设置
2. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;//设置下拉输入模式
3. GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化结构体
(2)初始化定时器参数,包含自动重装值,分频系数,计数方式等
要使用定时器功能,必须对定时器内相关参数初始化,其库函数如下:
void TIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef*
TIM_TimeBaseInitStruct);
(3)设置通用定时器的输入捕获参数,开启输入捕获功能
初始化定时器后,需要设置对应输入捕获通道参数,比如输入通道、滤波、
分频系数、映射关系、捕获极性等。输入捕获参数初始化函数如下:
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef*
TIM_ICInitStruct);
函数的第一个参数相信大家一看就清楚,是用来选择定时器的。第二个参数
是一个结构体指针变量,同样我们看下这个结构体 TIM_ICInitTypeDef 成员变
量:
1. typedef struct
2. {
3. uint16_t TIM_Channel; //通道
4. uint16_t TIM_ICPolarity; //捕获极性
5. uint16_t TIM_ICSelection;//映射
6. uint16_t TIM_ICPrescaler;//分频系数
7. uint16_t TIM_ICFilter; //滤波器长度
8. } TIM_ICInitTypeDef;
TIM_Channel:
输入捕获通道设置,通用定时器每个多达 4 个通道,假如我
们使用 TIM5 的通道 1,参数为 TIM_Channel_1。
TIM_ICPolarity:
输入信号的有效捕获极性设置,假如我们需要对输入信号 上升沿开始捕获,参数为 TIM_ICPolarity_Rising,如果是下降沿捕获,参数为
TIM_ICPolarity_Faling。库函数内还提供了单独设置通道捕获极性的函数,假
如要修改 TIM5 的通道 1 捕获极性为下降沿,函数如下:
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Faling);
此函数可以理解为通用函数 TIM_OCxPolarityConfig(),函数中的 x 表示通
道,所以如果是对通道 2 捕获极性操作,可以调用 TIM_OC2PolarityConfig 函数。
假如我们需要检测输入信号的高电平脉宽,就需要在第一次上升沿到来时捕
获一次,然后设置为下降沿捕获,等到下降沿到来时又捕获一次。如果输入信号
的高电平脉宽比较长,那么定时器就可能溢出,所以需要对定时器溢出进行处理,
否则计算的高电平时间将不准。所以需要开启定时器溢出中断。
假如我们要开启 TIM5 的捕获中断和定时器溢出中断,调用函数如下:
TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);