Stm32之TIM-定时器的使用

开发环境:Window 10开发工具:Keil uVision5 MDK硬件:STM32F103

资料参考:

1、【正点原子】STM32F103开发板资料(A盘);

2、stm32之TIM-基本定时器应用实例 https://blog.csdn.net/weixin_42653531/article/details/88527405

3、stm32的抢占优先级和响应优先级 https://blog.csdn.net/baidu_38988793/article/details/89522107

文章目录

Stm32之TIM-定时器的使用STM32F103ZE 简介一、定时器的概述二、定时器的使用步骤1)TIMx时钟使能2)初始化定时器参数3)设置TIMx_DIER允许中断4)TIMx中断优先级设置5)允许TIMx工作,即使能TIMx6)编写中断服务函数

STM32F103ZE 简介

内核:ARM Cortex-M3,72MHz

内存:64kB RAM,512kB ROM

时钟和电源:2.00V—3.60V,72 MHz

通信 :SPI、I2C、UART、I2S、CAN、USART、USB、Device

定时器/计数器/PWM :8 × 16 位定时器

模拟:2通道 12位DAC,21通道 12位ADC

I/O 和封装: -40℃—85℃,144-QFP,144-BGA

官网:https://www.keil.com/dd2/stmicroelectronics/stm32f103ze/

一、定时器的概述

定时器最基本的功能就是定时处理事情。比如定时发送USART数据、定时采集AD数据、测量输入脉冲的频率(输入捕获)、产生输出波形(比较输出或PWM)等。

STM32系列的定时器分为基本定时器、通用定时器、高级定时器。高级定时器包括前者的全部功能。

通常地,STM32包括高级定时器TIM1、TIM8,通用定时器TIM2、TIM3、TIM4、TIM5,基本定时器TIM6、TIM7,具体详见各芯片的数据手册。

基本定时器(TIM6、TIM7)通用定时器(TIM2、TIM3、TIM4、TIM5)高级定时器(TIM1、TIM8)

注释:STM32F103系列有8个16位的定时器,且均采用72MHz的内部时钟;而F407系列则有14个且每个定时器的时钟也不同,具体使用需结合数据手册,如下图。

二、定时器的使用步骤

1)TIMx时钟使能

2)初始化定时器参数,设置自动重装值,分频系数,计数方式等

3)设置TIMx_DIER允许中断

4)TIMx中断优先级设置

5)允许TIMx工作,即使能TIMx

6)编写中断服务函数

1)TIMx时钟使能

基本、通用定时器的时钟来自于APB1总线;

高级定时器(TIM1、TIM8)的时钟来自于APB2总线。

针对 TIM3 时钟使能范例:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // 时钟使能

2)初始化定时器参数

库函数中定时器的初始化通过TIM_TimeBaseInit()实现

TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)

第一个参数:确定哪个定时器; 第二个参数:定时器初始化参数结构体指针,即用结构体形式对定时器的相关参数进行配置。

typedef struct

{

u16 TIM_Period;

u16 TIM_Prescaler;

u8 TIM_ClockDivision;

u16 TIM_CounterMode;

u8 TIM_RepetitionCounter;

} TIM_TimeBaseInitTypeDef;

TIM_Period:定时器自动重装载计数周期值,当计数寄存器的值递增到等于该值时,将相关事件标志位置位,范围0~65535。TIM_Prescaler:定时器预分频设置。时钟源经该预分频器才是定时器时钟,范围0~65535。TIM_ClockDivision:时钟分频。有不分频、二分频、四分频。基本定时器没有这个功能。TIM_CounterMode:定时器计数方式设置,有向上计数、向下计数、对齐模式等,基本定时器只能向上计数。TIM_RepetitionCounter :重复计数器,只有高级定时器才有用。

针对 TIM3 初始化范例代码格式:

定时时间=(计数值)*(定时器预分频+1)/内部时钟

STM32F103的内部时钟为72MHz,为实现0.5s定时,预分频Prescaler设置为7200-1,定时器可以得到10KHz(72MHz/((7200-1)+1))的时钟频率,计数值Period设置为5000-1,可以得到定时为0.5s(5000*(1/10kHz))的定时器。

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

TIM_TimeBaseStructure.TIM_Period = 5000;//设置自动重装载计数值

TIM_TimeBaseStructure.TIM_Prescaler =7199;//设置预分频

TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//时钟不分频

TIM_TimeBaseStruc ture.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式

TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);//根据指定参数初始化TIMx

3)设置TIMx_DIER允许中断

在库函数里面定时器中断使能是通过 TIM_ITConfig 函数来实现

使能TIM3 的更新中断,格式为:

TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );

4)TIMx中断优先级设置

用 NVIC_Init()函数实现中断优先级的设置

NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)

根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

NVIC_InitTypeDef定义于文件“misc.h”

typedef struct

{

u8 NVIC_IRQChannel;

u8 NVIC_IRQChannelPreemptionPriority;

u8 NVIC_IRQChannelSubPriority;

FunctionalState NVIC_IRQChannelCmd;

} NVIC_InitTypeDef;

NVIC_IRQChannel:定义初始化哪个中断NVIC_IRQChannelPreemptionPriority:定义中断的抢占优先级别NVIC_IRQChannelSubPriority:定义这个中断的子优先级别NVIC_IRQChannelCmd:该中断是否使能

针对 TIM3 中断设置范例代码格式:

NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级0级

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能

NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器

NVIC 的优先级组

STM32用4位寄存器位的表示中断优先级,其的分组方式如下:

第0组:所有4位用于指定响应优先级

第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级,抢占级有2^1 =2 级;子优先级2^3=8级,共2*8=16级嵌套

第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级,抢占级有2^2 =4 级;子优先级2^2=4级,共4*4=16级嵌套

第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级,抢占级有2^3 =8 级;子优先级2^1=2级,共8*2=16级嵌套

第4组:所有4位用于指定抢占式优先级

中断响应的优先级由抢占优先级和响应优先级(子优先级)确定,若抢占优先级相同,则看响应优先级,数字越小优先级越高。

1.抢占相同,子优先级不同:按照子优先级顺序排序 2.抢占和子优先级都相同但有先后:此时无抢占剥夺,依照FIFO(先进先出),前一个执行完了再执行后者; 3.抢占和子优先级都相同且同时到达:按照中断向量表顺序排先后

5)允许TIMx工作,即使能TIMx

使能定时器的函数通过 TIM_Cmd 函数来实现

void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)

针对 TIM3 中断设置范例代码格式:

TIM_Cmd(TIM3, ENABLE); // 使能 TIMx 外设

6)编写中断服务函数

库函数中,用TIM_GetITStatus()来判断中断类型

比如要判断定时器3是否发生更新(溢出)中断,方法为:

if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)

固件库中使用TIM_ClearITPendingBit()清除中断标志位

比如在TIM3的溢出中断发生后,要清除中断标志位,方法是:

TIM_ClearITPendingBit(TIM3, TIM_IT_Update);

针对 TIM3 实现定时0.5s闪烁的中断服务函数范例:

/*注意:中断处理的事情要尽可能精简,避免过长时间停留在中断里面*/

void TIM3_IRQHandler(void) //TIM3中断

{

if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //判断TIM3更新中断发生与否

{

TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx更新中断标志

LED1=!LED1; //翻转LED1的状态,实现闪烁

}

}