2013-05-03 98 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或者調試
  • 它連接到下一個計時器鏈和重複。

一旦它們都觸發對方,你可以開始清理頻率,看看它是否都在速度運作。