STM32 高级定时器


本文为野火学习笔记。

高级定时器功能简介

  高级定时器对应为 TIM1/8 比基本定时器多了外部引脚,可以实现输入捕获,输出比较和互补输出,其有16为位计数器,可上下,两边计数,拥有重复计数器RCR。时钟来自 PCLK2 , 为72M.


功能框图

  整个框图非常大,分为6个部分逐步讲解。
在这里插入图片描述

1.时钟源

在这里插入图片描述

  1. 内部时钟源 CK_INT
      内部时钟源由RCC引入,挂载在 APB2 总线上,为72M,具体可见RCC时钟树
  2. 外部时钟1,2
      外部时钟的时钟信号来自第四部分的外部引脚,外部时钟1的具体框图如下:

  外部的信号经过滤波器,边沿检测器和两个数据选择器后,直接作为CK_PSC驱动定时器,这些元件下面就是控制它的寄存器及其对应位。使用较少。

2.控制器

  控制器用来控制,发送命令,主要对应了 CR1,CR2,SMCR,CCER.

3.时基

  时基和基本定时器一致,具体参考基本定时器
  相较基本定时器,高级定时器多了一个重复寄存器。在计数器计到ARR的值时,计数器清零,但不产生中断,重复寄存器会根据计数器的模式自动加一或减一,当重复寄存器达到设定值时,产生中断。

4.输入捕获

  输入捕获可以捕获输入信号的边沿,进而可测量输入信号的脉宽,频率和占空比。
  大致原理为:当检测到第一个上升沿时,CNT开始计数;检测到下降沿,产生中断,CNT的值被锁存到CCR寄存器中;CCR寄存器的值就是高电平时间。

在这里插入图片描述

  1. 输入通道
      当被测信号从定时器外部引脚输入 TIMx_CH1/2/3/4 时,把这些引脚记为 TI1/2/3/4.
  2. 输入滤波和边沿检测
      滤波用于滤去高频干扰或用于降频;边沿检测用于指定边沿有效性,如:设置上升沿有效的意思为当输入为上升沿时,边沿检测器输出高电平。
  3. 捕获通道
      捕获通道实际上是一个数据选择器;框图中可以看到,一个输入通道可以同时输入给两个捕获通道,这种使用方式就可以捕获PWM。当使用PWM捕获时,只能使用TI1/2.
  4. 预分频器
      ICx的输出信号会经过预分频器,用于决定发生多少次事件进行一次捕获。若希望每个边沿都捕获则不分频。
  5. 捕获寄存器
      最终捕获到的信号,当发生捕获时,计数器CNT的值会被锁存到CCR中,还会产生CCxI中断,相应CCxIF标志位置位。当软件读取CCR值时,标志位清零。
      若未清零,又一次发生捕获,则溢出标志位CCxOF会置位,CCxOF只能软件清零。

5.输出捕获

  输出PWM波,同样用到CNT,CCR,ARR寄存器。CNT从0开始计数,当计到CCR的值时,输出捕获寄存器输出电平发生一次跳变,计到ARR时,再次跳变。
  由此输出PWM波,ARR决定周期,CCR决定占空比。事实上,输出和输入捕获寄存器是同一个。
  由输出寄存器输出的信号需要经过死区寄存器输出。死区寄存器会使得输出的信号有一定的延时,这是为了照顾外部MOS管开启和关闭的延时。死区的延时时间可以在 TIMx_CR1 寄存器中配置。
  经过死区后,通过输出控制部分输出信号。

捕获的应用

  如图:为通道1的输入捕获框图,标出蓝色的为其对应的寄存器和其对应位。

输入捕获

  1. 测量频率
      当TIx出现上升沿,发生第一次捕获,CNT的值锁存在CCR,在中断中记录这次中断,记录CCR的值。出现第二次上升沿,重复上述过程,把两次的值相减即为周期,取倒数得到频率。
      对应寄存器的操作为:
  • 配置滤波器带宽,配置 TIMx_CCERIC1F=0011 。(按实际需要配置)
  • 配置边沿检测器,配置 TIMx_CCERCC1P=1 ,表示上升沿有效。
  • 选择输入有效端,配置TIMx_CCMR1寄存器的CC1S=01,表示CC1通道被设置为输入,且IC1映射到TI1上(即通道捕获器选取TI1作为输入)
  • 配置输入预分频器,配置 TIMx_CCMR1IC1PS=00,表示不分频。
  1. 测量脉宽
      和测量频率一致,只是第二次中断由下降沿产生。
  2. PWM输入模式

  这个模式只能使用通道1或2。一个输入通道占用两个捕获通道。
  信号从TI1进入后,被分为两路,分别进入两个捕获通道。设置触发极性即可设置某路代表的数值是周期或占空比;当设置一路的极性时,另一路极性和其相反,即设置一路为周期时,另一路就是占空比。
  用一个时序图说明:

  当输入信号第一次上升沿时,IC1和IC2同时捕获,计数器清零。第一个下降沿来临时,IC2捕获,计数器的值被锁存在CCR2;第二个上升沿来到时,IC1捕获,计数器的值被锁存在CCR1;此时,CCR2+1是高电平脉宽,CCR1+1为周期。(因计数器从0计数,+1是必要的
  当使用PWM输入模式时,启动触发信号开始捕获时,要把计数器CNT复位清零,这一点可以由SMCR寄存器的SMS位完成。

固件库编程

   stm32f10x_tim.h 中定义的四种初始化结构体,分别为时基,输出比较,输入捕获和断路死区结构体。其中基本定时器只用了时基,通用定时器不能用断路死区结构体。由此,我们开始介绍。

时基初始化结构体

typedef struct
{
  uint16_t TIM_Prescaler;            //预分频器
  uint16_t TIM_CounterMode;          //计数模式
  uint16_t TIM_Period;               //ARR
  uint16_t TIM_ClockDivision;        //时钟分频
  uint8_t TIM_RepetitionCounter;     //重复计数器
} TIM_TimeBaseInitTypeDef; 

   TIM_ClockDivision用于控制死区时间,滤波器采样时钟分频。重复计数器只有8位。

输出比较结构体

typedef struct
{
  uint16_t TIM_OCMode;           //输出模式
  uint16_t TIM_OutputState;      //输出使能
  uint16_t TIM_OutputNState;     //互补输出使能
  uint16_t TIM_Pulse;            //脉冲宽度
  uint16_t TIM_OCPolarity;        //输出极性
  uint16_t TIM_OCNPolarity;      //互补输出极性
  uint16_t TIM_OCIdleState;      //空闲下的输出状态
  uint16_t TIM_OCNIdleState;    //空闲下互补输出状态
} TIM_OCInitTypeDef;

  输出共有8中模式,最常用的是PWM1/2.

输入捕获结构体

typedef struct
{
  uint16_t TIM_Channel;       //输入通道选择
  uint16_t TIM_ICPolarity;    //边沿检测器
  uint16_t TIM_ICSelection;   //输入捕获选择
  uint16_t TIM_ICPrescaler;   //输入捕获预分频器
  uint16_t TIM_ICFilter;      //输入捕获滤波器
} TIM_ICInitTypeDef;

   TIM_Channel 用于选择ICx,可选择的通道有 TI1/2/3/4.若为PWM模式,只能使用TI1或TI2。
  TIM_ICSelection 用于选择ICx的输入通道,有三条通道可选。

开始编程

  高级定时器互补输出,带有死区和刹车功能。输出频率为1M,占空比为50%的pwm波。

硬件设计

  高级和通用定时器的引脚总结如下表:

  要注意的是,使用高级定时器的输入引脚时,一定要保证引脚的“洁净”,就是输入引脚不要连接其他设备,只是用作输入,这样可以最大限度保证输入检测的准确。
  这里我们使用TIM1,使用PA8,PB13作为CH1(输出)和CH1N(互补),PB12作为 BKIN (刹车)。

初始化GPIO

void ADVANCE_TIM_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitSturct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,
									ENABLE);
	//CH1
	GPIO_InitSturct.GPIO_Mode  = GPIO_Mode_AF_PP;
	GPIO_InitSturct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitSturct.GPIO_Pin   = GPIO_Pin_8;
	GPIO_Init(GPIOA,&GPIO_InitSturct);
	
	//CH1N
	GPIO_InitSturct.GPIO_Pin   = GPIO_Pin_13;
	GPIO_Init(GPIOB,&GPIO_InitSturct);
	//BKIN
	GPIO_InitSturct.GPIO_Pin   = GPIO_Pin_12;
	GPIO_Init(GPIOB,&GPIO_InitSturct);	
	//让BKIN输出低电平
	GPIO_ResetBits(GPIOB,GPIO_Pin_12);
}

  输出和刹车引脚为复用推挽输出,最后让刹车引脚输出低电平。

定时器模式配置

  定时器需要配置时基,输入捕获和刹车。

时基配置

static void ADVANCE_TIM_Mode_Config(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;
	RCC_APB1PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
/*********************TIM_BASE*********************************/	
	TIM_TimeBaseStruct.TIM_Period            = 7;    //ARR
	TIM_TimeBaseStruct.TIM_Prescaler         = 8;    //PSC
	TIM_TimeBaseStruct.TIM_ClockDivision     = TIM_CKD_DIV1;
	TIM_TimeBaseStruct.TIM_CounterMode       = TIM_CounterMode_Up;
	TIM_TimeBaseStruct.TIM_RepetitionCounter = 0;

	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStruct);
}

  配置ARR = 7,PSC = 8.当使用内部时钟频率,由频率计算公式 f = T I M x C L K ( P S C + 1 ) ( A R R + 1 ) f = \frac{TIMxCLK}{(PSC+1)(ARR+1)} f=(PSC+1)(ARR+1)TIMxCLK,可知配置的频率为1M.
  TIM_ClockDivision 是用来配置死区时间的,先配置为1分频。这里不使用重复计数器,因此配置为0.

配置输出捕获

	TIM_OCInitTypeDef       TIM_OCInitStruct;
   /***********************TIM_OC**********************************/
	TIM_OCInitStruct.TIM_OCMode       = TIM_OCMode_PWM1;
	TIM_OCInitStruct.TIM_OutputState  = TIM_OutputState_Enable;
	TIM_OCInitStruct.TIM_OutputNState = TIM_OutputNState_Enable;
	TIM_OCInitStruct.TIM_Pulse        = 4;
	TIM_OCInitStruct.TIM_OCPolarity   = TIM_OCPolarity_High;
	TIM_OCInitStruct.TIM_OCNPolarity  = TIM_OCNPolarity_High;
	TIM_OCInitStruct.TIM_OCIdleState  = TIM_OCIdleState_Set;
	TIM_OCInitStruct.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
	
	TIM_OC1Init(TIM1,&TIM_OCInitStruct);
	TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);//使能自动重装载

  配置输出模式为PWM1,使能输出和互补输出。
  配置脉宽为4,这一位配置的是CCR寄存器的值,根据配置的不同可以控制占空比,上面配置了ARR为7,则现在占空比为 C C R A R R + 1 = 50 % \frac{CCR}{ARR+1}=50\% ARR+1CCR=50%
  配置输出和互补高电平有效,空闲时,输出为高电平有效,互补电平低电平。
  最后初始化输出配置,互补输出不用初始化。使能自动重装载。

死区刹车

/***********************TIM_BD**********************************/	
	TIM_BDTRInitStruct.TIM_OSSRState  = TIM_OSSRState_Enable;
	TIM_BDTRInitStruct.TIM_OSSIState  = TIM_OSSIState_Enable;
	TIM_BDTRInitStruct.TIM_LOCKLevel  = TIM_LOCKLevel_1;
	
	TIM_BDTRInitStruct.TIM_DeadTime   = 11;
	TIM_BDTRInitStruct.TIM_Break      = TIM_Break_Enable;
	
	TIM_BDTRInitStruct.TIM_BreakPolarity   = TIM_BreakPolarity_High;
	TIM_BDTRInitStruct.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
  	TIM_BDTRConfig(TIM1, &TIM_BDTRInitStruct);

  前两条语句设置运行或空闲时,启动刹车后引脚对应输出效果。TIM_LOCKLevel设置写保护级别。
  TIM_DeadTime 配置死区时间为152ns,TIM_Break 使能刹车。TIM_BreakPolarity 配置什么事件导致刹车,配置为高电平导致刹车(即PB12高电平时,刹车).

完整代码

static void ADVANCE_TIM_Mode_Config(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;
	TIM_OCInitTypeDef       TIM_OCInitStruct;
	TIM_BDTRInitTypeDef     TIM_BDTRInitStruct;
	
	RCC_APB1PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
/*********************TIM_BASE*********************************/	
	TIM_TimeBaseStruct.TIM_Period            = 7;    //ARR
	TIM_TimeBaseStruct.TIM_Prescaler         = 8;    //PSC
	TIM_TimeBaseStruct.TIM_ClockDivision     = TIM_CKD_DIV1;
	TIM_TimeBaseStruct.TIM_CounterMode       = TIM_CounterMode_Up;
	TIM_TimeBaseStruct.TIM_RepetitionCounter = 0;

	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStruct);
/***********************TIM_OC**********************************/
	TIM_OCInitStruct.TIM_OCMode       = TIM_OCMode_PWM1;
	TIM_OCInitStruct.TIM_OutputState  = TIM_OutputState_Enable;
	TIM_OCInitStruct.TIM_OutputNState = TIM_OutputNState_Enable;
	TIM_OCInitStruct.TIM_Pulse        = 4;
	TIM_OCInitStruct.TIM_OCPolarity   = TIM_OCPolarity_High;
	TIM_OCInitStruct.TIM_OCNPolarity  = TIM_OCNPolarity_High;
	TIM_OCInitStruct.TIM_OCIdleState  = TIM_OCIdleState_Set;
	TIM_OCInitStruct.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
	
	TIM_OC1Init(TIM1,&TIM_OCInitStruct);
	TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);//自动重装载
/***********************TIM_BD**********************************/	
	TIM_BDTRInitStruct.TIM_OSSRState  = TIM_OSSRState_Enable;
	TIM_BDTRInitStruct.TIM_OSSIState  = TIM_OSSIState_Enable;
	TIM_BDTRInitStruct.TIM_LOCKLevel  = TIM_LOCKLevel_1;
	
	TIM_BDTRInitStruct.TIM_DeadTime   = 11;
	TIM_BDTRInitStruct.TIM_Break      = TIM_Break_Enable;
	
	TIM_BDTRInitStruct.TIM_BreakPolarity   = TIM_BreakPolarity_High;
	TIM_BDTRInitStruct.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
  TIM_BDTRConfig(TIM1, &TIM_BDTRInitStruct);

	
	TIM_Cmd(TIM1,ENABLE);
	TIM_CtrlPWMOutputs(TIM1,ENABLE);//主使能
}

  最后使能定时器,高级定时器需要主输出使能。

封装

void ADVANCE_TIM_Init(void)
{
	ADVANCE_TIM_GPIO_Config();
	ADVANCE_TIM_Mode_Config();
}

main函数

int main(void)
{
	ADVANCE_TIM_Init();
	while(1)
	{	
	}
}
  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值