[STM32F4] 输出比较模式的问题

[复制链接]
43|17
WHALEE 发表于 2026-4-23 21:51 | 显示全部楼层 |阅读模式
在STM32F407G 探索板上使用定时器的输出比较功能。我配置了 TIM1,并开启了全局中断,以下是定时器配置函数和回调函数。
回调函数:
//Callback function
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
        /*目标生成 500Hz 频率*/
        if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
        {
                ccr_content = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
                __HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_1,ccr_content+pulse1_value);
        }
}
定时器配置:
static void MX_TIM1_Init(void)
{

  /* USER CODE BEGIN TIM1_Init 0 */

  /* USER CODE END TIM1_Init 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 = 0;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 65535;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_OC_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_TIMING;
  sConfigOC.Pulse = 0;
  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_OSSR_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.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM1_Init 2 */

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

}
main 函数里应该写什么代码?我想要生成 1500Hz 频率、50% 占空比的信号。
还需要做哪些配置?能在 GPIO 引脚或者 LED 上看到输出效果?

又见江南雨 发表于 2026-4-24 14:13 | 显示全部楼层
要生成 1500Hz 信号,先计算自动重载值 ARR = 168MHz / 1500Hz / 预分频系数,并设置 CCR = ARR/2 得到 50% 占空比。
classroom 发表于 2026-4-24 15:13 | 显示全部楼层
输出比较模式不会主动翻转 GPIO 电平,应改用 TIM_OCMODE_TOGGLE 并在中断里不断翻转输出
cr315 发表于 2026-4-24 16:14 | 显示全部楼层
若使用 PWM 模式替代输出比较,只需配置 ARR 和 CCR,无需写中断回调即可获得连续 1500Hz/50% 波形。
duo点 发表于 2026-4-24 17:14 | 显示全部楼层
你当前的回调函数每次增加 pulse1_value,这个值必须等于 ARR 的一半才能维持 50% 占空比且与通道 1 绑定。
elephant00 发表于 2026-4-24 14:14 | 显示全部楼层
TIM1 是高级定时器,需要调用 HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1),并确保主输出使能 TIM_CCER_CC1E。
flycamelaaa 发表于 2026-4-24 19:15 | 显示全部楼层
GPIO 引脚需重映射到 TIM1_CH1,查看探索板原理图,常用 PA8 或 PE9 连接 LED 或示波器探头。
jcky001 发表于 2026-4-24 20:15 | 显示全部楼层
高级定时器还需调用 HAL_TIMEx_MasterConfigSynchronization 和使能刹车功能中的主输出 TIM1->BDTR |= TIM_BDTR_MOE。
onlycook 发表于 2026-4-24 21:15 | 显示全部楼层
在 main 函数里先 HAL_TIM_OC_Start_IT(&htim1, TIM_CHANNEL_1) 启动输出比较并开启中断,否则不会进入回调。
powerantone 发表于 2026-4-24 22:16 | 显示全部楼层
你的预分频器为 0,计数器时钟为 168MHz,ARR=65535 时最小输出频率约 2.56kHz,无法实现 1500Hz,需增加预分频。
powerantone 发表于 2026-4-24 14:46 | 显示全部楼层
探索板上的绿色 LED(LD3)通常连接 PD13 或 PA8,需查阅原理图确认该引脚是否支持 TIM1_CH1 复用功能。
probedog 发表于 2026-4-24 15:47 | 显示全部楼层
回调函数中修改比较值后,在下一次计数匹配前应处理比较值溢出 ARR 的情况,否则会暂停输出。
solty 发表于 2026-4-24 17:47 | 显示全部楼层
若坚持用输出比较中断,需要在 main 中开启全局中断 __enable_irq(),并确认 NVIC 中 TIM1 中断已使能。
spicy 发表于 2026-4-24 14:19 | 显示全部楼层
0% 占空比在输出比较模式下较难保证,因为每次匹配翻转后,下一次匹配的时间取决于 CCR 值,而 CCR 在动态变化
七毛钱 发表于 2026-4-24 18:51 | 显示全部楼层
在代码中调用 HAL_TIM_OC_ConfigChannel 时,sConfigOC.Pulse 应设为 ARR/2,这是首次匹配的计数值。
在海边聆听 发表于 2026-4-24 14:22 | 显示全部楼层
在回调函数中增加对 __HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) 的判断,避免重复进入中断导致比较值异常。
甜心puppy 发表于 2026-4-24 14:22 | 显示全部楼层
如果必须使用 TIM1 且要输出到 LED,可以改用 PWM 生成模式,代码更简单,只需 HAL_TIM_PWM_Start 一行。
茉璃夏 发表于 2026-4-24 14:23 | 显示全部楼层
在 main 函数中增加延时或等待循环,防止程序配置完立即结束或进入错误处理函数。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

183

主题

184

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部
0