一 定时器分类
STM32F1
系列中,除了互联型的产品,共有
8
个定时器,分为基本定时器,通用定时
二. 基本定时器功能框图讲解
基本定时器的核心是时基,不仅基本定时器有,通用定时器和高级定时器也有。学习
定时器时,我们先从简单的基本定时器学起,到了后面的通用和高级定时器的学习中,我
们直接跳过时基部分的讲解即可。基本定时器的功能框图见图
①时钟源
定时器时钟
TIMxCLK
,即内部时钟
CK_INT
,经
APB1
预分频器后分频提供,如果
数是
2
,即
PCLK1=36M
,所以定时器时钟
TIMxCLK=36*2=72M
。
②计数器时钟
具体计算方式为:
CK_CNT=TIMxCLK/(PSC+1)
。
③计数器
到自动重装载寄存器的时候产生更新事件,并清零从头开始计数。
④自动重装载寄存器
值。当计数到这个值的时候,如果使能了中断的话,定时器就产生溢出中断。
定时时间的计算
下,计一个数的时间则是
CK_CLK
的倒数,等于:
1/
(
TIMxCLK/(PSC+1)),产生一次中
来 记 录 中 断的 次 数,那 么 就 可 以计 算 出我们 需 要 的 定时 时 间等于 :
1/CK_CLK *
(ARR
+1)
*time
。
二 固件库讲解
定时器基本初始化结构体
1 typedef
struct
{
2
uint16_t
TIM_Prescaler;
//
预分频器
3
uint16_t
TIM_CounterMode;
//
计数模式
4
uint32_t
TIM_Period;
//
定时器周期
5
uint16_t
TIM_ClockDivision;
//
时钟分频
6
uint8_t
TIM_RepetitionCounter;
//
重复计算器
7
} TIM_TimeBaseInitTypeDef;
(1) TIM_Prescaler
:定时器预分频器设置,时钟源经该预分频器才是定时器时钟,它设定
TIMx_PSC
寄存器的值。可设置范围为
0
至
65535
,实现
1
至
65536
分频。
(2) TIM_CounterMode
:定时器计数方式,可是在为向上计数、向下计数以及三种中心对
齐模式。基本定时器只能是向上计数,即
TIMx_CNT
只能从
0
开始递增,并且无需初
始化。
影子寄存器。可设置范围为
0
至
65535
。
(4) TIM_ClockDivision
:时钟分频,设置定时器时钟
CK_INT
频率与数字滤波器采样时钟
频率分频比,基本定时器没有此功能,不用设置。
(5) TIM_RepetitionCounter
:重复计数器,属于高级控制寄存器专用寄存器位,利用它可
虽然定时器基本初始化结构体有
5
个成员,但对于基本定时器只需设置其中两个就可
以,想想使用基本定时器就是简单
三 基本定时器定时实验
本实验利用基本定时器
TIM6/7
定时
1s
,
1s
时间到
LED
翻转一次。基本定时器是
编程要点
(1)
开定时器时钟
;
(2)
初始化时基初始化结构体
;
(3)
使能
TIMx[6,7] update
中断;
(4)
打开定时器;
(5)
编写中断服务程序
通用定时器和高级定时器的定时编程要点跟基本定时器差不多,只是还要再选择下计
数器的计数模式,是向上还是向下。因为基本定时器只能向上计数,且没有配置计数模式
的寄存器,默认是向上
#include "basetime.h"
// 中断优先级配置
static void BASIC_TIM_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); // 设置中断组为0
NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn ; // 设置中断来源
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 设置主优先级为 0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 设置抢占优先级为3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //打开中断大门
NVIC_Init(&NVIC_InitStructure);
}
static void BASIC_TIM_Mode_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);// 开启定时器时钟,即内部时钟CK_INT=72M
TIM_TimeBaseStructure.TIM_Period = 1000-1;// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Prescaler= 72-1;// 时钟预分频数为
//TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;// 时钟分频因子 ,基本定时器没有,不用管
//TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; // 计数器计数模式,基本定时器只能向上计数,没有计数模式的设置
//TIM_TimeBaseStructure.TIM_RepetitionCounter=0;// 重复计数器的值,基本定时器没有,不用管
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure); // 初始化定时器
/*它由软件清除。0:没有产生更新。 1:产生了更新中断。下述情况下由硬件设置该位
计数器产生上溢或下溢并且TIMx_CR1中的Udis=0;
– 如果TIMx_CR1中的URS=0并且Udis=0,当使用TIMx_EGR寄存器的UG位重新初始化计数器CNT时。*/
TIM_ClearFlag(TIM6, TIM_FLAG_Update);// 清除计数器中断标志位
TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);// 开启计数器中断小门:使能更新中断,操作DIRE寄存器
TIM_Cmd(TIM6, ENABLE); // 使能计数器
}
void BASIC_TIM_Init(void)
{
BASIC_TIM_NVIC_Config();
BASIC_TIM_Mode_Config();
}
#include "stm32f10x.h"
#include "led.h"
#include "key.h"
#include "rcc.h"
#include "exti.h"
#include "systick.h"
#include "usart.h"
#include <stdio.h>
#include "basetime.h"
uint32_t time = 0; // ms 计时变量
int main(void)
{
LED0_GPIO_Config();
BASIC_TIM_Init();
while (1){
if ( time == 1000 ) /* 1000 * 1 ms = 1s 时间到 */
{
time = 0;
LED0_TOGGLE;
}
}
}