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 ;-) )
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.
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.
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
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.
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?
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
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
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
1 | sprintf (adrehmoment, "%.2f", adcergebnis); |
oder auch
1 | LCD_WritePosString(0, 0,"RS232-Modus aktiv", 1); |
Das dauert. Aber eigentlich hast du dir ja deine Frage im Code schon selber beantwortet.
1 | //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
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!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.