Forum: Mikrocontroller und Digitale Elektronik Encoder Timer3 und externer Interrupt stm32f4xx


von Ma B. (drumstick)


Lesenswert?

Hallo

Ich erfasse die zurückgelegten Pulse von einem Motor über einen Encoder 
mit dem Timer3 im Encoder Mode. Die Signale liegen an Pin 6 und 7 des 
Ports C. Das funktioniert. Um die Ist- Geschwindigkeit ermitteln zu 
können, möchte ich an Pin 6 einen externen Interrupt auslösen und dann 
einen Timer laufen zu lassen zwischen den Interrupts.

Jetzt meine Frage, kann ich beim STM32F405 einen Eingang PC6 als Encoder 
Eingang und gleichzeitig als externer Interrupt Sourcepin einsetzen? Bis 
jetzt sind meine alle gescheitert.

Danke und Gruss

MC Bu

von hatge (Gast)


Lesenswert?

Wann soll der Interrupt denn ausgelöst werden? Das habe ich nicht genau 
verstanden

von Ma B. (drumstick)


Lesenswert?

Jedesmal bei einer positiven Flanke an PC6. Dazwischen messe ich mittels 
Timer die Zeit zwischen den Interrupts. Incrementenauflösung des 
Encoders nach Datenblatt 100 Pulse pro Umdrehung.

Danke und Gruss

MC Bu

von Ma B. (drumstick)


Lesenswert?

Init des externen Interupts
1
void  MotorHall_setupPins_andPositionInterrupts(void)
2
{
3
  EXTI_InitTypeDef   EXTI_InitStructure;
4
  NVIC_InitTypeDef   NVIC_InitStructure;
5
  
6
  /* Configure EXTI6 line */
7
  EXTI_InitStructure.EXTI_Line = EXTI_Line6;                      
8
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;              
9
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;   
10
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;                        
11
  EXTI_Init(&EXTI_InitStructure);
12
    
13
  NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
14
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
15
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
16
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
17
  NVIC_Init(&NVIC_InitStructure);
18
  NVIC_EnableIRQ(EXTI9_5_IRQn);   
19
}

GPIO Init
1
void  GP_I_O_Init(void)
2
{
3
  GPIO_InitTypeDef GPIO_InitStructure;
4
  
5
6
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);  // Enable the Clock for Port C
7
8
// Configure PC.06 for encoder mode timer 3/8 Channel 2 CHA -------------------------
9
  GPIO_InitStructure.GPIO_Pin      = GPIO_Pin_6;
10
  GPIO_InitStructure.GPIO_Mode     = GPIO_Mode_AF;
11
  GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_100MHz;
12
  GPIO_InitStructure.GPIO_PuPd     =  GPIO_PuPd_NOPULL; 
13
  GPIO_Init(GPIOC, &GPIO_InitStructure);
14
  
15
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM3);
16
17
// Configure PC.07 for encoder mode timer 3/8 Channel 1 CHB -------------------------
18
  GPIO_InitStructure.GPIO_Pin      = GPIO_Pin_7;
19
  GPIO_InitStructure.GPIO_Mode     = GPIO_Mode_AF;
20
  GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_100MHz;
21
  GPIO_InitStructure.GPIO_PuPd     =  GPIO_PuPd_NOPULL; 
22
  GPIO_Init(GPIOC, &GPIO_InitStructure);
23
  
24
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_TIM3);
25
}

1
void timer_init(void)
2
{
3
  TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;
4
  TIM_OCInitTypeDef          TIM_TimeOutputModeStructure;
5
  RCC_ClocksTypeDef          SYSCLK_Frequency;
6
  
7
  RCC_GetClocksFreq(&SYSCLK_Frequency);
8
/*---Timer 3 Channel 2 in encoder mode----------------------------------*/
9
/*---Timer 3 Channel 1 in encoder mode----------------------------------*/
10
/*----------------------------------------------------------------------*/  
11
  
12
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
13
  TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
14
  TIM_SetAutoreload      (TIM3, 0xFFFF);
15
   TIM3->EGR |= (1 << TIM_EGR_UG);
16
  /* TIM enable counter */
17
  TIM_Cmd(TIM3, ENABLE);
18
}

Interrupt Handler (Testphase)
1
void EXTI9_5_IRQHandler(void)
2
{
3
  bool           positionChangeOK   = false;
4
  static uint8_t hallpattern_last  = 1; // valid pattern
5
  uint8_t        hallpattern_curr  = (GPIOC -> IDR / 32) & 0x6;
6
 
7
  EXTI9_5_IRQ_Hall_acknowledge();
8
}

von Uwe B. (derexponent)


Lesenswert?

wenn der Encoder funktioniert, warum dann nochmal einen externen 
Interrupt benutzen ?

du kannst doch zyklisch (mit einem Timer) den aktuellen Encoderwert 
auslesen und die Differenz zum letzten Wert bilden,
damit hast du die Drehzahl ermittelt

Gruss Uwe

von Ma B. (drumstick)


Lesenswert?

Ich versuchte dies in einem Thread (all 10ms), dies ist jedoch zu 
ungenau. Mit einem Timer quasi anstelle eines externen Interrupts ein 
Event? Das schau ich ich mir mal an.

Danke für den Tipp.

Gruss

MC Bu

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.