高级控制定时器(TIM1)可以输出两个互补信号,并管理输出切换为断开和切换为接通的那个时刻。
这个时间通常被称为死区时间,您必须根据连接到输出的设备及其特性(电平移位器的固有延迟、电源开关引起的延迟…)对其进行调整。
您可以为每个输出独立选择输出极性(主输出OCx
或互补输出OCxN
)。这是通过写入TIMx_CCER寄存器中的CCxP
和CCxNP
位来完成的。
互补信号OCx
和OCxN
由几个控制位的组合激活:TIMx_CCER寄存器中的CCxE
和CCxNE
位,以及TIMx_BDTR和TIMx_CR2寄存器中的MOE
、OISx
、OISxN
、OSSI
和OSSR
位。有关更多详细信息,请参阅第286页表46:带刹车功能的互补OCx和OCxN通道的输出控制位。特别地,当切换到IDLE状态(MOE下降到0)时,死区时间被激活。
死区插入通过设置CCxE
和CCxNE
位以及MOE
位(如果存在刹车回路)来启用。每个通道有一个10位死区时间发生器。根据参考波形OCxREF,它产生2个输出OCx和OCxN。如果OCx和OCxN是高电平有效:
- OCx输出信号与参考信号相同,除了相对于参考上升沿而延迟的上升沿。
- OCxN输出信号与参考信号相反,除了相对于参考下降沿而延迟的上升沿。
如果延迟大于有效输出的宽度(OCx或OCxN),则不产生相应的脉冲。
上面输出了一堆信息,先简要介绍几个寄存器的含义吧:
- CCxP与CCxNP的含义是一样的,配置输出极性,
0
为高电平有效,1
为低电平有效 - CCxE与CCxNE,表面上看是输出使能,但置
0
,并不是真正的禁用,以CC1E为例:- CC1通道配置为输出时:
0
:关,OC1处于无效状态。OC1电平则是MOE、OSSI、OSSR、OIS1、OIS1N和CC1NE位的函数。1
:开,OC1信号根据MOE、OSSI、OSSR、OIS1、OIS1N和CC1NE位在相应的输出引脚上输出。
- CC1通道配置为输出时:
- MOE就不说了,总开关,地球人都知道!
- OSSR,运行模式下关闭状态选择位。当
MOE=1
时,在具有互补输出的通道上(被配置为输出)使用该位。如果在定时器中没有实现互补输出,则不实现OSSR。0
:当处于无效状态时,OC/OCN输出被禁用(OC/OCN使能输出信号=0)。1
:当处于无效状态时,一旦CCxE=1
或CCxNE=1
,OC/OCN输出就会以无效电平使能。然后,OC/OCN使能输出信号=1
注意,一旦LOCK被编程为级别2(TIMx_BDTR寄存器中的LOCK位),就不能修改该位。
- OSSI,空闲模式下关闭状态选择位,当
MOE=0
时,在配置为输出的通道上使用此位。0
:当处于无效状态时,OC/OCN输出被禁用(OC/OCN使能输出信号=0)。1
:当处于无效状态时,一旦CCxE=1
或CCxNE=1
,OC/OCN输出首先被强制为空闲电平。(OC/OCN使能输出信号=1)
- OISx和OISxN,是对应通道的输出空闲状态,以OIS1为例:
0
:OC1=0(在死区时间之后,如果OC1N被实施),当MOE=0
时1
:OC1=1(在死区时间之后,如果OC1N被实施),当MOE=0
时
接下来就是令程序员望而生畏的Table 46
,输出控制位用于带刹车功能的互补OCx和OCxN通道
MOE=1,OSSI不起作用
OSSR | CCxE | CCxNE | OCx输出状态 | OCxN输出状态 |
---|---|---|---|---|
0 | 0 | 0 | 输出禁用(不被定时器驱动) OCx=0, OCx_EN=0 | 输出禁用(不被定时器驱动) OCxN=0, OCxN_EN=0 |
0 | 0 | 1 | 输出禁用(不被定时器驱动) OCx=0, OCx_EN=0 | OCxREF + Polarity OCxN=OCxREF xor CCxNP OCxN_EN=1 |
0 | 1 | 0 | OCxREF + Polarity OCx=OCxREF xor CCxP OCx_EN=1 | 输出禁用(不被定时器驱动) OCxN=0, OCxN_EN=0 |
0 | 1 | 1 | OCREF + Polarity + dead-time OCx_EN=1 | (Complementary to OCREF) + Polarity + dead-time OCxN_EN=1 |
1 | 0 | 0 | 输出禁用(不被定时器驱动) OCx=CCxP, OCx_EN=0 | 输出禁用(不被定时器驱动) OCxN=CCxNP, OCxN_EN=0 |
1 | 0 | 1 | 关闭状态(以无效状态使能输出) OCx=CCxP, OCx_EN=1 | OCxREF + Polarity OCxN=OCxREF xor CCxNP OCxN_EN=1 |
1 | 1 | 0 | OCxREF + Polarity OCx=OCxREF xor CCxP OCx_EN=1 | 关闭状态(以无效状态使能输出) OCxN=CCxNP, OCxN_EN=1 |
1 | 1 | 1 | OCREF + Polarity + dead-time OCx_EN=1 | (Complementary to OCREF) + Polarity + dead-time OCxN_EN=1 |
============================ | ================================================ |
是不是一头雾水,但只要弄懂OCxREF + Polarity
是什么意思,接下来就全明白了。它的下面一行有解释,是跟极性异或。看前面CCxP的极性定义,这个位复位后默认位0
,就是高电平有效。那么简单点理解,OCxREF + Polarity
的意思就是
- 只要你不去动CCxP(默认为
0
),输出与OCxREF一样的波。 - 如果你动了CCxP(把它改为
1
),输出与OCxREF相反的波。
现在是不是就一切明朗了,其中的Complementary to OCREF
是取OCREF的互补波,+dead-time
就是在波形里插入死区时间。那么针对这张表,总结如下:
- OSSR为0时,CCxE和CCxNE才真正发挥使能功能。使能时输出相应波形。禁用时就是禁用,对应的通道电平值打在
0
上。 - OSSR为1时,CCxE和CCxNE的使能功能为伪使能(我个人理解)。为什么这么说,有以下两点:
- 必须要两个都为0,他们的输出才禁用,而且这个虽然禁用了,但通道的输出为极性值(无效电平),这个极性值在系统复位后默认为0,也就是你只要不去动它,默认的无效电平为0。
- 只要其中有一个为1,则两个通道全部使能,只不过若其中有通道的使能位为0(CCxE或CCxNE为0),则那个通道变为关闭状态,且持续输出无效电平(极性值)。使能位不为0(CCxE或CCxNE非0),通道就正常输出波。
MOE=0,OSSR不起作用
OSSI | CCxE | CCxNE | OCx输出状态 | OCxN输出状态 |
---|---|---|---|---|
0 | 0 | 0 | 输出禁用(不被定时器驱动) OCx=CCxP, OCx_EN=0 | 输出禁用(不被定时器驱动) OCxN=CCxNP, OCxN_EN=0 |
0 | 0 | 1 | 输出禁用(不被定时器驱动) 异步:OCx=CCxP, OCx_EN=0, OCxN=CCxNP, OCxN_EN=0 然后,如果时钟存在:假设OISx和OISxN不对应于有效状态下的OCx和OCxN,则在死区时间之后,OCx=OISx并且OCxN=OISxN。 | |
0 | 1 | 0 | ||
0 | 1 | 1 | ||
1 | 0 | 0 | 输出禁用(不被定时器驱动) OCx=CCxP, OCx_EN=0 | 输出禁用(不被定时器驱动) OCxN=CCxNP, OCxN_EN=0 |
1 | 0 | 1 | 关闭状态(以无效状态使能输出) 异步:OCx=CCxP, OCx_EN=1, OCxN=CCxNP, OCxN_EN=1 然后,如果时钟存在:假设OISx和OISxN不对应于有效状态下的OCx和OCxN,则在死区时间之后,OCx=OISx并且OCxN=OISxN。 | |
1 | 1 | 0 | ||
1 | 1 | 1 | ||
========================= | ========================= |
注意,当一个通道的两个输出都没有使用时(CCxE=CCxNE=0),OISx、OISxN、CCxP和CCxNP位必须保持清零。(因为不清零是会出问题滴,看下面的分析。)
总结这张表,就是说主输出关掉后,MOE=0以后,两个通道的情况简单总结如下:
- 只要OSSI=0,不管怎样,两个通道输出都被禁用。且两个通道的输出先要保持在极性值上(无效电平)。然后看
- 两个通道都没使能(CCxE和CCxNE都为0),则通道的输出保持在极性值上(无效电平)。
- 只要其中有一个通道被使能(CCxE或CCxNE为1),则要在一段死区时间之后,把通道的输出改为空闲电平(不是无效电平)。
- 如果OSSI=1,输出要不要禁用要看两个通道的使能位(CCxE和CCxNE)
- 都为0,两个通道均被禁用,但通道的输出为极性值(无效电平)。
- 只要其中一个为1,两个通道均被使能,且通道的输出为极性值(无效电平),且要在一段死区时间之后,把通道的输出改为空闲电平(不是无效电平)。
接下来就是进入图表环节,别懵圈,比较简单!
下图显示了死区时间发生器的输出信号和参考信号OCxREF之间的关系。(在这些例子中,我们假设CCxP=0
,CCxNP=0
,MOE=1
,CCxE=1
和CCxNE=1
)
图74,具有死区时间插入的互补输出。
图75,延迟大于负脉冲的死区时间波形。
图76,延迟大于正脉冲的死区时间波形。
死区时间延迟对于每个通道都是相同的,并且可以使用TIMx_BDTR寄存器中的DTG
位进行编程。
死区时间计算
关于TIMx_BDTR寄存器中的DTG
位的定义如下:
DTG[7:0]:死区发生器设置
该位字段定义插入互补输出之间的死区持续时间。DT对应于该持续时间。
DTG[7:5]=0xx
=>DT=DTG[7:0] x tdtg
withtdtg=tDTS
.DTG[7:5]=10x
=>DT=(64+DTG[5:0]) x tdtg
withtdtg=2 x tDTS
.DTG[7:5]=110
=>DT=(32+DTG[4:0]) x tdtg
withtdtg=8 x tDTS
.DTG[7:5]=111
=>DT=(32+DTG[4:0]) x tdtg
withtdtg=16 x tDTS
.例如,如果
tDTS=125 ns
(8 MHz),死区时间可能值为:
- 0 to 15875 ns by 125 ns steps,
- 16 us to 31750 ns by 250 ns steps,
- 32 us to 63 us by 1 us steps,
- 64 us to 126 us by 2 us steps
可以看出,死区时间的计算上关键在确定tDTS
的值是多少。别被定义中的8MHz
误导,别误以为是晶振的频率。它的值取决于TIMx_CR1中的CKD[1:0]
,定义如下:
CKD[1:0]: 时钟分频
该位域指示定时器时钟(CK_INT)频率与死区发生器和数字滤波器(ETR、TIx)使用的死区和采样时钟(tDTS)之间的分频比,
- 00:
tDTS=tCK_INT
- 01:
tDTS=2 * tCK_INT
- 10:
tDTS=4 * tCK_INT
- 11: 保留,不要写入该值
复位后,如果你不去动CKD位,则默认tDTS
就是CK_INT
的一个周期。好,再来说CK_INT是啥?
内部时钟源(CK_INT)
如果从模式控制器被禁用(SMS=000),则CEN
、DIR
(在TIMx_CR1寄存器中)和UG
位(在TIMx_EGR寄存器中)是实际控制位,并且只能通过软件进行更改(UG
除外,它保持自动清除)。一旦CEN
位被写入1
,预分频器的时钟源就来自内部时钟CK_INT
。
大部分情况下,都是选择CK_INT作为定时器的时钟源的。这个CK_INT既然称之为定时器的内部时钟,也就可以理解为它就是系统供给定时器的时钟,这就要去了解STM32F0x的时钟系统,这里略过。定时器的时钟源与APB
有关,在STM32F0x里APB时钟最高可以到48MHz。一般情况下,AHB时钟配置为48MHz,要看APB的预分频设为多少,规则如下:
- APB的预分频值为
1
,则定时器的时钟源就是APB
。 - APB的预分频值不为
1
,则定时器的时钟源为APB x 2
。
所以假设AHB=48MHz
, APB=48MHz
或者APB=24MHz
,定时器的时钟源都是48MHz
,也就是CK_INT=48MHz
。所以大部分的应用场合,编程时按照下面的规则去做就行(tDTS=20.83ns
):
DTG[7:0] | dead-time (/us) | steps (/ns) |
---|---|---|
0 to 127 | 0 to 2.645833 | 20.83 |
128 to 191 | 2.66 to 5.29166 | 41.66 |
192 to 223 | 5.33 to 10.5 | 166.66 |
224 to 255 | 10.66 to 21 | 333.33 |
============== | ================== | =============== |