You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32F407VG正正交模拟设置频率后失效问题求助

稳定模拟STM32正交波形的解决方案

问题根源

你用TIM_OCMode_Toggle模式实现正交波时,OCx引脚的电平是每次计数器匹配CCR值时翻转。第一次配置时引脚初始状态为默认低电平,翻转逻辑正常;但调用SetFunction修改频率后,定时器计数器可能停在中间值,OCx的当前电平已偏离初始状态,而TIM_OCxInit在Toggle模式下不会重置输出状态,只会更新匹配值,导致后续配置的相位差完全混乱,且无法通过重复调用配置函数修复。

修复方案

核心是每次重新配置正交波形前,强制重置定时器和OC通道的初始状态,确保翻转逻辑从固定起点开始:

  1. 配置前关闭定时器,避免计数器在配置过程中运行
  2. 重置计数器到0,强制OC通道输出初始电平
  3. 统一频率更新与正交配置的流程,避免分开操作导致状态不一致

修改后的代码

1. 正交配置函数(修复版)

void TIM3_Configuration_positive_quadrature(void)
{
    QuadratureFunctionAlreadyCalled = 1;

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;
    uint32_t Period = 999; // 与TIM_Period保持一致

    // 先关闭定时器,重置计数器到初始状态
    TIM_Cmd(TIM3, DISABLE);
    TIM_SetCounter(TIM3, 0);

    // 配置时基:Toggle模式下输出频率为定时器更新频率的1/2,预分频需对应调整
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_Period = Period;
    TIM_TimeBaseStructure.TIM_Prescaler = (TIM3_FREQ / (LastSetFrequency * 2)) - 1;

    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    // 强制OC3/OC4输出低电平,重置初始状态(与TIM_OCPolarity_High对应)
    TIM_ForcedOC3Config(TIM3, TIM_ForcedAction_InActive);
    TIM_ForcedOC4Config(TIM3, TIM_ForcedAction_InActive);

    // 配置CH3(A相):25%周期位置触发翻转
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_Pulse = Period / 4;
    TIM_OC3Init(TIM3, &TIM_OCInitStructure);

    // 配置CH4(B相):75%周期位置触发翻转,滞后A相90度
    TIM_OCInitStructure.TIM_Pulse = (Period * 3) / 4;
    TIM_OC4Init(TIM3, &TIM_OCInitStructure);

    // 重新启用定时器
    TIM_Cmd(TIM3, ENABLE);
}

2. 频率设置函数(同步正交配置)

void SetFunction(uint16_t freq)
{
    LastSetFrequency = freq;
    
    // 直接调用修复后的正交配置函数,确保频率更新与状态重置同步
    TIM3_Configuration_positive_quadrature();

    // 计算实际生效频率(可选)
    uint32_t prescaler = (TIM3_FREQ / (freq * 2)) - 1;
    effective_freq = TIM3_FREQ / ((prescaler + 1) * 2);
}

替代方案(更稳定的PWM模式)

如果Toggle模式的状态问题仍难以控制,可改用TIM_OCMode_PWM1模式实现正交波,输出状态完全由CCR值和计数器周期决定,无需依赖翻转状态:

void TIM3_Configuration_quadrature_pwm(void)
{
    TIM_Cmd(TIM3, DISABLE);
    TIM_SetCounter(TIM3, 0);

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;
    // 每个正交周期包含4个计数步骤,定时器更新频率为目标频率的4倍
    uint32_t timer_update_freq = LastSetFrequency * 4;
    uint32_t prescaler = (TIM3_FREQ / timer_update_freq) - 1;
    uint32_t period = 3; // 计数器范围0~3,对应4个状态

    TIM_TimeBaseStructure.TIM_Prescaler = prescaler;
    TIM_TimeBaseStructure.TIM_Period = period;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    // A相:计数器<2时输出高(占空比50%,对应正交A相时序)
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_Pulse = 2;
    TIM_OC3Init(TIM3, &TIM_OCInitStructure);

    // B相:计数器<3且计数器>0时输出高(滞后A相90度,对应正交B相时序)
    TIM_OCInitStructure.TIM_Pulse = 3;
    TIM_OC4Init(TIM3, &TIM_OCInitStructure);

    TIM_Cmd(TIM3, ENABLE);
}

内容的提问来源于stack exchange,提问作者Aiman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 19:38:12