Forum: Compiler & IDEs UART in ISR (Mega32)


von Uli (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich versuche mit dem angehängten Testprogramm mit einem Mega32 eine
Sprungantwort aufzuzeichnen: ich gebe ein PWM-signal auf einen
Elektromotor (der als Ventilator eine Klappe hochbläst) und messe eine
Reaktion mittels ADC. Ich will möglichst in festen Zeitschritten die
AD-Werte mittels UART (ich verwende P.Fleurys Library) auslesen.

Ich löse das jetzt, indem ich in einer ISR die Daten sende. Ist das so
OK, oder eher schlecht weil ich in der ISR interruptbasierten UART
verwende? Ich bin mir auch nicht ganz im klaren darüber wie die
UART-Funktionen funktionieren - in der ISR sind ja Interrupts
eigentlich disabled (global interrupt enable flag gelöscht), aber die
interruptbasierte Kommunikation geht trotzdem - ich vermute das klappt
weil in der ISR nur der Buffer beschrieben wird und das eigentliche
Senden erst später erfolgt? Der Code in den ISRs soll ja zudem so kurz
wie möglich sein, ist meine Lösung in dieser Hinsicht OK? Alternativ
könnte ich in der while-Schleife des Hauptprogramms den AD-Wert jeweils
mit Timestamp (d. h. Anzahl durchlaufener ISRs) senden, aber die erste
Version ist denke ich besser weil die Abtastfrequenz fest ist. (Bei der
zweiten wird ab und zu eine ISR nicht übertragen, so dass Lücken
entstehen.) (Die LED lasse ich übrigens als Indikator blinken, ob die
ISRs gleichmässig durchlaufen oder sich bei Programmänderungen
Verzögerungen bemerkbar machen.)

Die Abtastfrequenz ist meiner Berechnung jetzt 50 Hz, oder täusche ich
mich da?

Vielen Dank für Antworten!
Uli

von Karl H. (kbuchegg)


Lesenswert?

Na ja: Wenn Interrupts gesperrt sind, geht ja die Anforderung
des Interrupts deswegen ja trotzdem nicht verloren.
D.h. du stellst was in den Buffer, die UART Routine sendet
ein Zeichen und generiert einen Interrupt sobald das
Zeichen draussen ist. Sind zu diesem Zeitpunk die Interrupts
noch nicht freigegeben, so wird die ISR Anforderung einfach
nur gespeichert und erst dann ausgeführt sobald die Interrupts
wieder freigegeben wurden. Im schlimmsten Fall entsteht ein
Zeitverzug zwischen senden des ersten Zeichens und senden des
zweiten Zeichens, da ja die ISR die das zweite Zeichen senden
würde warten muss, bis deine ISR die Interrupts wieder
freigegeben hat.

von Uli (Gast)


Lesenswert?

OK, dankeschön für die gute Erklärung! Aber itoa() in der ISR
durchzuführen ist auch sehr kritisch, oder? Ich vermute das haut bei
mir nur hin aufgrund der recht langsamen ISR-Frequenz, aber wenn ich
die Frequenz erhöhe oder mehr itoa()-Wandlungen in der ISR vornehme
geht das zeitlich nicht mehr? (zumindest blinkt dann die LED nicht
mehr...)

Ich will im nächsten Schritt nämlich mehrere Regelparameter per UART
auslesen, also pro ISR-Durchlauf einen ganzen Satz an Zahlen. Ist dann
der beste Weg (oder der einzige?) in der Schleife der main-Funktion die
Daten immer mit Timestamp zu senden (also so wies im Beispielprogramm
auskommentiert in der while-Schleife steht)? Nachteil ist halt dass das
nicht schnell genug geht so dass immer nur z.B. nur jeder dritte
ISR-Parametersatz (je nach ISR-Frequenz)gesendet wird. Gibt es
Alternativen oder bessere Möglichkeiten?

Vielen Dank
Uli

von Karl H. (kbuchegg)


Lesenswert?

Generell solltest du ISR zeitlich so kurz wie nur
irgend möglich halten. Aber das weist du eh.

> in der Schleife der main-Funktion die
> Daten immer mit Timestamp zu senden

So wuerde ich das machen.

> Nachteil ist halt dass das
> nicht schnell genug geht so dass immer nur z.B. nur jeder dritte
> ISR-Parametersatz (je nach ISR-Frequenz)gesendet wird.

Das liegt aber wahrscheinlich nicht am Pgm Aufbau an sich,
sondern daran, dass die UART Übertragung ja auch Zeit benötigt.
Wenn die Daten nun schneller anfallen als sie übertragen werden
können, fällt irgendetwas unter den Tisch. Dabei ist es aber
unerheblich wo due die Übertragung initiierst. Die UART
Übertragung ist einfach zu langsam. Da hilft nur:
Baudrate hochdrehen oder weniger Daten generieren oder weniger
übertragen.

von Uli (Gast)


Lesenswert?

Danke vielmals, das bestätigt was ich geahnt habe! Dann muss jetzt ein
Quarz für höhere Baudraten her...

von Wolfram (Gast)


Lesenswert?

Wenn ich sowas machen muesste wuerde ich folgendes beachten,
1. PWM Frequenz des Motor's mindestens bei 10 fachen der ADC
Abtastrate
2. vor ADC, Tiefpass mit entsprechender Grenzfrequenz
Am besten gehen sämtliche Samples erstmal in einen Puffer und erst wenn
man fertig aufgezeichnet hat fragt man am PC ab.
Sonst interruptgersteuerte UartKomunikation, Samples in Ringpuffer
zwischenspeichern. Auf Überlauf prüfen.
Du nennst keine Abtastraten, dies ist aber eigentlich das erste worüber
man sich Gedanken machen sollte. (Dauer des Vorgangs und nötige
zeitliche Auflösung)
Ich würde denken, dass ein AVR mit 8 MHz für sowas durchaus ausreicht.
Wahrscheinlich auch mit 1MHz

von Uli (Gast)


Lesenswert?

Hi Wolfram,
danke für die Hinweise. UART ist ja schon interruptbasiert, aber wie
kann ich denn den Buffer auf Überlauf prüfen und was passiert wenn er
überläuft (oder wo finde ich Infos dazu, hab gerade ergebnislos
gesucht)? Entgegenwirken kann ich am besten durch möglichst grossen
Buffer und hohe Baudraten vermute ich?
Abtastrate für die Sprungantwort ist 50Hz, das hatte ich am Anfang
erwähnt...

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.