2013-05-03 104 views
2

我试图用三个定时器产生一个相移PWM信号。stm32f405产生触发信号pwm

  • TIM1被用作参考(在1MHz运行)
  • TIM3被用作触发器来相移TIM4
  • TIM4用于生成相位由TIM3

移信号triggerd综上所述: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 
      ___  ___  ___  ___  ___ 
     ___| |___| |___| |___| |___| |_ 

这是我目前的代码。 Reference在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++; 
    } 
} 
+1

这种问题可能会非常令人沮丧。一般而言,您所能做的就是一遍一遍地检查定时器和GPIO的电源,时钟和配置,直到您发现隐藏的但头大的微不足道的错误,使其无法正常工作。您还可以查看是否有更简单的情况来验证部分功能,或涉及相同问题的例子。将代码移到不同编号的计时器时要小心,因为它可能需要更改APB总线或GPIO备用功能ID。 – 2013-05-06 01:22:10

+0

当然,确保使用UART输出日志记录或调试器或状态LED指示灯,您的代码已完全执行,而不是在断言失败后流入无限循环。 – 2013-05-06 01:25:09

回答

1

您确定您的initReferencePWM中没有错别字吗?

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

为什么TIM2突然出现?

1

这是通用的建议 - 我没有你的特定处理器的经验。

很难得到定时器的知名度,所以从下工作起来:

  • 拖慢了所有的计时器 - 开启预分频选项来最大。
  • 确保您的REF_CLK定时器计数 - 使用调试器或printf的证明计数寄存器是你所期望
  • 方向去检查它重置
  • 重复其他定时器(独立 - 没有触发器)

您现在有三个计时器,您知道计数。通常在这个阶段你会发现一个你没有意识到的额外的“启用位”,或者方向与你期望的方向相反,或者是像克里斯·斯特拉顿那样生动地描述它的一些这样的“头脑简单的小事”问题!)

  • 现在成立了第一个触发
  • 验证触发您希望的启动定时器的时候,你希望 - 再次printf或者调试
  • 它连接到下一个计时器链和重复。

一旦它们都触发对方,你可以开始清理频率,看看它是否都在速度运作。