简介
定时器的主要功能是用来定时,不过STM32中有多种类型的定时器-----基本定时器、通用定时器、高级控制定时器,以STM32F103ZET6为例,有有 8 个16位定时器,其中 TIM6 和 TIM7 是基本定时器,TIM2/3/4/5是通用定时器 ,TIM1/8是高级定时器,本篇主要讲基本定时器。
寄存器
- TIM6 和TIM7 控制寄存器 1(TIMx_CR1)
- TIM6 和TIM7 控制寄存器 1(TIMx_CR1)
- TIM6 和TIM7 控制寄存器 1(TIMx_CR1)
- TIM6 和TIM7 状态寄存器(TIMx_SR)
- TIM6 和TIM7 事件产生寄存器(TIMx_EGR)
- TIM6 和TIM7 计数器(TIMx_CNT)
- TIM6 和TIM7 计数器(TIMx_CNT)
- TIM6 和TIM7 计数器(TIMx_CNT)
功能框图
- 这里的CK_CNT也就是计数器时钟,是TIMxCLK经过PSC预分频器分频后得到的,PSC预分频器可以设置的分频范围为: 1~65536 ,具体计算方式为: CK_CNT=TIMxCLK/(PSC+1),注意这里的PSC要加一,因为不可能有0分频存在,至少是1分频
- 对于基本定时器只能向上计数,也就是只能从小加到大,加到多少主要由自动重装载寄存器 ARR决定,ARR是一个16位的寄存器,里面装着计数器能加到的最大值,如果计数器加到了这个值并且使能了中断的话就会产生溢出中断(更新中断)
- 由于基本定时器向上计数是从0开始的,因此计数的初始值为0,所以我们设置ARR的值的时候要减去1,也就是ARR-1,比如我们要计数十次,那么久设置ARR的值为9,因为计数是从0开始的,0计数到9就是计数了十次
定时时间的计算
每次计数加1的时候所需要的时间为:1/CK_CNT,而CK_CNT=TIMxCLK/(PSC+1),对于STM32F1系列,基本定时器的TIMxCLK的频率为72MHz,为了方便计算,我们把PSC+1设置成72,刚好可以得到一个整数的CK_CNT,这时候每一次计数+1所需的时间为:1us,一微秒,所以如果要计时1ms,就把ARR的值设置成999,也就是1us计数一千次
基本定时器的结构体
typedef struct {
TIM_Prescaler // PSC分频因子
TIM_CounterMode // 计数模式,基本定时器只能向上计数,不用设置
IM_Period //自动重转载寄存器ARR的值
TIM_ClockDivision // 外部输入时钟分频因子,基本定时器没有,其他都有
TIM_RepetitionCounter // 重复计数器,基本定时器没有
} TIM_TimeBaseInitTypeDef;
由此可知,对于基本定时器我们只需配置
- PSC分频因子 TIM_Prescaler
- 自动重转载寄存器ARR的值 IM_Period
利用基本定时器6实现500ms延时
首先先来计算一下产生1ms的延时要怎么配置ARR和PSC
首先把PSC预分频设置成72分频,也就是TIM_Prescaler =71,这时候每次计数所用时间为1us,我们计数1000次就是1ms,所以ARR的值要设置成999,也就是IM_Period = 999
配置流程图:
代码:
#include "stm32f10x.h"
#include "bsp_led.h"
uint16_t time=0;//定义全局变量time
//TIM6定时器NVIC配置
void TIM_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;//中断源
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//主优先级为 0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//NVIC使能
NVIC_Init(&NVIC_InitStructure);
}
//TIM6初始化
void BasicTIM_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);//使能定时器时钟
TIM_TimeBaseStructure.TIM_Period = 999; //自动重转载寄存器
TIM_TimeBaseStructure.TIM_Prescaler = 71; //PSC分频因子
TIM_TimeBaseInit(TIM6,&TIM_TimeBaseStructure);
TIM_ClearFlag(TIM6, TIM_FLAG_Update); //清除中断标志
TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);// 开启计数器中断
TIM_Cmd(TIM6, ENABLE);// 使能计数器
TIM_NVIC_Config();//TIM6定时器NVIC配置
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,DISABLE);//暂时关闭定时器的时钟 需要使用时再打开
}
//开启定时器6
void TIM6_ON()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);
}
//关闭定时器6
void TIM6_OFF()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,DISABLE);
}
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//由于使用到了中断,因此这里需要设置优先级分组
LED_Config();//初始化LED
BasicTIM_Config();//初始化TIM6
TIM6_ON();//开启定时器6
while(1)
{
if(time >= 500) //如果时间到了500ms
{
time = 0;
LED1(TOGGLE);//LED亮或灭
}
}
}
//TIM6中断服务函数
void TIM6_IRQHandler(void)
{
if(TIM_GetITStatus( TIM6, TIM_IT_Update) != RESET )//如果TIM6产生了更新中断
{
time++; //通过前面的运算,每产生一次更新中断的时间是1ms(计数器每次溢出为1ms)
TIM_ClearITPendingBit(TIM6 , TIM_FLAG_Update);//清除中断标志位
}
}