Hallo Zusammen, nach 3 Nächten des rum Probierens, versuche ich euch in Anspruch zu nehmen. Bei einem Projekt versuche ich eine RS485 Verbindung zu integrieren. Das Problem ist, dass ein Board 16 Bytes sendet und eine 16 byte antwort bekommt. das funktioniert wenn ich das erste Paket sende. Bei dem zweiten kommt keine Rückantwort. Gesendet wird das zweite Paket ordnungsgemäß (logikanalyser am Empfängerboard) Zig Varianten mit delay habe ich aus probiert: - delay vor/hinter senden/empfangen Sendempdus aktivieren/deaktivieren komme nicht weiter und bin am ende ;) Hardware: 2 Board mit Atmega --> usart --> MAx485... (später mehrere Boards). Test Distanz: Beide auf einem Tisch. Masse nicht mit geführt. Software: Baud 9600 Board A: - sende 16 byte - Empfange 16 byte antwort - warte 10 ms (wurde als versuch eingefügt, ging vorher genau so wenig) - sende 16 byte an Board B - Empfange 16 byte antwort Board B: - Empfange 16 byte - warte 10 ms (wurde als versuch eingefügt, ging vorher genau so wenig) - sende 16 byte antwort - Empfange 16 byte - warte 10 ms (wurde als versuch eingefügt, ging vorher genau so wenig) - sende 16 byte antwort Im Anhang ist eine die Ausgabe vom Logiganalyser. Unten sind die Ausgaben (send16Byte) von Board A und B. Oben sieht man wann welches Board in welchem Modus ist. Dafür ist unmittelbar vor und nach jedem Send16Byte und dem Rec16Byte ein Puls auf Portpin programmiert. Hier die Funktionen: (Bitte denkt dran, ich hab viel mit delay ausprobiert. Erstens würde ich selbst lieber ohne delay auskommen und zweitens habe ich viele Werte versucht, dass ich keine Ahnung mehr habe, welche besser wären. Daher nehme ich da sehr gerne Empfehlungen entgegen. Blödes rum gemotze weil delays im Code stehen, kann man sich sparen. Dann lieber Hinweise wie es besser geht :-) ) //___ ein byte empfangen unsigned int rs485_getc(void) { //___warten auf Receive Complete while(bit_is_clear(UCSR0A,RXC0)); return UDR0; } //16 Byte-String empfangen auf USART - Ohne Autolinefeed void rs485_rec_16Byte(char *s) { uint8_t i = 0; while(i<16) { s[i] = rs485_getc(); i++; } _delay_ms(1); } //___Ein Byte senden für RS485 void rs485_putc(unsigned char byte) { //___warten auf Datenregister "frei" while(bit_is_clear(UCSR0A,UDRE0)); //tue das nur wenn zuvor noch empfangsmodus ist (low) if( !(PINH & (1<<PORTH7)) ) { //RS485 auf Sendemodus //muss in den anderen Funktionen wieder beendet werden! PORTH |= (1<<PORTH7); //_delay_ms(1); } UDR0=byte; } //16 Byte-String senden auf USART - Ohne Autolinefeed void rs485_send_16Byte(char *s) { uint8_t i = 0; _delay_ms(10); while(i<16) { rs485_putc(*s); s++; i++; } while( bit_is_clear(UCSR0A, TXC0) ); _delay_ms(5); PORTH &= ~(1<<PH7); //sendemodus beenden - Empfänger aktiv _delay_ms(3); } Im Screenshot kann mann sehen, dass das erste Paket und die Antwort ankommen und danach auch erst der jweilige Empfänger aus der rec_16Byte funktion kommt (1. & 2.gestrichelte linie). Das zweite Paket hingegen wird nicht richtig empfangen. Board B verlässt die rec_16Byte funktion, obwohl nicht alle Byte auf dem Bus waren... Wie kann das sein? Eigentlich dürfte Board B zuvor nichts empfangen bis Board A sendet. Empfänger Controller scheint dann aber noch nicht "abgestürzt" zu sein. HILFEEEE! :-)
:
Bearbeitet durch User
Ist PH7 bei Dir das gleiche wie PORTH7? Wenn dem so ist, kann ich im Moment auf den ersten Blick nichts erkennen, warum das nicht öfter als 1x funktionieren sollte.
Hi > //___warten auf Datenregister "frei" > while(bit_is_clear(UCSR0A,UDRE0)); Du solltest auf TXC0 prüfen. UDRE0 gibt nur an, das der Puffer leer ist, aber nicht, das das Byte schon fertig gesendet wurde. MfG Spess
Bernhard Schröcker schrieb: > Ist PH7 bei Dir das gleiche wie PORTH7? Sollte so sein. AtmelStudion schimpft nicht... spess53 schrieb: > Du solltest auf TXC0 prüfen. UDRE0 gibt nur an, das der Puffer leer ist, > aber nicht, das das Byte schon fertig gesendet wurde. Sowas hatte ich mal aufgenschappt und in die send16Byte eingebaut. Also ist die 1Byte ebene put_c der richtige ort dafür?? Kann ich nicht sofort testen :-/ erst gleich... man kann leider von iphone nicht auf "absenden" drücken! danke schon mal und grüße!
Hi
>Also ist die 1Byte ebene put_c der richtige ort dafür??
Der richtige Ort ist die Stelle, an der deine Übertragung beendet ist.
MfG Spess
spess53 schrieb: > Hi > >> //___warten auf Datenregister "frei" >> while(bit_is_clear(UCSR0A,UDRE0)); > > Du solltest auf TXC0 prüfen. UDRE0 gibt nur an, das der Puffer leer ist, > aber nicht, das das Byte schon fertig gesendet wurde. Aus einem ATmega-Datenblatt:
1 | C Code Example |
2 | void USART_Transmit( unsigned char data ) |
3 | {
|
4 | /* Wait for empty transmit buffer*/
|
5 | while( !( UCSRnA & (1<<UDREn)) ) |
6 | ;
|
7 | /* Put data into buffer, sends the data*/
|
8 | UDRn = data; |
9 | }
|
Bernhard Schröcker schrieb: > Ist PH7 bei Dir das gleiche wie PORTH7? PH7 ist nichts anderes als ein
1 | # define PH7 7
|
Hi >Aus einem ATmega-Datenblatt: >C Code Example >void USART_Transmit( unsigned char data ) >{ > /* Wait for empty transmit buffer*/ > while( !( UCSRnA & (1<<UDREn)) ) > ; > /* Put data into buffer, sends the data*/ > UDRn = data; >} Und was heißt das? UDRE zeigt an das der USART-Puffer ein neues Byte aufnehmen kann. Das ist aber schon so, wenn das letzte Byte von UDR in das Schieberegister transferiert wurde und gerade gesendet wird. Mfg Spess
spess53 schrieb: > Der richtige Ort ist die Stelle, an der deine Übertragung beendet ist. das beantwortet meine frage nicht. für mich ist die übertragung nach 16 Byte zu ende... aber das Register reagiert ja nicht nach meinen wünschen. Aber ich habe die funktionen nun geändert und die Tx0 abfrage in die put_c gepackt. leider keine besserung. das zweite paket wird vom Board b noch immer zu früh als empfangen erkannt... //___Ein Byte senden für RS485 void rs485_putc(unsigned char byte) { //___warten auf Datenregister "frei" while(bit_is_clear(UCSR0A,UDRE0)); //tue das nur wenn zuvor noch empfangsmodus ist (low) if( !(PINH & (1<<PORTH7)) ) { //RS485 auf Sendemodus //dieser muss in den anderen Funktionen wieder beendet werden! PORTH |= (1<<PORTH7); //_delay_ms(1); } UDR0=byte; while( bit_is_clear(UCSR0A, TXC0) ); } //16 Byte-String senden auf USART - Ohne Autolinefeed void rs485_send_16Byte(char *s) { uint8_t i = 0; _delay_ms(10); while(i<16) { rs485_putc(*s); s++; i++; } //while( bit_is_clear(UCSR0A, TXC0) ); _delay_ms(5); PORTH &= ~(1<<PH7); //sendemodus beenden - Empfänger aktiv _delay_ms(3); } habt ihr noch weitere ideen? gruß
spess53 schrieb: > Der richtige Ort ist die Stelle, an der deine Übertragung beendet ist. das beantwortet meine frage nicht. für mich ist die übertragung nach 16 Byte zu ende... aber das Register reagiert ja nicht nach meinen wünschen. Aber ich habe die funktionen nun geändert und die Tx0 abfrage in die put_c gepackt. leider keine besserung. das zweite paket wird vom Board b noch immer zu früh als empfangen erkannt... //___Ein Byte senden für RS485 void rs485_putc(unsigned char byte) { //___warten auf Datenregister "frei" while(bit_is_clear(UCSR0A,UDRE0)); //tue das nur wenn zuvor noch empfangsmodus ist (low) if( !(PINH & (1<<PORTH7)) ) { //RS485 auf Sendemodus //dieser muss in den anderen Funktionen wieder beendet werden! PORTH |= (1<<PORTH7); //_delay_ms(1); } UDR0=byte; while( bit_is_clear(UCSR0A, TXC0) ); } //16 Byte-String senden auf USART - Ohne Autolinefeed void rs485_send_16Byte(char *s) { uint8_t i = 0; _delay_ms(10); while(i<16) { rs485_putc(*s); s++; i++; } //while( bit_is_clear(UCSR0A, TXC0) ); _delay_ms(5); PORTH &= ~(1<<PH7); //sendemodus beenden - Empfänger aktiv _delay_ms(3); } habt ihr noch weitere ideen? gruß
Christian Peskov schrieb: > das zweite paket wird vom Board b noch immer zu > früh als empfangen erkannt... Was genau meinst Du damit?
>für mich ist die übertragung nach 16 Byte zu ende... Die Übertragung ist zu Ende, wenn das letzte Byte den UART verlassen hat, nicht, wenn der UART für das 17. Byte bereit wäre (siehe auch oben) > aber das Register reagiert ja nicht nach meinen wünschen. Wie soll es auch, die Art, wie das Register reagiert ist im Dateblatt festgelegt, Deine Wünsche spielen da keine große Rolle.
* In welchen Pegel springt denn dein Bus, wenn du nichts sendest? Wird das von der Gegenstelle evtl. als Startbit interpretiert? * Oszillografier doch mal Daten und die SE/RE Signale der Transceiver. Dann weisst du, ob evtl. die Senderoutine zu früh auf RE umschaltet, oder ob da noch was auf SE steht, wenn doch eigentlich empfangen werden soll. Übrigens, im Datenblatt zum Mega8 steht der folgende Hinweis: The TXC Flag can be used to check that the Transmitter has completed all transfers, and the RXC Flag can be used to check that there are no unread data in the receive buffer. *Note that the TXC Flag must be cleared before each transmission (before UDR is written) if it is used for this purpose*.
:
Bearbeitet durch User
Rufus Τ. Firefly schrieb: > Was genau meinst Du damit? siehe screenshot oben - 3. gestrichelte linie. spontan schrieb: > Die Übertragung ist zu Ende, wenn das letzte Byte den UART verlassen > hat, nicht, wenn der UART für das 17. Byte bereit wäre (siehe auch oben) ok also nicht nach jedem byte sondern nach dem letzten. dem 16. Byte. Steht das nciht so 3 kommentare weiter oben?? Christian Peskov schrieb: > //16 Byte-String senden auf USART - Ohne Autolinefeed > void rs485_send_16Byte(char *s) > { > uint8_t i = 0; > _delay_ms(10); > while(i<16) > { > rs485_putc(*s); > s++; > i++; > } > //while( bit_is_clear(UCSR0A, TXC0) ); > _delay_ms(5); > PORTH &= ~(1<<PH7); //sendemodus beenden - Empfänger aktiv > _delay_ms(3); > } Matthias Sch. schrieb: > * Oszillografier doch mal Daten und die SE/RE Signale der Transceiver. > Dann weisst du, ob evtl. die Senderoutine zu früh auf RE umschaltet, > oder ob da noch was auf SE steht, wenn doch eigentlich empfangen werden > soll. Da komm ich so schlecht dranne, aber gute idee, werde ich heute tun! Matthias Sch. schrieb: > * In welchen Pegel springt denn dein Bus, wenn du nichts sendest? Wird > das von der Gegenstelle evtl. als Startbit interpretiert? das muss ich überprüfeni ch glaube die waren in der tag auf high pegel. schau ich nach! Matthias Sch. schrieb: > The TXC Flag can be used to check that the Transmitter has completed all > transfers, and the RXC Flag can be used to check that there are no > unread data in the receive buffer. *Note that the TXC Flag must be > cleared before each transmission (before UDR is written) if it is used > for this purpose*. das hatte ich gstern nicht richtig interpretieren können (vllt zu spät) jetzt liest es sich recht deutlich :-) Also vor dem senden "cleare" ich TX0 und warte danach auf TX =1. dann stellt sich folgende Frage wieder: Vor und nach jedem Byte? Oder vor und nach jedem 16 Byte paket? jede nachricht soll ja 16 Byte lang sein. ich danke euch!
was zum Screenshot vllt wichtig ist und bisher unwerähnt... das was unter A und B als gesendete Bytes in den unteren beiden Reihen zu sehen ist wurde jeweils auf dem Board B zwischen dem MAX485 und dem Atmega abgegriffen. ist also schon vom MAX485 auf atmega usart umgesetzt. Also kommt auch das zweite Paket sauber durch den MAX485 an Board B, an Rx an?! Durch die Peaks sieht man ja, dass Board B in die empfangs routine geht und sie zu früh verlässt. Das erste Paket kommt an und die erste Antwort geht fehlerfrei raus. Board B geht das zweite Mal in die Empfangsroutine und empfängt nicht vorhandene Daten und stoppt deshalb bevor alle 16 Byte des zweiten Pakets überhaupt aus Board A raus sind. Also werden doch zuvor schon Daten von der Empfangroutine get_c erkannt??! Gibt es typische Ursachen dafür? Wenn ich später usart, RS485 und SE/RE aufnehme werde ich mal noch peacks in //___warten auf Receive Complete while(bit_is_clear(UCSR0A,RXC0)); einfügen, um zu sehen wann er die while verlässt. Im Screenshot sieht man noch, dass die pegel von Rx und Tx (am atmega) zwischen allesn paketen auf HIGH ist. ist das in Ordnung?
Christian Peskov schrieb: > Im Screenshot sieht man noch, dass die pegel von Rx und Tx (am atmega) > zwischen allesn paketen auf HIGH ist. ist das in Ordnung? Jo, high auf den seriellen Leitungen bedeutet inaktiv. Christian Peskov schrieb: > Also vor dem senden "cleare" ich TX0 und warte danach auf TX =1. > dann stellt sich folgende Frage wieder: > Vor und nach jedem Byte? Du setzt TXC vor dem Senden des Byte zurück (1 reinschreiben). Dann UDR beschreiben. TXC wird gesetzt, wenn das Byte komplett gesendet wurde. Also vor jeden Byte zurücksetzen, bei dem du wissen willst, wann es fertig gesendet ist.
:
Bearbeitet durch User
Also... ich habe nun mit allen möglichen Pin den logic anlayser nochmal drüber gelassen. Alles sah gut aus und funktionierte totzdem nicht. Dann habe ich mal das übrige Projekt aus geklammert und mehrer hin und her sendungen funktionierten gut. mit verschieden pausenlängen. Werde also mal den code aufräumen müssen. Irgendwas im übrigen code fuscht da wohl rein. ist mir bisher unerklärlich... ich werde was melde wenn ich es herausfinde oder weitere probleme kommen. Danke schon mal an alle!
dummheit gehört bestraft :-/ oder verlorener überblick. problem war, dass Board B vor der Antwort Bytes vom Payload änderte. Board A schickte das übernommene Payload dann im zweiten Package zu Board B, wo es die Prüfung nicht bestand und deshalb keine zweites Mal gesendet wurde! Ziemlich dämlich so weit unten zu suchen wo der Fehler doch erst durch Änderungen in obere Ebene auftrat. Leider hat mich der Logic Analyser gleich auf die Bit-Ebene gedrängt. Auch dadurch habe ich nicht bemerkte, dass mein Code nicht in jedem Fall eine Antwort zu lässt bzw ich das Payload ändern lasse und dadurch die Bedingungen nicht mehr passen. jedenfalls trotzdem danke an alle. Meine RS485 Routinen sind durch eure Vorschläge jedenfalls nicht schlechter geworden! bzw sind optimierter. grüße! ps: kann ich das hier irgendwie als gelöst makieren?
Christian Peskov schrieb: > Leider hat mich der Logic Analyser gleich auf die Bit-Ebene gedrängt. Es war ja nicht vorherzusehen und deswegen gut, das du nachgeschaut hast. Es hat dich ja per Ausschlussverfahren zur Lösung gelenkt. Christian Peskov schrieb: > wo es die Prüfung nicht bestand und deshalb keine zweites Mal gesendet > wurde! Diesen Fehler musst du natürlich abfangen, denn im wahren Leben kann das auch passieren. Ein Signal a la 'Was war das denn, da war was faul' könnte dem Sender helfen, das Päckchen nochmal zu verschicken oder anderweitig sauber auszusteigen.
:
Bearbeitet durch User
Danke Matthias. leider ist da immer noch der wurm drin... hatte hier schon nen riesen roman geschrrieben aber versuche es nun mit bilder kürzer. ich empfange die zweite Antwort noch immer nicht richtig. Die zweite Rückantwort ist um 3 Bytes nach hinten verschoben. Das eigentliche Byte0 ist auf Stelle von Byte3. Die ersten 3 Bytes sind falsch und die Werte mir unbekannt :-( Wie soooo? Das nervt.... Ich stelle fest: Wenn der Empfänger das erste Mal Antwortet und auf Empfang umschaltet, werden umnittelbar 3 Bytes empfangen. Wie kann ich das verursacht haben?? die nächste nachricht ist da noch "längst" nicht in sicht!! Bild 1 zeigt die Übersicht Bild 2 zoomt auf die pseudo Bytes nach dem ersten Antwort des Empfängers Bild 3 zeigt die folgenden "kaputt" empfangenen 16 Bytes. zeigt das jemanden die Ursache auf?? Hiiilfe! zur Anschauung noch mal die verwendeten Funktionen: //___Ein Byte senden für folge funtkionen void rs485_putc(uint8_t byte) { while(bit_is_clear(UCSR0A,UDRE0)); //___warten auf Datenregister "frei" UDR0=byte; // PORTB |= (1<<PORTB3); // PORTB &= ~(1<<PORTB3); while( bit_is_clear(UCSR0A, TXC0) ); //___warten bis Sendung abgeschlossen } //16 Byte-String senden auf USART - Ohne Autolinefeed void rs485_send_16Byte(uint8_t *s) { uint8_t i = 0; _delay_ms(15); PORTC |= (1<<PORTC4); //RS485 auf Sendemodus _delay_ms(5); while(i<16) { rs485_putc(*s); s++; i++; } _delay_ms(5); PORTC &= ~(1<<PORTC4); //sendemodus beenden - Empfänger aktiv _delay_ms(5); } //___ ein byte empfangen unsigned int usart_getc(void) { //___warten auf Receive Complete while(bit_is_clear(UCSR0A,RXC0) ); PORTB |= (1<<PORTB3); PORTB &= ~(1<<PORTB3); return UDR0; } //16 Byte-String empfangen auf USART - Ohne Autolinefeed void rs485_rec_16Byte(uint8_t *s) { uint8_t i = 0; PORTB |= (1<<PORTB3); PORTB &= ~(1<<PORTB3); _delay_ms(5); while(i<16) { s[i] = usart_getc(); i++; } }
:
Bearbeitet durch User
HI > //___warten auf Receive Complete > while(bit_is_clear(UCSR0A,RXC0) ); So etwas wäre für mich ein absolutes No-Go. Wenns mit dem Empfang hapert, bleibt das Programm hängen. MfG Spess
spess53 schrieb: > HI > >> //___warten auf Receive Complete >> while(bit_is_clear(UCSR0A,RXC0) ); > > So etwas wäre für mich ein absolutes No-Go. Wenns mit dem Empfang > hapert, bleibt das Programm hängen. > > MfG Spess Bleibt so auch nicht... timeout ist nur aktuell aus geklammert bei der fehler suche ausgeklammert... spess du scheinst doch ahnng zu haben... Hast du eine Meinung zu dem Hinweis aus dem anderen Thread? Das gehört sich mit Pull-Ups oder? mfg
Hi >Das gehört sich mit Pull-Ups oder? Das ist die übliche Failsave Beschaltung. Näheres findest du hier (S.8): http://www.ti.com/lit/pdf/snla049 MfG Spess
In > void rs485_putc(uint8_t byte) > { > while(bit_is_clear(UCSR0A,UDRE0)); > UDR0=byte; > while( bit_is_clear(UCSR0A, TXC0) ); > } wurde das > The TXC Flag can be used to check that the Transmitter has completed all > transfers, and the RXC Flag can be used to check that there are no > unread data in the receive buffer. *Note that the TXC Flag must be > cleared before each transmission (before UDR is written) if it is used > for this purpose*. noch nicht beachtet!
auch mit den definierten Pegeln an den Busleitungen, werden die 3 Pseudobyte zu früh empfangen. ich weiß es nicht was ich noch machen soll. Muss immer ein MAX485 auf "Sender" eingestellt sein? muss ich den usart Empfänger zwischen durch mal abschalten oder "flushen"? danke. ich bin echt am ende ^^
Christian Peskov schrieb: > auch mit den definierten Pegeln an den Busleitungen, werden die 3 > Pseudobyte zu früh empfangen. > > > > ich weiß es nicht was ich noch machen soll. > Muss immer ein MAX485 auf "Sender" eingestellt sein? > > muss ich den usart Empfänger zwischen durch mal abschalten oder > "flushen"? > > danke. ich bin echt am ende ^^ danke bau ich sofort ein....
/___Ein Byte senden für RS485 uint8_t rs485_putc(unsigned char byte) { //___warten auf Datenregister "frei" while(bit_is_clear(UCSR0A,UDRE0)); //Timeout fehlt! UCSR0A &= ~(1<<TXC0); UDR0=byte; PORTK |= (1<<PK0); PORTK &= ~(1<<PK0); //___warten bis Sendung abgeschlossen while( bit_is_clear(UCSR0A, TXC0) ); } bringt leider keine Besserung... habe den bus aktuell so beschaltet: 5V -(620Ohm)- A -(120Ohm)- B -(620Ohm)- GND
:
Bearbeitet durch User
Christian Peskov schrieb: > UCSR0A &= ~(1<<TXC0); Nee, du musst beim AVR, um ein Bit zu löschen, eine 1 reinschreiben. Wäre zumindest das erste mal für mich, das es bei einem AVR umgekehrt wäre. Du hast ja bis jetzt tunlichst vermieden, uns den genauen Typ deines Mega zu nennen. Mach das bitte mal. Also, welcher Mega hat PORT K ? Christian Peskov schrieb: > peterfrosta Du unterschlägst übrigens den Adelstitel. M.W. heisst das 'Peter von Frosta' :-)
:
Bearbeitet durch User
Hi
>Also, welcher Mega hat PORT K ?
Z.B. ATmega640/1280/2560
MfG Spess
Matthias Sch. schrieb: > Christian Peskov schrieb: >> UCSR0A &= ~(1<<TXC0); > > Nee, du musst beim AVR, um ein Bit zu löschen, eine 1 reinschreiben. > Wäre zumindest das erste mal für mich, das es bei einem AVR umgekehrt > wäre. Ist das so? ist mir ja bisher nie aufgefallen.... ist das speziel für flag register so? habs aber gefunden: "The TXCn Flag bit is automatically cleared when a transmit complete interrupt is executed, or it can be cleared by writing a one to its bit location." Werde ich später unbedingt versuchen! > Du hast ja bis jetzt tunlichst vermieden, uns den genauen Typ deines > Mega zu nennen. Mach das bitte mal. Also, welcher Mega hat PORT K ? Das ist aber ohne Grund so heimlich ;) Board A (Sender) ist ein Atmega2560. Board B Empfänger (der mit den Pyseudo-Bytes) ist ein Atmega88. Hatte das nicht unterschieden, um es euch nicht noch komplizierter zu machen. Die 4 Funktionen sind auf beiden Boards identisch bis auf die Portnamen natürlich. Die > Du unterschlägst übrigens den Adelstitel. M.W. heisst das 'Peter von > Frosta' :-) tut mir leid matthias :-) ich weiß leider nicht wer der/die M.W is...
Matthias Sch. schrieb: > Übrigens, im Datenblatt zum Mega8 steht der folgende Hinweis: > > The TXC Flag can be used to check that the Transmitter has completed all > transfers, and the RXC Flag can be used to check that there are no > unread data in the receive buffer. *Note that the TXC Flag must be > cleared before each transmission (before UDR is written) if it is used > for this purpose*. Auweia, das gibt ne dicke Race-Condition. Nach dem Löschen von TXC kann just das vorherige Byte fertig sein und TXC wird gesetzt. Dann schreibst Du ins UDR und testest das bereits gesetzte TXC, d.h. das letzte Byte wird abgewürgt. Du mußt erst in UDR schreiben und danach TXC löschen und falls Interrupts enabled sind, muß das atomar erfolgen.
Danke für die Hinweise! Wenn ich Sie unten richtig umgesetzt habe, war das leider nocht nicht dir Hauptursache :-( alles wie gehabt... //___Ein Byte senden für folge funtkionen void rs485_putc(uint8_t byte) { while(bit_is_clear(UCSR0A,UDRE0)); //warten auf Datenregister "frei" UDR0=byte; UCSR0A |= (1<<TXC0); //1schreiben um flag-tx fertig zuLÖSCHEN!! while( bit_is_clear(UCSR0A, TXC0) ); //___warten bis Sendung // abgeschlossen }
1 | #include <util/atomic.h> |
2 | |
3 | void rs485_putc(uint8_t byte) |
4 | {
|
5 | ATOMIC_BLOCK(ATOMIC_FORCEON){ |
6 | UDR0=byte; |
7 | UCSR0A = UCSR0A; //1schreiben um flag-tx fertig zuLÖSCHEN!! |
8 | }
|
9 | while( bit_is_clear(UCSR0A, TXC0) ); //___warten bis Sendung |
10 | // abgeschlossen
|
11 | }
|
Peter Dannegger schrieb: > #include <util/atomic.h> > > void rs485_putc(uint8_t byte) > { > ATOMIC_BLOCK(ATOMIC_FORCEON){ > UDR0=byte; > UCSR0A = UCSR0A; //1schreiben um flag-tx fertig zuLÖSCHEN!! > } > while( bit_is_clear(UCSR0A, TXC0) ); //___warten bis Sendung > // abgeschlossen > } Danke für den code! aber könntest du mir das vllt erläutern? ATOMIC_BLOCK(ATOMIC_FORCEON).... sorgt dafür, dass > UDR0=byte; > UCSR0A = UCSR0A; ausgeführt bitweise oder atomar ausgeührt wird. Im Zusammenhang mit den Interrupt de- und aktivierung von Atomic. sorgt es wohl dafür, dass kein interrupt zwischen in diese beiden Zeilen fuscht. aber was soll UCSR0A = UCSR0A; bewirken?? Desweiteren... der Empfänger hatte mit dem Senden nicht die Probleme (denke ich). Nach dem er vom senden wieder auf Empfang umstellt, kommen die Speudo bytes. Allerdings ist da auch der RS485 schon deaktiviert(SE). und Dass passiert ja erst nach einer delay von Millisekunden. Da dprfte doch keine vergessenen Byte mehr abhol breit sein... und warum auch noch bis zu 3? Hm.... ich mache jetzt neue nackte Projekte auf und mache dort die Schnittstelle von grund auf :-(
Hallo, schaltest du am MAX485 den Empfänger während des Sendens aus (RE=1)? Wenn ja, dann wird der Receiver-Ausgang hochohmig, d.h. du must am AVR den Pullup am RX-Pin einschalten, oder extern einen Pullup vorsehen - sonst kann sich da was einschleichen. Sascha
Sascha Weber schrieb: > schaltest du am MAX485 den Empfänger während des Sendens aus (RE=1)? ja, da ich RS und SE gebrückt habe... Dann kann ich keinen Pull up dran löten, sehe ich doch richtig?! 5V -(620Ohm)- A -(120Ohm)- B -(620Ohm)- GND kommt wird doch nur an einem teilnehmer realisiert oder? dank vielmals für eure mühen!!
Christian Peskov schrieb: > dass kein > interrupt zwischen in diese beiden Zeilen fuscht. So isses. Mag vielleicht hier noch nicht nötig sein, aber Programme werden größer und größer und dann denkt man nicht mehr daran. Christian Peskov schrieb: > aber was soll > UCSR0A = UCSR0A; > bewirken?? Das | ist nicht nötig, ist es gesetzt, wird es gelöscht. Alle anderen Bits bleiben erhalten bzw. sind read-only.
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.