www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Verschachtelte Interrupts


Autor: David P. (chavotronic)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Ich habe eine Lageregelung (Atmega 644p) implementiert, die mit dem 
TIMER0_COMPA_vect x-mal pro Sekunde aufgerufen wird. Nun möchte ich 
einige Variablen gerne über die serielle Schnittstelle rausschicken 
(Interruptbasierte Uart Library), allerdings wird die Übertragung durch 
die Timer Routine unterbrochen. Ich kann ja nun schlecht die Interrupts 
deaktivieren vor dem schicken, da ja dann auch das serielle nicht mehr 
läuft.
Was gibt es da für Lösungsansätze? Kann man zB die Timerinterrupts 
einzeln deaktivieren?

Vielen Dank,

David

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
David P. schrieb:

> Was gibt es da für Lösungsansätze? Kann man zB die Timerinterrupts
> einzeln deaktivieren?

Wenn dir die durch den UART Interrupt verurschte Interrupt Latenz die 
Regelung ausser Tritt bringt, wirst du wohl schweren Herzens auf eine 
Interrupt getriebene UART verzichten müssen. Gerade bei der UART ist das 
auch nicht so der Beinbruch, wenn man die eigentliche 
Zeichen-Senderoutine aus der Hauptschleife heraus zyklisch aufruft.


> Nun möchte ich einige Variablen gerne über die serielle
> Schnittstelle rausschicken (Interruptbasierte Uart Library),
> allerdings wird die Übertragung durch die Timer Routine unterbrochen.

Dein Problem klingt allerdings nach einem Denkfehler:
Du kannst nicht innerhalb der Regelschleife jedesmal einen Satz 
Messwerte ausgeben, wenn die Ausgabe grundsätzlich schon mal länger 
dauert als von einem Aufruf der Regelschleife zur nächsten vergeht.

Autor: David P. (chavotronic)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl-Heinz,

Ich würde diese Werte auch nur 1x pro Sekunde rausgeben wollen.
Es ist übrigens umgekehrt, das senden der Zeichen wird von der Regelung 
unterbrochen (und macht danach auch nicht weiter ..)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
David P. schrieb:
> Hallo Karl-Heinz,
>
> Ich würde diese Werte auch nur 1x pro Sekunde rausgeben wollen.
> Dann muss ich wohl auf die Uart Interrupt verzichten...

Ehe du das umbaust: Hast du es schon ausprobiert.
So eine UART Interrupt Routine ist ja im Normalfall eine von der kurzen 
Art: Zeichen aus Rungbuffer holen und aufs UDR zuweisen.

Klar das ist ein Arrayzugriff, ein Index erhöhen und ein paar Abfragen.

Summa summarum nichts was den µC länger als ein paar zig-Tatzyklen 
beschäftigen sollte. Wenn deine Regelschleife diese Verzögerung abkann, 
ist doch alles in Butter.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Es ist übrigens umgekehrt, das senden der Zeichen wird von der
> Regelung unterbrochen (und macht danach auch nicht weiter ..)

Zeig mal.
Das klingt nach einem Designflaw.

Autor: Bernhard R. (barnyhh)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo David,
dann debugge bitte Dein Programm. Das von Dir beschriebene Verhalten 
deutet auf Designfehler bzw Programmfehler hin.
Meine Glaskugel sagt: Zeile 42.

Bernhard

Edit: Da war wer schneller.

Autor: David P. (chavotronic)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich poste mal das Wichtigste:
int main(void) {
  
  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
  uint16_t chk;
  char i = 0;
  
  DDRA = 0x00;
  PORTA = 0x00;
  
  DDRB = 0x00;
  PORTB = 0xFF;
  
  DDRC = 0xFF;
  DDRD = 0xFE;
  
  
  // motorcontroller disabled / PWM-Signals to zero//
  PORTD |= _BV(PD2);
  OCR1A = 255;
  OCR1B = 0;
    
  init();
  

  PORTD &= ~_BV(PC7);
  
  *Dazwischen einige Routinen mit Lesen aus dem Eeprom usw*

  TCCR0B |= _BV(CS00) | _BV(CS02);
  TCCR0A |= _BV(WGM01);
  TCCR0A = (1<<WGM01);
  OCR0A = 155;
    
  TIMSK0 = _BV(OCIE0A); // compare interrupt

  
  sei();
  uart_puts("Teststring");
  
  while (1) {}
  }
}
ISR (TIMER0_COMPA_vect) {

* Hier werden dann Regelungsfunktionen aufgerufen * 
  TCNT0 = 0; 
}

Der Teststring kommt nicht komplett an. Lib ist übrigens die von Peter 
Fleury.

: Bearbeitet durch Admin
Autor: Detlev T. (detlevt)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Interruptroutinen sollte man immer so kurz wie möglich machen. Nur das 
machen, was sofort passieren muss, dann ein Flag setzen, damit die 
Hauptschleife weiß, dass es neue Daten zum Verarbeiten gibt.

Autor: David P. (chavotronic)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Müsste er nicht wenigstens nach dem Timer-Interrupt zurückspringen und 
die fehlenden Zeichen ausgeben?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
David P. schrieb:
> Müsste er nicht wenigstens nach dem Timer-Interrupt zurückspringen und
> die fehlenden Zeichen ausgeben?

Müsste er und tut er im Normalfall auch.
Irgendwas hast du da verbockt.

Autor: David P. (chavotronic)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich mach mich mal ans debuggen...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was ich mir zb vorstellen könnte:
Dass deine Reglungsfunktionen viel zu lange brauchen.
Dadurch steckt der µC praktisch nur noch in der Regelung und für das 
Drumherum bleibt keine Zeit mehr übrig.

Autor: Joe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst auch eine Zeitscheibe programmieren.

Beitrag "Genaue Sekunde und Zeitscheibe mit Timer0 erzeugen"


Oder auch am Ende eines jeden Interrupts innerhalb der Interruptroutine 
jeweils ein Zeichen über UART übertragen, falls noch ein Zeichen zur 
Ausgabe vorhanden ist die Zeit noch reicht.

Oder aber deine Interruptroutine so kurz machen und nur Flags setzen, so 
dass die serielle Schnittstelle nur geringfügige Fehler erhält.
Deine IRQ-Aufgaben werden dann außerhalb der IR_Routine erledigt.

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]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [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.