Ich habe ein Problem mit einem Atmega und einem ADM3070, welcher über Half Duplex als slave arbeitet.
RE und DE habe ich zuammen an einem IO pin und bevor ich Daten senden möchte muss ich den IO pin auf High setzen. Allerdings habe ich immer Kommunikationsprobleme wenn ich zwischen Senden und abschalten des Senders nicht mindestens eine Millisekunde warte. Der Bus ist jeweils auf ca 350mV gebiast und abgeschlossen. Wo kann ich bei der Suche ansetzen?
Mit dem Stopbit ist der Bus doch sowieso im Standy-Zustand.
Wenn man da umschaltet, sollte doch alls gut sein.
Mit Bias-Widerständen, die viele vergessen, ja. Aber das scheint hier ja nicht das Problem zu sein.
Da es ab 1ms Wartezeit funktioniert, sagt meine Glaskugel, dass der TO mit 9600bps arbeitet, die Zeit ab Befüllen des UDR misst und somit ziemlich genau die Zeit erwischt, die der UART braucht, um das Byte zu senden.
Ich arbeite mit 9600 Baud mit Einem Startbit und einem Stopbit. Es handelt sich um ein simples request response Protokoll.
An RXD des Controllers hängt kein Pullup. Bevor ich etwas sende und die RE/DE Leitung auf 1 setze schalte ich das RXE Bit im Kontrollregister des UART aus um in der Zeit nichts zu empfangen.
Es handelt sich bei dem Controller um einen Atmega328P. Zum empfangen benutze ich den Interrupt aber gesendet werden Nachrichten blockierend, da die Nachrichten immer gleiche Länge haben.
Senden geht dann so:
1
txEnable(true);
2
_delay_ms(1);
3
4
for(unsignedinti=0;i<size;++i){
5
UDR0=data[i];
6
while(!(UCSR0A&(1<<UDRE0)));
7
}
8
9
_delay_ms(1);
10
txEnable(false);
Das heißt das Byte müsste auch ohne das Delay am Schluss vollständig gesendet sein wenn der Transmitter wieder abgeschaltet wird.
Die Abschaltung/Einschaltung des Empfängers erfolgt in der txEnable Routine.
Das heißt das Byte müsste auch ohne das Delay am Schluss vollständig
gesendet sein wenn der Transmitter wieder abgeschaltet wird.
Teste am Ende deiner ("geklauten") Senderoutine das TXC-Bit deines UART.
Was das ist, und wo das zu finden ist, steht im Datenblatt des Controllers (was man beim Embedded-Programmieren vorliegen haben sollte).
Bei STM-Controllern gilt das für das (etwas umfangreicherer) Referencemanual.
Die Abschaltung/Einschaltung des Empfängers erfolgt in der txEnable
Routine.
Die leider komplett unsichtbar ist und auch gar nicht interessiert, weil es die "falsche" Richtung ist: Du willst aus dem TX-Modus in den RX-Modus wechseln.
Teste am Ende deiner ("geklauten") Senderoutine das TXC-Bit deines UART.
Was das ist
Die Routine ist nicht geklaut. ich denke, dass ich langsam das Problem sehe. Bisher habe ich nicht mit RS485 im Half-Duplex Modus gearbeitet.
Es ist ein unterschied, ob man UDRE (Also ob man das nächste byte in UDR schreiben kann) abfragt oder TXC abfragt. Das funktioniert sehr gut bis zum letzten byte, wo UDRE schon 1 ist obwohl das ende einer Frame noch nicht komplett gesendet wurde.
Die txEnable Routine sieht so aus:
1
voidtxEnable(boolvalue){
2
if(value){
3
UCSR0B&=~(1<<RXEN0);
4
PORTD|=(1<<PIND2);
5
}else{
6
PORTD&=~(1<<PIND2);
7
UCSR0B|=(1<<RXEN0);
8
}
9
}
Ich müsste also nach der for Schleife noch einmal TXC abfragen. Was mich eben nur wundert ist, dass es auch beim senden per Interrupt nur mit Wartezeit am Ende funktioniert hat.
Es ist ein unterschied, ob man UDRE (Also ob man das nächste byte in UDR
schreiben kann) abfragt oder TXC abfragt.
Ja, der UART schiebt nicht direkt UDR raus, sondern übernimmt es in ein Schieberegister, so dass es wieder beschrieben werden kann, bevor der Frame komplett gesendet wurde.
Ja, der UART schiebt nicht direkt UDR raus, sondern übernimmt es in ein
Schieberegister, so dass es wieder beschrieben werden kann, bevor der
Frame komplett gesendet wurde.
Mich verwirrt noch etwas folgende Aussage aus dem Datenblatt: "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. The TXCn flag can generate a transmit complete interrupt
(see description of the TXCIEn bit)."
Im grunde wäre es doch besser in der for schleife auf TXC zu prüfen um sich den Schritt am Ende zu sparen. Damit wäre wirklich sichergestellt, dass man immer ein Byte mit Stopbit sendet.
Mich verwirrt noch etwas folgende Aussage aus dem Datenblatt: "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. The
TXCn flag can generate a transmit complete interrupt
(see description of the TXCIEn bit)."
Was verwirrt Dich daran?
Wenn Du den Interrupt nutzt, musst Du Dich um nichts kümmern. Wenn nicht, musst Du das Flag wie beschrieben clearen, sonst bleibt es gesetzt, was natürlich wenig hilfreich ist.
Eine eigene Frage?
Dieser Thread ist über 2 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.