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
Wann soll der Interrupt denn ausgelöst werden? Das habe ich nicht genau verstanden
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
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 | }
|
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.