STM32F4 Frequenz messen mit Timer5

OP #3792623
Lesenswert?

Hallo

Ich möchte bei einem STM32F407 eine Frequenz bei PA2 messen. Dazu nehme 
ich den Timer5. Mit dem Capture Compare müsste das doch gehen oder was 
mache ich falsch?

TIM_ICInitTypeDef  TIM_ICInitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);

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

  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL ;
  //GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP ;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL ;
  //GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP ;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  // Connect TIM pin to AF2
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_TIM5);

  NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV8;
  TIM_ICInitStructure.TIM_ICFilter = 0x2;

  TIM_PWMIConfig(TIM5, &TIM_ICInitStructure);

  TIM_SelectInputTrigger(TIM5, TIM_TS_TI2FP2);

Oder geht das bei PA2 nicht?
Ich habe einen externen Encoder bei PA2 (Spur A) und PA3 (Spur B) 
angeschlossen, davon möchte ich die Geschwindigkeit messen..
Danke
OP #3798416
Lesenswert?

Hallo

Ich habe Deine Initialisierung übernommen, jedoch leider immer noch ohne 
Erfolg. Was ist denn daran falsch, ich finde den Fehler einfach nicht:

    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);  // Timer5 
aktivieren
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // PortA 
aktivieren

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // PA5 und PA6 als capture-input zu T5
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_TIM5);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_TIM5);

    NVIC_EnableIRQ(TIM5_IRQn);       // Int-T9 aktivieren
    NVIC_SetPriority(TIM5_IRQn,14);  // sehr hohe Priorität

    TIM5->CCMR1 = TIM_CCMR2_CC3S_0 + TIM_CCMR2_CC3S_1;     // capture 
zuordnung IC1 -> TI1
    TIM5->CCER = TIM_CCER_CC3E;         // capture freigeben

    TIM5->CCMR1 |= TIM_ICPSC_DIV8;      // Vorteiler /8 aktivieren

    TIM5->DIER |= TIM_DIER_CC1IE + TIM_DIER_UIE; // mit interrupts
    TIM5->CR1 |= TIM_CR1_CEN;           // T5 starten


Danke
Gast #3798572
Lesenswert?

holger schrieb:
>>    RCC_APB2PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);  // Timer5
>             ^                      ^
>             |                      |
>
> Schau mal GENAU hin.

Meckert da nicht schon der Compiler?
Aber immerhin hast Du einen Blick für diesen Kopierkram :-) Längere 
Quelltexte der STM (u.a.) sind ja fast nicht mehr lesbar, da sich 
gleiche Befehlssequenzen immer wiederholen, sich dann aber doch in nur 
einem Zeichen unterscheiden.

Mach Fax schrieb:
> Ich habe Deine Initialisierung übernommen, jedoch leider immer noch ohne
> Erfolg.

Du hättest auch TIM9 auf PA2+PA3 legen können, um erst einmal einen 
Erfolg zu haben, aber jetzt sollte es bei Dir auch so funktionieren.
OP #3799598
Lesenswert?

m.n. schrieb:
> Du hättest auch TIM9 auf PA2+PA3 legen können, um erst einmal einen
> Erfolg zu haben, aber jetzt sollte es bei Dir auch so funktionieren.

Nein kann ich leider nicht, da Timer9 schon benutzt wird, aber Danke 
habe ich am späteren Abend übersehen...
Werde ich ausprobieren und danach ein Feedback geben.

Danke & Gruss
OP #3801947
Lesenswert?

Ich habe das jetzt mit dem TimerLib gemacht, jedoch funktioniert da 
immer noch etwas nicht wie gewünscht, sprich es wird kein Interrupt 
ausgelöst bei Flanken auf PA2. Das kann doch nicht so schwierig sein, 
hat niemand eine Lösung dazu?

void EncoderSyncConfig(void)
{
  GPIO_InitTypeDef       GPIO_InitStructure;
  TIM_TimeBaseInitTypeDef    TIM_TimeBaseInitStructure;
  TIM_ICInitTypeDef       TIM_ICInitStructure;
  NVIC_InitTypeDef       NVIC_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // PortA 
aktivieren

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //GPIO_PuPd_NOPULL; 
//GPIO_PuPd_UP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //GPIO_PuPd_NOPULL; 
//GPIO_PuPd_UP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

/////////////////////////////////////////

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_TIM5);
  //GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_TIM5);

  TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //Control 
with dead zone.
  TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; 
//Counter direction
  TIM_TimeBaseInitStructure.TIM_Prescaler = 10;// 84-1;   //Timer clock 
= sysclock /(TIM_Prescaler+1) = 2M
  TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInitStructure.TIM_Period = 0xFFFF;
  TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);

  TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;
  TIM_ICInitStructure.TIM_ICFilter = 0;
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; 
//TIM_ICSelection_IndirectTI
  TIM_ICInit(TIM5,&TIM_ICInitStructure);

  NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x05;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  NVIC_SetPriority(TIM5_IRQn,14);  // sehr hohe Priorität
  NVIC_EnableIRQ(TIM5_IRQn);       // Int-T9 aktivieren

  TIM_ITConfig(TIM5, TIM_IT_CC3, ENABLE);

  TIM_Cmd(TIM5,ENABLE);
}
OP #3802121
Lesenswert?

So, es funktioniert jetzt (Code unten)

Was aber noch nicht geht, ist dass bei einer positiven Flanke auf PA3 
der Timer automatisch wieder auf 0 gestellt wird, jetzt wird der 
Interrupt ausgelöst, ich kann den Capture Wert auslesen in der IRQ 
Routine aber der Timer zählt munter weiter und bei der nächsten 
positiven Flanke habe ich den alten TimerStand plus den neuen im 
Register. Es sollte laut Library mit diesen beiden Zeilen eigentlich den 
Timer bei einer Flanke von extern zurücksetzen, oder was fehlt da noch?

TIM_SelectInputTrigger(TIM5, TIM_TS_ETRF);
TIM_SelectSlaveMode(TIM5, TIM_SlaveMode_Reset);

Danke


void EncoderSyncConfig(void)
{
  GPIO_InitTypeDef       GPIO_InitStructure;
  TIM_TimeBaseInitTypeDef    TIM_TimeBaseInitStructure;
  TIM_ICInitTypeDef       TIM_ICInitStructure;
  NVIC_InitTypeDef       NVIC_InitStructure;

  //Activate PortA
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  //Activate the Timer5
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);

  //connect the Timer5 to the Sync Encoder PINs
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_TIM5);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_TIM5);

  //configure the Counter
  TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; 
//without ClockDivision
  TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; 
//Counter direction Up
  TIM_TimeBaseInitStructure.TIM_Prescaler = 1;               //Timer 
clock = sysclock /(TIM_Prescaler+1) = 2M
  TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInitStructure.TIM_Period = 0xFFFFFFFF;
  TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);

  TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;
  TIM_ICInitStructure.TIM_ICFilter = 0;
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; 
//TIM_ICSelection_IndirectTI
  TIM_ICInit(TIM5,&TIM_ICInitStructure);

  //Enable the TIM5 CC3 Interrupt Request
    TIM_ITConfig(TIM5, TIM_IT_CC3, ENABLE);

  //TIM enable counter
    TIM_Cmd(TIM5, ENABLE);

  TIM_SelectInputTrigger(TIM5, TIM_TS_ETRF);
    TIM_SelectSlaveMode(TIM5, TIM_SlaveMode_Reset);
    TIM_SelectMasterSlaveMode(TIM5, TIM_MasterSlaveMode_Enable);
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren