Hallo zusammen Ich möchte einen 1-Wire Master mit dem UART eines AVR programmieren. Dazu müssen bekannterweise der RX- und der TX-Pin zusammengeschaltet werden, damit man sowohl Senden als auch Empfangen kann. Wenn man dann beispielsweise einen Reset sendet, schaut man hinterher im Empfangsregister, ob auf den Reset geantwortet wurde. Aber: Wie kann ich ermitteln, ob der UART überhaupt fürs Senden bereit ist? Ich darf ja erst mit dem Senden beginnen, wenn das vorige "alte" Byte aus dem Schieberegister vollständig gesendet wurde. Ich könnte zwar schon mein neues Byte in den Sendepuffer (UDR) schreiben, aber dann weiß ich ja nicht, ob ich beim Auswerten des Empfangsregisters (UDR) fälschlicherweise das vorige "alte" Byte auswerte, oder bereits das Neue! Ich vermute, ich muss das TXC Bit auslesen, oder? Wenn das TXC Bit gesetzt ist ('1'), sind sowohl Sendepuffer (UDR) als auch Schieberegister leer. Es liegt also keine Datenübertragung an. Wenn das Bit gesetzt ist ('1'), kann ich also mein Byte senden und gleich wieder als empfangenes Byte auswerten. Dummerweise wird das TXC Bit aber mit '0' initialisiert!!! D.h., wenn ich nach einem µC-Reset etwas Senden möchte, und darauf warte, dass das Senderegister frei wird und das TXC Bit gesetzt wird, hängt sich die Schleife auf :-(( Wie macht mans richtig? Ich kann das Bit leider auch nicht manuell, etwa bei der Initialisierung nach einem Reset, auf '1' setzen. Oder bin ich mit dem TXC Bit ganz auf dem Holzweg? Danke und Gruß, Steffen
Nimm einfach das UDRE (Usart Data Register empty) Flag! Das wird gesetzt wenn Daten gesendet werden können! Und wird auch nach einem RESET gesetzt. Grüße Clemens
Hallo Clemens Das UDRE ist aber leider auch dann gesetzt, wenn das Senderegister (UDR) zwar frei ist, aber das interne Schieberegister noch am Senden ist! Das Problem ist dann, dass ich nicht weiß, welche Daten ich im Anschluß im Empfangsregister auswerte! Sind es die Daten, die noch im internen Schieberegister waren, als ich ins Senderegister geschrieben habe? Oder war das Schieberegister leer und es sind die richtigen Daten? Hmm, schwierig zu erklären... Verstehst Du, wie ich das meine? Gruß, Jasper
Hallo Steffen, das ist im neuen Buch von Claus Kühnel sehr gut beschrieben. (BASCOM für AVR) Gruss Kurt
Kurt, verrätst Du mir auch, was Herr Kühnel dazu meint? Ich programmiere z.Z. mit Assembler und möchte mir nun kein BASCOM Buch kaufen. Außerdem brennt mir das Problem unter den Nägeln ;-) P.s.: Sorry, für den doppelten Eintrag oben!
TXC (Transmit Complete) ist schon das richtige. Seite 166 des DAtenblatts zum ATmega162 (hatte ich gerade zur Hand): "The Transmit Complete (TXC) Flag bit is set to one when the entire frame ... has been shifted out... The TXC Flag bit is automatically cleared when transmit complete interrupt is executed, or it can be be cleared by writing a one to to its bit location." Im nächsten Absatz steht dann noch was davon, dass sich bei einer TXC-Interrupt-Routine nicht um das Bit gekümmert werden muß. Das erledigt die ISR... Vielleicht hilft es. Bei mir läuft es seit über einem Jahr stabil in einem RS485-Netzwerk. Gruß Rahul
Das Problem ist doch, dass ich wissen muss, ob der Transmitter mit Senden beschäftigt ist. Das zeigt mir das TXC Bit auch an, wenn es gesetzt ist, dann ist die "Transmission" (TX) "completed" (C). Einzige Ausnahme: wenn seit dem letzten Reset noch überhaupt kein Byte gesendet wurde. Dann ist die Übertragung natürlich noch nicht beendet (="Transmission completed"), eben weil es gar keine Übertragung gab! Deshalb wird das TXC Bit nach einem Reset mit '0' initialisiert. Meine Empfangsroutine ist aber dumm, sie soll immer funktionieren, unabhängig davon ob schon einmal was gesendet worden ist, oder nicht. Soll ich ein Dummy-Byte senden? Aber da muss es doch noch eine elegante Lösung geben...! Gruß, Steffen
UDRE muß 1 sein, dann TXC testen. Hast du es auch freigeschaltet? Ich habe die Routinen gerade nicht da, aber bei mir klappt das wunderbar...
Nein, das funktioniert nicht. Nach einem Reset ist UDRE mit '1' initialisiert und TXC mit '0'. Obwohl ich mit dem Senden beginnen könnte (das Senderegister ist ja leer), tritt meine Bedingung (UDRE='1' & TXC='1') nie ein. Aber ich habe das Problem jetzt von hinten aufgerollt. Bisher wollte ich abfragen, ob der Bus fürs Senden frei ist. Jetzt gehe ich einfach davon aus, dass er frei ist. Ich muss nur dafür sorgen, dass meine "Senden" Routine auch erst dann verlassen wird, wenn ich mit dem Senden tatsächlich fertig bin! Dann ist der Bus logischerweise automatisch frei. Vielleicht ist das auch Deine damals angewendete Lösung, Rahul. Wenn Dir die Routinen nochmal in die Hände fallen, wäre ich sehr an Deiner Lösung interessiert! Ansonsten vielen Dank für Deine und Eure Hilfe :-) Steffen
Das geht so nicht, die UART-Funktion hat einen Gegentaktausgang, Du brauchst aber einen open-drain Ausgang ! Warum machst Du das nicht einfach in Software (siehe Codesammlung) ? Ansonsten hast Du recht. Du brauchst ein Zusatzbit um das allererste Senden-Ende zu erkennen, da Du Interruptbits nicht setzen kannst. Peter
Hallo Steffen! Meiner Meinung nach kannst du das UDRE bit trotzdem verwenden! Du merkst dir einfach was du geschickt hast und sobald es zurückkommt löscht du es! Wenn der Slave dasselbe schickt empfängst du es trotzdem 2x. Müsste doch gehn oder? Grüße
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.