31章-定时器

基本定时器TIM

STM32F1 系列中,除了互联型的产品,共有8 个定时器,分为基本定时器,通用定时器和高级定时器。基本定时器TIM6 和TIM7 是一个16 位的只能向上计数的定时器,只能定时,没有外部IO。通用定时器TIM2/3/4/5 是一个16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,每个定时器有四个外部IO。高级定时器TIM1/8 是一个16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,还可以有三相电机互补输出信号,每个定时器有8 个外部IO。

基本定时器

时钟源

定时器时钟TIMxCLK,即内部时钟CK_INT,经APB1 预分频器后分频提供,如果APB1 预分频系数等于1,则频率不变,否则频率乘以2,库函数中APB1 预分频的系数是2,即PCLK1=36M,所以定时器时钟TIMxCLK=36*2=72M。

计数器时钟

定时器时钟经过PSC 预分频器之后,即CK_CNT,用来驱动计数器计数。PSC 是一个16 位的预分频器,可以对定时器时钟TIMxCLK 进行1~65536 之间的任何一个数进行分频。具体计算方式为:CK_CNT=TIMxCLK/(PSC+1)。

定时器初始化结构体

 typedef struct {
 uint16_t TIM_Prescaler; // 预分频器CK_CNT = CK_INT / (71+1)
 uint16_t TIM_CounterMode; // 计数模式
 uint32_t TIM_Period; // 定时器周期---ARR
 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 个成员,但对于基本定时器只需设置其中两个(分频和周期)就可以,想想使用基本定时器就是简单。

基本定时器定时实验

编程要点
(1) 开定时器时钟TIMx_CLK, x[6,7];
(2) 初始化时基初始化结构体;
(3) 使能TIMx, x[6,7] update 中断;
(4) 打开定时器;
(5) 编写中断服务程序

基本定时器配置

 void BASIC_TIM_Config(void)
 {
	 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	
	 // 开启定时器时钟, 即内部时钟CK_INT=72M
	 BASIC_TIM_APBxClock_FUN(BASIC_TIM_CLK, ENABLE);
	
	 // 自动重装载寄存器周的值(计数值)ARR
	 TIM_TimeBaseStructure.TIM_Period=1000;
	
	 // 累计TIM_Period 个频率后产生一个更新或者中断
	 // 时钟预分频数为71,则驱动计数器的时钟CK_CNT = CK_INT / (71+1)=1M
	 TIM_TimeBaseStructure.TIM_Prescaler= 71;
	
	 // 时钟分频因子,基本定时器没有,不用管
	 //TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	
	 // 计数器计数模式,基本定时器只能向上计数,没有计数模式的设置
	 //TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
	
	 // 重复计数器的值,基本定时器没有,不用管
	 //TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
	
	 // 初始化定时器
	 TIM_TimeBaseInit(BASIC_TIM, &TIM_TimeBaseStructure);
	
	 // 清除计数器中断标志位
	 TIM_ClearFlag(BASIC_TIM, TIM_FLAG_Update);
	
	 // 开启计数器中断
	 TIM_ITConfig(BASIC_TIM,TIM_IT_Update,ENABLE);

	// 使能计数器
	TIM_Cmd(BASIC_TIM, ENABLE);
	
	// 暂时关闭定时器的时钟,等待使用
	BASIC_TIM_APBxClock_FUN(BASIC_TIM_CLK, DISABLE);
}

驱动计数器
的时钟: C K C N T = C K I N T ( 71 + 1 ) = 1 M { {CK_{CNT}} = \dfrac{CK_{INT}} {(71+1)}=1M} CKCNT=(71+1)CKINT=1M,则计数器计数一次的时间等于: 1 C K C N T = 1 u s { \dfrac{1}{CK_{CNT}}=1us} CKCNT1=1us
,当计数器计数到ARR 的值1000 时,产生一次中断,则中断一次的时间为: 1 C K C N T ∗ A R R = 1 1 M ∗ 1000 = 1 m s { \dfrac{1}{CK_{CNT}}*ARR=\dfrac{1}{1M}*1000=1ms} CKCNT1ARR=1M11000=1ms

必备的
定时器中断优先级配置
定时器中断服务程序

TIM—高级定时器

高级控制定时器(TIM1 和TIM8) 和通用定时器在基本定时器的基础上引入了外部引脚,可以实现输入捕获输出比较功能。高级控制定时器比通用定时器增加了可编程死区互补输出重复计数器带刹车(断路) 功能,这些功能都是针对工业电机控制方面。这几个功能在本书不做详细的介绍,主要介绍常用的输入捕获和输出比较功能。
高级控制定时器时基单元包含一个16 位自动重装载寄存器ARR,一个16 位的计数器CNT,可向上/下计数,一个16 位可编程预分频器PSC,预分频器时钟源有多种可选,有内部的时钟、外部时钟。还有一个8 位的重复计数器RCR,这样最高可实现40 位的可编程定时。
内部时钟源(CK_INT)
内部时钟CK_INT 即来自于芯片内部,等于72M,一般情况下,我们都是使用内部时钟。当从模式控制寄存器TIMx_SMCR 的SMS 位等于000 时,则使用内部时钟。

输入捕获

输入捕获可以对输入的信号的上升沿,下降沿或者双边沿进行捕获,常用的有测量输入信号的脉宽和测量PWM 输入信号的频率占空比这两种。
原理:当捕获到信号的跳变沿的时候,把计数器CNT 的值锁存到捕获寄存器CCR 中,把前后两次捕获到的CCR 寄存器中的值相减,就可以算出脉宽或者频率。

输入通道

需要被测量的信号从定时器的外部引脚TIMx_CH1/2/3/4 进入,通常叫TI1/2/3/4,

捕获通道

捕获通道就是图中的IC1/2/3/4,每个捕获通道都有相对应的捕获寄存器CCR1/2/3/4,当发生捕获的时候,计数器CNT 的值就会被锁存到捕获寄存器中。
这里我们要搞清楚输入通道和捕获通道的区别,输入通道是用来输入信号的,捕获通道是用来捕获输入信号的通道,一个输入通道的信号可以同时输入给两个捕获通道。比如输入通道TI1 的信号经过滤波边沿检测器之后的TI1FP1 和TI1FP2 可以进入到捕获通道IC1 和IC2,其实这就是我们后面要讲的PWM 输入捕获,只有一路输入信号(TI1)却占用了两个捕获通道(IC1 和IC2)。当只需要测量输入信号的脉宽时候,用一个捕获通道即可。输入通道和捕获通道的映射关系具体由寄存器CCMRx 的位CCxS[1:0] 配置。

输出比较

输出比较就是通过定时器的外部引脚对外输出控制信号,有冻结、将通道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] 配置。死区时间的大小必须根据与输出信号相连接的器件及其特性来调整。

输出控制

输出控制

在输出比较的输出控制中,参考信号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。

输入捕获应用

PWM 输入模式

测量脉宽和频率还有一个更简便的方法就是使用PWM 输入模式,该模式是输入捕获的特例,只能使用通道1 和通道2,通道3 和通道4 使用不了。与上面那种只使用一个捕获寄存器测量脉宽和频率的方法相比,PWM 输入模式需要占用代价两个捕获寄存器。
当使用PWM 输入模式的时候,因为一个输入通道(TIx) 会占用两个捕获通道(ICx),所以一个定时器在使用PWM 输入的时候最多只能使用两个输入通道(TIx)。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 输出模式

PWM 输出就是对外输出脉宽(即占空比)可调的方波信号,信号频率由自动重装寄存器ARR 的值决定,占空比由比较寄存器CCR 的值决定
PWM 模式分为两种,PWM1 和PWM2,差不多
pwm输出模式
下面我们以PWM1 模式来讲解,以计数器CNT 计数的方向不同还分为边沿对齐模式和中心对齐模式。PWM 信号主要都是用来控制电机,一般的电机控制用的都是边沿对齐模式,FOC 电机一般用中心对齐模式。我们这里只分析这两种模式在信号感官上(即信号波形)的区别,具体在电机控制中的区别不做讨论,到了你真正需要使用的时候就会知道了。
PWM边沿对齐模式
ARR=8 周期为8,CCR=4 高电平时间为4.
pwm中心对齐模式
顾名思义:中心对称的波形。ARR=8,因为对称,所以可以看做周期为82=16;CCR=4,因为对称,高电平时间为42=8

定时器初始化结构体

基本定时器部分有,此处不赘述。
(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] 位的值。STM32 TIM高级定时器死区时间的计算
(5) TIM_Break:断路输入功能选择,可选使能或禁止。它设定BDTR 寄存器BKE 位的值。
(6) TIM_BreakPolarity:断路输入通道BRK 极性选择,可选高电平有效或低电平有效。它设定BDTR 寄存器BKP 位的值。
(7) TIM_AutomaticOutput:自动输出使能,可选使能或禁止,它设定BDTR 寄存器AOE 位的值。

PWM 互补输出实验

编程要点

(1) 定时器用到的GPIO 初始化
(2) 定时器时基结构体TIM_TimeBaseInitTypeDef 初始化
(3) 定时器输出比较结构体TIM_OCInitTypeDef 初始化
(4) 定时器刹车和死区结构体TIM_BDTRInitTypeDef 初始化

高级定时器-6 定时器复用功能引脚初始化

 static void ADVANCE_TIM_GPIO_Config(void)
 {
 GPIO_InitTypeDef GPIO_InitStructure;

 // 输出比较通道GPIO 初始化
 RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1_GPIO_CLK, ENABLE);
 GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1_PIN;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(ADVANCE_TIM_CH1_PORT, &GPIO_InitStructure);

 // 输出比较通道互补通道GPIO 初始化
 RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1N_GPIO_CLK, ENABLE);
 GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1N_PIN;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(ADVANCE_TIM_CH1N_PORT, &GPIO_InitStructure);

 // 输出比较通道刹车通道GPIO 初始化
 RCC_APB2PeriphClockCmd(ADVANCE_TIM_BKIN_GPIO_CLK, ENABLE);
 GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_BKIN_PIN;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(ADVANCE_TIM_BKIN_PORT, &GPIO_InitStructure);
 // BKIN 引脚默认先输出低电平
 GPIO_ResetBits(ADVANCE_TIM_BKIN_PORT,ADVANCE_TIM_BKIN_PIN);
 }

ADVANCE_TIM_GPIO_Config() 函数初始化了定时器用到的相关的GPIO,当使用不同的GPIO 的时候,只需要修改头文件里面的宏定义即可,而不需要修改这个函数

定时器模式配置

 static void ADVANCE_TIM_Mode_Config(void)
 {
 // 开启定时器时钟, 即内部时钟CK_INT=72M
 ADVANCE_TIM_APBxClock_FUN(ADVANCE_TIM_CLK,ENABLE);

 /*--------------------时基结构体初始化-------------------------*/
 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
 // 自动重装载寄存器的值,累计TIM_Period+1 个频率后产生一个更新或者中断
 TIM_TimeBaseStructure.TIM_Period=ADVANCE_TIM_PERIOD;
 // 驱动CNT 计数器的时钟= Fck_int/(psc+1)
 TIM_TimeBaseStructure.TIM_Prescaler= ADVANCE_TIM_PSC;
 // 时钟分频因子,配置死区时间时需要用到
 TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
 // 计数器计数模式,设置为向上计数
 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
 // 重复计数器的值,没用到不用管
 TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
 // 初始化定时器
 TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure);

 /*--------------------输出比较结构体初始化-------------------*/
 TIM_OCInitTypeDef TIM_OCInitStructure;
 // 配置为PWM 模式1
 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
 // 输出使能
 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
 // 互补输出使能
 TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
 // 设置占空比大小
TIM_OCInitStructure.TIM_Pulse = ADVANCE_TIM_PULSE;
// 输出通道电平极性配置
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
// 互补输出通道电平极性配置
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
// 输出通道空闲电平极性配置
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
// 互补输出通道空闲电平极性配置
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OC1Init(ADVANCE_TIM, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(ADVANCE_TIM, 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;
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
// 当BKIN 引脚检测到高电平的时候,输出比较信号被禁止,就好像是刹车一样
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(ADVANCE_TIM, &TIM_BDTRInitStructure);

// 使能计数器
TIM_Cmd(ADVANCE_TIM, ENABLE);
// 主输出使能,当使用的是通用定时器时,这句不需要
TIM_CtrlPWMOutputs(ADVANCE_TIM, ENABLE);
}

ADVANCE_TIM_Mode_Config() 函数中初始化了三个结构体,有关这三个结构体成员的具体含义可参考“定时器初始化结构体详解” 小节, 剩下的程序参考注释阅读即可。如果需要修改PWM 的周期和占空比, 修改头文件里面的ADVANCE_TIM_PERIOD、ADVANCE_TIM_PSC 和ADVANCE_TIM_PULSE 这三个宏即可。
PWM 信号的频率的计算公司为: F = T I M c l k ( A r r + 1 ) × ( P s c + 1 ) {F=\dfrac{TIM_{clk}}{{(Arr+1)}×{(Psc+1)}}} F=(Arr+1)×(Psc+1)TIMclk其中TIM_CLK 等于72MHZ,ARR 即自动重装载寄存器的值,对应ADVANCE_TIM_PERIOD 这个宏,PSC 即计数器时钟的分频因子,对应ADVANCE_TIM_PSC这个宏。

END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值