TIM简介

  • TIM(Timer)定时器。
  • 定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断。
  • 16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时。
  • 不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能。
  • 根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型。

定时器类型

类型编号总线功能
高级定时器TIM1、TIM8APB2拥有通用定时器全部功能,并额外具有重复计数器、死区生成、互补输出、刹车输入等功能
通用定时器TIM2、TIM3、TIM4、TIM5APB1拥有基本定时器全部功能,并额外具有内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等功能
基本定时器TIM6、TIM7APB1拥有定时中断、主模式触发DAC的功能
  • STM32F103C8T6定时器资源:TIM1、TIM2、TIM3、TIM4

高级定时器

通用定时器

!

[](https://mulin.fun/usr/uploads/2023/05/3415216998.png)

基本定时器

定时中断基本结构

预分频器时序

计数器计数频率:CK_CNT = CK_PSC / (PSC + 1)

计数器时序

计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR+1) = CK_PSC / (PSC+ 1) / (ARR+1)

计数器无预装时序

计数器有预装时序

RCC时钟树

定时器定时中断

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"


uint16_t Num;

int main(void)
{
    OLED_Init();
    Timer_Init();
    OLED_ShowString(1,1,"Num:");

    while(1)
    {
        OLED_ShowNum(1,5,Num,5);
        OLED_ShowNum(2,5,TIM_GetCounter(TIM2),5);
    }

}

void TIM2_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
    {
        Num++;
        TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
    }
}

Timer.c

#include "stm32f10x.h"                  // Device header

void Timer_Init(void)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);        //开启时钟

    TIM_InternalClockConfig(TIM2);                                //选择时基单元时钟

    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;  //指定时钟分频(滤波)---一分频
    TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;            //周期 ARR
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//指定计数器模式---向上计数
    TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;            //PSC
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;        //重复计数器(高级定时器)
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);

    TIM_ClearFlag(TIM2, TIM_FLAG_Update);                        //把更新中断标志位清除———避免刚初始化化完就进中断的问题

    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);                    //开启更新中断到NVIC的通路

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                //NVIC优先级分组

    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;                //中断通道
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;    //抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;            //响应优先级
    NVIC_Init(&NVIC_InitStructure);

    TIM_Cmd(TIM2, ENABLE);                                      //使能计数器
}

/*
void TIM2_IRQHandler(void)                                        //TIM2中断函数
{
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)            //获取中断标志位---更新标志位
    {

        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);                //清除标志位
    }
}
*/

Timer.h

#ifndef __TIMER_H
#define __TIMER_H

void Timer_Init(void);


#endif

定时器外部时钟

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"


uint16_t Num;

int main(void)
{
    OLED_Init();
    Timer_Init();
    OLED_ShowString(1,1,"Num:");
    OLED_ShowString(2,1,"CNT:");
    while(1)
    {
        OLED_ShowNum(1,5,Num,5);
        OLED_ShowNum(2,5,Timer_GetCounter(),5);
    }

}

void TIM2_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
    {
        Num++;
        TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
    }
}

Timer.c

#include "stm32f10x.h"                  // Device header

void Timer_Init(void)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    GPIO_InitTypeDef GPIO_InitStructer;
    GPIO_InitStructer.GPIO_Mode =GPIO_Mode_IPU ;
    GPIO_InitStructer.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructer.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructer);

    TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x0F);//ETR引脚外部时钟2

    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;                            //预分频选择--不分频
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;                        //指定计数器模式---向上计数
    TIM_TimeBaseInitStructure.TIM_Period = 10 - 1;                                        //周期 ARR--
    TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;                                    //PSC
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;                                //重复计数器(高级定时器)
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);

    TIM_ClearFlag(TIM2, TIM_FLAG_Update);                                                //把更新中断标志位清除———避免刚初始化化完就进中断的问题
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);                                            //开启更新中断到NVIC的通路

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                                        //NVIC优先级分组

    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;                                        //中断通道
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;                            //抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;                            
    NVIC_Init(&NVIC_InitStructure);                                

    TIM_Cmd(TIM2, ENABLE);                                                                //使能计数器
}

uint16_t Timer_GetCounter(void)
{
    return TIM_GetCounter(TIM2);        //返回CNT计数器的值
}

/*
void TIM2_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
    {

        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    }
}
*/

Timer.h

#ifndef __TIMER_H
#define __TIMER_H

void Timer_Init(void);
uint16_t Timer_GetCounter(void);

#endif

参考资料

STM32入门教程-2023版 细致讲解 中文字幕\_哔哩哔哩\_bilibili

最后修改:2023 年 10 月 21 日
如果觉得我的文章对你有用,请随意赞赏