stm32定时器分三种,TIM1和TIM8是高级定时器,TIM2~TIM5是通用计时器,TIM6和TIM7是基本定时器。本文主要讲解TIM1。
下面是定时器1的配置代码:
GPIO_InitTypeDef GPIO_InitStructure2;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//定时器基本配置
TIM_OCInitTypeDef TIM_OCInitStructure;//pwm输出配置
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;//死区和刹车功能配置,高级定时器独有
第一步:配置时钟
/* Enable GPIOA, GPIOC, GPIOE, AFIO clocks */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA |
RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOB| RCC_APB2Periph_GPIOD, ENABLE);
/* Enable TIM1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
第二步,配置gpio口
/* GPIOE Configuration: Channel 1, 1N, 2, 2N, 3, 3N and 4 Output */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
第三步,定时器基本配置
/* TIM1 Registers reset */
TIM_DeInit(TIM1);//初始化TIM1
/* Time Base configuration */
TIM1_TimeBaseStructure.TIM_Prescaler = psc;//设置时钟频率除数的预分频值
TIM1_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1;//对齐模式,中心对齐1
TIM1_TimeBaseStructure.TIM_Period = arr;//设置自动重装载寄存器周期的值
TIM1_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV2;//设置时钟分割
// Initial condition is REP=0 to set the UPDATE only on the underflow
TIM1_TimeBaseStructure.TIM_RepetitionCounter = RCR;
TIM_TimeBaseInit(TIM1, &TIM1_TimeBaseStructure);
首先讲解TIM_RepetitionCounter,对应重复计数寄存器(TIMx_RCR),影响更新事件(中断)产生的周期。
下面看STM32参考手册中的一张图:
从图中不难发现;
中央对齐模式下:
- RCR = 0,更新事件没有延迟;
- RCR = 1,更新事件延后了半个PWM周期;
- RCR = 2, 更新事件延后了一个PWM周期;
- RCR = 3,更新事件延后了3/2个PWM周期。
因此,中央对齐模式,更新事件延迟的PWM
周期数量等于RCR/2。
RCR 寄存器的范围是 0~0xFF;
边沿对齐模式下:
- RCR = 0,更新事件没有延迟;
- RCR = 1,更新事件延后了一个PWM周期;
- RCR = 2, 更新事件延后了两个PWM周期;
- RCR = 3,更新事件延后了三个PWM周期。
因此,边沿对齐模式,更新事件延迟的PWM
周期数量等于RCR;
即,TIM_RepetitionCounter的作用是倍数中断更新事件的时间。
(1)中断时间计算
1.STM32时钟系统
参考正点原子讲解。
下面讲解系统时钟初始化函数。
/*******************************************************************************
* Function Name : RCC_Configuration
* Description : Configures the different system clocks.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void RCC_Configuration(void)
{
ErrorStatus HSEStartUpStatus;// 正\否标志结构体
/* RCC system reset(for debug purpose) */
RCC_DeInit();
/* Enable HSE */
RCC_HSEConfig(RCC_HSE_ON);
/* Wait till HSE is ready */
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if(HSEStartUpStatus == SUCCESS)
{
/* HCLK = SYSCLK */
RCC_HCLKConfig(RCC_SYSCLK_Div1);
/* PCLK2 = HCLK */
RCC_PCLK2Config(RCC_HCLK_Div1);
/* PCLK1 = HCLK/2 */
RCC_PCLK1Config(RCC_HCLK_Div2);
/* Flash 2 wait state */
FLASH_SetLatency(FLASH_Latency_2);
/* Enable Prefetch Buffer */
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
/* PLLCLK = 8MHz * 9 = 72 MHz */
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
/* Enable PLL */
RCC_PLLCmd(ENABLE);
/* Wait till PLL is ready */
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
{
}
/* Select PLL as system clock source */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* Wait till PLL is used as system clock source */
while(RCC_GetSYSCLKSource() != 0x08)
{
}
}
}
通过阅读RCC_Configuration()函数可知,函数开启了外部时钟HSE(8M),经9倍频后到达PLLCLK后变为72MHz。且AHB未分频,APB2未分频,所以APB2挂载的TIM1的时钟频率为72MHz。
接下来,我们可以计算TIM1的中断时间了。
实际频率 = 72MHz/psc;
中断时间 = arr/实际频率;
若是定义了重复定时器
TIM1_TimeBaseStructure.TIM_RepetitionCounter = RCR;
则实际中断时间 = 计算得到的中断时间*RCR;
第四步:pwm输出配置
/* Channel 1, 2,3 in PWM mode */
TIM1_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM1_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM1_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM1_OCInitStructure.TIM_Pulse = 0x505; //dummy value
TIM1_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM1_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM1_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM1_OCInitStructure.TIM_OCNIdleState = LOW_SIDE_POLARITY;
TIM_OC1Init(TIM1, &TIM1_OCInitStructure);
TIM_OC2Init(TIM1, &TIM1_OCInitStructure);
TIM_OC3Init(TIM1, &TIM1_OCInitStructure);
/* Channel 4 Configuration in OC */
TIM1_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM1_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM1_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
TIM1_OCInitStructure.TIM_Pulse = PWM_PERIOD - 1;
TIM1_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM1_OCInitStructure.TIM_OCNPolarity =TIM_OCNPolarity_Low;
TIM1_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM1_OCInitStructure.TIM_OCNIdleState = LOW_SIDE_POLARITY;
TIM_OC4Init(TIM1, &TIM1_OCInitStructure);
/* Enables the TIM1 Preload on CC1 Register */
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
/* Enables the TIM1 Preload on CC2 Register */
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
/* Enables the TIM1 Preload on CC3 Register */
TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);
/* Enables the TIM1 Preload on CC4 Register */
TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);
参数TIM_OCMode。
TIMx_CCR1即 TIM1_OCInitStructure.TIM_Pulse。
TIM_OC4Init()可以跳过,这里定义只是预留一下,便于修改。
TIM_OC1PreloadConfig(x,x)如果使能了这个函数,则占空比发生改变后,不会立即生效,而是等下一个中断发生后才会更新。
第五步:死区和刹车功能配置,高级定时器独有
/* Automatic Output enable, Break, dead time and lock configuration*/
TIM1_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM1_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM1_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
TIM1_BDTRInitStructure.TIM_DeadTime = DEADTIME;
TIM1_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
TIM1_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low;
TIM1_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;
TIM_BDTRConfig(TIM1, &TIM1_BDTRInitStructure);