| 本帖最后由 南河壹号 于 2023-9-12 16:37 编辑 
 通用定时器简介
 通用定时器以时基单元为核心,拥有输入捕获和输出比较等功能,可以用来测量脉冲宽度、频率和占空比,以及产生输出波形。当然还有最基本的功能——定时,定时器和定时器之间是相互独立的,它们可以实现同步和级联。今天我们实现最简单的功能——定时
 
 时基单元
 时基单元包含:
 ● 计数器寄存器(TIMx_CNT)
 ● 预分频器寄存器 (TIMx_PSC)
 ● 自动装载寄存器 (TIMx_ARR)
 计数器寄存器、自动装载寄存器和预分频器寄存器可以由软件读写,并且在计数器运行时仍可以读写
 
 计数器寄存器(TIMx_CNT):该寄存器是定时器的计数器,该寄存器存储了当前定时器的计数值。
 
 预分频寄存器(TIMx_PSC):该寄存器用于对时钟进行分频,然后提供给计数器,作为计数器的时钟。
 
 TIM_PrescalerConfig(TIM2 , 7200-1 , TIM_PSCReloadMode_Immediate);//设置预分频值,且立即装入
//函数本质上是产生一次更新事件(在TIMx_EGR寄存器中设置UG位产生一个更新事件),把预分频值装入预分频器寄存器
自动重装载寄存器(TIMx_ARR):该寄存器在物理上实际对应着 2 个寄存器。一个是程序员可以直接操作的,另外一个是程序员看不到的,这个看不到的寄存器被叫做影子寄存器。事实上真正起作用的是影子寄存器。根据 TIMx_CR1 寄存器中 APRE 位的设置:APRE=0 时,预装载寄存器的内容可以随时传送到影子寄存器;而 APRE=1 时,在每一次更新事件(UEV)时,才把预装在寄存器的内容传送到影子寄存器。
 
 计数器模式
 向上计数模式
 在向上计数模式中,计数器从0计数到自动加载值(TIMx_ARR计数器的内容),然后重新从0开始计数并且产生一个计数器溢出事件。
 每次计数器溢出时(上溢)可以产生更新事件,在TIMx_EGR寄存器中设置UG位也同样可以产生一个更新事件。
 
 向下计数模式
 在向下模式中,计数器从自动装入的值(TIMx_ARR计数器的值)开始向下计数到0,然后从自动装入的值重新开始并且产生一个计数器向下溢出事件。
 每次计数器溢出时(下溢)可以产生更新事件,在TIMx_EGR寄存器中设置UG位,也同样可以产生一个更新事件。
 
 中央对齐模式(向上/向下计数)
 在中央对齐模式,计数器从0开始计数到自动加载的值(TIMx_ARR寄存器)−1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器下溢事件;然后再从0开始重新计数。
 在这个模式,不能写入TIMx_CR1中的DIR方向位。它由硬件更新并指示当前的计数方向。
 可以在每次计数上溢和每次计数下溢时产生更新事件;也可以通过(软件或者使用从模式控制器)设置TIMx_EGR寄存器中的UG位产生更新事件。
 
 时钟选择
 计数器时钟可由下列时钟源提供:
 ● 内部时钟(CK_INT)
 ● 外部时钟模式1:外部输入脚(TIx)
 ● 外部时钟模式2:外部触发输入(ETR)
 ● 内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器
 定时器的时钟来源具体选择哪个可以通过从模式控制寄存器TIMx_SMCR 寄存器的相关位来设置。
 
 内部时钟源(CK_INT)
 如果禁止了从模式控制器(TIMx_SMCR寄存器的SMS=000),则CEN(TIMx_CR1寄存器)、DIR(TIMx_CR1寄存器)和UG位(TIMx_EGR寄存器)是事实上的控制位,并且只能被软件修改(UG位仍被自动清除)。只要CEN位被写成’1’,预分频器的时钟就由内部时钟CK_INT提供。
 
 外部时钟模式1:外部输入脚(TIx)
 当从模式控制寄存器TIMx_SMCR寄存器的SMS=111时,此模式被选中。计数器可以在选定输入端的每个上升沿或下降沿计数
 
     
 外部时钟模式2:外部触发输入(ETR)
 选定此模式的方法为:令从模式控制寄存器TIMx_SMCR寄存器中的ECE=1
 计数器能够在外部触发ETR的每一个上升沿或下降沿计数。
 
     
 
 内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器
 使用该模式时,可以将另一个TIM设置为主模式,从而可以TRGO输出时钟,用作该TIM的时钟。
 
     
 TIM_TimeBaseInitTypeDef结构体
 
 typedef struct
{
  uint16_t TIM_Prescaler;\\TIM_Prescaler:设置用来作为TIMx时钟频率除数的预分频值。它的取值必须为0x0000~OxFFFF。
         
  uint16_t TIM_CounterMode;\\TIM_CounterMode:选择计数器模式    
   
  uint16_t TIM_Period;\\TIM_Period:设置计数周期。它的取值必须为0x0000~0xFFFF。  
          
  uint16_t TIM_ClockDivision;\\TIM_ClockDivision:设置时钟分割——不分频、二分频、四分频
   
  uint8_t TIM_RepetitionCounter;\\TIM_RepetitionCounter是高级定时器才有用的  
} TIM_TimeBaseInitTypeDef; 
定时器定时中断配置流程:
 
 定义结构体变量开启TIMx时钟结构体变量赋值初始化定时器配置NVIC清除中断标志位使能中断使能定时器编写中断服务函数
 
 #include "basictim.h"
void NVIC_BasicTim_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_Init(&NVIC_InitStructure);
    
}
void BasicTim_Config(uint16_t Period,uint16_t Prescaler)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);
    
    //定时时间:Period/(主频/Prescaler)
    TIM_TimeBaseInitStructure.TIM_Period = Period-1;
    TIM_TimeBaseInitStructure.TIM_Prescaler = Prescaler-1;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;     //不分频
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM6,&TIM_TimeBaseInitStructure);
    
//  TIM_PrescalerConfig(TIM2 , 7200-1 , TIM_PSCReloadMode_Immediate);
    
    NVIC_BasicTim_Config();
    
    TIM_ClearITPendingBit(TIM6,TIM_IT_Update);
    TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);
    TIM_Cmd(TIM6,ENABLE);
    
    
}
 源码自取:
 
 链接:https://pan.baidu.com/s/1tCIY84VpgIlzzNnvO1kILg
 提取码:1234
 --来自百度网盘超级会员V5的分享
 
 
 
 
 |