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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Hüpfer (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.