www.mikrocontroller.net

Forum: Compiler & IDEs Problem bei Programmablauf mit Interrupts


Autor: Jens K. (jens_)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich habe mittlerweile mein Programm theoretisch soweit, dass es macht 
was es machen soll -> nur wie immer kommt es immer anders als man denkt.

Die Programmteile einzeln (ADC-Auswertung (Interrupt); 
Frequenzauswertung (Interrupt); Menü, Ausgabe) funktionieren, dies hab 
ich getestet.

Nur beim Zusammenspiel hapert es, wenn die beiden Interruptroutinen 
gleichzeitig im Programmablauf vorhanden sind.
Prinzipieller Programmablauf ist folgender:
(endlosschleife)

wenn adc mehr als 8 mal ausgewertet wurde -> auswertung 
vornehmen,variable setzen, damit erst wieder Interrupt durchlaufen wird, 
wenn Ausgabe erfolgt ist und "Erlaubnis" für Display geben;

wenn Frequenzmessung beendet -> auswertung vornehmen,variable setzen, 
damit erst wieder Interrupt durchlaufen wird, wenn Ausgabe erfolgt ist 
und "Erlaubnis" für Display geben;

wenn Ausgabe erlaubt -> Schreibe werte auf Display, setze 
Interruptvariablen zurück;

(ende)

So als kurzer Auszug.(Teil des Quellcodes ist oben angehängt.)

Mein Poblem ist jetzt, dass bei der Frequenzmessung ca. jedes 3. mal 
extrem falsche werte vorhanden sind  -> und ich hab keine Ahnung warum?
Wäre super wenn sich dasjemand mal ansehen könnte.

MFG


P.S. Die Variablen die nicht lokal in der main() deklariert sind, sidn 
alle  global deklariert (ja, mit volatile ;-) )

Autor: Jens K. (jens_)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Niemand eine Idee worans leigen könnt?

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1/ Der angegebene Quellcode ist nicht vollständig.

2/ Welche Variablen sind global und werden wo in welchen Funktionen 
(Interrupts) benutzt? Eine tabellarische Übersicht kann hier helfen.

Autor: Mister mit Kanister (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn sich die Interrupts gegenseitig unterbrechen, kann helfen wenn man 
in jeder ISR am Anfang und Ende ein cli(); bzw. sei(); macht. Wenn z.B. 
die Frequenzmessung unterbrochen wird, läuft der Timer weiter aber kann 
keine Ereignisse zählen.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mister mit Kanister wrote:
> Wenn sich die Interrupts gegenseitig unterbrechen, kann helfen wenn man
> in jeder ISR am Anfang und Ende ein cli(); bzw. sei(); macht.


Das ist Quatsch mit Soße.

Beim AVR kann kein Interrupt einen anderen unterbrechen.


Unterbrechung ist nur bei MCs (z.B. 8051) mit Interruptprioritäten 
möglich.

Und da muß man erst einem Interrupt eine höhere Priorität zuweisen, ehe 
er andere unterbrechen darf.

Und dann wäre es superblöd, wenn man die höhere Priorität wieder mit 
Interruptsperre aushebelt.

Man wird ja wohl nicht ohne Grund eine hohe Priorität vergeben haben.


Peter

Autor: Jens K. (jens_)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Also anbei mal der Quellcode -> Nur das Menü und das Display wurde 
weggelassen.
Das Interessante ist, dass solange ich in der main() die Schleife für 
die ADC-Auswertung weglasse die Frequenzauswertung funktioniert.
Ist die ADC-Auswertung aktiv, funktioniert die Frequenzauswertung nur in 
einem Bereich von ca. 5kHz bis 25kHz.

MFG und Danke.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du sperrst in main()/while bei der Ausgabe zeitweise die Interrupts und 
wunderst dich, dass die Frequenzauswertung (die auf Interrupts basiert) 
nicht richtig funktioniert? Nee, oder?

Autor: Jens K. (jens_)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Also das mit den Interrupts deaktivieren is Absicht(sind "nur" der ICP 
und der Timer Overflow) -> steht auch im Kommentar dahinter warum. Das 
bereitet auch bei einer "satnd-alone"(Also ohne ADC) Messung keinerlei 
Probleme. Ganz nebenbei findet während einer Ausgabe so oder so keine 
Auswertung der Frequenz statt.(Ich kann das mit dem 
Interruptabschalten(nur Timer/ICP) auch weglassen - Effekt: keiner, 
ausser dass bei hohen Frequenzen der Overflow Interrupt vom Timer so oft 
aufgerufen wird, dass meine Displayausgabe extrem verlangsamt wird.)
Wie gesagt - solange ich das ADC Ergebnis nicht auswerte oder nur den 
ADC auswerete hab ich auch kein Problem.(Interrupts beliben jeweils an, 
aber die if-Schleifen in der main() werden weggelassen)
Erst wenn beides "zeitgleich" aktiv ist hab ich ein Problem -> es kommen 
komiche Werte für die Frequenz raus - und ich hab keine Ahnung warum.

MFG

Autor: Mister mit Kanister (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, hab das mit den Interrupts verwechselt. Bei AVR gibts das 
natürlich nicht. Danke Peter.

Autor: Hans Dampf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Also ich hab das Problem jetzt dadurch gelöst, dass ich von "quasi 
Multitasking" dazu übergegangen bin, den ADC durch Polling auszuwerten 
und nur noch die Frequenzmessung über Interrupts laufen zu lassen.
-> Zumindestens funktioniert das ganze schon mal sicher.

Danke soweit für eure Tips.

MFG

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
arrgh - falschen Button erwischt. Also nochmal:

Hast du dir mal überlegt, wie lange deine Interrupts tatsächlich
gesperrt sind? Dein Code dazwischen enthält immerhin solch "harmlose"
Zeilen wie
sprintf (adrehmoment, "%.2f", adcergebnis);
 oder auch
LCD_WritePosString(0, 0,"RS232-Modus aktiv", 1);
Das dauert.

Aber eigentlich hast du dir ja deine Frage im Code schon selber
beantwortet.
//Interrupts für Timer deaktvieren, da sonst Displayausgabe bei sehr hohen Frequenzen extrem verlangsamt (->Überlauf sehr oft voll) 
UND eine flankengesteuerte Frequenzmessung passt nicht zusammen.

Oliver

Autor: Jens K. (jens_)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Oliver!

Ja dass die Displayausgabe sehr lange dauert war mir klar. Daher war 
meine ursprüngliche Idee folgende:
Interrupts ADC + ICP aktiv, solange nicht auf Display geschrieben wird.
Sobald hier eine Messung zu Ende ist -> Interrupts deaktivieren um quasi 
in Ruhe aufs Display schreiben zu können.
Interrupts nach Displayausgabe wieder aktivieren.
[Und ich mache ja immer erst nach einer Ausgabe wieder eine neue 
Messung]

Das Problem war ja nicht, dass die Frequenzmessung an sich nicht 
funktioniert hat, das Problem war eher, dass die Auswertung des ADC 
durch Interrupts nur einen gewissen messbaren Frequenzbereich zugelassen 
hat.
Um dies nun zu umgehen bin ich hergegangen und hab die ADC-Auswertung 
als Polling mit in die Ausgabefunktion gezogen, während der keine 
Frequenzmessung stattfindet.
Ich hoffe es ist klar geworden, wie ich das jetzt "gelöst" habe.
Bzw. wenn jemand Anmerkunge, weitere Verbesserungsvorschläge, etc. hat 
immer her damit -> ich lerne gerne und steh auch noch ziehmlich am 
Anfang mit meinem "Können"(wenn mandavon überhaupt schon sprechen kann ) 
bei der µC Programmierung.

Danke auf jeden Fall an alle!

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.