TIM–基本定时器
大纲
- 定时器分类
- 时基
- 基本定时器
- 高级控制定时器
- 高级控制定时器功能框图
- 输入捕获应用
- 输出比较应用
- 定时器初始化结构体详解
具体案例
定时器分类
STM32F1 系列中,除了互联型的产品,共有 8 个定时器,分为基本定时器,通用定时器和高级定时器
基本定时器 TIM6 和 TIM7 是一个 16 位的只能向上计数的定时器,只能定时,没有外部
IO
通用定时器 TIM2/3/4/5 是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,每个定时器有四个外部 IO
高级定时器 TIM1/8 是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,还可以有三相电机互补输出信号,每个定时器有 8 个外部 IO
注意:针对不同的容量,定时器的个数会有差异,详情请根据容量和芯片型号来查询数据手册
时基
时基单元包含:
● 计数器寄存器(TIMx_CNT)
● 预分频器寄存器 (TIMx_PSC)
● 自动装载寄存器 (TIMx_ARR)
● 重复次数寄存器 (TIMx_RCR)
下图是时基地框图:
我们简单介绍每一个部分的工作原理
时钟源(配置TIMxCLK)
定时器时钟 TIMxCLK,即内部时钟 CK_INT,经 APB1 预分频器后分频提供,如果 APB1 预分频系数等于 1,则频率不变,否则频率乘以 2,库函数中 APB1 预分频的系数是 2,即 PCLK1=36M,所以定时器时钟 TIMxCLK=36*2=72M。(可以参考手册RCC时钟树)
计数器时钟
定时器时钟经过 PSC 预分频器之后,即 CK_CNT,用来驱动计数器计数。PSC 是一个 16 位的预分频器,可以对定时器时钟 TIMxCLK 进行 1~65536 之间的任何一个数进行分频。具体计算方式为:CK_CNT=TIMxCLK/(PSC+1)。
注:这个计算方式要牢记,编码容易翻车
计数器
计数器 CNT 是一个 16 位的计数器,只能往上计数(针对基本计时器),最大计数值为 65535。当计数达到自动重装载寄存器的时候产生更新事件,并清零从头开始计数。
自动重装载寄存器(ARR)
自动重装载寄存器 ARR 是一个 16 位的寄存器,这里面装着计数器能计数的最大数值。当计数到这个值的时候,如果使能了中断的话,定时器就产生溢出中断。
定时时间的计算
定时器的定时时间等于计数器的中断周期乘以中断的次数。计数器在 CK_CNT 的驱动下,计一个数的时间则是 CK_CLK 的倒数,等于:1/(TIMxCLK/(PSC+1)),产生一次中断的时间则等于:1/(CK_CLK * ARR)。如果在中断服务程序里面设置一个变量 time,用来记录中断的次数,那么就可以计算出我们需要的定时时间等于:1/CK_CLK* (ARR+1)*time。
基本定时器
定时器初始化结构体详解
标准库函数头文件 stm32f10x_tim.h 中对定时器外设建立了四个初始化结构体,基本定时器只用到其中一个即 TIM_TimeBaseInitTypeDef
typedef struct {
uint16_t TIM_Prescaler; // 预分频器
uint16_t TIM_CounterMode; // 计数模式
uint32_t TIM_Period; // 定时器周期
uint16_t TIM_ClockDivision; // 时钟分频
uint8_t TIM_RepetitionCounter; // 重复计算器
} TIM_TimeBaseInitTypeDef;
(1) TIM_Prescaler:定时器预分频器设置,时钟源经该预分频器才是定时器时钟,它设定 TIMx_PSC寄存器的值。可设置范围为 0 至 65535,实现 1 至 65536 分频。
(2) TIM_CounterMode:定时器计数方式,可是在为向上计数、向下计数以及三种中心对齐模式。基本定时器只能是向上计数,即 TIMx_CNT 只能从 0 开始递增,并且无需初始化。
(3) TIM_Period:定时器周期,实际就是设定自动重载寄存器的值,在事件生成时更新到影子寄存器。可设置范围为 0 至 65535。
(4) TIM_ClockDivision:时钟分频,设置定时器时钟 CK_INT 频率与数字滤波器采样时钟频率分频比,基本定时器没有此功能,不用设置。
(5) TIM_RepetitionCounter:重复计数器,属于高级控制寄存器专用寄存器位,利用它可以非常容易控制输出 PWM 的个数。这里不用设置。
虽然定时器基本初始化结构体有 5 个成员,但对于基本定时器只需设置其中两个就可以
高级控制定时器
高级控制定时器 (TIM1 和 TIM8) 和通用定时器在基本定时器的基础上引入了外部引脚,可以实现输入捕获和输出比较功能。高级控制定时器比通用定时器增加了可编程死区互补输出、重复计数器、带刹车 (断路) 功能,这些功能都是针对工业电机控制方面。这里主要介绍常用的输入捕获和输出比较功能。
下面是手册里功能的描述:
TIM1和TIM8定时器的功能包括:
● 16位向上、向下、向上/下自动装载计数器
● 16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65535之间的任意数值
● 多达4个独立通道:
─ 输入捕获
─ 输出比较
─ PWM生成(边缘或中间对齐模式)
─ 单脉冲模式输出
● 死区时间可编程的互补输出
● 使用外部信号控制定时器和定时器互联的同步电路
● 允许在指定数目的计数器周期之后更新定时器寄存器的重复计数器
● 刹车输入信号可以将定时器输出信号置于复位状态或者一个已知状态
● 如下事件发生时产生中断/DMA:
─ 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
─ 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
─ 输入捕获
─ 输出比较
─ 刹车信号输入
● 支持针对定位的增量(正交)编码器和霍尔传感器电路
● 触发输入作为外部时钟或者按周期的电流管理
高级控制定时器时基单元包含一个 16 位自动重装载寄存器 ARR,一个 16 位的计数器 CNT,可向上/下计数,一个 16 位可编程预分频器 PSC,预分频器时钟源有多种可选,有内部的时钟、外部时钟。还有一个 8 位的重复计数器 RCR,这样最高可实现 40 位的可编程定时。
具体的引脚接入参考stm32参考手册Description一节(因芯片型号而异)
影子寄存器
在下面的框图,你会发现有些寄存器下面是带阴影的,这个就代表它有影子寄存器,而影子寄存器本质上起缓冲和同步的作用,下面举两个例子
这是没有启用影子寄存器:
可以发现我们原来设置的达到FF才重新计数,而当我们更改ARR到36,这个时候只需要达到36就可以完成更新和从零开始计数
下面是启用影子寄存器:
我们原来设置的是F5,而我们在自动加载寄存器如图所示的时序更改为了36,而上面的计数寄存器不是在达到36完成更新的,是因为有影子寄存器的存在,它需要完成此处计数周期后,才会把我们写入的36重新赋给寄存器,如下图自动加载影子寄存器所示,在后面本次计数周期结束的时候才实现更改为36
影子寄存器有什么用?
当我们计数本来设置的为10才产生更新,而现在计数到了9,此时我们重新设置到5才完成一次周期,由于现在计的数大于我们设定的值,所以它会从9一直加,加到计数器的上限后再从零开始计数,到5后才完成更新
而如果使用影子寄存器,当我们设定为5后,ARR不会立即更改,而是从9继续增加到10后,此时本次计数周期结束,从零开始开始计数,并修改计数到5完成一个计数周期
高级控制定时器功能框图
注:图中有些寄存器是带影子的,表示其有影子寄存器。影子寄存器的功能可以大概理解为buffer缓冲的感觉
时钟源
高级控制定时器有四个时钟源可选:
• 内部时钟源 CK_INT
• 外部时钟模式 1:外部输入引脚 TIx(x=1,2,3,4)
• 外部时钟模式 2:外部触发输入 ETR
• 内部触发输入 (ITRx)
当然这是官方的说法,通俗一点,请见下:
按序解释一下:
- CK_INT是通过内部时钟完成配置的
- ETR引脚的配置,在出来之后可以进行直接配置时钟,也可以占用TRGI通道,占用这个通道后,也可以配置时钟,但是主要是可以配置从模式
- 通过选用ITR作为时钟源,可以把其它的定时器作为时钟源,我们称为级联,这里的ITR与定时器的选择不是随便选的,需要查看手册,下面是一个例子:
比如:正常的时基配置,我们是 频率 x 预分频器值 x 一共计多少次数,最大可以是1/72M x 65535 x 65535 ,最大是59.65秒,而我们如果以其它定时器为时钟源,就代表最开始的频率计一次数是59.65秒,经过倍频和计数器之后,可以在产生一次更新中断前记录的最大的数是 59.65 x 65535 x 65535 这么多时间,而且可以继续级联 - 通过CH1的边沿触发
- 通过CH1和CH2触发,后面会详细介绍
内部时钟源 (CK_INT)
内部时钟 CK_INT 即来自于芯片内部,等于 72M,一般情况下,我们都是使用内部时钟。当从模式控制寄存器 TIMx_SMCR 的 SMS 位等于 000 时,则使用内部时钟。
外部时钟模式 1
1:时钟信号输入引脚
当使用外部时钟模式 1 的时候,时钟信号来自于定时器的输入通道,总共有 4 个,分别为 TI1/2/3/4,即 TIMx_CH1/2/3/4。具体使用哪一路信号,由 TIM_CCMRx 的位 CCxS[1:0] 配置,其中 CCMR1控制 TI1/2,CCMR2 控制 TI3/4。
下面是从stm32操作手册中的贴图:(注意:CCMR的每个位在输入和输出模式的功能是不同的)
2:滤波器
如果来自外部的时钟信号的频率过高或者混杂有高频干扰信号的话,我们就需要使用滤波器对信号重新采样,来达到降频或者去除高频干扰的目的,具体的由 TIMx_CCMRx 的位 ICxF[3:0] 配置。
原理:通过重新一个计数器进行采样
3:边沿检测
边沿检测的信号来自于滤波器的输出,在成为触发信号之前,需要进行边沿检测,决定是上升沿有效还是下降沿有效,具体的由 TIMx_CCER 的位 CCxP 和 CCxNP 配置。
4:触发选择
当使用外部时钟模式 1 时,触发源有两个,一个是滤波后的定时器输入 1(TI1FP1)和滤波后的定时器输入 2(TI2FP2),具体的由 TIMxSMCR 的位 TS[2:0] 配置。
5:从模式选择
选定了触发源信号后,最后我们需把信号连接到 TRGI 引脚,让触发信号成为外部时钟模式 1 的输入,最终等于 CK_PSC,然后驱动计数器 CNT 计数。具体的配置 TIMx_SMCR 的位 SMS[2:0]为 000 即可选择外部时钟模式 1。
6:使能计数器
经过上面的 5 个步骤之后,最后我们只需使能计数器开始计数,外部时钟模式 1 的配置就算完成。使能计数器由 TIMx_CR1 的位 CEN 配置。
外部时钟模式 2
1:时钟信号输入引脚
当使用外部时钟模式 2 的时候,时钟信号来自于定时器的特定输入通道 TIMx_ETR,只有 1 个。
2:外部触发极性
来自 ETR 引脚输入的信号可以选择为上升沿或者下降沿有效,具体的由 TIMx_SMCR 的位 ETP配置。
3:外部触发预分频器
由于 ETRP 的信号的频率不能超过 TIMx_CLK(72M)的 1/4,当触发信号的频率很高的情况下,就必须使用分频器来降频,具体的由 TIMx_SMCR 的位 ETPS[1:0] 配置。
4:滤波器
如果 ETRP 的信号的频率过高或者混杂有高频干扰信号的话,我们就需要使用滤波器对 ETRP 信号重新采样,来达到降频或者去除高频干扰的目的。具体的由 TIMx_SMCR 的位 ETF[3:0] 配置,其中的 fDTS 是由内部时钟 CK_INT 分频得到,具体的由 TIMx_CR1 的位 CKD[1:0] 配置。
5:从模式选择
经过滤波器滤波的信号连接到 ETRF 引脚后,触发信号成为外部时钟模式 2 的输入,最终等于CK_PSC,然后驱动计数器 CNT 计数。具体的配置 TIMx_SMCR 的位 ECE 为 1 即可选择外部时钟模式 2。
6:使能计数器
经过上面的 5 个步骤之后,最后我们只需使能计数器开始计数,外部时钟模式 2 的配置就算完成。使能计数器由 TIMx_CR1 的位 CEN 配置
内部触发输入
内部触发输入是使用一个定时器作为另一个定时器的预分频器。硬件上高级控制定时器和通用定时器在内部连接在一起,可以实现定时器同步或级联。主模式的定时器可以对从模式定时器执行复位、启动、停止或提供时钟
控制器
高级控制定时器控制器部分包括触发控制器、从模式控制器以及编码器接口。触发控制器用来针对片内外设输出触发信号,比如为其它定时器提供时钟和触发 DAC/ADC 转换
编码器接口专门针对编码器计数而设计。从模式控制器可以控制计数器复位、启动、递增/递减、计数。有关控制器部分只需熟练阅读寄存器描述即可
时基单元
在前面基本定时器中讲过,但是这里的配置更详细
高级控制定时器时基单元功能包括四个寄存器,分别是计数器寄存器 (CNT)、预分频器寄存器
(PSC)、自动重载寄存器 (ARR) 和重复计数器寄存器 (RCR)。其中重复计数器 RCR 是高级定时器
独有,通用和基本定时器没有。前面三个寄存器都是 16 位有效,TIMx_RCR 寄存器是 8 位有效
预分频器 PSC
预分频器 PSC,有一个输入时钟 CK_PSC 和一个输出时钟 CK_CNT。输入时钟 CK_PSC 就是上
面时钟源的输出,输出 CK_CNT 则用来驱动计数器 CNT 计数。通过设置预分频器 PSC 的值可以
得到不同的 CK_CNT,实际计算为:fCK_CNT 等于 fCK_PSC/(PSC[15:0]+1),可以实现 1 至 65536 分频
计数器 CNT
高级控制定时器的计数器有三种计数模式,分别为递增计数模式、递减计数模式和递增/递减 (中
心对齐) 计数模式
(1) 递增计数模式下,计数器从 0 开始计数,每来一个 CK_CNT 脉冲计数器就增加 1,直到计数器
的值与自动重载寄存器 ARR 值相等,然后计数器又从 0 开始计数并生成计数器上溢事件,计数
器总是如此循环计数。如果禁用重复计数器,在计数器生成上溢事件就马上生成更新事件 (UEV);
如果使能重复计数器,每生成一次上溢事件重复计数器内容就减 1,直到重复计数器内容为 0 时
才会生成更新事件
(2) 递减计数模式下,计数器从自动重载寄存器 ARR 值开始计数,每来一个 CK_CNT 脉冲计数
器就减 1,直到计数器值为 0,然后计数器又从自动重载寄存器 ARR 值开始递减计数并生成计数
器下溢事件,计数器总是如此循环计数。如果禁用重复计数器,在计数器生成下溢事件就马上生
成更新事件;如果使能重复计数器,每生成一次下溢事件重复计数器内容就减 1,直到重复计数
器内容为 0 时才会生成更新事件
(3) 中心对齐模式下,计数器从 0 开始递增计数,直到计数值等于 (ARR-1) 值生成计数器上溢事
件,然后从 ARR 值开始递减计数直到 1 生成计数器下溢事件。然后又从 0 开始计数,如此循环。
每次发生计数器上溢和下溢事件都会生成更新事件
自动重载寄存器 ARR
自动重载寄存器 ARR 用来存放与计数器 CNT 比较的值,如果两个值相等就递减重复计数器。可
以通过 TIMx_CR1 寄存器的 ARPE 位控制自动重载影子寄存器功能,如果 ARPE 位置 1,自动重
载影子寄存器有效,只有在事件更新时才把 TIMx_ARR 值赋给影子寄存器。如果 ARPE 位为 0,
则修改 TIMx_ARR 值马上有效
重复计数器 RCR
在基本/通用定时器发生上/下溢事件时直接就生成更新事件,但对于高级控制定时器却不是这样,
高级控制定时器在硬件结构上多出了重复计数器,在定时器发生上溢或下溢事件是递减重复计
数器的值,只有当重复计数器为 0 时才会生成更新事件。在发生 N+1 个上溢或下溢事件 (N 为
RCR 的值) 时产生更新事件
输入捕获
输入捕获可以对输入的信号的上升沿、下降沿或者双边沿进行捕获,常用的有测量输入信号的脉
宽,和测量 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 位的描述可知,采样频率 fSAMPLE 可以由 fCK_INT 和 fDTS 分频后的时钟提供,其中是 fCK_INT 内部时钟,fDTS是 fCK_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 都导通了,这样电路会短路
输出控制
在输出比较的输出控制中,参考信号 OCxREF 在经过死区发生器之后会产生两路带死区的互补信号 OCx_DT 和 OCxN_DT(通道 1~3 才有互补信号,通道 4 没有,其余跟通道 1~3 一样),这两路带死区的互补信号然后就进入输出控制电路,如果没有加入死区控制,那么进入输出控制电路的信号就直接是 OCxREF
进入输出控制电路的信号会被分成两路,一路是原始信号,一路是被反向的信号,具体的由寄存器 CCER 的位 CCxP 和 CCxNP 控制。经过极性选择的信号是否由 OCx 引脚输出到外部引脚CHx/CHxN 则由寄存器 CCER 的位 CxE/CxNE 配置
如果加入了断路(刹车)功能,则断路和死区寄存器 BDTR 的 MOE、OSSI 和 OSSR 这三个位会共同影响输出的信号
输出引脚
输出比较的输出信号最终是通过定时器的外部 IO 来输出的,分别为 CH1/2/3/4,其中前面三个通道还有互补的输出通道 CH1/2/3N。更加详细的 IO 说明还请查阅相关的数据手册
断路功能
断路功能就是电机控制的刹车功能,使能断路功能时,根据相关控制位状态修改输出信号电平。在任何情况下,OCx 和 OCxN 输出都不能同时为有效电平,这关系到电机控制常用的 H 桥电路结构原因
断路源可以是时钟故障事件,由内部复位时钟控制器中的时钟安全系统 (CSS) 生成,也可以是外部断路输入 IO,两者是或运算关系
系统复位启动都默认关闭断路功能,将断路和死区寄存器 (TIMx_BDTR) 的 BKE 为置 1,使能断路功能。可通过 TIMx_BDTR 寄存器的 BKP 位设置,设置断路输入引脚的有效电平,设置为 1 时输入 BRK 为高电平有效,否则低电平有效
发送断路时,将产生以下效果:
• TIMx_BDTR 寄存器中主输出模式使能 (MOE) 位被清零,输出处于无效、空闲或复位状态;
• 根据相关控制位状态控制输出通道引脚电平;当使能通道互补输出时,会根据情况自动控制输出通道电平;
• 将 TIMx_SR 寄存器中的 BIF 位置 1,并可产生中断和 DMA 传输请求
• 如果 TIMx_BDTR 寄存器中的自动输出使能 (AOE) 位置 1,则 MOE 位会在发生下一个 UEV事件时自动再次置 1
使用从模式触发
什么是从模式触发?
我们看下图左边部分,主模式是用来发送TRGO信号的,如图,它可以从Reset,Enable,等当中选择发送,而下图右边部分,触发源选择是当接收到我们主模式发出的信号时,会根据信号自动做出相应的操作
输入捕获应用
输入捕获一般应用在两个方面,一个方面是脉冲跳变沿时间测量,另一方面是 PWM 输入测量
测量频率
这里测量频率有如上图所示的几个方法:
测频法:是自己设定一个时间,然后自己选定记录上升沿或者下降沿(后文选择的是上升沿),然后记录上升沿在这个时间周期内出现的次数,最后用出现的次数除以我们设定的测量时间T,就可以得到最后的频率(注意:这种测量方法适合测量高频,因为当频率高时,一个测量时间T里出现的次数会更多一些,误差就更小一些)
更新慢,值平滑
测周法:同样选择以上升沿或下降沿为一个待测信号的开始(这里选择上升沿),当一个上升沿开始时,就开始以标准频率 fc 进行计数,直到下一个上升沿到来,通过这种方法,我们可以计算出周期为 N / fc ,那么频率为 fc / N (注意: 这种方法适合测量低频,因为这样一个周期相对较长,我们能以标准频率计的数会更多,这样误差会更小)
更新快,受波动影响大
中界频率:是令上面两个方法的N相等时算出来的临界值,当待测频率大于中界频率时,选择测频法,否则,反之
使用中断
当捕获通道 TIx 上出现上升沿时,发生第一次捕获,计数器 CNT 的值会被锁存到捕获寄存器 CCR中,而且还会进入捕获中断,在中断服务程序中记录一次捕获(可以用一个标志变量来记录),并把捕获寄存器中的值读取到 value1 中。当出现第二次上升沿时,发生第二次捕获,计数器 CNT的值会再次被锁存到捕获寄存器 CCR 中,并再次进入捕获中断,在捕获中断中,把捕获寄存器的值读取到 value3 中,并清除捕获记录标志。利用 value3 和 value1 的差值我们就可以算出信号的周期(频率)
使用从模式触发
当我们在上面使用中断进行捕获和赋值操作时,会频繁的进入中断,这种方式比较占用资源,而我们可以通过设置从模式,来避免进入中断,而实现不占用CPU资源的全自动捕获,但是在上面的中断捕获中,进行的是 value3 - value1 ,而我们设置从模式。就会自动发送信号让CCR计0,只能进行 value - 0 的操作来测量频率
怎样设置从模式:
如下图:当我们发射出T1FP1信号时,有两路去处,一路笔直走过,经过一系列配置,进入分频器,得到IC1PS信号,然后进行把CNT的值锁入到CCR寄存器的操作
而另一条路:向上走,进入从模式触发,然后进行更新CCR复位操作
下面分析一下流程:
如下图:
我们以高电平为采样,当上升沿来临的时候,此时将CNT的值锁入到CCR寄存器,然后从模式触发,使CNT归0,然后当下次上升沿来临的时候,把CNT的值再锁入到CCR,此时我们计数CCR - 0 就是 计数的值
测量脉宽
当捕获通道 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,另外一路是 TI1FP2。其中一路是周期,另一路是占空比,具体哪一路信号对应周期还是占空比,得从程序上设置哪一路信号作为触发输入,作为触发输入的哪一路信号对应的就是周期,另一路就是对应占空比。作为触发输入的那一路信号还需要设置极性,是上升沿还是下降沿捕获,一旦设置好触发输入的极性,另外一路硬件就会自动配置为相反的极性捕获,无需软件配置。一句话概括就是:选定输入通道,确定触发信号,然后设置触发信号的极性即可,因为是PWM 输入的缘故,另一路信号则由硬件配置,无需软件配置
PWM 信号由输入通道 TI1 进入,因为是 PWM 输入模式的缘故,信号会被分为两路,一路是TI1FP1,另外一路是 TI1FP2。其中一路是周期,另一路是占空比,具体哪一路信号对应周期还是占空比,得从程序上设置哪一路信号作为触发输入,作为触发输入的哪一路信号对应的就是周期,另一路就是对应占空比。作为触发输入的那一路信号还需要设置极性,是上升沿还是下降沿捕获,一旦设置好触发输入的极性,另外一路硬件就会自动配置为相反的极性捕获,无需软件配置。一句话概括就是:选定输入通道,确定触发信号,然后设置触发信号的极性即可,因为是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 输入模式测量脉宽和周期更容易,付出的代价是需要占用两个捕获寄存器
从模式
和上面一样,我们选用上升沿为周期采样的开始,当接收到上升沿信号时,会把 CNT 的值锁入到 CCR1 当中,然后从模式触发使 CNT 计数归为0,然后等到下降沿来临时,会把 CNT 的值锁入到CCR2当中,然后等待下一次上升沿到达,此时把 CNT 的值锁入CCR1中,同时从模式触发,使 CNT 归为0
而频率的次数就为 CCR1 的值 减 0,脉宽的次数 为 CCR2 - 0
输出比较应用
输出比较模式总共有 8 种,具体的由寄存器 CCMRx 的位 OCxM[2:0] 配置。我们这里讲解最常用的 PWM 模式,其他几种模式具体的看数据手册即可
PWM 输出模式
PWM 输出就是对外输出脉宽(即占空比)可调的方波信号,信号频率由自动重装寄存器 ARR 的值决定,占空比由比较寄存器 CCR 的值决定
PWM 模式分为两种,PWM1 和 PWM2,总得来说是差不多,就看你怎么用而已,具体的区别见
如下表格
下面我们以 PWM1 模式来讲解,以计数器 CNT 计数的方向不同还分为边沿对齐模式和中心对齐模式。PWM 信号主要都是用来控制电机,一般的电机控制用的都是边沿对齐模式,FOC 电机一般用中心对齐模式。我们这里只分析这两种模式在信号感官上(即信号波形)的区别,具体在电机控制中的区别不做讨论,到了你真正需要使用的时候就会知道了
PWM 边沿对齐模式
在递增计数模式下,计数器从 0 计数到自动重载值(TIMx_ARR 寄存器的内容),然后重新从 0开始计数并生成计数器上溢事件
在边沿对齐模式下,计数器 CNT 只工作在一种模式,递增或者递减模式。这里我们以 CNT 工作
在递增模式为例,在中,ARR=8,CCR=4,CNT 从 0 开始计数,当 CNT<CCR 的值时,OCxREF
为有效的高电平,于此同时,比较中断寄存器 CCxIF 置位。当 CCR=<CNT<=ARR 时,OCxREF
为无效的低电平。然后 CNT 又从 0 开始计数并生成计数器上溢事件,以此循环往复
PWM 中心对齐模式
在中心对齐模式下,计数器 CNT 是工作做递增/递减模式下。开始的时候,计数器 CNT 从 0 开始
计数到自动重载值减 1(ARR-1),生成计数器上溢事件;然后从自动重载值开始向下计数到 1 并生成计数器下溢事件。之后从 0 开始重新计数
上图的 PWM1 模式的中心对齐波形 是 PWM1 模式的中心对齐波形,ARR=8,CCR=4。第一阶段计数器 CNT 工作在递增模式下,从 0 开始计数,当 CNT<CCR 的值时,OCxREF 为有效的高电平,当CCR=< CNT<= ARR 时,OCxREF 为无效的低电平。第二阶段计数器 CNT 工作在递减模式,从 ARR的值开始递减,当 CNT>CCR 时,OCxREF 为无效的低电平,当 CCR=>CNT>=1 时,OCxREF 为有效的高电平
在波形图上我们把波形分为两个阶段,第一个阶段是计数器 CNT 工作在递增模式的波形,这个
阶段我们又分为 ① 和 ② 两个阶段,第二个阶段是计数器 CNT 工作在递减模式的波形,这个阶段
我们又分为 ③ 和 ④ 两个阶段。要说中心对齐模式下的波形有什么特征的话,那就是 ① 和 ③ 阶
段的时间相等,② 和 ④ 阶段的时间相等
中心对齐模式又分为中心对齐模式 1/2/3 三种,具体由寄存器 CR1 位 CMS[1:0] 配置。具体的区
别就是比较中断中断标志位 CCxIF 在何时置 1:中心模式 1 在 CNT 递减计数的时候置 1,中心对
齐模式 2 在 CNT 递增计数时置 1,中心模式 3 在 CNT 递增和递减计数时都置 1
定时器初始化结构体详解
在定时器这章主要涉及到四个结构体,分别是:
时基初始化结构体 TIM_TimeBaseInitTypeDef
输出比较初始化结构体 TIM_OCInitTypeDef
输入捕获初始化结构体 TIM_ICInitTypeDef
断路和死区初始化结构体 TIM_BDTRInitTypeDef
高级控制定时器可以用到所有初始化结构体,通用定时器不能使用 TIM_BDTRInitTypeDef 结构体,基本定时器只能使用时基结构体
TIM_TimeBaseInitTypeDef(定时器基础)
时基结构体 TIM_TimeBaseInitTypeDef 用于定时器基础参数设置,与 TIM_TimeBaseInit 函数配合
使用完成配置
typedef struct {
uint16_t TIM_Prescaler; // 预分频器
uint16_t TIM_CounterMode; // 计数模式
uint32_t TIM_Period; // 定时器周期
uint16_t TIM_ClockDivision; // 时钟分频
uint8_t TIM_RepetitionCounter; // 重复计算器
} TIM_TimeBaseInitTypeDef;
(1) TIM_Prescaler:定时器预分频器设置,时钟源经该预分频器才是定时器计数时钟 CK_CNT,它
设定 PSC 寄存器的值。计算公式为:计数器时钟频率 (fCK_CNT) 等于 fCK_PSC / (PSC[15:0] + 1),可实现 1 至 65536 分频
(2) TIM_CounterMode:定时器计数方式,可设置为向上计数、向下计数以及中心对齐。高级控制
定时器允许选择任意一种
(3) TIM_Period:定时器周期,实际就是设定自动重载寄存器 ARR 的值,ARR 为要装载到实际自
动重载寄存器(即影子寄存器)的值,可设置范围为 0 至 65535
(4) TIM_ClockDivision:时钟分频,设置定时器时钟 CK_INT 频率与死区发生器以及数字滤波器
采样时钟频率分频比。可以选择 1、2、4 分频
(5) TIM_RepetitionCounter:重复计数器,只有 8 位,只存在于高级定时器
TIM_OCInitTypeDef(输出比较)
输出比较结构体 TIM_OCInitTypeDef 用于输出比较模式,与 TIM_OCxInit 函数配合使用完成指定
定时器输出通道初始化配置。高级控制定时器有四个定时器通道,使用时都必须单独设置。
typedef struct {
uint16_t TIM_OCMode; // 比较输出模式
uint16_t TIM_OutputState; // 比较输出使能
uint16_t TIM_OutputNState; // 比较互补输出使能
uint32_t TIM_Pulse; // 脉冲宽度
uint16_t TIM_OCPolarity; // 输出极性
uint16_t TIM_OCNPolarity; // 互补输出极性
uint16_t TIM_OCIdleState; // 空闲状态下比较输出状态
uint16_t TIM_OCNIdleState; // 空闲状态下比较互补输出状态
} TIM_OCInitTypeDef;
(1) TIM_OCMode:比较输出模式选择,总共有八种,常用的为 PWM1/PWM2。它设定 CCMRx 寄存器 OCxM[2:0] 位的值
(2) TIM_OutputState:比较输出使能,决定最终的输出比较信号 OCx 是否通过外部引脚输出。它设定 TIMx_CCER 寄存器 CCxE/CCxNE 位的值
(3) TIM_OutputNState: 比较互补输出使能,决定 OCx 的互补信号 OCxN 是否通过外部引脚输出。它设定 CCER 寄存器 CCxNE 位的值
(4) TIM_Pulse:比较输出脉冲宽度,实际设定比较寄存器 CCR 的值,决定脉冲宽度。可设置范围为 0 至 65535
(5) TIM_OCPolarity:比较输出极性,可选 OCx 为高电平有效或低电平有效。它决定着定时器通道有效电平。它设定 CCER 寄存器的 CCxP 位的值
(6) TIM_OCNPolarity:比较互补输出极性,可选 OCxN 为高电平有效或低电平有效。它设定TIMx_CCER 寄存器的 CCxNP 位的值
(7) TIM_OCIdleState:空闲状态时通道输出电平设置,可选输出 1 或输出 0,即在空闲状态(BDTR_MOE 位为 0) 时,经过死区时间后定时器通道输出高电平或低电平。它设定 CR2 寄存器的 OISx 位的值
(8) TIM_OCNIdleState:空闲状态时互补通道输出电平设置,可选输出 1 或输出 0,即在空闲状态(BDTR_MOE 位为 0) 时,经过死区时间后定时器互补通道输出高电平或低电平,设定值必须与TIM_OCIdleState 相反。它设定是 CR2 寄存器的 OISxN 位的值
TIM_ICInitTypeDef(输入捕获)
输入捕获结构体 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,具体的区别见图输入通道与捕获通道 IC 的映射图 。如果是普通的输入捕获,4 个通道都可以使用,如果是 PWM输入则只能使用通道 1 和通道 2。它设定 CCRMx 寄存器的 CCxS[1:0] 位的值
(4) TIM_ICPrescaler:输入捕获通道预分频器,可设置 1、2、4、8 分频,它设定 CCMRx 寄存器的 ICxPSC[1:0] 位的值。如果需要捕获输入信号的每个有效边沿,则设置 1 分频即可
(5) TIM_ICFilter:输入捕获滤波器设置,可选设置 0x0 至 0x0F。它设定 CCMRx 寄存器 ICxF[3:0]位的值。一般我们不使用滤波器,即设置为 0
TIM_BDTRInitTypeDef(断路和死区)
断路和死区结构体 TIM_BDTRInitTypeDef 用于断路和死区参数的设置,属于高级定时器专用,用于配置断路时通道输出状态,以及死区时间。它与 TIM_BDTRConfig 函数配置使用完成参数配置。这个结构体的成员只对应 BDTR 这个寄存器,有关成员的具体使用配置请参考手册 BDTR 寄存器的详细描述
typedef struct {
uint16_t TIM_OSSRState; // 运行模式下的关闭状态选择
uint16_t TIM_OSSIState; // 空闲模式下的关闭状态选择
uint16_t TIM_LOCKLevel; // 锁定配置
uint16_t TIM_DeadTime; // 死区时间
uint16_t TIM_Break; // 断路输入使能控制
uint16_t TIM_BreakPolarity; // 断路输入极性
uint16_t TIM_AutomaticOutput; // 自动输出使能
} TIM_BDTRInitTypeDef;
(1) TIM_OSSRState:运行模式下的关闭状态选择,它设定 BDTR 寄存器 OSSR 位的值
(2) TIM_OSSIState:空闲模式下的关闭状态选择,它设定 BDTR 寄存器 OSSI 位的值
(3) TIM_LOCKLevel:锁定级别配置,BDTR 寄存器 LOCK[1:0] 位的值
(4) TIM_DeadTime:配置死区发生器,定义死区持续时间,可选设置范围为 0x0 至 0xFF。它设定
BDTR 寄存器 DTG[7:0] 位的值
(5) TIM_Break:断路输入功能选择,可选使能或禁止。它设定 BDTR 寄存器 BKE 位的值
(6) TIM_BreakPolarity:断路输入通道 BRK 极性选择,可选高电平有效或低电平有效。它设定
BDTR 寄存器 BKP 位的值
(7) TIM_AutomaticOutput:自动输出使能,可选使能或禁止,它设定 BDTR 寄存器 AOE 位的值