Externen Interrupt tritt nur einmal auf STM32F107

Gast #5082491
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?
Gast #5082510
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.
Gast #5082519
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?
#5082530
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.
#5082737
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.

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