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...
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...
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.
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.
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.
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.
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.
> 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.'
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! :-(
1
ISR(USART1_TX_vect)
2
{
3
if(uart1_pos_out_tx==uart1_pos_put_tx)
4
{
5
_uart1_txd_off();
6
}
7
}
Klasse! Funktioniert 1A :-D
Vielen Dank, Gruß AVRli...
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.
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
...
...
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.
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.
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.
> 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.