通用定时器介绍

               通用定时器有4个,分别是:TIM2、TIM3、TIM4、TIM5。它们拥有基本定时器所有功能。并增加如下功能:

  • 多种时钟源
  • 向上计数、向下计数、向上/向下。
  • 输入捕获
  • 输出比较
  • PWM生成
  • 支持针对定位的增量编码器和霍尔传感器电路

通用计时器功能框图

通用定时器时钟源

1. 内部时钟源(CK_INT)

  • 原理:内部时钟源(CK_INT)来自于APB总线时钟(APBx)经过倍频后的信号,当APB预分频系数为1时,定时器的时钟频率等于APB总线时钟频率;当APB预分频系数不等于1时,定时器的时钟频率是APB总线时钟频率的两倍。CK_INT是默认的时钟源输入,通过内部的连接图直接连接到时基单元。只要定时器开启,在没有选择其他时钟源的情况下,就会使用CK_INT作为时钟源进行计数。
  • 适用场景:适用于大多数对时钟精度要求不是特别高,且与系统内部其他模块同步工作的场景,例如简单的定时任务、PWM 输出等

2.外部时钟模式1(ETR引脚)

  • 原理:外部时钟模式 1 使用定时器的外部触发输入引脚(ETR)作为时钟源。当 ETR 引脚上的信号满足一定的触发条件(如上升沿、下降沿或双边沿触发)时,定时器开始计数。ETR 引脚的信号可以是来自外部传感器、其他定时器或者外部设备的脉冲信号。
  • 功能框图位置:在功能框图中,ETR 引脚的信号首先经过外部触发极性选择器和滤波器,然后经过分频器,最终作为时钟源输入到时基单元。
  • 适用场景:适用于需要与外部设备的脉冲信号同步的场景,例如测量外部脉冲的频率、周期等。

3. 外部时钟模式 2(TIx 引脚)

  • 原理:外部时钟模式 2 使用定时器的输入捕获引脚(TIx)作为时钟源。当 TIx 引脚上的信号满足触发条件时,定时器开始计数。TIx 引脚通常用于连接外部的编码器、传感器等设备,通过捕获这些设备输出的信号来实现定时器的计数。
  • 功能框图位置:在功能框图中,TIx 引脚的信号经过输入捕获滤波器和边沿检测器后,作为时钟源输入到时基单元。
  • 适用场景:适用于需要与外部编码器或传感器信号同步的场景,例如电机控制中的编码器反馈、位置测量等。

4. 内部触发输入(ITRx)

  • 原理:内部触发输入(ITRx)允许一个定时器使用另一个定时器的输出作为时钟源,实现定时器之间的级联。通过这种方式,可以扩展定时器的功能,例如实现更长时间的定时或者更复杂的定时逻辑。
  • 功能框图位置:在功能框图中,ITRx 信号通过内部触发选择器连接到时基单元。不同的定时器之间可以通过配置相关寄存器来选择合适的内部触发信号。
  • 适用场景:适用于需要多个定时器协同工作的场景,例如实现多通道的 PWM 输出、复杂的定时序列控制等。

通用定时器计数器

向上计数模式

计数器从 0 开始,每来一个时钟脉冲,计数器的值加 1,当计数器的值达到自动重载寄存器(ARR)设定的值时,计数器会被清零并重新开始计数,同时会产生一个更新事件。

向下计数模式

计数器从自动重载寄存器(ARR)设定的值开始,每来一个时钟脉冲,计数器的值减 1,当计数器的值减到 0 时,计数器会重新加载 ARR 的值并重新开始计数,同时产生更新事件。

中心对齐计数模式

在中央对齐模式,计数器从0开始计数到自动加载的值(TIMx_ARR寄存器)−1,产生一个计数器
溢出事件,然后向下计数到1并且产生一个计数器下溢事件;然后再从0开始重新计数

PWM

频率=1/Ts

占空比=Ton/Ts

分辨率=占空比变化步距

输出比较

输出比较包含三部分内容

  • 计数器部分
  • 捕获比较寄存器 ,   每个定时器有4个通道,1个通道1个捕获比较寄存器(CCR),可以实现同时4路比较
  • 输出部分:4路输出。

输出比较原理

比较寄存器的值计数器的值进行大小比较,根据比较结果(>=<)不同,产生不同输出;高电平or低电平

输出比较的8中模式

        由CCMRx[1...4]寄存器的OCx[1...4]M[2,0],共3位来控制

假设计数器的值是CNT,比较寄存器1的值CCR=60

1.OC1M[2,0]=000, 输出冻结

        输出冻结。CNT和CCR比较结构不影响输出

2.OC1M[2,0]=001,强制输出高电平

        强制输出高电平。一旦CNT=CCR,强制输出高电平,再不改变。

3.OC1M[2,0]=010,  强制输出低电平

        强制输出低电平。一旦CNT=CCR,强制输出低电平,再不改变。

4.OC1M[2,0]=011,输出翻转

      输出翻转。一旦CNT=CCR,则翻转输出。高->低,低->高。。。

       输出结果其实就是一个方波;频率为计数器的溢出频率的一半占空比为50%

5.OC1M[2,0]=100, 强制输出低电平

        强制输出低电平。

6.OC1M[2,0]=101, 强制输出高电平

        强制输出高电平。

7.OC1M[2,0]=110,PWM模式1

   PWM模式1,CNT<CRR  输出高电平,CNT>=CRR  输出低电平

8.OC1M[2,0]=111, PWM模式2

   PWM模式2,CNT<CRR  输出低电平,CNT>=CRR  输出高电平

相关寄存器

控制寄存器1(TIMx_CR1)

  1. 位 0 - CEN(计数器使能位)
    • 0:禁用计数器。
    • 1:使能计数器。
  2. 位 4 - DIR(计数方向)
    • 0:向上计数模式。
    • 1:向下计数模式。
  3. 位 7 - ARPE(自动重载预装载使能)
    • 0:自动重载寄存器(ARR)没有缓冲。
    • 1:自动重载寄存器(ARR)被装入缓冲器。
  4. 位 8 - 9 - CMS [1:0](中心对齐模式选择)
    • 00:边沿对齐模式。
    • 01:中心对齐模式 1。
    • 10:中心对齐模式 2。
    • 11:中心对齐模式 3。

控制寄存器 2(TIMx_CR2)

TIMx_CR2 寄存器提供了一系列用于扩展定时器功能的配置选项,涉及定时器的主从模式控制、触发输出选择、重复计数器功能等。通过对该寄存器不同位的设置,可以使定时器在更复杂的应用场景中发挥作用。

1. 位 4 - 7:MMS [2:0](主模式选择)
  • 用于选择定时器作为主模式时的触发输出信号。不同的组合值可以使定时器输出不同的触发信号,例如更新事件、比较匹配事件等,以便控制其他从定时器或外设。常见取值及含义如下:
    • 000:复位 - 计数器复位时产生触发输出。
    • 001:使能 - 计数器使能时产生触发输出。
    • 010:更新 - 更新事件时产生触发输出。
    • 其他值对应不同的特定触发条件。
2. 位 8 - 11:TI1S(TIMx 输入 1 选择)
  • 用于选择 TIMx 的输入 1(TI1)的信号源。可以将 TI1 连接到不同的内部或外部信号源,以实现不同的输入捕获或计数功能。
    • 0:TI1 连接到 TIMx_CH1 引脚。
    • 1:TI1 连接到内部触发信号。
3. 位 12:CCPC(捕获 / 比较预加载控制)
  • 控制捕获 / 比较寄存器的预加载功能。
    • 0:捕获 / 比较寄存器没有预加载功能。
    • 1:捕获 / 比较寄存器具有预加载功能,即写入的值会先存放在缓冲寄存器中,在更新事件时才会更新到实际的捕获 / 比较寄存器中。

捕获/比较模式寄存器 1(TIMx_CCMR1)

低 8 位(通道 1)
  • 位 0 - 1:CC1S(捕获 / 比较 1 选择)
    • 00:输出比较模式。
    • 01:输入捕获模式,IC1 映射到 TI1。
    • 10:输入捕获模式,IC1 映射到 TI2。
    • 11:输入捕获模式,IC1 映射到 TRC。
  • 位 2 - 3:OC1M [1:0](输出比较 1 模式)
    • 当 CC1S 为 00(输出比较模式)时有效,用于选择输出比较的具体模式,如冻结、匹配时置有效电平、PWM 模式等。
  • 位 4 - 7:IC1F(输入捕获 1 滤波器)
    • 当 CC1S 为输入捕获模式时有效,用于设置输入捕获信号的滤波器,可滤除信号中的高频噪声。
高 8 位(通道 2)
  • 位 8 - 9:CC2S(捕获 / 比较 2 选择)
    • 功能与 CC1S 类似,用于选择通道 2 的工作模式(输入捕获或输出比较)及信号映射。
  • 位 10 - 11:OC2M [1:0](输出比较 2 模式)
    • 用于设置通道 2 在输出比较模式下的具体模式。
  • 位 12 - 15:IC2F(输入捕获 2 滤波器)
    • 用于设置通道 2 输入捕获信号的滤波器。

代码

寄存器模式

#include "stm32f10x.h"                  // Device header


void main(void){
	
    //开启GPIO和TIM5时钟
	RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
	RCC->APB1ENR |= RCC_APB1ENR_TIM5EN;
	
    //设置GPIO工作模式, PA1:复用推挽输出,CNF -10 MODE -11
	GPIOA->CRL |= GPIO_CRL_MODE1;
	GPIOA->CRL |= GPIO_CRL_CNF1_1;
	GPIOA->CRL &= GPIO_CRL_CNF1_0;
	
	
    //时基单元配置,预分频值 7199 ,得到10000Hz
	TIM5->PSC=7199;

    //重装载值配置,99 每个10ms 溢出一次
	TIM5->ARR=99;
    
    // 设置计数方向	,DIR位取0,为向下计数
	TIM5->CR1 &=~TIM_CR1_DIR;
	
     //设置通道2的CCR值
	TIM5->CCR2 =50;
	
    //配置通道2为PWM1模式,OC2M-110
	TIM5->CCMR1 |= TIM_CCMR1_OC2M_2;
	TIM5->CCMR1 |= TIM_CCMR1_OC2M_1;
	TIM5->CCMR1 &= ~TIM_CCMR1_OC2M_0;
	
	//捕获/比较使能寄存器
	TIM5->CCER |= TIM_CCER_CC2E;
	
}

void TIM5_Start(void){
	
    //定时器使能
	TIM5->CR1 |= TIM_CR1_CEN;
	
}

void TIM5_Stop(void){
	
	TIM5->CR1 &= ~TIM_CR1_CEN;	 
	
}

void TIM5_SetDutyCycle(uint8_t dutyCycle){
	
	
	TIM5->CCR2 = dutyCycle;
	
}


标准库模式

#include "stm32f10x.h"                  // Device header

int  main(void){
	
    //引脚、通用定时器 时钟使能,
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
    //引脚初始化,这里需要用到的是复用推挽输出
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	
    //GPIO初始化
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
    //TIM2结构体定义
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;

    //使用不分频率,则还是为72MHz
	TIM_TimeBaseInitStructure.TIM_ClockDivision= TIM_CKD_DIV1;

    //计数模式,设置为向上计数,从0加到自动重载寄存器(ARR)中预先设定的值
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;

    //ARR 自动重载寄存器中预先设定的值
	TIM_TimeBaseInitStructure.TIM_Period=10000-1;

    //对系统时钟进行7200分频,得到的定时器频率为10000MHz,
	TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1;

    //高级定时器用到的,暂时设置成0
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
	
    //初始化TIM2定时器
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	//定义捕获比较寄存器通道结构体
	TIM_OCInitTypeDef TIM_OCInitStructure;

    //首先进行初始化,因为结构体的参数有些没有用到,没有用到的就给初始值
	TIM_OCStructInit(&TIM_OCInitStructure);

    //设置PWM1模式
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;

    //满足条件给高电平
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;

    //因为要将PWM信号输出,所以给出输出使能
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;

    //CCR  比较寄存器的值
	TIM_OCInitStructure.TIM_Pulse=60;
    
    //OC1通道使能
	TIM_OC1Init(TIM2,&TIM_OCInitStructure);
		
    //定时器使能
	TIM_Cmd(TIM2,ENABLE);
	
}

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐