STM32高级定时器从模式 四种

时间:2021-08-20 23:32:19

 一、通用定时器从模式:复位模式

        使用TIM1的CH1输出PWM脉冲 
        使用TIM4的CH1作为触发输入通道。
       PWM的上升沿触发TIM4的复位模式,复位TIM4计数器并触发中断.
   
                              定时器1配置,用来产生PWM脉冲

TIM_HandleTypeDef htimx;              //基本定时器句柄

void ADVANCED_TIMx_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig;    //定时器时钟配置
  TIM_MasterConfigTypeDef sMasterConfig;       //定时器主从模式配置
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;//刹车和死区时间配置
  TIM_OC_InitTypeDef sConfigOC;        //输出比较配置
  
  ADVANCED_TIM_RCC_CLK_ENABLE();
  
  htimx.Instance = TIM1;
  htimx.Init.Prescaler = ADVANCED_TIM_PRESCALER;   //预分频设置
  htimx.Init.CounterMode = TIM_COUNTERMODE_UP;      //计数方式,向上或者向下
  htimx.Init.Period = ADVANCED_TIM_PERIOD;           //定时器周期
  htimx.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;    //时钟分频,基本定时器没有
  htimx.Init.RepetitionCounter = ADVANCED_TIM_REPETITIONCOUNTER;  //重复计数器
  HAL_TIM_Base_Init(&htimx);  //初始化

//定时器时钟配置
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;   
HAL_TIM_ConfigClockSource(&htimx, &sClockSourceConfig); //初始化    
HAL_TIM_PWM_Init(&htimx); 

//定时器主从模式配置
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;  
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; //从模式,设置是否使用定时器的被动触发。
HAL_TIMEx_MasterConfigSynchronization(&htimx, &sMasterConfig);

//刹车和死区时间配置
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;//设置运行模式下非工作状态选项
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;//设置在空载下非工作状态选项
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; //锁电平参数  
sBreakDeadTimeConfig.DeadTime = 100; //死区时间设置  
sBreakDeadTimeConfig.BreakState = TIM_BREAK_ENABLE; //使能或失能TIMx刹车输入  
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;//TIMx刹车输入管脚极性
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;//使能和失能自动输出功能
HAL_TIMEx_ConfigBreakDeadTime(&htimx, &sBreakDeadTimeConfig);

 //输出比较配置
sConfigOC.OCMode = TIM_OCMODE_PWM1; //输出比较模式  
sConfigOC.Pulse = 100; //设置电平跳变值  
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; //输出比较级性  
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;//互补输出比较级性 
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; //输出比较快速使能和失能
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; //选择空闲状态下非工作状态 
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;//设置空闲状态下非工作状态
HAL_TIM_PWM_ConfigChannel(&htimx, &sConfigOC, TIM_CHANNEL_1);       
HAL_TIM_MspPostInit(&htimx);  }

    定时器4配置为从模式--复位模式

void GENERAL_TIMx_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig;    //定时器时钟配置  
  TIM_SlaveConfigTypeDef  sSlaveConfig;         //从模式配置

 /* 基本定时器外设时钟使能 */  
  htimx_GeneralTIM.Instance = TIM4;
  htimx_GeneralTIM.Init.Prescaler = GENERAL_TIM_PRESCALER;
  htimx_GeneralTIM.Init.CounterMode = TIM_COUNTERMODE_UP;
  htimx_GeneralTIM.Init.Period = GENERAL_TIM_PERIOD;
  htimx_GeneralTIM.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  HAL_TIM_IC_Init(&htimx_GeneralTIM);

  /* 定时器时钟源选择 */
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  HAL_TIM_ConfigClockSource(&htimx_GeneralTIM, &sClockSourceConfig);

  /* 从模式:复位模式 TI1 输入上出现上升沿时,递增计数器清零*/
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;    // 从模式:外部触发复位
  sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;     // 输入触发:选择 TI1 作为输入源
  sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING;// 触发极性:上升沿
  sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1;// 触发预分频:无
  sSlaveConfig.TriggerFilter = 0x0;             // 滤波:本例中不需要任何滤波
  HAL_TIM_SlaveConfigSynchronization(&htimx_GeneralTIM,&sSlaveConfig);
  
  /* 外设中断配置 */
  HAL_NVIC_SetPriority(GENERAL_TIM_IRQ, 0, 0);
  HAL_NVIC_EnableIRQ(GENERAL_TIM_IRQ);
}

二、通用定时器从模式:门控模式

使用TIM2的CH1作为触发输入通道,当相应的引脚为低电平时,触发从模式:门控模式,TIM2计数器开始工作;如果引脚悬空,TIM2不工作。

void GENERAL_TIMx_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_SlaveConfigTypeDef  sSlaveConfig;
  /* 基本定时器外设时钟使能 */
 GENERAL_TIM_RCC_CLK_ENABLE();
  /* 定时器基本功能初始化  */
  htimx_GeneralTIM.Instance = TIM2;
  htimx_GeneralTIM.Init.Prescaler = GENERAL_TIM_PRESCALER;
  htimx_GeneralTIM.Init.CounterMode = TIM_COUNTERMODE_UP;
  htimx_GeneralTIM.Init.Period = GENERAL_TIM_PERIOD;
  htimx_GeneralTIM.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  HAL_TIM_IC_Init(&htimx_GeneralTIM);

  /* 定时器时钟源选择 */
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  HAL_TIM_ConfigClockSource(&htimx_GeneralTIM, &sClockSourceConfig);

/* 从模式:复位模式 TI1 输入上出现下降沿时,从定时器使能 */
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_GATED;               // 从模式:门控模式
  sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;                  // 输入触发:选择 TI1 作为输入源
  sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_FALLING; // 门控极性:低电平
  sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1;  // 触发预分频:无
  sSlaveConfig.TriggerFilter = 0x0;                           // 滤波:本例中不需要任何滤波
  HAL_TIM_SlaveConfigSynchronization(&htimx_GeneralTIM,&sSlaveConfig);
  
  
  /* 外设中断配置 */
  HAL_NVIC_SetPriority(GENERAL_TIM_IRQ, 0, 0);
  HAL_NVIC_EnableIRQ(GENERAL_TIM_IRQ);
}

三、通用定时器从模式:触发模式

TIM4的CH2通道作为触发输入通道,开机之后并不启动定时器,将相应输入通道的端口与GND短接,给通道一个上升沿,即可触发使能TIM4。

void GENERAL_TIMx_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_SlaveConfigTypeDef  sSlaveConfig;
  /* 基本定时器外设时钟使能 */
  GENERAL_TIM_RCC_CLK_ENABLE();
  
  htimx_GeneralTIM.Instance = TIM4;
  htimx_GeneralTIM.Init.Prescaler = GENERAL_TIM_PRESCALER;
  htimx_GeneralTIM.Init.CounterMode = TIM_COUNTERMODE_UP;
  htimx_GeneralTIM.Init.Period = GENERAL_TIM_PERIOD;
  htimx_GeneralTIM.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  HAL_TIM_IC_Init(&htimx_GeneralTIM);


  /* 定时器时钟源选择 */
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  HAL_TIM_ConfigClockSource(&htimx_GeneralTIM, &sClockSourceConfig);


  /* 从模式:复位模式 TI2 输入上出现下降沿时,使能从计数器*/
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;             // 从模式:触发模式
  sSlaveConfig.InputTrigger = TIM_TS_TI2FP2;                  // 输入触发:选择 TI2 作为输入源
  sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_FALLING; // 触发极性:下降沿触发
  sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1;  // 触发预分频:无
  sSlaveConfig.TriggerFilter = 0x0;                           // 滤波:本例中不需要任何滤波
  HAL_TIM_SlaveConfigSynchronization(&htimx_GeneralTIM,&sSlaveConfig);
  
  /* 外设中断配置 */
  HAL_NVIC_SetPriority(GENERAL_TIM_IRQ, 0, 0);
  HAL_NVIC_EnableIRQ(GENERAL_TIM_IRQ);
}

主函数中只使能中断,而不启动。

 /* 通用定时器初始化 */
  GENERAL_TIMx_Init();
  /* 使能中断,但不启动TIM */
  __HAL_TIM_ENABLE_IT(&htimx_GeneralTIM,TIM_IT_UPDATE);     // 使能更新中断

四、定时器从模式:外部时钟2模式_从模式_触发模式

       示例试验:通过短接GND给TIM4的CH1一个下降沿,使能TIM4,然后按下按键1,没按一次,LED灯闪烁一次。
     
   说明:使用TIM4的CH1作为触发输入通道,对应的引脚是PD12,开机是没有使能定时器,给CH1一个下降沿
  触发使能TIM4,这个时候,TIM4的时钟有ETR引脚提供,对应引脚是PE0,也就是KEY1,所以按下KEY1,计
  数器开始递增,LED闪烁.


void GENERAL_TIMx_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_SlaveConfigTypeDef  sSlaveConfig;
  /* 基本定时器外设时钟使能 */
  GENERAL_TIM_RCC_CLK_ENABLE();
  
  htimx_GeneralTIM.Instance = TIM4;
  htimx_GeneralTIM.Init.Prescaler = GENERAL_TIM_PRESCALER;    //预分频为0
  htimx_GeneralTIM.Init.CounterMode = TIM_COUNTERMODE_UP;      //加计数
  htimx_GeneralTIM.Init.Period = GENERAL_TIM_PERIOD;       //定时器周期:0XFFFF 
  htimx_GeneralTIM.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  HAL_TIM_IC_Init(&htimx_GeneralTIM);


  /* 定时器时钟源选择:外部时钟模式2 */
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_ETRMODE2;//        获取外部时钟,这里使用按键来模拟,定时器本身就是一个计数器,理解这一点
  sClockSourceConfig.ClockFilter = 0x0;
  sClockSourceConfig.ClockPolarity = TIM_CLOCKPOLARITY_FALLING;
  sClockSourceConfig.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1;
  HAL_TIM_ConfigClockSource(&htimx_GeneralTIM, &sClockSourceConfig);

  /* 从模式:复位模式 TI1 输入上出现上升沿时,触发从定时器*/
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;             // 从模式:触发模式
  sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;                  // 输入触发:选择 TI1 作为输入源
  sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING;  // 触发极性:上升沿触发
  sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1;  // 触发预分频:无
  sSlaveConfig.TriggerFilter = 0x0;                           // 滤波:本例中不需要任何滤波
  HAL_TIM_SlaveConfigSynchronization(&htimx_GeneralTIM,&sSlaveConfig);
  
  /* 外设中断配置 */
  HAL_NVIC_SetPriority(GENERAL_TIM_IRQ, 0, 0);
  HAL_NVIC_EnableIRQ(GENERAL_TIM_IRQ);
}

在主函数中,只要计数器中的数值变化后,就翻转LED。

while (1)
  {
    /* 循环读取TIMx的计数器,只有变化,就翻转LED电平 */
    Counter = __HAL_TIM_GET_COUNTER(&htimx_GeneralTIM); 
    if( last_Counter != Counter)
    {
      LED1_TOGGLE;
      LED2_TOGGLE;
      LED3_TOGGLE;
      last_Counter = Counter ;
    }    
  }

上述四种从模式的配置方式基本相同,仅是在于触发条件不同而已。理解了一个其他的都没问题。