XuSenfeng

个人站

复读了,更新随缘,有的文件不全或者图片缺失具体看我的笔记库(https://github.com/XuSenfeng/note)


定时器

目录

定时器

有三种功能, 定时, 输出比较, 输出捕获, 互补输出

有三种: 基本定时器: 定时

通用定时器: 没有互补

高级定时器: 都有

image-20230717150629149

基本定时器

16bit, 只能向上计数, 只有TIM6, TIM7

没有GPIO, 是内部资源, 时钟来自PCLK1, 72M可以实现1-65535分频,

image-20230717151044639

控制器: 复位, 使能, 计数, 触发DAC, 涉及的寄存器是CR1/2, DIER, SR

时基单元: 包括预分频器, 计数器, 自动重装载寄存器, 计数时钟CK_CNT = CK_PSC/(PSC+1)

影子寄存器: 起到缓冲寄存器, 有一个缓冲的功能, 用户值->寄存器->影子寄存器->起作用, 不使用的话用户的值写到之后起作用, 使用的话这一周期计数之后起作用, TIMx_CR1:APRE控制

stm32实现

  • TIMx_CR1: 控制寄存器

image-20230717153402120

image-20230717154321210

  • TIMx_CR2
  • TIMx_SMCR: 从模式控制寄存器
  • TIMx_DIER: DMA/中断使能寄存器
  • TIMx_SR: 状态寄存器
  • TIMx_EGR: 事件产生寄存器
  • TIMx_CCMR1: 捕获/比较模式寄存器

image-20230717172716414

image-20230717172857298

  • TIMx_CCMR2
  • TIMx_CCER: 捕获/比较使能寄存器

image-20230717173212170

  • TIMx_CNT: 计数器

image-20230717154825674

  • TIMx_PSC: 预分频器

image-20230717154814765

  • TIMx_ARR: 自动重装载寄存器

image-20230717154804279

  • TIMx_RCR

image-20230717155356355

计数器的值到达之后不发生中断, 到达这个值的时候才产生

  • TIMx_CCR1: 捕获/比较寄存器
  • TIMx_CCR2
  • TIMx_CCR3
  • TIMx_CCR4
  • TIMx_BDTR: TIM1 和TIM8 刹车和死区寄存器

image-20230719100615309

  • TIMx_DCR: DMA控制寄存器
  • TIMx_DMAR: 连续模式的DMA地址

固件库

typedef struct
{
  uint16_t TIM_Prescaler;         /*!< Specifies the prescaler value used to divide the TIM clock.
                                       This parameter can be a number between 0x0000 and 0xFFFF 
                                       分频因子*/

  uint16_t TIM_CounterMode;       /*!< Specifies the counter mode.
                                       This parameter can be a value of @ref TIM_Counter_Mode
                                       计数模式, 基础寄存器只能向下计数*/

  uint16_t TIM_Period;            /*!< Specifies the period value to be loaded into the active
                                       Auto-Reload Register at the next update event.
                                       This parameter must be a number between 0x0000 and 0xFFFF.
                                       自动重装载*/ 

  uint16_t TIM_ClockDivision;     /*!< Specifies the clock division.
                                      This parameter can be a value of @ref TIM_Clock_Division_CKD
                                      外部输入时钟分频因子, 基础定时器没有*/

  uint8_t TIM_RepetitionCounter;  /*!< Specifies the repetition counter value. Each time the RCR downcounter
                                       reaches zero, an update event is generated and counting restarts
                                       from the RCR value (N).
                                       This means in PWM mode that (N+1) corresponds to:
                                          - the number of PWM periods in edge-aligned mode
                                          - the number of half PWM period in center-aligned mode
                                       This parameter must be a number between 0x00 and 0xFF. 
                                       @note This parameter is valid only for TIM1 and TIM8.
                                       重复计数器, 高级计数器的*/
} TIM_TimeBaseInitTypeDef;  

实际使用

void BASIC_TIM_Config(void)
{
	TIM_TimeBaseInitTypeDef TIM_BaseStructure;
	BASIC_TIM_APBxClock_FUN(BASIC_TIM_CLK, ENABLE);
	
	
	TIM_BaseStructure.TIM_Period = BASIC_TIM_Period;
	
	TIM_BaseStructure.TIM_Prescaler = BASIC_TIM_Prescaler;
	/****基础定时器没有****/
	TIM_BaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_BaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_BaseStructure.TIM_RepetitionCounter = 0;
	/********************/
	
	TIM_TimeBaseInit(BASIC_TIM, &TIM_BaseStructure);
    //清除中断标志位
	TIM_ClearFlag(BASIC_TIM, TIM_FLAG_Update);
	TIM_ITConfig(BASIC_TIM, TIM_FLAG_Update, ENABLE);
	TIM_Cmd(BASIC_TIM, ENABLE);
	
}

高级定时器

定时, 输出比较, 输出捕获, 输入捕获, 互补输出, 断路输出

16bit, 上/下/两边计数, 重复计数器, 四个GPIO, 通道1-3还有互补输出GPIO, 时钟使用PCLK2, 72M

image-20230717171657107

image-20230717171928852

image-20230717171950102

时钟源: CK_INT(TIMx_CLK在PSC分频之后), 内部时钟, 72MHz,

image-20230717172438019

来自外部GPIO, 对应TIMx_CH1/2/3/4, TIM_CCMRx的CCxS位控制, 经过滤波(TIMx_CCMR:ICxF)之后, 之后进行边沿检测, 控制有效的边沿, TIM_CCER:CCxP和CCxNP, 最后进行触发选择, 很少使用

image-20230717194237657

f~DTS~, TIMx_CR1:CKD决定,

内部触发输入

使用一个定时器作为另一个定时器的预分频器, 实现级联, TIMx_SMCR:TS

**总结: **有四种输入源, 内部时钟CK_INT, 外部时钟1引脚TIx, 外部触发输入ETR, 内部触发输入

  • 时基同普通

image-20230717200012120

  • 输入捕获

image-20230717200024126

对信号的上升下降或者双边捕获, 大概的原理就是跳变的时候把CNT计数器的值捕获到CCR寄存器

① 输入通道, 输入的信号从定时器外部引脚TIMx_CH1/2/3/4进入, 通常叫TI1/2/3/4

② 输入滤波以及边沿检测, 存在高频干扰的信号进行滤波

③ 捕获通道, 捕获的时候CNTx计入CCRx, 一个输入通道可以进入两个捕获通道(PWM捕获, 只能使用IC1, IC2)

image-20230717201101387

④ 预分频器

⑤ 捕获寄存器, 会产生 CCxI 中断,相应的中断位 CCxIF(在 SR 寄存器中)会 被置位,通过软件或者读取 CCR 中的值可以将 CCxIF 清 0。如果发生第二次捕获(即重复捕获: CCR 寄存器中已捕获到计数器值且 CCxIF 标志已置 1),则捕获溢出标志位 CCxOF(在 SR 寄存 器中)会被置位,CCxOF 只能通过软件清零。

  • 输出比较

image-20230717201347531

计数到CCR的时候发生电平跳变, 计数到ARR的时候重装载切跳变

DTG: 死区寄存器, 一般输出的PWM不可以直接驱动电机, 需要一个半桥驱动电路, 需要互补的PWM信号, 加入PWM的时候由于MOS管打开关闭需要一定时间, 所以需要预留一定的时间, 这就是死区

输出控制, 不需要了解

image-20230717202403178

实际使用

  • 测量脉宽和频率

当测试到跳变的时候会发生中断, 测量脉宽的时候需要不断地改变触发的边沿

  • PWM输入模式

通道一通道二, IC1是周期, IC2是占空比, 也可以反过来叫做非直连

在第一个上升沿发生跳变, IC2在第一个下降沿发生捕获, IC1在下一个上升沿发生捕获

image-20230718183208629

计数的值是从零开始, 计算的时候需要加一

  • 输出比较

一共有八种, )CCMRx的OCxM配置

一般使用为PWM模式, 频率是ARR控制, 占空比CRR

image-20230718183715608

中心对齐模式, 计数器达到重装载的值之后向下计数, 重新回到0之后开始递增

PWM

image-20230718184739691

原理, 输出的信号主要控制CCR以及ARR, 以及PSC进行分频

typedef struct
{
  uint16_t TIM_OCMode;        /*!< Specifies the TIM mode.
                                   This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes
                                   使用的PWM模式*/

  uint16_t TIM_OutputState;   /*!< Specifies the TIM Output Compare state.
                                   This parameter can be a value of @ref TIM_Output_Compare_state
                                   设置的是正通道*/

  uint16_t TIM_OutputNState;  /*!< Specifies the TIM complementary Output Compare state.
                                   This parameter can be a value of @ref TIM_Output_Compare_N_state
                                   @note This parameter is valid only for TIM1 and TIM8.
                                   设置的是互补通道*/

  uint16_t TIM_Pulse;         /*!< Specifies the pulse value to be loaded into the Capture Compare Register. 
                                   This parameter can be a number between 0x0000 and 0xFFFF
                                   设置的是比较寄存器的值*/

  uint16_t TIM_OCPolarity;    /*!< Specifies the output polarity.
                                   This parameter can be a value of @ref TIM_Output_Compare_Polarity
                                   设置的是极性, 设置是高电平有效还是低电平有效*/

  uint16_t TIM_OCNPolarity;   /*!< Specifies the complementary output polarity.
                                   This parameter can be a value of @ref TIM_Output_Compare_N_Polarity
                                   @note This parameter is valid only for TIM1 and TIM8. */

  uint16_t TIM_OCIdleState;   /*!< Specifies the TIM Output Compare pin state during Idle state.
                                   This parameter can be a value of @ref TIM_Output_Compare_Idle_State
                                   @note This parameter is valid only for TIM1 and TIM8. 
                                   输出的时候空闲电平极性设置, 用到断路功能的时候使用*/

  uint16_t TIM_OCNIdleState;  /*!< Specifies the TIM Output Compare pin state during Idle state.
                                   This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State
                                   @note This parameter is valid only for TIM1 and TIM8. */
} TIM_OCInitTypeDef;

输出比较控制结构体

typedef struct
{

  uint16_t TIM_Channel;      /*!< Specifies the TIM channel.
                                  This parameter can be a value of @ref TIM_Channel */

  uint16_t TIM_ICPolarity;   /*!< Specifies the active edge of the input signal.
                                  This parameter can be a value of @ref TIM_Input_Capture_Polarity */

  uint16_t TIM_ICSelection;  /*!< Specifies the input.
                                  This parameter can be a value of @ref TIM_Input_Capture_Selection */

  uint16_t TIM_ICPrescaler;  /*!< Specifies the Input Capture Prescaler.
                                  This parameter can be a value of @ref TIM_Input_Capture_Prescaler */

  uint16_t TIM_ICFilter;     /*!< Specifies the input capture filter.
                                  This parameter can be a number between 0x0 and 0xF */
} TIM_ICInitTypeDef;

输入

typedef struct
{

  uint16_t TIM_OSSRState;        /*!< Specifies the Off-State selection used in Run mode.
                                      This parameter can be a value of @ref 
                                      OSSR_Off_State_Selection_for_Run_mode_state 
                                      运行模式下关闭状态的选择
                                      0:当定时器不工作时,禁止OC/OCN输出(OC/OCN使能输出信号=0);
								   1:当定时器不工作时,一旦CCxE=1或CCxNE=1,首先开启OC/OCN并输出无效电平,然后
								   置OC/OCN使能输出信号=1。*/

  uint16_t TIM_OSSIState;        /*!< Specifies the Off-State used in Idle state.
                                      This parameter can be a value of @ref 
                                      OSSI_Off_State_Selection_for_Idle_mode_state 
                                      空闲模式下关闭状态的选择*/

  uint16_t TIM_LOCKLevel;        /*!< Specifies the LOCK level parameters.
                                      This parameter can be a value of @ref Lock_level
                                      写保护寄存器*/ 

  uint16_t TIM_DeadTime;         /*!< Specifies the delay time between the switching-off and the
                                      switching-on of the outputs.
                                      This parameter can be a number between 0x00 and 0xFF 
                                      死区时间*/

  uint16_t TIM_Break;            /*!< Specifies whether the TIM Break input is enabled or not. 
                                      This parameter can be a value of @ref Break_Input_enable_disable
                                      刹车是否使能*/

  uint16_t TIM_BreakPolarity;    /*!< Specifies the TIM Break Input pin polarity.
                                      This parameter can be a value of @ref Break_Polarity
                                      引脚为什么电平的时候进行刹车*/

  uint16_t TIM_AutomaticOutput;  /*!< Specifies whether the TIM Automatic Output feature is enabled or not. 
                                      This parameter can be a value of @ref TIM_AOE_Bit_Set_Reset 
                                      自动使能输出*/
} TIM_BDTRInitTypeDef;

刹车死区控制

实际PWM

#include "bsp_pwm.h"

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);	
}

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;	
	// 时钟分频因子 ,配置死区时间时需要用到,配置的是CK_INT,死区时间采用的分频
	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);
	
}

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