STM32:定时器

时间:2024-03-22 16:07:39
  • TIM(Timer)定时器
    • 定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断
    • 16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时72/65536/65536
    • 不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能
    • 类型 编号 总线 功能
    • 高级定时器 TIM1、TIM8 APB2 拥有通用定时器全部功能,并额外具有重 复计数器、死区生成、互补输出、刹车输入等功能
    • 通用定时器 TIM2、TIM3、TIM4、TIM5 APB1 拥有基本定时器全部功能 并额外具有内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等功能
    • 基本定时器 TIM6、TIM7 APB1 拥有定时中断、主模式触发DAC的功能
    • STM32F103C8T6定时器资源:TIM1、TIM2、TIM3、TIM4
  • 基本定时器:基准时钟->预分频器->计数器

    • 预分频器
      • 如果预分频器写0,不分频,输出频率=输入频率=72MHz
      • 如果预分频器写1,二分频,输出频率=输入频率/2=36MHz
      • 如果预分频器写,三分频,输出频率=输入频率/3=24MHz
      • 最大值可以写65535也就是65536分频,输出频率=72/65536
    • CNT计数器
      • 对预分频后的始终进行计数,计数时钟每来一个上升沿,计数器的值就加
    • 自动重装寄存器,当计数值等于自动重装值时,代表计时时间到,会产生中断信号,并且清零计数器。(图中向上箭头:更新中断;更新中断通往NVIC)(图中向下箭头:更新时间,更新事件不睡出发中断,但是可以触发内部其他电路的工作)
    • 主模式触发DAC的功能:主模式把更新事件映射到 触发输出TRGO的位置,TRGO直接接到DAC的触发转换引脚上,直接触发DAC,不需要软件的参与,实现了硬件的自动化。
  • 通用定时器:

    • 除了向上计数,通用定时器和高级定时器还支持向下计数模式和*对齐模式
    • 向下计数模式:从重装值开始,向下自减。
    • *对齐模式:从0开始,先向上自增,到重装值,申请中断,然后向下自减到0 再次申请中断。
    • 内外时钟源选择:
      • 第一个外部时钟:TIMx_ETR引脚(PA0)上的外部时钟。两个输出:1.ETRF进入触发控制器,进而到时基单元,这一路也叫外部时钟模式2;2.TRGI:用作触发输入使用,触发输入和从模式,以后课程讲。这一路叫外部时钟模式1.
      • ITRx(ITR0~ITR3)信号来来源于其他定时器,主模式的TRGO可以通向其他定时器。
      • 表格意思为:例如:TIM2定时器的ITR0信号来自于上一个时钟(TIM1)

      • 定时器级联功能,比如:先初始化TIM3,然后使用主模式把它的更新事件映射到TRGO上,然后再初始化TIM2,这里算则ITR2,对应的就是TIM3的TRGO
      • 时钟还能通过CH1获得,ED是边沿的意思,可以是上升沿可以是下降沿。
      • last :时钟还能通过TI1FP1和TI2FP2获得。
      • 总结:外部时钟模式1的引脚可以是ETR引脚、(ITR)其他定时器、CH1引脚的边沿、CH1和CH2引脚的TI1FP1和TI2FP2获得
      • 右下角是输出比较电路,共有四个通道,分别对应CH1到CH4的引脚,可以用于输出PWM波形,驱动电机。
      • 左下角是输入捕获电路,也有四个通道。对应的也是CH1到CH4的引脚,可以用于侧输入方波的频率等。
      • 中间是捕获/比较寄存器,是输入捕获和输出比较电路共用的。因为输入捕获和输出比较不能停驶使用,所以寄存器共用,引脚共用。之后再具体分析。
  • 高级定时器:

    • 申请中断的地方加了一个重复次数计数器,可以实现每隔几个计数周期,才发生一次更新事件和更新中断。
  • 定时中断基本结构图:

    • 中断输出控制(即,中断输出允许位):解决定时器模块有很多地方都要申请中断,看是否需要这个中断,如果需要就允许,如果不需要这个中断,就禁止。(更新会申请中断,触发信号(TRGO)也会申请中断、输入捕获和输出比较匹配时也会申请中断)
  • 时基单元运行细节问题:
    • 预分频时序:

    • 计数器计数频率:CK_CNT= CK_PSC/(PSC + 1)
    • CK_PSC:预分频器的输入时钟。一般为72Mhz
    • CNT_EN:计数器使能,高电平计数器正常运行,低电平计数器停止。
    • CK_CNT:计数器时钟,即时分频器的时钟输出,也是计数器的时钟输入。
    • 一个计时周期结束时,产生了更新事件,预分频(控制)寄存器的值才会杯传递到缓冲器里去,才会生效。
    • 计数器时序:

    • 计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR +1)=CK_PSC / (PSC +1) / (ARR +1)
    • 计数器无预装时序:

    • 计数器有预装时序:

    • RCC时钟树:

    • P13 TIM定时中断,44分钟。
    • 无论什么定时器,内部基准时钟都是72Mhz。
  • void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);初始化时基单元;
  • void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct); 把结构体变量赋一个默认值;
  • void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);使能计数器;
  • void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);使能中断输出信号;TIM_IT 选择配置哪个中断输出,NewState使能还是失能。
  • void TIM_InternalClockConfig(TIM_TypeDef* TIMx);选择内部时钟
  • void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);选择ITRx其他定时器的时钟。
  • void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,uint16_t TIM_ICPolarity, uint16_t ICFilter);选择TIx捕获通道的时钟。TIM_TIxExternalCLKSource选择TIx的某个引脚;TIM_ICPolarity输入的极性;ICFilter滤波器。
  • void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);选择ETR通过外部时钟模式1输入的时钟。TIM_ExtTRGPrescaler外部触发预分频器:可以对ETR的外部时钟再提前做一个分频;
  • void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);选择ETR通过外部时钟模式2输入的时钟。如果不需要触发输入的功能,上两个函数可以互换
  • void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);单独用来配置ETR引脚的预分频器,极性滤波器这些参数的。
  • void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);写预分频值;TIM_PSCReloadMode选择模式:1.听从安排等待更新事件生效,2.在写入后,手动产生一个更新事件,让这个值立即生效。
  • void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);用来改变计数器的计数模式。
  • void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);自动重装器预装功能配置
  • 定时器代码如下:
  • #include "stm32f10x.h"                  // Device header
    
    extern uint16_t Num;
    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_CounterMode=TIM_CounterMode_Up;//向上计数
    	TIM_TimeBaseInitStructure.TIM_Period=10000-1;//ARR自动重装器的值
    	TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1;//预分频器的值 72MHz/7200/10000=1
    	TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//重复计数器的值(高级计数器才需要,目前不需要用给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_InitTypeDef NVIC_InitStruct;
    	NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQn;//定时器2在NVIC里的通道
    	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
    	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;
    	NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
    	NVIC_Init(&NVIC_InitStruct);
    	
    	TIM_Cmd(TIM2,ENABLE);//开启定时器;
    }
    void TIM2_IRQHandler(void)
    {
    	if (TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
    	{
    		Num++;
    		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
    	}	
    	
    }