一、定时器简介
定时器对输入时钟进行计数,并在计数值达到设定值时触发中断。主体部分是16位的计数器、预分频器和自动重装寄存器组成的时基单元。
本文以STM32F103C8T6为例,介绍通用定时器的结构以及TIM2的初始化流程,在最后编写了初始化函数。此芯片有3个通用定时器:TIM2、TIM3、TIM4。
二、定时器的结构
下图是通用定时器的结构,本文主要配置上半部分定时器的内部时钟输入和时基单元 (内部输入时钟频率为72MHz),不涉及下半部分的输出比较和输入捕获。
下图是B站江科大做的定时中断结构图,初始化时只需从左到右依次配置 内部时钟、时基单元 、中断控制器 (NVIC) 、最后启动 运行控制 就完成了定时器TIM2的初始化 (如不需要使用中断可跳过第三步) 。
三、时基单元
1. 时基单元包含:
- 计数器寄存器(TIMx_CNT)
- 预分频器寄存器 (TIMx_PSC)
- 自动装载寄存器 (TIMx_ARR)
2. 寄存器值的计算:
- 计数器计数频率:CK_CNT= CK_PSC / (PSC + 1)
- 计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1)
= CK_PSC / (PSC + 1) / (ARR + 1 )
例如:定时器每过1秒产生一次中断,则中断频率 (溢出频率)为1Hz。内部时钟为72MHz,可取 PSC = 7200 - 1 、ARR = 10000 - 1 (或PSC = 3600 - 1 、ARR = 20000 - 1) 。计算CK_CNT_OV = 72M / 7200 / 10000 = 1Hz
三、初始化实例程序
1. 初始化函数
代码如下:
void Timer_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能,TIM2挂载在APB1总线
TIM_InternalClockConfig(TIM2); //使用内部时钟(默认)72MHz
//外部时钟配置: 使用外部时钟(计数器功能)
//TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00);
//配置时基单元
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; //PSC预分频率的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器,用于高级定时器
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //TIM2初始化
TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清除中断标志位(不清除会在初始化完成后立即进入中断)
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //定时器中断使能,不用中断无需配置
//NVIC(嵌套向量中断控制器)配置,不用中断无需配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //NVIC优先级分组
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //IRQ通道
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //响应优先级
NVIC_Init(&NVIC_InitStructure); //NVIC初始化
TIM_Cmd(TIM2, ENABLE); //启动定时器
}
2. 中断服务函数
代码如下:
void TIM2_IRQHandler(void) //TIM2_IRQHandler:中断向量地址,定义在汇编启动文件
{
if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) //判断中断标志位
{
; //中断服务程序
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除中断标志位(不清除会一直重复执行中断函数)
}
}
总结
本文介绍了通用定时器TIM2的初始化程序,如需初始化其他通用定时器,可将程序中TIM2修改为TIMx (x = 2~4) 。详细教程请参考B站江科大的STM32入门教程。