一、stm32f103系列定时器介绍
先声明:stm32f103c8t6中没有基本定时器、只有TIM1-TIM4:分别是高级定时器和通用定时器(对照下图请自行阅读stm32f103x的datasheet)1、定时器功能:定时、输出比较、输入捕获、互补输出,其中基本定时器只有定时功能、通用定时器只没有互补输出功能、高级定时器具有所有功能。2、定时器分类:
(1)基本定时器:TIM6、7
(2)通用定时器:TIM2345
(3)高级定时器:TIM1、8
3、定时器总线时钟:
无特殊情况,给到定时器的内部时钟都是72M
二、基本定时器
基本定时器分为三部分讲解:
(1)时钟源
(2)控制器
(3)时基单元
1、时钟源
时钟源来自RCC的TIMXCLK,就是内部时钟(CK_INT)直接经过控制器传给时基单元充当CK_PSC
2、控制器
控制定时器的复位、使能、计数、DAC触发
3、时基单元
基本定时器的时基单元包括三个部分
(1)预分频器:分频、得到计时器的时钟,即CNT计数1次所需要的时间,预分频器时16位的寄存器、所以可分频为1-65536
(2)计数器:用来计数、基本定时器的CNT计数器只能向上计数
(3)自动装载寄存器ARR:即CNT加到ARR的值之后,会产生一个事件或中断或DMA请求,中断用得比较多(定时x时间之后、当点灯大师)
(4)其实、时基单元里面还有非常重要的寄存器、叫做影子寄存器,什么是影子寄存器呢?仔细看上面的图会发现PSC和自动重装载寄存器ARR都有阴影,它们就是影子寄存器
影子寄存器的作用:其实,PSC和ARR都是当影子寄存器被写入新的值时,电路才会生效,所以是用户值->寄存器->影子寄存器->生效,影子寄存器可以起到缓冲的作用,一般不会使用影子寄存器
如何实现500ms定时
1.分频器PSC设置:72-1(即计数器时钟为1us)
2.ARR设置为1000,即计数一次1ms
3.可通过计数产生中断,中断里面设置全局变量,每次加1,当从0加到500时,就是500ms了。
基本定时器代码实例
bsp_BasicTim.c
#include "bsp_BasicTim.h"
// 中断优先级配置
static void BASIC_TIM_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// 设置中断组为0
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
// 设置中断来源
NVIC_InitStructure.NVIC_IRQChannel = BASIC_TIM_IRQ ;
// 设置主优先级为 0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
// 设置抢占优先级为3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
static void BASIC_TIM_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 开启定时器时钟,即内部时钟CK_INT=72M
BASIC_TIM_APBxClock_FUN(BASIC_TIM_CLK, ENABLE);
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period = BASIC_TIM_Period;
// 时钟预分频数为
TIM_TimeBaseStructure.TIM_Prescaler= BASIC_TIM_Prescaler;
// 时钟分频因子 ,基本定时器没有,不用管
//TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
// 计数器计数模式,基本定时器只能向上计数,没有计数模式的设置
//TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
// 重复计数器的值,基本定时器没有,不用管
//TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
// 初始化定时器
TIM_TimeBaseInit(BASIC_TIM, &TIM_TimeBaseStructure);
// 清除计数器中断标志位
TIM_ClearFlag(BASIC_TIM, TIM_FLAG_Update);
// 开启计数器中断:计数器溢出、产生更新事件、计数器的更新事件能够产生中断、并被使能
TIM_ITConfig(BASIC_TIM,TIM_IT_Update,ENABLE);
// 使能计数器
TIM_Cmd(BASIC_TIM, ENABLE);
}
void BASIC_TIM_Init(void)
{
BASIC_TIM_NVIC_Config();
BASIC_TIM_Config();
}
bsp_BasicTim.h
#ifndef __BSP_TIMEBASE_H
#define __BSP_TIMEBASE_H
#include "stm32f10x.h"
/********************基本定时器TIM参数定义,只限TIM6、7************/
#define BASIC_TIM6 // 如果使用TIM7,注释掉这个宏即可
#ifdef BASIC_TIM6 // 使用基本定时器TIM6
#define BASIC_TIM TIM6
#define BASIC_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define BASIC_TIM_CLK RCC_APB1Periph_TIM6
#define BASIC_TIM_Period (1000-1)
#define BASIC_TIM_Prescaler 71
#define BASIC_TIM_IRQ TIM6_IRQn
#define BASIC_TIM_IRQHandler TIM6_IRQHandler
#else // 使用基本定时器TIM7
#define BASIC_TIM TIM7
#define BASIC_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define BASIC_TIM_CLK RCC_APB1Periph_TIM7
#define BASIC_TIM_Period 1000-1
#define BASIC_TIM_Prescaler 71
#define BASIC_TIM_IRQ TIM7_IRQn
#define BASIC_TIM_IRQHandler TIM7_IRQHandler
#endif
void BASIC_TIM_Init(void);
#endif /* __BSP_TIMEBASE_H */
中断服务子程序:BASIC_TIM_IRQHandler
void BASIC_TIM_IRQHandler(void)
{
if ( TIM_GetITStatus( BASIC_TIM, TIM_IT_Update) != RESET ) //当更新时间到来、定时器TIM的状态寄存器就不为0,满足条件。
{
time++;
TIM_ClearITPendingBit(BASIC_TIM , TIM_FLAG_Update);
}
}
三、高级定时器
高级定时器分为6个部分讲解:
(1)时钟源
(2)控制器
(3)时基单元
(4)输入捕获
(5)输出比较
(6)刹车控制区
附上功能框图:
1、时钟源
高级定时器的时钟源有4种:
(1)内部时钟源IN_CLK
(2)外部时钟模式1: TIx(x=1,2,3,4)
(3)外部始终模式2: ETR
(4)内部触发输入: ITRx
二、控制器
触发控制器用来针对片内外设输出触发信号,比如为其它定时器提供时钟和触发 DAC/ADC 转换。
从模式控制器可以控制计数器复位、启动、递增/递减、计数。
三、时基单元
参考基本定时器