Triggers stm32f405产生触发信号pwm

Triggers stm32f405产生触发信号pwm,triggers,embedded,pwm,stm32f4discovery,Triggers,Embedded,Pwm,Stm32f4discovery,我试图用三个定时器产生一个相移PWM信号 TIM1用作参考(在1MHz下运行) TIM3用作相移TIM4的触发器 TIM4用于产生由TIM3触发的相移信号 综上所述:TIM1---触发器-->TIM3---触发器-->TIM4 信号应如下所示: Reference: TIM1 (1 MHz) ___ ___ ___ ___ ___| |___| |___| |___| |___| TIM

我试图用三个定时器产生一个相移PWM信号

  • TIM1用作参考(在1MHz下运行)
  • TIM3用作相移TIM4的触发器
  • TIM4用于产生由TIM3触发的相移信号
综上所述:TIM1---触发器-->TIM3---触发器-->TIM4

信号应如下所示:

Reference: TIM1 (1 MHz) 
                 ___     ___     ___     ___
             ___|   |___|   |___|   |___|   |___| 
TIM Count    0  84 168
Update Event ^      ^       ^       ^       ^

Trigger signal: TIM 3 triggered by TIM1 ((SINGLE PULSE MODE!!) 1MHz
              /|      /|      /|      /|      /|
             / |     / |     / |     / |     / |
TIM Count    0 20 
Update Event   ^       ^       ^       ^       ^

Phase shift signal TIM4 (1MHZ) same duty cycle as TIM1 triggered by TIM3
            ___     ___     ___     ___     ___
        ___|   |___|   |___|   |___|   |___|   |_
这是我目前的代码。参考信号在1MHz下正常运行。但是触发信号现在不起作用。错误应该在initReferenceTimer()或initReferencePWM()函数中的任何位置。到目前为止,它还不能像上面提到的那样产生触发信号。因此,我无法测试相移信号是否正确触发

有人对此有好主意吗

为了进行调试,我还将触发信号绑定到输出引脚

#define TIMER_CLOCK 84
#define TIM1_TIMER_CLOCK 168
#define FREQU 1 //MHz
#define SHIFT 20 
#define MasterPeriod (TIM1_TIMER_CLOCK/FREQU)-1
#define MasterPulse ((TIM1_TIMER_CLOCK/FREQU)-1)/2
#define ReferencePeriod SHIFT
#define ReferencePulse (SHIFT/2)
#define SlavePeriod (TIM1_TIMER_CLOCK/FREQU)-1
#define SlavePulse ((TIM1_TIMER_CLOCK/FREQU)-1)/2

//TIM1 Channel1: PA7 N
void initMasterPin()
{
    GPIO_InitTypeDef     GPIO_InitStructureTimer;

    // Port clock enable
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

    // Set PWM Port, Pin and method
    GPIO_InitStructureTimer.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStructureTimer.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructureTimer.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructureTimer.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructureTimer.GPIO_PuPd = GPIO_PuPd_UP ;
    GPIO_Init(GPIOA, &GPIO_InitStructureTimer);

    // Connect TIM pin to AF
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_TIM1);
}
//TIM3 Channel1 PC6
void initReferencePin()
{
    GPIO_InitTypeDef     GPIO_InitStructureTimer;

    // Port clock enable
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

    // Set PWM Port, Pin and method
    GPIO_InitStructureTimer.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructureTimer.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructureTimer.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructureTimer.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructureTimer.GPIO_PuPd = GPIO_PuPd_UP ;
    GPIO_Init(GPIOC, &GPIO_InitStructureTimer);

    // Connect TIM pin to AF
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM3);
}
//TIM4 Channel1: PB6
void initSlavePin()
{
    GPIO_InitTypeDef     GPIO_InitStructureTimer;

    // Port clock enable
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

    // Set PWM Port, Pin and method
    GPIO_InitStructureTimer.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructureTimer.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructureTimer.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructureTimer.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructureTimer.GPIO_PuPd = GPIO_PuPd_UP ;
    GPIO_Init(GPIOB, &GPIO_InitStructureTimer);

    // Connect TIM pin to AF
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_TIM4);
}

//Tim1 Channel1: PA7
void initMasterTimer()
{
    // set timer frequencies
    TIM_TimeBaseInitTypeDef TIM_Config;

    // 1.Enable TIM clock
    RCC_APB2PeriphClockCmd (RCC_APB2Periph_TIM1, ENABLE);

    // 2.Fill the TIM_TimeBaseInitStruct with the desired parameters.
    // Time Base configuration
    TIM_TimeBaseStructInit (&TIM_Config);
    TIM_Config.TIM_Period = MasterPeriod;
    TIM_Config.TIM_Prescaler = 0;
    TIM_Config.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_Config.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_Config.TIM_RepetitionCounter = 0;
    //configure the Time Base unit with the corresponding configuration
    TIM_TimeBaseInit (TIM1, &TIM_Config);

    // Enable the NVIC if you need to generate the update interrupt.
    // Enable the corresponding interrupt
}
//TIM3 Channel1 PC6
void initReferenceTimer()
{
     // set timer frequencies
    TIM_TimeBaseInitTypeDef TIM_Config;

    // 1.Enable TIM clock
    RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM3, ENABLE);

    // 2.Fill the TIM_TimeBaseInitStruct with the desired parameters.
    // Time Base configuration
    TIM_TimeBaseStructInit (&TIM_Config);
    TIM_Config.TIM_Period = ReferencePeriod;//One Step Phase Shift
    TIM_Config.TIM_Prescaler = 0;
    TIM_Config.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_Config.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_Config.TIM_RepetitionCounter = 0;
    //configure the Time Base unit with the corresponding configuration
    TIM_TimeBaseInit (TIM3, &TIM_Config);

    // Enable the NVIC if you need to generate the update interrupt.
    // Enable the corresponding interrupt
}
//TIM4 Channel1: PB6
void initSlaveTimer()
{
    // set timer frequencies
    TIM_TimeBaseInitTypeDef TIM_Config;

    // 1.Enable TIM clock
    RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM4, ENABLE);

    // 2.Fill the TIM_TimeBaseInitStruct with the desired parameters.
    // Time Base configuration
    TIM_TimeBaseStructInit (&TIM_Config);
    TIM_Config.TIM_Period = SlavePeriod;
    TIM_Config.TIM_Prescaler = 0;
    TIM_Config.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_Config.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_Config.TIM_RepetitionCounter = 0;
    //configure the Time Base unit with the corresponding configuration
    TIM_TimeBaseInit (TIM4, &TIM_Config);

    // Enable the NVIC if you need to generate the update interrupt.
    // Enable the corresponding interrupt
}

//Tim1 Channel1: PA7
void initMasterPWM(void)
{
    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_OCStructInit(&TIM_OCInitStructure);
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
    TIM_OCInitStructure.TIM_Pulse = MasterPulse;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;

    TIM_OC1Init(TIM1, &TIM_OCInitStructure);

    /* Master Mode selection */
    TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update);
    /* Select the Master Slave Mode */
    TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);
}
//TIM3 Channel1 PC6
void initReferencePWM(void)
{
    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_OCStructInit(&TIM_OCInitStructure);
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
    TIM_OCInitStructure.TIM_Pulse = ReferencePulse; // set the duty cycle / pulse here!
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;

    TIM_OC1Init(TIM3, &TIM_OCInitStructure);

    TIM_SelectOnePulseMode(TIM3, TIM_OPMode_Single);

    /* Slave Mode selection: TIM3 */
    TIM_SelectInputTrigger(TIM3, TIM_TS_ITR0);
    TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Gated);

    /* Select the Master Slave Mode */
    TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);
    TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);
}
//TIM4 Channel1: PB6
void initSlavePWM(void)
{
    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_OCStructInit(&TIM_OCInitStructure);
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
    TIM_OCInitStructure.TIM_Pulse = SlavePulse; 
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;

    TIM_OC1Init(TIM4, &TIM_OCInitStructure);

    TIM_SelectInputTrigger(TIM4, TIM_TS_ITR2);
    TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Gated);
    TIM_SelectOnePulseMode(TIM4, TIM_OPMode_Single);
}

int main(void)
{
   initMasterPin();
   initReferencePin(); //FOR DEBUGGING ONLY
   initSlavePin();

   initMasterTimer();
   initReferenceTimer();
   initSlaveTimer();

   initMasterPWM();
   initReferencePWM();
   initSlavePWM();

   // enable timer / counter
   TIM_Cmd(TIM1, ENABLE);
   TIM_Cmd(TIM3, ENABLE);
   TIM_Cmd(TIM4, ENABLE);

       TIM_CtrlPWMOutputs(TIM1, ENABLE);
   TIM_CtrlPWMOutputs(TIM3, ENABLE);
   TIM_CtrlPWMOutputs(TIM4, ENABLE);

  /* Busy loop */
   int i;
  while (1)
  {
    i++;
  }
}

这是一般用途的建议-我对您的特定处理器没有经验

很难看到计时器,因此从底部开始:

  • 降低所有定时器的速度-将预分频器选项调至最大值
  • 确保您的ref clk计时器正在计数-使用调试器或printf显示计数器寄存器正朝您期望的方向运行
  • 检查它是否复位
  • 对其他计时器重复此操作(独立-无触发器)
你现在知道有三个计时器正在计数。通常到了这个阶段,你已经发现了一个你没有意识到的额外的“启用位”,或者方向与你期望的相反,或者一些类似的“令人头痛的琐碎”问题(正如Chris Stratton如此生动地描述的!)

  • 现在设置第一个触发
  • 验证触发是否在预期的时间启动所需的计时器-再次是printf或debugger
  • 将其连接到链中的下一个计时器并重复

一旦它们都互相触发,你就可以开始收起频率,看看它们是否都能快速工作。

你确定你的initReferencePWM中没有输入错误吗

void initReferencePWM(void)
{
    ...
    TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Gated);
    ...
}

为什么会突然出现TIM2?

这种问题会让人非常沮丧。一般来说,你所能做的就是一遍又一遍地检查定时器和GPIO的电源、时钟和配置,直到你发现隐藏的、但却让它无法工作的微不足道的错误。您还可以查看是否存在验证部分功能的简单案例,或者是否存在涉及相同问题的示例。将代码移动到不同编号的计时器时要小心,因为它可能需要更改APB总线或GPIO备用函数ID。当然,要确保使用UART输出日志记录或调试器或状态指示灯,您的代码正在完全执行,而不是在断言失败后进入无限循环。