Hallo, habe da ein Problem, zu dem ich weder ueber Google noch ueber Faq's zu einer brauchbaren Loesung gekommen bin: Eine globale Variable, welche ich als 'static volatile' deklariert habe, wird bei mir in einem kleinen Testprogramm beim Auftreten von Interrupts (SIG_INTERRUPT0 und SIG_UART_RECV) jedesmal um eins erhoeht. Bei SIG_INTERRUPT0 funktioniert das auch genauso wie erwartet - nur bei SIG_UART_RECV eben nicht. Hier wird die Variable jedesmal auf null zurueckgesetzt und dann erhoeht, wodurch sie bei eins haengen bleibt. Ich kann da irgendwie keinen Denkfehler meinerseits sehen. Eigentlich sollten doch alle Interruptaufrufe eine Variable gleich behandeln. Nachdem ich fuer die Interrupts 'Signal' verwende, koennen sie sich auch nicht gegenseitig beeinflussen. Ach ja, es handelt sich um einen Atmega8 (real device) und compiliert wird unter WinAvr. Bin fuer jeden Hinweis/Vorschlag dankbar! m.f.G. Thomas
Du hast das Problem beschrieben, aber den Code vergessen (als Dateianhang). Peter
Hallo Peter, da ich im Moment echt das gleiche Problem habe, hoffe Du mir vielleicht bereit bist zu helfen. Ich dachte bisher, das Problem würde an dem nicht richtig erkannten <CR> liegen. Aber der Code hat ne Macke! Was soll der Code machen? Ich möchte die empfangen Daten bis zum <CR> (0xD) in einen 32 Byte großen Puffer per Interrupt schreiben und danach diesen Auswerten. Dazu dient die Funktion: unsigned char* UART_recv (void); Die Funktionen: void UART_init(void) ; void UART_transmitt (unsigned char* Transmitt); funktionieren bereits einwandfrei. Um meine Vermutung zu validieren habe ich das Backlight des LCD's innerhalb der Interrupt Routine ausschalten lassen. Es wird eigentlich nach Beendigung von UART_recv wieder eingeschaltet. Der Code erzeugt aber folgendes Phänomen: wenn ich die SIGNAL Funktion benutze wird erst nach dem dritten Datentransfer das Display dunkel, aber aus irgendeinem Grund wird es permanent aus und wieder eingeschaltet. Das ist aber etwas, das mein Code nicht zulassen sollte, denn nach Ende der Übertragung sollte die Interrupt Routine nicht mehr durchlaufen werden, also das Display wieder an sein. Eigentlich sollte entweder UART_global.recv_pos den Wert 0 oder >0 aufweisen, warum die Variable permanent hin und her schwingt, ist mir schleierhaft. Hoffe Dir kann das ganze mehr sagen, als mir. Gruß Marcus
Also ich vermisse in dem Quellcode irgendwo vor einer Variable ein volatile.
Hallo, hier nun der Code. Ist nur ein kleines Testprogramm um das Problem, welches ich habe (und nicht verstehe) zu demonstrieren. m.f.G. Thomas
Hallo Marvel, Sorry, wenn mein Code im Moment sehr durcheinander ist - und unkommentiert arg. Ich bastelle da nun schon seit zwei Tagen dran und somit sind einige zugegeben unnötige überprüfungen und LCD_Light Befehle drin. Du brauchst die Variable IMHO nicht unbedingt als static volatile zu deklarieren, wenn Du sie wie ich an ein bestimmtest Register bindest. Ich habe dies damals bei der Entwicklung auf dem Tiny26 lernen müssen. @Thomas: Versuchs mal bitte mit folgender Deklaration: register unsigned char value asm ("r3); Dann wird die Variable definitiv an ein bestimmtes Register gebunden und niemand wird dieses Register wieder anpacken. So ähnliche Probleme habe ich mit dem Tiny auch gehabt. BTW: Ich bin mit meinem Problem auch ein ganzes Stück weiter. Wüßte von Euch jemand, warum diese Routine nach ihrer Beendigung jedesmal wieder einen SIG_UART_RECV Interrupt auslöst? Das Problem, was ich nur noch habe, ist das die Schnittstelle permanent SIG_UART_RECV Interrupts auslöst arg Im Pollbetrieb funktioniert alles einwandfrei! SIGNAL (SIG_UART_RECV) { LCD_Light_off; temp_recv = UDR; if (temp_recv == 0xc) status |= (1 << RECV); else rec_buff[temp++] = temp_recv; }
Hallo Markus, danke fuer deinen Hinweis. Leider hat dies mein Problem nicht behoben. m.f.G. Thomas
Hallo Marvel, ich habe leider irgendwie ein ähnliches Problem, wie Du. Leider schaffe ich es nicht mehr, das jetzt alles noch durchzutesten - Jörg hoffe Du hilfst uns -. Versuch mal folgendes: erzeuge einen Pointer: static volatile unsinged char value; void init_UART(void) { .... value_ptr = &value; .... SIGNAL (SIG_UART_RECV) { unsinged char* value_ptr = &value; (*value_ptr)++; } Hier passiert folgendes: dein Object value hat eine Adresse. Diese Adresse weißt Du nun dem Pointer value_ptr zu. Damit hast Du nun zwei möglichkeiten Dein Object zu manupilieren. Entweder du greift direkt drauf zu: value++; oder indirekt über Deinen Pointer: (*value)++; Was nun in der Signalroutine passiert ist folgendes: Du erzeugst einen lokalen Pointer, der defaultmäßig auf das Object value verweißt. Da ich bisher herausgefunden habe, das innerhalb der SIGNAL_ROUTINE, alle Variablen korrekt behandelt werden, aber leider Ihren Wert nicht behalten, da sie ja nicht vom Stack geholt sondern vorher gesichert werden, benutzt du nun diesen Pointer um das Problem zu umgehen. Du bearbeitest also direkt die Speicherzellen, ohne Dich irgendwie um den Aufenthaltsort zu scheren. Meiner Meinung nach müßte value in dem Moment auf dem Heap gesichert worden sein. Vielleicht hilft dies. Gruß Marcus
Hallo Markus, auch dieser Tipp fuehrt leider nicht dazu, dass ich einen Wert aus dem SIG_UART_RECV-Interrupt 'heraustransportieren' kann. Mit anderen Interrupts funktioniert es wieder (wie erwartet) problemlos :-(. Habe es mit einem globalen Pointer versucht, dessen 'Inhalt' in SIG_UART_RECV veraendert wird => kein Erfolg. Habe es auch mit einem lokalen Pointer in SIG_UART_RECV probiert, welcher direkt auf die Adresse von 'value' zeigt => kein Erfolg. Schoen langsam bin ich ratlos... Vielleicht liest ja jemand mit, der schon einmal erfolgreich aus dem SIG_UART_RECV-Interrupt einen Wert nach 'auszen' gebracht hat, und koennte mir diesbezueglich einen Tipp geben. m.f.G. Thomas
Hallo Thomas, mitlerweile habe ich es geschafft Daten über aus dem SIG_UART_RECV heraus zu transportieren. Leider sind die aber nie ganz vollständig und teilweise lückenhaft. Ich schicke Dir heute NAchmittag aber mal den Code. Gruß Marcus
@Thomas, versuch doch mal die Interrupts erstmal einzeln zu testen und nicht miteinander zu verwursteln. Schreib z.B. das "PORTC = value;" in die Mainloop und disable erstmal den externen Interrupt. Wenn was nicht funktioniert und man weiß nicht wo es klemmt, dann immer schön in gleichgroße Brocken unterteilen und diese separat testen. Denn bei der Programmierung gilt immer: Der Fehler liegt nie dort, wo er sich bemerkbar macht. Peter
So, hier ist mein Code, der zwar etwas einließt, aber meist irgendwie mit dem Zeichen durcheinander gerät. Vielleicht weiß jemand von Euch, was da so falsch läuft... . Gruß und auf Hilfe hoffend!! Marcus
Hallo Thomas, ich habe den Fehler gefunden, zugegeben erst nach viel Probieren, weil ich schon lange mit meinem Latein am Ende war. Der folgende Code füllt Dir den rec_buff: unsigned char rec_buff[16]; volatile unsigned char temp_recv; SIGNAL(SIG_UART_RECV) { while ((UCSRA & (1 << RXC)) && (temp_recv < 16)) { ---Fehler-----> *&rec_buff[temp_recv] = UDR; temp_recv ++; } if (temp_recv > 15) { temp_recv = 0; status |= (1 << RECV); } } Die Zeile *&rec_buff[temp_recv] = UDR; besagt eigendlich folgendes: Zuerst wird die Adresse von rec_buff[temp_recv] nachgeschlagen und anschließend wird dieses Register, auf das diese Adresse zeigt mit dem Inhalt von UDR gefüllt. Laut Standart-C ist die equvalent mit: rec_buff[temp_recv] = UDR; Warum ich nun aber diesen Umweg gehen muß, kann mir nur der gcc sagen. Vielleicht weiß uns Gott Jörg Wunsch dazu etwas zu sagen. Ich hab keine Ahnung, warum dieser Code funktionert und der andere nicht. Gruß Marcus
Davon abgesehen, daß ich von "*&foo[bar]" einen Knoten im Gehirn bekomme :-), nein, ich kann da genausowenig einen Unterschied zu "foo[bar]" feststellen wie mein Compiler.
Ich bekomme auch nen Knoten davon, daß Marcus diesen Thread gehijackt hat. Sowas macht man nicht. Wer blickt jetzt noch durch, was sich worauf bezieht. Peter
Hallo Peter, Sorry, da wir beide das gleiche Problem haben, wollte ich deswegen nicht nochmal einen Thread aufmachen. <OT> Die Sprüche a là schau Dir den Thread, der gerade läuft an, haben mich schon ziemlich genervt in der letzten längeren Vergangenheit. Werd aber demnächst immer einen zweiten Thread aufmachen. Dann nehmts mir bitte auch nciht übel, wenn ich dann auch pampisch reagiere </OT> Trozdem hoffe ich, das meine letzten schlaflosen Nächte Thomas irgendwie helfen konnten. Sorry nochmals, hatte eben gedacht diesmal etwas besser zu machen. Marcus
Hallo Tobias, falls Du noch Probleme mit der SIGNAL hast, versuch mal den beigefügten Code zu testen. Gruß Marcus
Hallo zusammen, danke an alle, die mir bis jetzt Tipps zur Loesung des Problems gegeben haben! @Marcus Ich habe deinen Loesungsansatz in mein Mini-Testprogramm eingebaut - erhalte aber noch immer kein brauchbares Ergebnis (es will mir einfach nicht gelingen :-( ). Aus, mir unerklaerlichen Gruenden, wird nach einem Aufruf von SIG_UART_RECV die Variable 'value' wieder auf ihren Initialisierungswert zurueckgesetzt. Schoen langsam habe ich die Vermutung, dass dieser Interrupt-Aufruf irgendwie einen Reset ausloest. Vielleicht koennte sich ja jemand die Muehe machen und das Programm auf seinem uC kurz testen und mir dann mitteilen ob es dort funktioniert oder nicht. Dies wuerde dann zumindest jeglichen Verdacht von meiner Hardware nehmen Danke! m.f.G. Thomas
"...da wir beide das gleiche Problem haben..." ??? Also ich sehe da Welten zwischen Deinem und Thomas Code. Ich glaub deshalb nicht, daß er mit Deinem Code überhaupt etwas anfangen kann. Aber auch bei ähnlichen Problemen sollte man einen Fragethread erst hijacken, wenn die Ursprungsfrage schon gelöst ist. Man schiebt sonst den Erstfrager nach hinten weg und seine Chancen auf eine Antwort sinken (wie man hier ja gut sieht). Ich würde es daher Thomas nicht übelnehmen, wenn er seine Frage nochmal in einem neuen Thread stellt. Peter
Thomas, Du aktivierst alle möglichen UART-Interrupts, hast aber nur einen Handler für einen (von dreien)!? Das kann nicht gut gehen. Sowie einer der beiden anderen ausgelöst wird, wird der default Vektor angesprochen, der einen [r]jmp 0 ausführt.
Hallo Thomas, nachdem ich einen Handler für SIGNAL(SIG_UART_TRANS) { } SIGNAL (SIG_UART_DATA) { } hinzugefügt und die Zeile: unsigned char value = 7; in unsigned char value; geändert habe, läuft bei mir immer alles nach Plan. Letztere Änderung glaube ich nicht, das irgendwas ausmacht. Getestet habe ich auf Mega32, Mega16 Nega8535. Einen Mega8 habe ich leider nicht hier. Sorry :-( Gruß Marcus PS: Sorry fürs hijacken und thx für die Infos
@Joerg und Marcus Habt vielen Dank - jetzt funktioniert es! Ich habe beim vielen Herumprobieren vergessen die nicht verwendeten Interrupts wieder zu deaktivieren. In weiterer Folge hab ich den Fehler dann krampfhaft an anderer Stelle gesucht, also sprichwoertlich den Wald vor lauter Baeumen nicht mehr gesehen ;-). Nochmals Danke! m.f.G. Thomas
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.