Hallo zusammen :) ich hab ne kurze Fage was Interrupts betrifft. Ich hab mal im Tutorial gelesen, das während der Controller auf einen vollen Empfangspuffer wartet der komplette Programmablauf blockiert ist. Gilt das auch für Interrupts? Das Problem hab ich nämlich momentan. Der Controller wartet auf Zeichen von der Seriellen (was mir durch eine LED angezeigt wird, um sicher zugehen das ich wirklich in meiner "Empfangspuffer-Warten-Schleife" bin) dann löse ich einen Interrupt aus und es tut sich nix. Wenn er nicht auf Zeichen wartet dann funktioniert der Interrupt. Controller ist AT Mega 32. AVR Studio mit Win AVR. Programmierspare C. Kann mir jemand helfen?
Moin, Klaus Dietz schrieb: > Gilt das auch für Interrupts? nein, wenn er (der Interrupt) freigegeben ist schlägt er zu. Ohne deine Quelltexte ist eine Hilfe nur schwer möglich. MfG
Sauger schrieb: > nein, wenn er (der Interrupt) freigegeben ist schlägt er zu. theoretisch könnte aber die > "Empfangspuffer-Warten-Schleife" ja auch in einem Interrupt sein...
Moin, Justus Skorps schrieb: > ja auch in einem Interrupt sein... deswegen > Ohne deine Quelltexte ist eine Hilfe nur schwer möglich. MfG
ich versuch nen code auf die Beine zu stellen. Denn der Echte Quellcode ist etwas zu lang fürs Forum.
meine Frage war ja nur ob die Interrupts dann deaktiviert sind wenn er auf Zeichen wartet. Ich versuch das Problem erst mal alleine zu lösen. Ihr sollt schließlich nicht meine Arbeit vollrichten. MFG
Klaus Dietz schrieb: > meine Frage war ja nur ob die Interrupts dann deaktiviert sind wenn er > auf Zeichen wartet. dann musst du uns aber erstmal sagen was du darunter verstehst, wie wartest du denn auf die Daten? Ist das eventuell innerhalb eines Interupts?
ich Frage das Bit ab das gesetzt wird wenn der Puffer voll ist. Sprich alle zeichen Empfangen hat. Zusätzlich will ich aber das mein Interrupt zuschlagen kann. Was er im moment nicht macht.
Moin, Klaus Dietz schrieb: > meine Frage war ja nur ob die Interrupts dann deaktiviert sind wenn er > auf Zeichen wartet. Ich versuch das Problem erst mal alleine zu lösen. > Ihr sollt schließlich nicht meine Arbeit vollrichten. lobenswert, Sauger schrieb: > nein, wenn er (der Interrupt) freigegeben ist schlägt er zu. also drauf achten der Interrupt nicht gesperrt ist (wird) MfG
ist alles eingestellt. Im Hauptprogramm ist sei(); drin, und ein Unterprogramm wird aufgerufen das dann die entsprechenden Bits einstellt. ISR steht auserhalb vom hauptprogramm. Das funktioniert alles wunderbar. Problem ist nur wenn er auf dieses Bit wartet (Puffer voll) dann intressiert ihn der Interrupt nicht.
Klaus Dietz schrieb: > ich Frage das Bit ab das gesetzt wird wenn der Puffer voll ist. Sprich > alle zeichen Empfangen hat. Zusätzlich will ich aber das mein Interrupt > zuschlagen kann. es sollte zwar gehen, aber der sinn ist mir nicht ganz klar. Denn warum willst du an der stelle überhaupt auf das Zeichen warten, wenn du es eh im Interupt auswertest?
weil ich eine Aktion machen will, die von der Seriellen aus gesteuert werden kann und wenn ich über die serielle nichts machen will dann drücke ich einfach eine andere Taste.
Ob Dein Interrupt zubeißt oder nicht, ist nicht davon abhängig, wo im Programm sich die CPU gerade rumtreibt. Ausschlaggebend dafür ist ausschließlich das I-Flag im Statusregister.
Klaus Dietz schrieb: > weil ich eine Aktion machen will, die von der Seriellen aus gesteuert > werden kann und wenn ich über die serielle nichts machen will dann > drücke ich einfach eine andere Taste. versteht ich nicht? Du kannst doch auch die Aktion im Interupt machen.
Moin, Vermutung: du liest UDR in einer Schleife aus. Warum sollte noch ein Interrupt ausgelöst werden wenn das Register gelesen ist? MfG
Es sei denn, die Bitabfrage ist so geschrieben, dass die Interruptsgespert sind.
1 | cli(); // ATOMIC_BLOCK(ATOMIC_FORCEON) wäre auch eine Möglichkeit... |
2 | while(1) |
3 | {
|
4 | if(Bitabfrage()) |
5 | {
|
6 | do(); |
7 | }
|
8 | }
|
9 | sei(); |
Sauger schrieb: > du liest UDR in einer Schleife aus. Warum sollte noch ein Interrupt > ausgelöst werden wenn das Register gelesen ist? ich denke aber das das Interupts flag gesetzt bleibt, auch wenn die daten schon gelesen sind. Problematisch wird es dann wenn im Interupt noch einmal gefragt wird ob zeichen zum lesen vorhanden sind, dann blockert in der ISR.
Klaus Dietz schrieb: > wird das I-Flag nicht über den Befehl sei() gesetzt? Ja. Ab dann sind Interrupts erlaubt. Und das bleiben sie, solange kein cli() kommt und solange nichts sonst am Statusregister manipuliert (beim Interrupt wird das Flag übrigens gelöscht, aber beim Beenden des Interrupts wieder auf den alten Wert gesetzt). Wenn diese Bedingungen erfüllt sind und wenn Dein Programm also auf ein Flag vom Interrupt ewig wartet, aber keines kommt, würde ich davon ausgehen, dass es vom Interrupt nicht gesetzt wird (und nicht, dass kein Interrupt ausgeführt wird).
ich hab den Prägnanten teil des Programms mal zusammengefasst. so sieht das dann ungefähr aus.
Klaus Dietz schrieb: > ich hab den Prägnanten teil des Programms mal zusammengefasst. > > so sieht das dann ungefähr aus. Du hast deine Lektion von gestern immer noch nicht gelernt. Poste ein komplettes, getestetes Program. Das Programm muss sich hier bei uns kompilieren lassen und wenn du uns sagst, das und das muss auf den Eingängen gemacht werden, damit man das Problem sieht (vorher bei dir ausprobieren ob das zurechtgestutzte Programm bei dir auch wirklich dieses Verhalten zeigt), dann kann man auf dieser Seite des Montiors auf Fehlersuche gehen.
Klaus Dietz schrieb: > Lektion von gestern? > ich glaub du verwechselst mich mit jemandem... Mag sein. In dem Fall entschuldige ich mich. Mir ist nur der Anfang von main sehr bekannt vorgekommen, und da ging es auch um einen INT0 Die Variable 'Interrupt' (übrigens ein selten dämlicher Name für eine Variable), ... ist die volatile? (Und im Grunde gilt es trotzdem: mach ein komplettes Beispiel fertig)
Klaus Dietz schrieb: > ich hab den Prägnanten teil des Programms mal zusammengefasst. leider ist das testprogramm nichts wert!!!
1 | ISR(INT1_vect) // Wenn Interrupt eintritt dann Starte Prüfung |
2 | {
|
3 | Interrupt = 1; // |
4 | Start = 1; |
5 | }
|
wir wissen nicht wie "Interrupt" definiert ist. (Stichwort: volatil)
1 | int main (void) |
2 | {
|
3 | sei(); // Interrupts einschalten |
4 | interrupt(); // Interrupt Unterprogramm aufrufen |
5 | init(); |
6 | initusart(); |
7 | |
8 | if (bit_is_set (PINA,PINA0)) |
9 | {Serielle Daten();} |
wo ist die entlosschleife? das if (bit_is_set (PINA,PINA0)) wird also nur beim programmstart einmal ausgewertet.
1 | #ifdef UCSRA
|
woher sollen wir wissen ob das true oder false ist?
ich werde ein fertiges Programm schreiben. Drüfte aber ein wenig dauern
Sag vorher noch ganz schnell ob 'Interrupt' volatile ist oder nicht. Wenn nicht, dann hast du dein Problem identifiziert.
was meinst du mit volatile? das unterprogramm heisst void interrupt (void) . . .Bit einstellungen für interrupt. . und die variable interrupt ist mit uint8_t definiert.
Klaus Dietz schrieb: > und die variable interrupt ist mit uint8_t definiert. und hast du dir mal angeschaut, was für ein Assembler-Code aus deinem C-Code ensteht?
Klaus Dietz schrieb: > was meinst du mit volatile? und die variable interrupt ist mit uint8_t definiert. dann lies mal hier http://www.mikrocontroller.net/articles/Interrupt#Steuersignale_zwischen_ISR_und_Hauptprogramm
Peter schrieb: > Klaus Dietz schrieb: >> was meinst du mit volatile? >> >> und die variable interrupt ist mit uint8_t definiert. > > dann lies mal hier > http://www.mikrocontroller.net/articles/Interrupt#Steuersignale_zwischen_ISR_und_Hauptprogramm Oder hier http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Datenaustausch_mit_Interrupt-Routinen
Justus Skorps schrieb: > Klaus Dietz schrieb: >> und die variable interrupt ist mit uint8_t definiert. > > und hast du dir mal angeschaut, was für ein Assembler-Code aus deinem > C-Code ensteht? Im Prinzip keine schlechte Idee, aber wenn die Variable nicht volatile ist, brauchen wir erst mal gar nicht weiter suchen :-) (Zumal ja auch gar nicht gesagt ist, dass er mit dem Assembler-Output was anfangen kann)
so jetzt gehts... die variable auf volatile umbenannt und schon funktionierts. Danke :)
Karl heinz Buchegger schrieb: > Im Prinzip keine schlechte Idee, aber wenn die Variable nicht volatile > ist, brauchen wir erst mal gar nicht weiter suchen :-) jo, das hätte man vorher mal machen sollen > (Zumal ja auch gar nicht gesagt ist, dass er mit dem Assembler-Output > was anfangen kann) na ja, aber wenn da ein kompletter Abschnitt fehlt, dann sollte das einem schon irgendwie auffallen denke ich mir
Klaus Dietz schrieb: > variable auf volatile umbenannt sicher, sie jetzt heist sie also nicht mehr interrupt sondern volatile und der compieler versteht das?
Nein. Sie heißt "I_Flag" Und sie ist vom Datentyp "volatile uint8_t" (und I_Flag ist immer noch ein selten dämlicher Name. Er sagt so rein gar nichts darüber aus, welche Aufgabe diese Variable hat, was es anzeigt, wenn sie 0 oder 1 ist. Benenne Variablen weder nach ihrem Datentyp noch wer sie setzt. Benenne sie nach ihrer Funktion. Die Variable zeigt an, dass eine Taste gedrückt wurde (das rate ich jetz, weil ich nicht weiß woher der INterrupt bedient wird). Also könnte sie einen Namen bekommen, der das ausdrückt. Wenn dieser Interrupt ausschliesslich dafür zuständig ist, dass dein Benutzer sich beim System bemerkbar macht um mmitzuteile "Was immer du momentan tust, hör auf damit", dann könnte man auch das als Name nehmen, irgendwas mit den Worten Cancel und Operation. Mglw. auch noch ein Request da mit drinnen dann liest sich die Schleife plötzlich while( irgendwas && ! OperationCanceled ) oder while( irgendwas && ! CancelRequested ) oder while( irgendwas && ! KeyPressed ) und das ist dann schon fast Klartext. Lass dich bei deiner Namenswahl von der Verwendung der Variablen leiten! Sieh dir an, wie und wo sie abgefragt wird und dann denk über einen Namen nach, der in diesem Abfragezusammenhang maximalen Sinn ergibt.
ich hab sie I_Flag genannt wegen Interrupt. leitet sich so her wenn ein Interrupt eintrifft wird das I_Flag (Interrupt Flag) gesetzt. In der Originalsoftware heisst sie Start.
Lies mal was zum Thema Interrupt. Das erspart die 1001 philosopische Diskussion über das ewig gleiche Thema. MfG Falk
Klaus Dietz schrieb: > ich hab sie I_Flag genannt wegen Interrupt. es gibt aber sehr viele Interupts bei dem Atmel, nennst du sie dann I_Flag1, I_Flag2 ...
warum den nicht? Aber wenns mehr werden dann bevorzuge ich schon das was Karl Heinz gesagt hat. Spricht ja auch irgendwie dafür das man einen Code selbsterklärend schreibt.
Klaus Dietz schrieb: > warum den nicht? Aber wenns mehr werden dann bevorzuge ich schon das was > Karl Heinz gesagt hat. Spricht ja auch irgendwie dafür das man einen > Code selbsterklärend schreibt. Nicht: 'spricht ja irgendwie dafür' Es spricht alles dafür! Unter anderem auch die Erfahrung, dass diejenigen mit den fehleranfälligsten und unwartbarsten Programmen auch meistens die sind, die sich einen feuchten Kehrricht um formale Dinge, wie Codeformatierung oder Funktions- und Variablennamen, Konsistenz etc. kümmern. Seltsamerweise haben die Programmierer, die auf solche Dinge achten, meistens auf lange Sicht deutlich weniger Probleme :-)
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.