Forum: Mikrocontroller und Digitale Elektronik ADM3070 RE/DE Leitung


von Gustav G. (gustavgggg)


Lesenswert?

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?

von Rahul D. (rahul)


Lesenswert?

Gustav G. schrieb:
> Wo kann ich bei der Suche
> ansetzen?

Verwendest du das TXC-Flag / -Interrupt?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Wimre setzen die meisten MC das TXC Flag bereits, wenn das Stopbit 
anfängt und nicht erst, wenn es fertig gesendet ist.

von Hmmm (hmmm)


Lesenswert?

Gustav G. schrieb:
> RE und DE habe ich zuammen an einem IO pin

Hast Du an RXD des Controllers einen Pullup hängen oder den internen 
aktiviert?

Gustav G. schrieb:
> mindestens eine Millisekunde warte

Du hast die verwendete Baudrate und das Abschaltkriterium nicht genannt.

von Rahul D. (rahul)


Lesenswert?

Matthias S. schrieb:
> Wimre setzen die meisten MC das TXC Flag bereits, wenn das Stopbit
> anfängt und nicht erst, wenn es fertig gesendet ist.

Mit dem Stopbit ist der Bus doch sowieso im Standy-Zustand.
Wenn man da umschaltet, sollte doch alls gut sein.

von Hmmm (hmmm)


Lesenswert?

Rahul D. schrieb:
> 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.

von Gustav G. (gustavgggg)


Lesenswert?

Hier nochmal die fehlenden Informationen.

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(unsigned int i = 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.

von Rahul D. (rahul)


Lesenswert?

Gustav G. schrieb:
> 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.

von Gustav G. (gustavgggg)


Lesenswert?

Rahul D. schrieb:
> 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
void txEnable(bool value) {
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.

von Hmmm (hmmm)


Lesenswert?

Gustav G. schrieb:
> An RXD des Controllers hängt kein Pullup.

Eleganter wäre es, trotz des beim Senden deaktivierten RXE den 
integrierten Pullup zu aktivieren, um das Floaten von RXD zu verhindern.

Gustav G. schrieb:
> 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.

Gustav G. schrieb:
> Was mich eben nur wundert ist, dass es auch beim senden per Interrupt
> nur mit Wartezeit am Ende funktioniert hat.

Welchen Interrupt hast Du denn genommen?

von Gustav G. (gustavgggg)


Lesenswert?

Hmmm schrieb:
> Eleganter wäre es, trotz des beim Senden deaktivierten RXE den
> integrierten Pullup zu aktivieren, um das Floaten von RXD zu verhindern.

Das habe ich jetzt einfach mal gemacht. Es kostet nichts.

Hmmm schrieb:
> 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.

Hmmm schrieb:
> Welchen Interrupt hast Du denn genommen?

Es gibt beim Atmega328 für ein Interrupt für Transmit complete und das 
ist USART, Tx complete Vector 21

von Hmmm (hmmm)


Lesenswert?

Gustav G. schrieb:
> 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.

Gustav G. schrieb:
> Im grunde wäre es doch besser in der for schleife auf TXC zu prüfen um
> sich den Schritt am Ende zu sparen.

Eigentlich ist es ganz einfach: Für das UDR-Befüllen ist UDRE relevant, 
für das Abschalten des Treibers TXC.

Gustav G. schrieb:
> Es gibt beim Atmega328 für ein Interrupt für Transmit complete

Mit dem hätte es eigentlich funktionieren müssen. Wenn nicht, einfach 
mal Oszi oder Logic Analyzer dranhängen und ansehen, was tatsächlich 
passiert.

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
Noch kein Account? Hier anmelden.