mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik UART TXD nur aktivieren, wenn Daten gesendet werden?


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: AVRli .. (avrli)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich möchte den UART Transmitter eines ATmega2560 nur für die Zeit, wie 
auch wirklich Daten gesendet werden, einschalten.

Werden KEINE Daten ausgesendet, muss der Ausgang als Eingang hochohmig 
sein.

Der Grund ist der, das der µC an einem 1-Draht Bus hängt wo RXD und TXD 
miteinander verbunden sind. Es darf immer nur ein Teilnehmer senden, 
sonst hört er auf dem Bus.

Ich aktiviere den TXD Ausgang in der Routine, in der ich die zu 
sendenden Bytes in den UART_TX_BUFFER übertrage, wie folgt...
  SET_BIT(UART1_DDR, UART1_TXD_PIN);  // Output
  SET_BIT(UART1_PORT, UART1_TXD_PIN);  // PIN HIGH
  SET_BITS(UCSR1B, (1<<TXEN1));    // Enabled transmitter

...deaktiviert wird der UART Transmitter im "Data Register Empty" 
Interrupt, wenn keine weiteren Zeichen mehr im Buffer sind, mit...
  CLEAR_BIT(UART1_DDR, UART1_TXD_PIN);  // Input
  CLEAR_BIT(UART1_PORT, UART1_TXD_PIN);  // Pullup off
  CLEAR_BITS(UCSR1B, (1<<TXEN1));    // Disabled transmitter

Das ganze funktioniert auch so lange, wie die Zeichen die rausgehen 
sollen, direkt hintereinander folgen. Kommt es zu einer nur ganz kurzen 
Verzögerung bei der Ausgabe, gehen Bytes verloren. :-(

Ich habe die Vermutung das ich entweder zu spät einschalte oder aber zu 
früh wieder aus. Wo wäre der richtige Zeitpunkt um es dennoch 
realisieren zu können?

Gruß AVRli...

Autor: Karl M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo AVRli .. schrieb:

ich löse das nicht per Programm, denn der Zustand des TXD eines AVR ist 
direkt vom Ein- und Ausschalten des Sendezweigs des Uart abhängig.

Was einfach geht, ist per Logikschaltung über ein ODER-Gatter, das kann 
in diesem Fall eine Germanium oder Silizium Diode sein.

Autor: Stefanus F. (Firma: Äppel) (stefanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich schätze, dass du einen Pull-Up Widerstand am Bus brauchst, damit die 
Leitung einen definierten Pegel hat, während der Tx-Ausgang deaktiviert 
ist.

Autor: Amateur (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du weißt, was Du tust, also Daten sendest und "Dir" selber zuhörst, 
ignoriere doch einfach den Schrott. Du weißt ja, wie es gemeint ist.
Ansonsten: UART-Eingang als "normalen" Eingang (I/O) konfigurieren.

Autor: Georg A. (georga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt ja zwei Möglichkeiten:

a) Du erzeugst beim Einschalten mit zuerst DDR und dann HIGH einen 
Low-Glitch, der das erste Sende-Byte ruiniert. Evtl. mal die Reihenfolge 
drehen. Hatte der AVR nicht einen schwachen Pullup, wenn man als Eingang 
den Ausgangsregister auf 1 gesetzt hat (oder verwechsle ich das mit 
einem der zig anderen CPUs, die ich schon mal misbraucht habe...)?

b) Du drehst zu früh ab, weil "Buffer empty" nur sagt, dass das 
Laderegister leer ist, aber das eigentliche Schieberegister noch ein 
paar Bits raustaktet.

Kannst du dir das nicht mal auf einem Oszi anschauen?

Oder ohne Oszi (jaja, ganz böse, aber es würde weiterhelfen...) vor dem 
Enable bzw. Disable ein delay() machen? Dann wüsste man wenigstens, 
welches Eck man anschauen muss.

Autor: da1l6 (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Hallo,

Auf DRE warten reicht nicht, da wird noch gesendet ("double buffer").
Verwende den TXC interrupt zum deaktivieren des USARTs.

da1l6

Autor: S. Landolt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie von den Anderen bereits geschrieben, ist das DDR-Umschalten unnötig, 
evtl. sogar kontraproduktiv: 'TXENn: The Transmitter will override 
normal port operation for the TxDn pin when enabled'.
  Ich würde den TxD-Pin auf Eingang lassen und nur mit UART1_PORT den 
internen Pullup-Widerstand einschalten.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
da1l6 schrieb:
> Auf DRE warten reicht nicht, da wird noch gesendet ("double buffer").
> Verwende den TXC interrupt zum deaktivieren des USARTs.

Das kann ich nur so unterstreichen. Wenn das letzte Zeichen 
rausgeschickt wird, ist es noch lange nicht physikalisch vollständig auf 
der Leitung raus.

Der TX Complete Interrupt ist genau der richtige, um festzustellen, das 
wirklich auch das letzte Bit über den Draht ging.

: Bearbeitet durch Moderator
Autor: S. Landolt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Du drehst zu früh ab ...
> Auf DRE warten reicht nicht, da wird noch gesendet

'The disabling of the Transmitter (writing TXENn to zero) will not 
become effective until ongoing and pending transmissions are completed, 
that is, when the Transmit Shift Register and Transmit Buffer Register 
do not contain data to be transmitted.'

Autor: AVRli .. (avrli)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Georg A. schrieb:
> Oder ohne Oszi (jaja, ganz böse, aber es würde weiterhelfen...) vor dem
> Enable bzw. Disable ein delay() machen? Dann wüsste man wenigstens,
> welches Eck man anschauen muss.

Tcha ein "_delay_ms(1)" vor dem einleiten des Abschaltens bringt keine 
Fehler und somit ist...

da1l6 schrieb:
> Auf DRE warten reicht nicht, da wird noch gesendet ("double buffer").
> Verwende den TXC interrupt zum deaktivieren des USARTs.

Genau richtig! Das habe ich nun aktiviert, ich habe nicht mehr auf dem 
Schirm gehabt das es diesen Interrupt überhaupt gibt! :-(
ISR(USART1_TX_vect)
{
  if (uart1_pos_out_tx == uart1_pos_put_tx)
  {
    _uart1_txd_off();
  }
}

Klasse! Funktioniert 1A :-D

Vielen Dank, Gruß AVRli...

: Bearbeitet durch User
Autor: S. Landolt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schön, dass es läuft, aber die Ursache war es nicht, diese liegt an 
anderer Stelle.

Autor: AVRli .. (avrli)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na jetzt schalte ich erst ab, wenn er über den USART1_TX Interrupt 
signalisiert, dass die Übertragung abgeschlossen ist. Damit drehe ich 
nicht mehr zu früh ab, wie zuvor bei dem USART1_UDRE.

Autor: S. Landolt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Haben Sie mein Zitat aus dem Datenblatt nicht gelesen? Sie können gar 
nicht "zu früh abdrehen", das macht der Controller selbsttätig richtig.
  Nachfolgendes Programm bringt auf dem Monitor:

mega48
mega48
mega48
...
...

.macro  disp
    ldi     tmp0,@0
disp_:
     lds    tmp1,UCSR0A
     sbrs   tmp1,UDRE0
    rjmp    disp_
    sts     UDR0,tmp0
.endmacro

main:
    ldi     tmp0,(1<<TXEN0)
    sts     UCSR0B,tmp0
    disp    'm'
    disp    'e'
    disp    'g'
    disp    'a'
    ldi     tmp0,0
    sts     UCSR0B,tmp0
    ldiw    Z,1843/4
wait100us:
     sbiw   ZL,1
    brne    wait100us
    ldi     tmp0,(1<<TXEN0)
    sts     UCSR0B,tmp0
    disp    '4'
    disp    '8'
    disp    '\r'
    disp    '\n'
    rcall   wait1s
 rjmp       main

Autor: S. Landolt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PS:
Die Übertragung läuft mit 115200 Bd, dieses wait100us ist also etwas 
mehr als 1 Zeichen.

Autor: AVRli .. (avrli)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
S. Landolt schrieb:
> Haben Sie mein Zitat aus dem Datenblatt nicht gelesen? Sie können gar
> nicht "zu früh abdrehen", das macht der Controller selbsttätig richtig.

Doch, das wird auch stimmen!
Nur kann ich wohl zu früh an den Ports "rumfummeln"? Also zu früh auf 
Eingang/Ausgang umschalten?

Eine andere Erklärung habe ich erst mal nicht, warum es denn nun 
funktioniert, wie ich es wollte.

Autor: S. Landolt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zu dieser Umschaltung Ein-/Ausgang hatte ich ja auch etwas geschrieben, 
jedoch hängt das natürlich stark davon ab, was die Anwendung sonst noch 
macht.
  Aber wie gesagt, es läuft, und das ist schön. Eine Erklärung habe ich 
auch nicht, man sollte nur im Auge behalten, dass da eventuell noch ein 
Problem lauert.

Autor: Stefan E. (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
AVRli .. schrieb:
> Eine andere Erklärung habe ich erst mal nicht, warum es denn nun
> funktioniert, wie ich es wollte.

Ich vermute, dass du vorher in der Logik "Abschalten ja oder nein" einen 
Fehler hattest, und somit ganz früh (vielleicht schon nach dem ersten 
Byte) abgeschaltet hast.

AVRli .. schrieb:
> Das ganze funktioniert auch so lange, wie die Zeichen die rausgehen
> sollen, direkt hintereinander folgen.

Eben weil (wie S. Landolt ausgeführt hat) das Abschalten keinen Effekt 
hat, solange sich noch Daten in einem der Sende-Register befinden.

AVRli .. schrieb:
> Kommt es zu einer nur ganz kurzen
> Verzögerung bei der Ausgabe, gehen Bytes verloren. :-(

"Kurze Verzögerung" bedeutet dann vermutlich, dass die Sende-Register 
leer laufen. Das (im Code schon längst erfolgte) Abschalten findet an 
dem Punkt dann tatsächlich auch in der Hardware statt, und die 
restlichen Bytes gehen verloren.

Autor: Stefanus F. (Firma: Äppel) (stefanus)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
> man sollte nur im Auge behalten, dass da eventuell
> noch ein Problem lauert.

Jepp. Wenn man ein Problem gelöst hat, ohne die Lösung genau zu 
verstehen, kommt das Problem oft irgendwann wieder.

Autor: AVRli .. (avrli)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe mir Eure Bedenken und Anmerkungen im Projekt hinterlegt und 
hoffe, dass ich das Problem nicht wieder hoch spüle. ;-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.