Forum: Mikrocontroller und Digitale Elektronik [STM32F407VG, Discovery-board] Timer-interrupt verwirrt mich


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 Luigi (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Servus zusammen,

ich steige gerade wieder auf den STM32 ein (hatte länger nix damit 
gemacht und fange bei den basics an) aber leider bin ich jetzt auf ein 
Problem gestoßen, dessen Hintergrund ich gerne Verstanden hätte. Sollte 
auch super leich zu reproduzieren sein, sofern ein STM32F4-discovery 
board und CooCox CoIDE vorliegen. (Damit hätte ich dann wohl auch meine 
Umgebung definiert)
Die veränderten Dateien habe ich angehängt, der Rest ist von den 
Standard-Libs, die man in CoIDE einfach aktiviert und die dann 
automatisch ins Projekt kopiert werden.

Folgende Aufgabe :
Ich will eine LED innerhalb einer Interruptroutine ein- und ausschalten. 
Etwa im 1s Zyklus.

Das Problem :
So gehts :
1
void TIM2_IRQHandler(void)
2
{
3
  static uint8_t i = 0;
4
5
  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
6
7
  GPIO_ToggleBits(GPIOD, GPIO_Pin_13); // LD3, orange
8
9
  if( 2 == ++i )
10
  {
11
    GPIO_ToggleBits(GPIOD, GPIO_Pin_14); // LD5, red
12
    i=0;
13
  }
14
}
So gehts nicht :
  (nur die rote LED blinkt, die orange nicht)
1
void TIM2_IRQHandler(void)
2
{
3
  static uint8_t i = 0;
4
5
  GPIO_ToggleBits(GPIOD, GPIO_Pin_13); // LD3, orange
6
7
  if( 2 == ++i )
8
  {
9
    GPIO_ToggleBits(GPIOD, GPIO_Pin_14); // LD5, red
10
    i=0;
11
  }
12
13
  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
14
}

Woran kann das liegen?
Ich stehe vollkommen auf dem Schlauch. Für mich ist das gerade völlig 
unerklärlich!

Vielen Dank für eure Hilfe!
Grüße
Luigi

von Leo B. (luigi)


Bewertung
0 lesenswert
nicht lesenswert
PS:

Hervorzuheben ist vielleicht, dass nur die Zeile
1
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
in der Position verändert wird. Das ist der einzuge Unterschlied 
zwischen "funktionier" und "funktioniert nicht".



PPS:
war nicht eingelogt, bin aber ich

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Bewertung
0 lesenswert
nicht lesenswert
Da gabs mal was hier bei mc.net, man muss erst das Interrupt Flag 
löschen, bevor man an GPIOs rumfummelt. Ist mir auch mal beim STM32F100 
untergekommen.
Frag mich aber bitte nicht mehr nach dem Thread - ich habe nur diese 
Bemerkung in meinen Sourcen gefunden:
1
void TIM1_UP_TIM16_IRQHandler(void){
2
//uint8_t speedRegTicks = 0;
3
// microcontroller.net : Clear the IT pending bit before doing any GPIO stuff
4
TIM_ClearITPendingBit(TIM1,(TIM_IT_Update | TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3));
5
  LED_GPIO_PORT->BSRR = ERROR_LED_PIN;  // debug
6
//....

von Jim M. (turboj)


Bewertung
0 lesenswert
nicht lesenswert
Luigi schrieb:
> Woran kann das liegen?
> Ich stehe vollkommen auf dem Schlauch. Für mich ist das gerade völlig
> unerklärlich!

TIM_ClearITPendingBit() kommt im 2. Falls zu spät. Der µC braucht ein 
paar Takte bis das Timer Peripherial die Interrupt Anforderung 
wirklich zurück nimmt - man bedenke z.B. den Schreib Puffer.

Dummerweise macht der µC dadurch beim Interrupt Return ein Tail-Chain 
wieder in denselben Handler, der dadruch 2x hintereinander aufgerufen 
wird. Du solltest bei der roten LED die doppelte Frequenz erkennen 
können.

Abhilfe: Entweder rechtzeitig Flag zurück setzen (1. Variante) oder 
nochmal ein Dummy Lesezugriff auf die Hardware ausführen (z.B. irgenden 
Register lesen).

von Leo B. (luigi)


Bewertung
0 lesenswert
nicht lesenswert
Jim M. schrieb:
> TIM_ClearITPendingBit() kommt im 2. Falls zu spät. Der µC braucht ein
> paar Takte bis das Timer Peripherial die Interrupt Anforderung
> wirklich zurück nimmt - man bedenke z.B. den Schreib Puffer.
>
> Dummerweise macht der µC dadurch beim Interrupt Return ein Tail-Chain
> wieder in denselben Handler, der dadruch 2x hintereinander aufgerufen
> wird. Du solltest bei der roten LED die doppelte Frequenz erkennen
> können.

Eindeutig, du hast recht. Vielen Dank. Das Erklärt zu 100% das Phänomen.
Kurz Warten (2*NOP) nach dem rücksetzten ist ebenfalls eine Lösung, zu 
kurz warten (1*NOP) löst das Problem nicht (ich sage mal: q.e.d.)



Der vollständigkeit halber, so gehts auch :
1
void TIM2_IRQHandler(void)
2
{
3
  static uint8_t i = 0;
4
5
  GPIO_ToggleBits(GPIOD, GPIO_Pin_13); // LD3, orange
6
7
  if( 2 == ++i )
8
  {
9
    GPIO_ToggleBits(GPIOD, GPIO_Pin_14); // LD5, red
10
    i=0;
11
  }
12
13
  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
14
15
  __asm volatile ("NOP");
16
  __asm volatile ("NOP");
17
}

Vielen Dank!

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.