一 高级定时器功能框图
高级控制定时器时基单元包含一个
16
位自动重装载寄存器
ARR
,一个
16
位的计数器
CNT
,可向上
/
下计数,一个
16
位可编程预分频器
PSC
,预分频器时钟源有多种可选,有
内部的时钟、外部时钟。还有一个
8
位的重复计数器
RCR
,这样最高可实现
40
位的可编
程定时。
STM32F103ZET6
的高级
/
通用定时器的
IO
分配具体见表
。配套开发板因为
IO
资
源紧缺,定时器的
IO
很多已经复用它途,故下表中的
IO
只有部分可用于定时器的实验。因为只有几个定时器IO是纯净的
![](https://i-blog.csdnimg.cn/blog_migrate/a24a23eca4320781cf63b397891d2ab7.png)
1 ①时钟源 高级控制定时器有四个时钟源可选:
内部时钟源
CK_INT
外部时钟模式
1
:外部输入引脚
TIx
(
x=1,2,3,4
)
外部时钟模式
2
:外部触发输入
ETR
内部触发输入
(ITRx)
内部时钟源
(CK_INT)
内部时钟
CK_INT
即来自于芯片内部RCC外设,等于
72M
,一般情况下,我们都是使用内部时
钟。当从模式控制寄存器
TIMx_SMCR
的
SMS
位等于
000
时,则使用内部时钟。
外部时钟模式
1
![](https://i-blog.csdnimg.cn/blog_migrate/e5fe31b5fde40243285f8374f159c74c.png)
①:时钟信号输入引脚
当使用外部时钟模式
1
的时候,时钟信号来自于定时器的输入通道,总共有
4
个,分
别为
TI1/2/3/4
,即
TIMx_CH1/2/3/4
。具体使用哪一路信号,由
TIM_CCMRx
的位
CCxS[1:0]
配置,其中
CCMR1
控制
TI1/2
,
CCMR2
控制
TI3/4
。
②:滤波器
如果来自外部的时钟信号的频率过高或者混杂有高频干扰信号的话,我们就需要使用
滤波器对信号重新采样,来达到降频或者去除高频干扰的目的,具体的由
TIMx_CCMRx
的位
ICxF[3:0]
配置。
③:边沿检测
边沿检测的信号来自于滤波器的输出,在成为触发信号之前,需要进行边沿检测,决
定是上升沿有效还是下降沿有效,具体的由
TIMx_CCER
的位
CCxP
和
CCxNP
配置。
④:触发选择
当使用外部时钟模式
1
时,触发源有两个,一个是滤波后的定时器输入
1
(
TI1FP1
)
和滤波后的定时器输入
2
(
TI2FP2
),具体的由
TIMxSMCR
的位
TS[2:0]
配置。
⑤:从模式选择
选定了触发源信号后,最后我们需把信号连接到
TRGI
引脚,让触发信号成为外部时
钟模式
1
的输入,最终等于
CK_PSC
,然后驱动计数器
CNT
计数。具体的配置
TIMx_SMCR
的位
SMS[2:0]
为
000
即可选择外部时钟模式
1
。
⑥:使能计数器
经过上面的
5
个步骤之后,最后我们只需使能计数器开始计数,外部时钟模式
1
的配
置就算完成。使能计数器由
TIMx_CR1
的位
CEN
配置
外部时钟模式
2
![](https://i-blog.csdnimg.cn/blog_migrate/a9ed0533ab1f2fa32338d3c592c50394.png)
①:时钟信号输入引脚
当使用外部时钟模式
2
的时候,时钟信号来自于定时器的特定输入通道
TIMx_ETR
,
只有
1
个。
②:外部触发极性
来自
ETR
引脚输入的信号可以选择为上升沿或者下降沿有效,具体的由
TIMx_SMCR
的位
ETP
配置。
③:外部触发预分频器
由于
ETRP
的信号的频率不能超过
TIMx_CLK
(
72M
)的
1/4
,当触发信号的频率很高
的情况下,就必须使用分频器来降频,具体的由
TIMx_SMCR
的位
ETPS[1:0]
配置。
④:滤波器
如果
ETRP
的信号的频率过高或者混杂有高频干扰信号的话,我们就需要使用滤波器
对
ETRP
信号重新采样,来达到降频或者去除高频干扰的目的。具体的由
TIMx_SMCR
的
位
ETF[3:0]
配置,其中的
f
DTS
是由内部时钟
CK_INT
分频得到,具体的由
TIMx_CR1
的位
CKD[1:0]
配置。
⑤:从模式选择
经过滤波器滤波的信号连接到
ETRF
引脚后,触发信号成为外部时钟模式
2
的输入,
最终等于
CK_PSC
,然后驱动计数器
CNT
计数。具体的配置
TIMx_SMCR
的位
ECE
为
1
即可选择外部时钟模式
2
。
⑥:使能计数器
经过上面的
5
个步骤之后,最后我们只需使能计数器开始计数,外部时钟模式
2
的配
置就算完成。使能计数器由
TIMx_CR1
的位
CEN
配置。
内部触发输入
内部触发输入是使用一个定时器作为另一个定时器的预分频器。硬件上高级控制定时
器和通用定时器在内部连接在一起,可以实现定时器同步或级联。主模式的定时器可以对
从模式定时器执行复位、启动、停止或提供时钟。
2.
②控制器
高级控制定时器控制器部分包括触发控制器、从模式控制器以及编码器接口。触发控
制器用来针对片内外设输出触发信号,比如为其它定时器提供时钟和触发
DAC/ADC
转换。
编码器接口专门针对编码器计数而设计。从模式控制器可以控制计数器复位、启动、递增
/
递减、计数。有关控制器部分只需熟练阅读寄存器描述即可。
3.
③时基单元
![](https://i-blog.csdnimg.cn/blog_migrate/ba8b607b3e248e154fec268795afa9f7.png)
高级控制定时器时基单元功能包括四个寄存器,分别是计数器寄存器
(CNT)
、预分频
器寄存器
(PSC)
、自动重载寄存器
(ARR)
和重复计数器寄存器
(RCR)
。其中重复计数器
RCR
是高级定时器独有,通用和基本定时器没有。前面三个寄存器都是
16
位有效,
TIMx_RCR
寄存器是
8
位有效。
预分频器
PSC
预分频器
PSC
,有一个输入时钟
CK_PSC
和一个输出时钟
CK_CNT
。输入时钟
CK_PSC
就是上面时钟源的输出,输出
CK_CNT
则用来驱动计数器
CNT
计数。通过设置
预 分 频 器
PSC
的 值 可 以 得 到 不 同 的
CK_CNT
,实际计算为:
f
CK_CNT
等 于
f
CK_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
的值
)
时产生更新事件。
4.
④输入捕获
![](https://i-blog.csdnimg.cn/blog_migrate/28f972e5e93a5a1c0811ed757acbfd36.png)
输入捕获可以对输入的信号的上升沿,下降沿或者双边沿进行捕获,常用的有测量输
入信号的脉宽和测量
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
只能通过软件清零
5.
⑤输出比较
![](https://i-blog.csdnimg.cn/blog_migrate/1e7cb46b7d121f1e5a7641aaaae5738d.png)
输出比较就是通过定时器的外部引脚对外输出控制信号,有冻结、将通道
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
信号的应用,我们以一个板桥驱动电路为例。
![](https://i-blog.csdnimg.cn/blog_migrate/a500512e8f947f97cecd9c0dd1a4435b.png)
③输出控制
在输出比较的输出控制中,参考信号
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
说明还请查阅相关的数据手
册。
6.
⑥断路功能
断路功能就是电机控制的刹车功能,使能断路功能时,根据相关控制位状态修改输出
信号电平。在任何情况下,
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
。
一 . 一 输入捕获应用
输入捕获一般应用在两个方面,一个方面是脉冲跳变沿时间测量,另一方面是
PWM
输入测量
测量脉宽或者频率
![](https://i-blog.csdnimg.cn/blog_migrate/f77c639bb520d54c888d197f33826acb.png)
1.
测量频率
当捕获通道
TIx
上出现上升沿时,发生第一次捕获,计数器
CNT
的值会被锁存到捕获
寄存器
CCR
中,而且还会进入捕获中断,在中断服务程序中记录一次捕获(可以用一个标
志变量来记录),并把捕获寄存器中的值读取到
value1
中。当出现第二次上升沿时,发生
第二次捕获,计数器
CNT
的值会再次被锁存到捕获寄存器
CCR
中,并再次进入捕获中断,
在捕获中断中,把捕获寄存器的值读取到
value3
中,并清除捕获记录标志。利用
value3
和
value1
的差值我们就可以算出信号的周期(频率)。
2.
测量脉宽
当捕获通道
TIx
上出现上升沿时,发生第一次捕获,计数器
CNT
的值会被锁存到捕获
寄存器
CCR
中,而且还会进入捕获中断,在中断服务程序中记录一次捕获(可以用一个标
志变量来记录),并把捕获寄存器中的值读取到
value1
中。然后把捕获边沿改变为下降沿
捕获,目的是捕获后面的下降沿。当下降沿到来的时候,发生第二次捕获,计数器
CNT
的
值会再次被锁存到捕获寄存器
CCR
中,并再次进入捕获中断,在捕获中断中,把捕获寄存
器的值读取到
value3
中,并清除捕获记录标志。然后把捕获边沿设置为上升沿捕获。
3.PWM
输入模式
测量脉宽和频率还有一个更简便的方法就是使用
PWM
输入模式,该模式是输入捕获
的特例,只能使用通道
1
和通道
2
,通道
3
和通道
4
使用不了。与上面那种只使用一个捕
获寄存器测量脉宽和频率的方法相比,
PWM
输入模式需要占用两个捕获寄存器。
![](https://i-blog.csdnimg.cn/blog_migrate/5fa33641e8de43d0b27a47a88767d496.png)
当使用
PWM
输入模式的时候,因为一个输入通道
(TIx)
会占用两个捕获通道
(ICx)
,所
以一个定时器在使用
PWM
输入的时候最多只能使用两个输入通道
(TIx)
。
我们以输入通道
TI1
工作在
PWM
输入模式为例来讲解下具体的工作原理,其他通道
以此类推即可。
PWM
信号由输入通道
TI1
进入,因为是
PWM
输入模式的缘故,信号会被分为两路,
一路是
TI1FP1
,另外一路是
TI2FP2
。其中一路是周期,另一路是占空比,具体哪一路信
号对应周期还是占空比,得从程序上设置哪一路信号作为触发输入,作为触发输入的哪一
路信号对应的就是周期,另一路就是对应占空比。作为触发输入的那一路信号还需要设置
极性,是上升沿还是下降沿捕获,一旦设置好触发输入的极性,另外一路硬件就会自动配
置为相反的极性捕获,无需软件配置。一句话概括就是:选定输入通道,确定触发信号,
然后设置触发信号的极性即可,因为是
PWM
输入的缘故,另一路信号则由硬件配置,无
需软件配置。
当使用
PWM
输入模式的时候必须将从模式控制器配置为复位模式(配置寄存器
SMCR
的位
SMS[2:0]
来实现),即当我们启动触发信号开始进行捕获的时候,同时把计数
器
CNT
复位清零
一 . 二 输出比较应用
输出比较模式总共有
8
种,具体的由寄存器
CCMRx
的位
OCxM[2:0]
配置。我们这里
只讲解最常用的
PWM
模式,其他几种模式具体的看数据手册即可。
32.4.1 PWM
输出模式
PWM
输出就是对外输出脉宽(即占空比)可调的方波信号,信号频率由自动重装寄
存器
ARR
的值决定,占空比由比较寄存器
CCR
的值决定。
PWM
模式分为两种,
PWM1
和
PWM2
,总得来说是差不多,就看你怎么用而已,具
体的区别见表
![](https://i-blog.csdnimg.cn/blog_migrate/b7f6297291d9454f615c3ba6e66b5944.png)
1. PWM
边沿对齐模式
在递增计数模式下,计数器从
0
计数到自动重载值(
TIMx_ARR
寄存器的内容),然后重新
从
0
开始计数并生成计数器上溢事件
图
32-13 PWM1
模式的边沿对齐波形
在边沿对齐模式下,计数器
CNT
只工作在一种模式,递增或者递减模式。这里我们以
CNT
工作在递增模式为例,在中,
ARR=8
,
CCR=4
,
CNT
从
0
开始计数,当
CNT<CCR
的
值时,
OCxREF
为 有 效的 高 电平 ,于 此同 时, 比 较中 断寄 存器
CCxIF
置位。当
CCR=<CNT<=ARR
时,
OCxREF
为无效的低电平。然后
CNT
又从
0
开始计数并生成计数
器上溢事件,以此循环往复。
2. PWM
中心对齐模式
图
32-14 PWM1
模式的中心对齐波形
在中心对齐模式下,计数器
CNT
是工作做递增
/
递减模式下。开始的时候,计数器
CNT
从
0
开始计数到自动重载值减
1(ARR-1)
,生成计数器上溢事件;然后从自动重载值开
始向下计数到
1
并生成计数器下溢事件。之后从
0
开始重新计数。
图
32-14
是
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
。
二
定时器初始化结构体详解
在标准库函数头文件
stm32f4xx_tim.h
中对定时器外设建立了四个初始化结构体,分别
为 时 基 初 始 化 结 构 体
TIM_TimeBaseInitTypeDef
、 输 出 比 较 初 始 化 结 构 体
TIM_OCInitTypeDef
、输入捕获初始化结构体
TIM_ICInitTypeDef
和断路和死区初始化结构
体
TIM_BDTRInitTypeDef
,高级控制定时器可以用到所有初始化结构体,通用定时器不能
使用
TIM_BDTRInitTypeDef
结构体,基本定时器只能使用时基结构体。接下来我们具体讲
解下这四个结构体。
1. TIM_TimeBaseInitTypeDef
时 基 结 构 体
TIM_TimeBaseInitTypeDef
用 于 定 时 器 基 础 参 数 设 置 , 与
TIM_TimeBaseInit
函数配合使用完成配置。
代码清单
32-1
定时器基本初始化结构体
1 typedef
struct
{
2
uint16_t
TIM_Prescaler;
//
预分频器
3
uint16_t
TIM_CounterMode;
//
计数模式
4
uint32_t
TIM_Period;
//
定时器周期
5
uint16_t
TIM_ClockDivision;
//
时钟分频
6
uint8_t
TIM_RepetitionCounter;
//
重复计算器
7
} TIM_TimeBaseInitTypeDef;
(5) TIM_Prescaler
:定时器预分频器设置,时钟源经该预分频器才是定时器计数时钟
CK_CNT
,它设定
PSC
寄存器的值。计算公式为:计数器时钟频率
(f
CK_CNT
)
等于
f
CK_PSC
/ (PSC[15:0] + 1)
,可实现
1
至
65536
分频。
(6) TIM_CounterMode
:定时器计数方式,可设置为向上计数、向下计数以及中心对齐。
高级控制定时器允许选择任意一种。
(7) TIM_Period
:定时器周期,实际就是设定自动重载寄存器
ARR
的值,
ARR
为要装载
到实际自动重载寄存器(即影子寄存器)的值,可设置范围为
0
至
65535
。
(8) TIM_ClockDivision
:时钟分频,设置定时器时钟
CK_INT
频率与死区发生器以及数字
滤波器采样时钟频率分频比。可以选择
1
、
2
、
4
分频。
(9) TIM_RepetitionCounter
:重复计数器,只有
8
位,只存在于高级定时器。
2. TIM_OCInitTypeDef
输出比较结构体
TIM_OCInitTypeDef
用于输出比较模式,与
TIM_OCxInit
函数配合使
用完成指定定时器输出通道初始化配置。高级控制定时器有四个定时器通道,使用时都必
须单独设置。
代码清单
32-2
定时器比较输出初始化结构体
1 typedef
struct
{
2
uint16_t
TIM_OCMode;
//
比较输出模式
3
uint16_t
TIM_OutputState;
//
比较输出使能
4
uint16_t
TIM_OutputNState;
//
比较互补输出使能
5
uint32_t
TIM_Pulse;
//
脉冲宽度
6
uint16_t
TIM_OCPolarity;
//
输出极性
7
uint16_t
TIM_OCNPolarity;
//
互补输出极性
8
uint16_t
TIM_OCIdleState;
//
空闲状态下比较输出状态
9
uint16_t
TIM_OCNIdleState;
//
空闲状态下比较互补输出状态
10
} 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
位的值。
3. TIM_ICInitTypeDef
输入捕获结构体
TIM_ICInitTypeDef
用于输入捕获模式,与
TIM_ICInit
函数配合使用
完成定时器输入通道初始化配置。如果使用
PWM
输入模式需要与
TIM_PWMIConfig
函数
配合使用完成定时器输入通道初始化配置。
代码清单
32-3
定时器输入捕获初始化结构体
1 typedef
struct
{
2
uint16_t
TIM_Channel;
//
输入通道选择
3
uint16_t
TIM_ICPolarity;
//
输入捕获触发选择
4
uint16_t
TIM_ICSelection;
//
输入捕获选择
5
uint16_t
TIM_ICPrescaler;
//
输入捕获预分频器
6
uint16_t
TIM_ICFilter;
//
输入捕获滤波器
(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
,具
体的区别见图
32-15
。如果是普通的输入捕获,
4
个通道都可以使用,如果是
PWM
输
入则只能使用通道
1
和通道
2
。它设定
CCRMx
寄存器的 CCxS[1:0]位的值。
![](https://i-blog.csdnimg.cn/blog_migrate/94a041ef57467a638a036cc6d90c2a60.png)
(4) TIM_ICPrescaler
:输入捕获通道预分频器,可设置
1
、
2
、
4
、
8
分频,它设定
CCMRx
寄存器的
ICxPSC[1:0]
位的值。如果需要捕获输入信号的每个有效边沿,则设置
1
分频
即可。
(5) TIM_ICFilter
:输入捕获滤波器设置,可选设置
0x0
至
0x0F
。它设定
CCMRx
寄存器
ICxF[3:0]位的值。一般我们不使用滤波器,即设置为 0。
4. TIM_BDTRInitTypeDef
断路和死区结构体
TIM_BDTRInitTypeDef
用于断路和死区参数的设置,属于高级定时
器专用,用于配置断路时通道输出状态,以及死区时间。它与
TIM_BDTRConfig
函数配置
使用完成参数配置。这个结构体的成员只对应
BDTR
这个寄存器,有关成员的具体使用配
置请参考手册
BDTR
寄存器的详细描述。
代码清单
32-4
断路和死区初始化结构体
1 typedef
struct
{
2
uint16_t
TIM_OSSRState;
//
运行模式下的关闭状态选择
3
uint16_t
TIM_OSSIState;
//
空闲模式下的关闭状态选择
4
uint16_t
TIM_LOCKLevel;
//
锁定配置
5
uint16_t
TIM_DeadTime;
//
死区时间
6
uint16_t
TIM_Break;
//
断路输入使能控制
7
uint16_t
TIM_BreakPolarity;
//
断路输入极性
8
uint16_t
TIM_AutomaticOutput;
//
自动输出使能
9
} 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
位的值。
三 PWM互补输出实验
输出比较模式比较多,这里我们以
PWM
输出为例讲解,并通过示波器来观察波形。
实验中不仅在主输出通道输出波形,还在互补通道输出与主通道互补的的波形,并且添加
了断路和死区功能。
硬件设计
根据开发板引脚使用情况,并且参考
中定时器引脚信息 ,使用高级定时器
TIM1
的通道
1
及其互补通道作为本实验的波形输出通道,对应选择
PA8
和
PB13
引脚。将
示波器的两个输入通道分别与
PA8
和
PB13 引脚连接,用于观察波形,还有注意共地。
为增加断路功能,需要用到
TIM1_BKIN
引脚,这里选择
PB12
引脚。程序我们设置该
引脚为高电平有效,当
BKIN
引脚被置高低电平的时候,两路互补的
PWM
输出就被停止,
就好像是刹车一样。
32.6.2
软件设计
1.
编程要点
(1)
定时器用到的
GP IO
初始化
(2)
定时器时基结构体
TIM_TimeBaseInitTypeDef
初始化
(3)
定时器输出比较结构体
TIM_OCInitTypeDef
初始化
(4)
定时器刹车和死区结构体
TIM_BDTRInitTypeDef
初始化
#include "advancetime.h"
//先把TIM1的gpio进行初始化:推挽复用输出
static void ADVANCE_TIM_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 输出比较通道PA8初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 输出比较通道互补通道PB13初始化
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 输出比较通道刹车通道 PB12 初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB,GPIO_Pin_12);// BKIN引脚默认先输出低电平
}
//再配置定时器结构体成员初始化
static void ADVANCE_TIM_Mode_Config(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);// 开启定时器时钟,即内部时钟CK_INT=72M
/*--------------------时基结构体初始化:确定计数器时钟频率与周期-------------------------*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period= (8-1);// 自动重装载ARR寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Prescaler= (9-1); // 驱动CNT计数器的时钟 = Fck_int/(psc+1) 72/(8+1) = 8M 信号频率:(8-1+1)/8 = 1M
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;// 时钟分频因子,不分频 ,配置死区时间时需要用到,随便配也可以 详见TIMxCR1寄存器8-9位
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; // 计数器计数模式,设置为向上计数
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;// 重复计数器的值,没用到不用管
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);// 初始化定时器
/*--------------------输出比较结构体初始化-------------------*/
TIM_OCInitTypeDef TIM_OCInitStructure;//设置c99标准支持任意地方初始化这个变量
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;// 配置为PWM模式1:平时用它
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; // 互补输出使能
TIM_OCInitStructure.TIM_Pulse = 4;// 设置占空比大小
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;// 输出通道电平极性配置
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;// 互补输出通道电平极性配置
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;// 输出通道空闲电平极性配置:当pwm用刹车时候会被禁止电平,这时候用这个set1电平
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;// 互补输出通道空闲电平极性配置
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
/*-------------------刹车和死区结构体初始化-------------------*/
// 有关刹车和死区结构体的成员具体可参考BDTR寄存器的描述
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
// 输出比较信号死区时间配置,具体如何计算可参考 BDTR:UTG[7:0]的描述
// 这里配置的死区时间为152ns
TIM_BDTRInitStructure.TIM_DeadTime = 11;//写入寄存器值11 即1011
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
// 当BKIN引脚检测到高电平的时候,输出比较信号被禁止,就好像是刹车一样
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
TIM_Cmd(TIM1, ENABLE); // 使能计数器
TIM_CtrlPWMOutputs(TIM1, ENABLE);// 主输出使能,当使用的是通用定时器时,这句不需要
}
void ADVANCE_TIM_Init(void)
{
ADVANCE_TIM_GPIO_Config();
ADVANCE_TIM_Mode_Config();
}
#include "stm32f10x.h"
#include "led.h"
#include "key.h"
#include "rcc.h"
#include "exti.h"
#include "systick.h"
#include "usart.h"
#include <stdio.h>
#include "basetime.h"
#include "advancetime.h"
//高级定时器1的通道1与互补通道输出1Mh 占空比50%的pwm,带刹车功能与死区时间。
int main(void)
{
ADVANCE_TIM_Init();
while (1){
}
}