一、定时器的分类
STM32F1 系列中,除了互联型的产品,共有 8 个定时器,分为基本定时器,通用定时器和高级
定时器。
基本定时器
TIM6 和 TIM7 是一个 16 位的只能向上计数的定时器,只能定时,没有外部IO。
通用定时器
TIM2/3/4/5 是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,每个定时器有四个外部 IO。
高级定时器
TIM1/8 是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,还可以有三相电机互补输出信号。
二、基本定时器功能框图
1.1、时钟源
基本定时器的时钟源主要由内部时钟CK_INT经APB1预分频器分频提供,如果 APB1 预分频
系数等于 1,则频率不变,否则频率乘以 2,库函数中 APB1 预分频的系数是 2,即 PCLK1=36M,所以定时器时钟 TIMxCLK=36*2=72M。
1.2、计数器时钟
定时器时钟经过 PSC 预分频器之后,用来驱动计数器计数。 PSC 是一个 16 位的预分频器,可以对定时器时钟 TIMxCLK 进行 1~65536 之间的任何一个数进行分频。
具体计算方式为: CK_CNT=TIMxCLK/(PSC+1)
1.3、计数器
计数器 CNT 是一个 16 位的计数器,只能往上计数,最大计数值为 65535。当计数达到自动重装
载寄存器的时候产生更新事件,并清零从头开始计数
1.4、自动重装载寄存器
自动重装载寄存器 ARR 是一个 16 位的寄存器,这里面装着计数器能计数的最大数值。当计数到
这个值的时候,如果使能了中断的话,定时器就产生溢出中断。
1.5、定时时间计算
定时器的定时时间等于计数器的中断周期乘以中断的次数。计数器在 CK_CNT 的驱动下,计一个数的时间则是 CK_CLK 的倒数,等于: 1/(TIMxCLK/(PSC+1)),产生一次中断的时间则等于:1/(CK_CLK * ARR)。如果在中断服务程序里面设置一个变量 time,用来记录中断的次数,那么就可以计算出我们需要的定时时间等于: 1/CK_CLK* (ARR+1)*time。
PSC=72-1 72M/72=1M=1us
计数65526 65536us=65ms
设定ARR=1000-1 1000us=1ms
三、基本定时器-定时闪烁LED
TIM.H
#ifndef __TIMING_H
#define __TIMING_H
extern uint16_t tim;
#define RCC_TIMx_CLK RCC_APB1Periph_TIM6
#define TIMx TIM6
#define TIM_PSC 72-1
#define TIM_ARR 1000-1
void TIMing_Init(void);
#endif
TIM.C
#include "stm32f10x.h"
#include "timing.h"
uint16_t tim=0;
void NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel=TIM6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; //抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0; //响应优先级
NVIC_Init(&NVIC_InitStructure);
}
void TIMing_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
//初始化外设时钟
RCC_APB1PeriphClockCmd(RCC_TIMx_CLK,ENABLE);
//初始化时基单元
TIM_TimeBaseInitStructure.TIM_Prescaler=TIM_PSC;//预分频系数
TIM_TimeBaseInitStructure.TIM_Period=TIM_ARR;//计数设定值
// TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
// TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//默认向上计算
// TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//高级定时器才有效
TIM_TimeBaseInit(TIMx,&TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIMx,TIM_FLAG_Update);//清除TIM中断标志
TIM_ITConfig(TIMx,TIM_IT_Update,ENABLE);//启用指定的定时中断
TIM_Cmd(TIMx,ENABLE);
}
void TIMing_Init(void)
{
NVIC_Config();
TIMing_Config();
}
void TIM6_IRQHandler(void)
{
if(TIM_GetITStatus(TIMx,TIM_IT_Update)==SET)
{
tim++;
TIM_ClearITPendingBit(TIMx,TIM_IT_Update);
}
}
Main.c
#include "stm32f10x.h" // Device header
#include "led.h"
#include "timing.h"
int main(void)
{
LED_Init();
TIMing_Init();
while(1)
{
if(tim==500)
{
LED_ON();
}
if(tim==1000)
{
tim=0;
LED_OFF();
}
}
}