2013-05-03 7 views
2

나는 세 개의 타이머를 사용하여 위상 쉬프트 PWM 신호를 생성하려고합니다.stm32f405 트리거 신호 생성 PWM

  • TIM1가
  • TIM3는
  • TIM4의 위상을 생성하는데 사용되는 시프트 TIM4, 위상 트리거로서 사용된다 (는 1MHz에서 실행) 기준으로 사용된다

을 TIM3하여 신호 triggerd 시프트 요약하면 : - :

0,123,473 TIM1 --- 트리거> TIM3 --- 트리거 ---> TIM4

신호는 같아야합니다

다음은 현재 코드입니다. 참조가 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가 필요할 수 있으므로 다른 번호가 매겨진 타이머로 코드를 이동할 때주의하십시오. –

+0

물론 어설 션 실패 후 무한 루프로 벗어나지 말고 코드가 완전히 실행되는 UART 출력 로깅이나 디버거 또는 상태 LED로 확인하십시오. –

답변

1

initReferencePWM에 오타가 없습니까?

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

갑자기 TIM2가 필요한 이유는 무엇입니까?

1

이것은 일반적인 조언입니다. 귀하의 특정 프로세서에 대한 경험이 없습니다.

이 타이머의 가시성을 얻을, 그래서 바닥에서 위로 작동하기 어렵다 :

  • 모든 타이머를 느리게 - 최대 프리스케일러 옵션을 설정합니다.
  • - (NO 트리거 독립적)는 다른 타이머에 대한
  • 반복을 다시 확인 카운터 레지스터는
  • 을 기대하는 방향으로 가고 있음을 보여 디버거 또는의 printf를 사용 -
  • 는 타이머가 카운트 귀하의 심판 CLK를 보장

이제 세 개의 타이머가 계산 중입니다. 종종이 단계를 통해 당신은 당신이 알지 못했던 여분의 "활성화 비트"를 발견했거나 방향이 당신이 기대하는 것의 반대이거나 그런 "머리가 두드리는 사소한"문제점을 발견했습니다 (Chris Stratton이 그렇게 생생하게 묘사 할 때). ! 다시의 printf 또는 디버거

  • 체인 반복의 다음 타이머에 연결 -)

    • 지금
    • 는 트리거가 예상 시간에 원하는 타이머를 시작하는지 확인 트리거 최초 설정 .

    일단 모두 서로를 트리거하면 주파수를 감고 모든 것이 빠르게 작동하는지 확인할 수 있습니다.