stm32定时器之Output Compare

本文详细介绍了如何使用STM32F103VB单片机通过MOC3020驱动BTA16可控硅,实现对电机进行相位控制调速。通过定时器配置和中断处理,实现在检测到过零信号时延时输出,从而达到调速目的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

stm32f103vb发出逻辑信号给MOC3020,控制BTA16可控硅的通断。

在检测到过零信号时,延时x毫秒,输出1;延时y毫秒,关闭输出。 实现相位控制调速感应电机(小功率)。



在stm32 discovery开发板上,使用蓝灯和绿灯模拟。


采用定时器的OC,比较输出来做。

选用VBT6的一个Timer来做,它有4个通道可以使用,可以拿来控制4路可控硅输出。


使用CubeMX做外设配置。

针脚配置:


这样不把输出直接发送到Pin上。 能直接发送到Pin上,使用One Pulse Mode 比较方便。 受限于委托公司的设计限制,没法使用脉冲模式。


注意Prescaler的值, 值  = 时钟频率/1000 - 1, 及为1ms.

Pulse 值,表示计数器到达多少时,做输出,触发中断。


中断需要启用。


使用按键来触发定时器,启用两个通道,这里简单使用延时来按键消抖,可以使用状态机处理:

    if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) {
      
      HAL_Delay(20);
      if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) {
        // strat timer
        __HAL_TIM_SET_COUNTER ( &htim2, 0); // 设置0
        HAL_TIM_OC_Start_IT  ( &htim2,  TIM_CHANNEL_1); 
        HAL_TIM_OC_Start_IT  ( &htim2,  TIM_CHANNEL_2); 

      }
    }

定义两个flag:

__IO uint8_t on_led_blue = 0;
__IO uint8_t on_led_green = 0;

在回调函数处理:

void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
  
  if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
  {
    if (!on_led_blue) {
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
      on_led_blue = 1;
      HAL_TIM_OC_Stop_IT  ( &htim2, TIM_CHANNEL_1);
      //设置新的时间
      uint16_t delay_new = __HAL_TIM_GET_COMPARE(&htim2, TIM_CHANNEL_1);
      __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, delay_new + 1999);
      HAL_TIM_OC_Start_IT  ( &htim2, TIM_CHANNEL_1);
    }
    else if (on_led_blue) {
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
      on_led_blue = 0;
      HAL_TIM_OC_Stop_IT  ( &htim2, TIM_CHANNEL_1); 
    }
    
 
  } 

  
    if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
    {
      if (!on_led_green) {
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);#define __HAL_TIM_SET_COMPARE (   __HANDLE__,  
    __CHANNEL__,  
    __COMPARE__  
 ) 
        on_led_green = 1;
        HAL_TIM_OC_Stop_IT  ( &htim2, TIM_CHANNEL_2);
        //设置新的时间
        uint16_t delay_new = __HAL_TIM_GET_COUNTER(&htim2, TIM_CHANNEL_2);
        __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, delay_new + 1999);
        HAL_TIM_OC_Start_IT  ( &htim2, TIM_CHANNEL_2);
      }
      else if (on_led_green) {
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
        on_led_green = 0;
        HAL_TIM_OC_Stop_IT  ( &htim2, TIM_CHANNEL_2); 
      }
    }
  
}

使用flag来区别HAL_TIM_ActiveChannel是 delay_on,还是delay_off。

#define __HAL_TIM_SET_COMPARE (   __HANDLE__,  
    __CHANNEL__,  
    __COMPARE__  
 ) 

这个宏可以方便的 Sets the TIM Capture Compare Register value on runtime without calling another time ConfigChannel function.


效果表现为:

按键按下,蓝灯3秒亮,2秒后灭;绿灯5秒后亮,2秒后灭。


总之,使用Timer的输出Pin接Moc3020,脉冲方式是最省事省心的做法。 

而其他Pin的话,只能这里使用一个替代的方法来实现。

<think>嗯,用户想了解STM32中的Output Compare Preload功能及其作用。我需要先回忆一下之前学过的相关知识,并结合提供的引用内容来组织回答。 首先,根据引用[1],Output Compare Preload(输出比较预装载)是用来设置CCR是否使用预装载功能的。当这个功能启用时,对CCR寄存器的修改不会立即生效,而是等到下一个更新事件发生时才更新。这在不需要动态修改CCR值的场景下,可以避免误操作带来的影响。例如,示例中提到如果不动态修改CCR的值,启用或禁用这个功能都没影响。 接下来,引用[2]解释了比较功能的基本原理,即比较CCRx寄存器的值和计数器CNT的值,触发中断或生成PWM信号。这说明CCR的值对输出比较非常重要,而预装载功能可能影响到CCR的更新时机。 然后,引用[3]提到需要将数据写入TIMx_ARR和TIMx_CCRx寄存器来设定比较值。这里如果启用了预装载,写入CCRx的值不会立即生效,而是等到更新事件。这有助于同步更新多个寄存器,避免中间状态的问题。 引用[4]讨论了Auto-reload preload(ARR预装载)的功能,类似地,CCR预装载应该也是类似的机制。ARR预装载决定了ARR的修改是立即生效还是等到更新事件,而Output Compare Preload则是针对CCR的类似机制。 综合这些信息,Output Compare Preload的作用应该是允许用户预先设置CCR的值,并在合适的时机(如下一个更新事件)生效,从而保证在PWM生成等应用中,占空比或频率的变化不会在周期中间被修改,避免信号的不稳定。这在需要精确控制时序的应用中尤为重要,比如电机控制或LED调光。 用户可能的应用场景可能涉及需要稳定PWM输出的情况,比如控制步进电机或者生成精确的脉冲信号。如果用户没有正确配置预装载功能,可能会导致PWM信号出现毛刺或不连续,影响系统性能。因此,解释清楚预装载的作用和配置方法非常重要。 此外,用户可能想知道如何配置这个功能,以及在不同情况下启用或禁用它会有何影响。例如,在需要实时调整占空比的情况下,可能需要禁用预装载以立即生效新的CCR值,但这需要确保在安全的时间点进行修改,比如在计数器溢出时,以避免竞争条件。 最后,生成的相关问题需要覆盖功能对比、配置步骤和应用场景,帮助用户进一步理解相关知识。</think>### STM32Output Compare Preload功能详解 #### 功能定义 Output Compare Preload(输出比较预装载)是STM32定时器中针对捕获/比较寄存器(CCR)的配置选项,用于控制CCR值的更新时机。其核心作用是通过预装载机制**保证时序的稳定性**,避免动态修改CCR值时产生意外输出。 #### 作用机制 1. **启用预装载时**: - 对CCR寄存器的写入操作会存入**预装载寄存器**,而非直接修改当前有效的CCR值 - 新的CCR值仅在**更新事件(UEV)**发生时(如计数器溢出)才生效 - 示例:在PWM周期中修改占空比时,新值会在下一个周期生效 2. **禁用预装载时**: - 对CCR寄存器的写入会**立即更新**当前有效值 - 可能导致当前周期内的输出异常跳变 #### 典型应用场景 1. **PWM信号生成** 在电机控制中,若需改变占空比,启用预装载可确保修改后的值在完整PWM周期开始时生效,避免脉冲宽度突变。例如: ```c TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStruct.TIM_Pulse = 50; // 占空比50% TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); // 启用预装载[^3] ``` 此时修改`TIMx_CCRx`寄存器值不会立即影响当前周期输出。 2. **同步修改多通道参数** 当需要同时调整多个CCR值时,预装载机制保证所有修改在同一更新事件生效,避免时序错位[^4]。 #### 配置要点 | 配置项 | 启用预装载 | 禁用预装载 | |---------|------------|------------| | 适用场景 | 需要同步更新/稳定输出 | 需要即时生效 | | 寄存器操作 | 写操作缓冲至预装载寄存器 | 直接写入有效寄存器 | | 更新时间 | 下一个更新事件 | 立即生效 | | 典型应用 | PWM周期参数修改 | 实时响应事件 | 建议在初始化时通过`TIM_OCxPreloadConfig()`函数配置,并与ARPE(Auto-reload preload enable)配合使用。例如: ```c TIM_ARRPreloadConfig(TIM1, ENABLE); // 同时启用ARR预装载 TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

容沁风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值