Forum: Mikrocontroller und Digitale Elektronik Externen Interrupt tritt nur einmal auf STM32F107


von Hüpfer (Gast)


Lesenswert?

Hallo Experten,
ich versuche gerade für meine Bachelorarbeit ein Programm für einen 
STM32F107VC zuschreiben. Ursprünglich sollte ich im Rahmen dieser Arbeit 
nur eine Hardware entwickeln. Da ich (leider) ohne Probleme gut damit 
durchgekommen bin, die Hardware zu entwickelt und zu bauen. Soll ich nun 
die noch übrige Zeit nutzen und ein Programm für das Board schreiben. 
Mein Problem darin ist, dass ich in diesem Bereich kaum Ahnung habe und 
daher auf eure Hilfe angewiesen bin.

Jetzt zu meinem Problem.
Ich muss mit einem Externen Taster mehrere Programmabschnitte ansteuern.
Wird der Taster an Pin PE8 gedrückt, so wird Funktion1 abgearbeitet. 
Sobald diese Fertig ist kann erneut der Taster an Pin PE8 gedrückt 
werden um die zweite Funktion zu starten. Die Funktionen setzen am Ende 
immer eine Variable.

Ich versuche also mit dem Interrupt Handler immer eine Variable um eins 
zu erhöhen. Beim ersten betätigen des Taster startet er auch die 
Funktion1 nur beim erneuten drücken geschieht nichts.

Einstellung des Interrupt´s
1
void Init_ExternIRQ_CAL (void)              
2
{
3
  GPIO_InitTypeDef GPIO_InitStructure;
4
  EXTI_InitTypeDef EXTI_InitStructure;
5
  NVIC_InitTypeDef NVIC_InitStructure;
6
  
7
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE | RCC_APB2Periph_AFIO, ENABLE);
8
  
9
  //Taster S3 an Port PE8  (CAL Taste)
10
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
11
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
12
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
13
  GPIO_Init(GPIOE, &GPIO_InitStructure);
14
  
15
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource8);
16
  
17
  EXTI_InitStructure.EXTI_Line = EXTI_Line8;
18
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
19
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
20
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
21
  EXTI_Init(&EXTI_InitStructure);
22
  
23
  NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
24
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
25
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
26
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
27
  
28
  NVIC_Init(&NVIC_InitStructure);
29
  
30
}

Interrupt Handler
1
 
2
void EXTI9_5_IRQHandler (void)    //Aufruf des Interrupt der durch drücken der CAL Taste ausgelöst wird.
3
{
4
  
5
  ProgFunktion = 10;  //ProgFunktion auf 10 setzen 
6
                      
7
 if (zaehler == 0) 
8
        {                                      
9
  EXTI_ClearITPendingBit(EXTI_Line8); 
10
  CalTasterValue = 1;
11
  }
12
  
13
if (zaehler == 1)   
14
  {                                        
15
  EXTI_ClearITPendingBit(EXTI_Line8);  
16
  CalTasterValue = 2;
17
  }
18
  
19
if (zaehler == 2)  
20
  {                                                              
21
  EXTI_ClearITPendingBit(EXTI_Line8);    
22
  CalTasterValue = 3;
23
  }
24
  
25
if (zaehler == 3)  
26
  {                                                              
27
  EXTI_ClearITPendingBit(EXTI_Line8);    
28
  CalTasterValue = 4;
29
  }
30
  
31
auswahl_funktion();    // Aufruf der Funktion
32
}

Also mit der Variablen ProgFunktion = 10, wird in der Funktion 
auswahl_funktion() die richtige Funktion ausgewählt. In dieser Funktion 
wird mit Hilfe der Variablen CalTasterValue, die im Interrupt Händler 
gesetzt wird der jeweilige Programmschritt ausgewählt. Am Ende diesem 
Programmschritt wird die Variable zaehler um eins erhöht um bei neuen 
Drücken der Taste im Programm weiter zukommen. Nur startet der Interrupt 
nicht mehr.
Kann mir jemand da einen Tipp geben, wo der Fehler liegt?

von Teo D. (teoderix)


Lesenswert?

Hüpfer schrieb:
> auswahl_funktion();    // Aufruf der Funktion
> }

Hab ja keinen Plan von dem Ding, aber mir scheint das du die ISR NIE 
verlässt!

von STM Apprentice (Gast)


Lesenswert?

Heisser Tip: zeige dein ganzes Programm.
Aber bitte als Anhang.

Noch ein heisser Tip:

Hüpfer schrieb:
> void EXTI9_5_IRQHandler

Ein IRQ Handler der mehrere Interrupts bedient sollte

a) den Interrupt auf jeden Fall löschen den er bekommt.
Das ist in deinem Programm nicht gewährleistet.

b) die Ursache des Interrupts kennen, sonst weiss er
womöglich nicht was er löschen soll.

von Teo D. (teoderix)


Lesenswert?

Teo D. schrieb:
> Hab ja keinen Plan von dem Ding, aber mir scheint das du die ISR NIE
> verlässt!

Zu langsam fürs korrigieren/erweitern. :(

STM Apprentice schrieb:
> a) den Interrupt auf jeden Fall löschen den er bekommt.
> Das ist in deinem Programm nicht gewährleistet.
> ....

von Hüpfer (Gast)


Lesenswert?

Danke... Ja das war es.
Damit ich das richtig Verstehe. Ich darf keine Funktionen in einen 
Interrupt Händler aufrufen, weil so die Unterbrechung des Interrupts das 
Programm in der Unterbrechung weiter fortsetzt, ohne zum normalen 
Programmablauf zurück zukehren?

von Peter D. (peda)


Lesenswert?

Interrupts sind auf den ARM nicht so einfach. Die haben in der Regel 2 
Pending-Bits, eins in der Peripherie und eins im Interruptcontroller. 
Die müssen beide in der richtigen Reihenfolge gelöscht werden.
Manchmal muß man noch einige Zyklen warten, eh sie als gelöscht erkannt 
werden. Sonst rauscht man nach dem RETI sofort wieder in den Handler.

Im Example-Verzeichnis sollten ja Beispiele für Interupts zu finden 
sein.
Ich würd aber erstmal drauf verzichten und die Flankenerkennung in der 
Mainloop machen.

von Jim M. (turboj)


Lesenswert?

Peter D. schrieb:
> Die haben in der Regel 2
> Pending-Bits, eins in der Peripherie und eins im Interruptcontroller.
> Die müssen beide in der richtigen Reihenfolge gelöscht werden.

Üblicherweise nur das in der Peripherie - aber das pending Bit im NVIC 
kann ein paar Takte nachziehen, Stichwort Write Buffer.

Bei der Funktion im OP sehe ich nur einen Fehler wenn zaehler außerhalb 
von [0,3] liegt. Hint: EXTI_ClearITPendingBit(EXTI_Line8) gehört 
oberhalb der "if"s, am Besten in die 1. Zeile des Handlers.

Hüpfer schrieb:
> Damit ich das richtig Verstehe. Ich darf keine Funktionen in einen
> Interrupt Händler aufrufen, weil so die Unterbrechung des Interrupts das
> Programm in der Unterbrechung weiter fortsetzt, ohne zum normalen
> Programmablauf zurück zukehren?

Doch, man kann Unterfunktionen im Handler aufrufen. Die Abarbeitung des 
Interrupts ist natürlich erst dann abgeschlossen wenn die Handler 
Funktion komplett inklusive aller Unterfunktionen beendet ist. Weswegen 
ein delay() im Interrupt eher blöd ist.

Allerdings kann der C-Optimizer bei Variablenzugriffen durcheinander 
kommen, wenn die in sowohl main (und deren Unterfunktionen) als auch im 
Handler (und dessen Unterfunktionen) verwendet werden - Stichwort 
"volatile" und atomarer Zugriff.

von Jim M. (turboj)


Lesenswert?

Jim M. schrieb:
> Allerdings kann der C-Optimizer bei Variablenzugriffen durcheinander

Genau deswegen bräuchten wir hier übrigens auch den Rest des Programms 
vom OP: Der Fehler scheint im nicht geposteten Code zu liegen.

Bitte als .c und .h Dateianhang posten, das Forum hier kann das gut 
anzeigen.

: Bearbeitet durch User
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.