有了视频之后,接下来我们一起来学习STM32的定时器吧。
先来了解了解STM32F103C8T6的定时器,此芯片一共有四个定时器,其中一个高级定时器TIM1,3个通用定时器TIM2~TIM3,我主要学习的是通用定时器。高级定时器我自己现在学得还不是很明白,呵呵。通用定时器有四个独立通道。可以用来作为输入捕获、输出比较,PWM生成(边缘或中间对齐模式)、单脉冲模式输出。
这个小车四个定时器均有使用,其中使用了TIM2和TIM4的编码器,TIM3用于PWM波输出功能。定时器的溢出时间公式计算如下:
Tout=((arr+1)×(psc+1))/Tclk。
其中Tclk为TIM3的输入时钟频率,Tout为TIM3溢出时间
注意:STM32的通用定时器是挂在APB1上的,但是时钟频率是72MHz,是APB1的两倍
接下来以TIM2的定时器中断为例介绍一下定时器的使用过程
第一步:TIM2时钟使能
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
第二步:初始化定时器参数
定时器的参数全在下面这个结构体里面
typedef struct
{
uint16_t TIM_Prescaler;
uint16_t TIM_CounterMode;
uint16_t TIM_Period;
uint16_t TIM_ClockDivision;
uint8_t TIM_RepetitionCounter;
} TIM_TimeBaseInitTypeDef;
第一个参数是用来设置分频系数的。
第二个参数是用来设置计数方式的,有向上计数、向下计数和中央对齐计数方式,比较常用的是向上计数模式。
第三个参数是设置自动重载计数周期值
第四个参数是用来设置时钟分频因子的
第五个参数只有使用高级定时器时才使用,这里就先不做介绍。
第三步:设置TIM2的允许更新中断,在库函数中是通过TIM_ITConfig函数来实现的
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
第四步:进行TIM2的中断优先级设置
在定时器中断使能之后因为要产生中断,必不可少地要设置NVIC相关寄存器及中断优先级。
关于中断优先级的讲解,下面这个链接讲的还是比较清楚
http://www.amobbs.com/thread-5540241-1-1.html
第五步:使能定时器TIM2
光配置好定时器还不能使用,不要忘了还要开启它哦
TIM_Cmd(TIM2, ENABLE);
第六步:编写中断服务函数
定时器溢出中断后,我们就可以在中断服务函数干自己想干的事啦,哈哈
接下来还是贴上我自己的代码吧
void TIM2_Init(u16 arr, u16 psc) //arr:自动重装值。psc:时钟预分频数
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseStructure.TIM_Period = arr;
TIM_TimeBaseStructure.TIM_Prescaler = psc;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
//TIM_TimeBaseStructure.TIM_RepetitionCounter = 高级定时器才用,通用定时器不用
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2, ENABLE);
}
这就是定时器参数的配置代码,在附上中断函数的代码吧
void TIM2_IRQHandler(void) { if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { LED1 =! LED1; TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } }