STM32定时器输出比较不能正常工作

Posted

技术标签:

【中文标题】STM32定时器输出比较不能正常工作【英文标题】:STM32 Timer Output compare not working proper 【发布时间】:2020-07-09 17:52:23 【问题描述】:

我正在使用 STM32L476 Nucleo 板和 STM32CubeMX。我想将输出比较通道 1 用于 2 毫秒的超时。我已经配置了定时器,但定时器没有为输出比较提供中断。我在给定时器的时间段内收到中断,但不是输出比较。

这是我的定时器配置:

static void MX_TIM1_Init(void)


  /* USER CODE BEGIN TIM1_Init 0 */

  /* USER CODE END TIM1_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = 0;
  TIM_SlaveConfigTypeDef sSlaveConfig = 0;
  TIM_MasterConfigTypeDef sMasterConfig = 0;
  TIM_OC_InitTypeDef sConfigOC = 0;
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = 0;

  /* USER CODE BEGIN TIM1_Init 1 */

  /* USER CODE END TIM1_Init 1 */
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = TIMER1_PRESCALER_VAL;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = TIMER_PERIOD;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  
    Error_Handler();
  
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
  
    Error_Handler();
  
  if (HAL_TIM_OC_Init(&htim1) != HAL_OK)
  
    Error_Handler();
  
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_DISABLE;
  sSlaveConfig.InputTrigger = TIM_TS_ITR0;
  if (HAL_TIM_SlaveConfigSynchro(&htim1, &sSlaveConfig) != HAL_OK)
  
    Error_Handler();
  
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1REF;
  sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  
    Error_Handler();
  
  sConfigOC.OCMode = TIM_OCMODE_ACTIVE;
  sConfigOC.Pulse = 1000 * TIMER_OC_1_VAL;
  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;
  if (HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  
    Error_Handler();
  
  sBreakDeadTimeConfig.OffStateRunMode = TIM_Os-s-r_DISABLE;
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
  sBreakDeadTimeConfig.DeadTime = 0;
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
  sBreakDeadTimeConfig.BreakFilter = 0;
  sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
  sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
  sBreakDeadTimeConfig.Break2Filter = 0;
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
  
    Error_Handler();
  
  /* USER CODE BEGIN TIM1_Init 2 */
  HAL_TIM_OC_Start_IT(&htim1,TIM_IT_CC1);

  /* USER CODE END TIM1_Init 2 */
  HAL_TIM_MspPostInit(&htim1);


我尝试更改 sConfigOC.Pulse 值,但没有看到预期的行为。

【问题讨论】:

【参考方案1】:

您是否在中断处理程序中检查正确的中断标志? 另外请记住,您必须立即清除标志。

我的 IRQHandler 看起来像这样,如果这对你有帮助的话。

void TIM3_IRQHandler(void) 

    if(LL_TIM_IsActiveFlag_CC1(TIM3) == 1) 
        LL_TIM_ClearFlag_CC1(TIM3);
        TimerCaptureCompare_Callback();
    


编辑:

看起来不错,HAL_TIM_OC_DelayElapsedCallback 中断仅在计时器溢出(即重置)时触发。 这意味着您必须启用溢出中断,因为HAL_TIM_OC_Start_IT 仅启用捕获/比较中断。 您只需要在启用计时器之前启用它即可。

__HAL_TIM_ENABLE_IT(&tim3, TIM_IT_UPDATE );

【讨论】:

这个标志在 HAL 库的定时器处理函数中被清除。 好的,我做了一些研究,发现了一些有趣的东西。但它没有很好的记录。【参考方案2】:

尝试将“TIM_IT_CC1”替换为“TIM_CHANNEL_1”。

【讨论】:

虽然它可能会解决问题,但这更像是一个评论而不是一个答案,因为它是一个问题并且没有上下文。【参考方案3】:

首先,您必须在启动定时器之前初始化输出引脚:

/* USER CODE END TIM1_Init 2 */
HAL_TIM_MspPostInit(&htim1);

/* USER CODE BEGIN TIM1_Init 2 */
HAL_TIM_OC_Start_IT(&htim1,TIM_IT_CC1);

其次,你要启动输出定时器

HAL_TIM_OC_Start_IT( &htim1, TIM_CHANNEL_1 );
HAL_TIM_Base_Start_IT( &htim1 );

你的输出引脚是这样启用的: (此代码适用于 Stm32F4xx)

GPIO_InitStruct.Pin = GPIO_PIN_9; // channel 1
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

我不确定您是否需要 BREAK 代码。看看参考手册中的17.3.12使用break函数

【讨论】:

以上是关于STM32定时器输出比较不能正常工作的主要内容,如果未能解决你的问题,请参考以下文章

STM32-定时器详解

STM32 PWM输出(映射)

STM32使用TIM闪烁LED——输出比较方式

STM32F103定时器最多可以输出多少路PWM波

STM32 通用定时输出PWM

关于STM32单片机PWM输出实验定时器的问题