TIMER定时器
timer外设是STM32芯片当中比较复杂,而且功能比较强大的外设之一,主要有定时中断,输入捕获/输出比较,编码器等模式可以配置。把本章节我们首先先学习timer最基础的定时功能。
一个STM32芯片当中,有基本定时器,通用定时器,高级定时器(timer1/timer8)三种类型定时器,那么他们能够实现的功能都是可以向下兼容的,也就是说通用定时器可以实现基本定时器的所有功能,而高级定时器可以实现通用定时器的所有功能。
定时功能
定时器可以对输入的时钟进行计数,并在数值达到设定值时触发中断。
我们首先来看下定时器的电路结构:
通用定时器主要是分为4个部分,首先是时钟选择、极性选择的部分,主要是选择定时器的时钟来源。第二部分主要是时基单元的配置,配置他的预分频系数以及自动重装载计数器(这两个系数控制定时的长短)。之后便是输入捕获/输出比较两个部分了,这个之后我们学到了在进行详细的讲解。
产生定时中断的原理就是,我们选择时钟源,设置好他的预分频系数和自动重装载计数器的值(ARR),时基单元的CNT计数器按照一定的频率开始计数,当CNT的值达到ARR计数器的值之后,就会产生一个中断,我们就可以书写中断处理函数,在中断函数中完成自己想要的操作了。
配置流程
1.打开时钟
2.选择timer的时钟源
3.配置时基单元
4.配置NVIC中断
5.使能TIMER
6.中断服务函数
代码
/*
计数器频率:CK_CNT=CK_PSC(时钟源频率)/(PSC+1)(预分频系数)
计数器溢出频率(定时时间):CK_CNT_OV=CK_PSC/(PSC+1)/(ARR+1)
*/
void Timer_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//timer是在APB1总线上的
TIM_InternalClockConfig(TIM2);//选择内部时钟,也就是72M
//配置时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//和时基单元无关系,主要是与时钟源选择滤波有关,这里可以随意配置
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式
TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;//ARR寄存器的值(自动重装载计数器)
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;//psr,预分频系数
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//高级定时器用的参数(重复次数计数器)
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//开启更新中断
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置NVIC的中断分组,整个工程只需要设置一次,一般放在主函数当中
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//响应优先级
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2, ENABLE);
}
//中断服务函数
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
结语
本次主要是讲解定时中断,我们可以通过定时中断去定时做一些任务,比如定时发送消息日志等。关于定时中断一些小细节问题,就是影子寄存器等一些小概念还需要大家自己学习。