Forum: Mikrocontroller und Digitale Elektronik [AVR] One-Wire UART


von Fabian K. (fabian_k)


Lesenswert?

Hallo,

vor ein paar Tagen wurde das Thema schon mal behandelt, die Situation 
war dabei allerdings etwas anders.

Meine zwei Ansätze:
- Hardware: RX direkt am One-Wire Bus, TX über 1k-Widerstand auf den Bus
  Software: + Empfangen wird wie sonst auch
            + Gesendet wird eigentlich auch normal, nur muss das
              gesendete Byte gleich danach aus UDR ausgelesen werden
              (weil ja RX und TX verbunden sind)
              Man könnte auch den Receiver vor dem Senden abschalten und
              nach erfolgreichen Sendevorgang (über Polling oder
              Interrupt) wieder aktivieren.

- Hardware: RX und TX direkt verbinden
  Software: + Empfangen wird wie sonst auch
            + Der Transmitter muss hier deaktiviert werden, wenn er
              nicht gebraucht wird (als Eingang). Vor dem Senden wird er
              wieder aktiviert, nach erfolgreichem Sendevorgang wieder
              deaktiviert.
              Hier nach dem Senden entweder vorher den Receiver
              deaktivieren und dann wieder aktivieren, oder UDR nach dem
              Senden gleich auslesen.


Was haltet ihr davon, bzw. wie würdet ihr das realisieren?

MfG Fabian

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


Lesenswert?

Wenn du TXD und RXD nicht über z.B. Dioden entkoppelst, bleibt dir nur 
der 2. Ansatz, denn des Freigeben des Sendeteil überschreibt die 
Portfunktion und macht TXD zwangsweise zu einem Ausgang. Zitat aus dem 
ATMega8 Datenblatt:
> When the Transmitter is enabled, the normal port operation of the TxD pin
> is overridden by the USART and given the function as the Transmitter’s
> serial output.
Ein empfangenes Signal würde also mit dem TXD Ausgang kollidieren, der 
bei inaktivem Sender auf high ist.
Wenn du die Aktivierung/Deaktivierung des Senders vermeiden willst, wäre 
ein möglicher Ansatz, beide RXD Leitungen fast zu verbinden (sind ja 
immer Eingänge) und die TXDs über Dioden mit auf den 1-wire zu legen.

RXD A             RXD B
O------+---------+----O
       |         |
       --        --
TXD A  \/        \/
       |         | TXD B
O-------         -----O

von Fabian K. (fabian_k)


Lesenswert?

Matthias Sch. schrieb:
> Wenn du TXD und RXD nicht über z.B. Dioden entkoppelst, bleibt dir nur
> der 2. Ansatz, denn des Freigeben des Sendeteil überschreibt die
> Portfunktion und macht TXD zwangsweise zu einem Ausgang. Zitat aus dem
> ATMega8 Datenblatt:
>> When the Transmitter is enabled, the normal port operation of the TxD pin
>> is overridden by the USART and given the function as the Transmitter’s
>> serial output.
> Ein empfangenes Signal würde also mit dem TXD Ausgang kollidieren, der
> bei inaktivem Sender auf high ist.

Wirkt der Widerstand am Transmitter im inaktiven Zustand nicht einfach 
als Pull-Up?

> Wenn du die Aktivierung/Deaktivierung des Senders vermeiden willst, wäre
> ein möglicher Ansatz, beide RXD Leitungen fast zu verbinden (sind ja
> immer Eingänge) und die TXDs über Dioden mit auf den 1-wire zu legen.
>
> RXD A             RXD B
> O------+---------+----O
>        |         |
>        --        --
> TXD A  \/        \/
>        |         | TXD B
> O-------         -----O

Mal angenommen ich realisiere das Ganze mit dem zweiten Ansatz.
Ich deaktiviere den Receiver / aktiviere den Transmitter vor jedem 
Sendevorgang und deaktiviere den Transmitter / aktiviere den Receiver 
nach erfolgreichem Sendevorgang wieder.

Der Transmitter kann dabei direkt nach dem Laden des UDR-Registers 
deaktiviert werden (TXEN=0), da laut Datenblatt erst nach dem Abschluss 
des Sendevorgangs Änderungen vom TXEN-Bit berücksichtigt werden.
(The disabling of the Transmitter (setting the TXEN to zero) will not 
become effective until ongoing and pending transmissions are completed, 
i.e., when the Transmit Shift Register and Transmit Buffer Register do 
not contain data to be transmitted.)

Kann es zu Empfangsproblemen kommen (zu langsam), wenn ich jedesmal den 
Receiver wieder neu aktiviere (das Aktivieren wird wohl kaum nur drei 
Taktzyklen brauchen / ldi+sts)?

von Stephan B. (matrixstorm)


Lesenswert?

Dazu gibt es von ATmel ein APnote: AVR274.

http://www.atmel.com/Images/AVR274.pdf

von Wusel D. (stefanfrings_de)


Lesenswert?

> Wirkt der Widerstand am Transmitter im inaktiven
> Zustand nicht einfach als Pull-Up?

Bei ATTiny und ATmega kannst Du Transmitter und Receiver vom UART nicht 
unabhängig voneinander deaktivieren. Aber wenn Du nicht den integrierten 
UART verwendest, sondern ihn per Software implementierst, dann hast Du 
volle Kontrolle über die einzelnen Pins.

Bei Xmega Controllern ist der Ausgang separat aktivierbar und 
standardmäßig inaktiv, soweit ich mich erinnere.

von MWS (Gast)


Lesenswert?

Stefan Frings schrieb:
> Bei ATTiny und ATmega kannst Du Transmitter und Receiver vom UART nicht
> unabhängig voneinander deaktivieren.

So, so, dann wurde RXEN und TXEN von Atmel also nur zum Spaß 
vorgesehen...

von gfhf (Gast)


Lesenswert?

kannst auch den RX ISR dazu nutzen um eine collision zu erkennen

ist das gesendete byte == dem empfangene war alles schön und nächstes 
byte ins UDR

ist das empfangene byte != gesendete -- timer setzen zurück zum anfang 
und erstmal gucken was passiert

zum senden brauchst du nur den RX ISR + ein byte zum start senden


die senderoutine sendet genau 1 byte .. der rest läuft automatisch ab


wenn  der buss defekt sein sollte erkennst du das sogar mit .. weil nix 
emopfangen wird

von Michael M. (technikus)


Lesenswert?

Fabian K. schrieb:
> - Hardware: RX und TX direkt verbinden
>   Software: + Empfangen wird wie sonst auch
>             + Der Transmitter muss hier deaktiviert werden, wenn er
>               nicht gebraucht wird (als Eingang). Vor dem Senden wird er
>               wieder aktiviert, nach erfolgreichem Sendevorgang wieder
>               deaktiviert.

Genau so habe ich es gemacht. Ich habe sogar den RX während der TX-Phase 
ausgeschaltet, weil ich das lokale Echo nicht immer rausklauben wollte. 
Transmitter deaktiveren war etwas trickreich: Pollen von TXC0 in UCSR0A 
hat nicht richtig geklappt. Habe dann einen IRQ-Handler für 
USART_TX_vect aufgesetzt, der TX aus und RX einschaltet.

Servus
Michael

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Michael M. schrieb:
> Pollen von TXC0 in UCSR0A
> hat nicht richtig geklappt.

Obwohl das sehr gut klappt - zumindest in unseren Projekten ;-)

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Michael M. schrieb:
> Habe dann einen IRQ-Handler für
> USART_TX_vect aufgesetzt, der TX aus und RX einschaltet.

Das kann u.U. schon zu spät sein, wenn der "Slave" unmittelbar und mit 
hoher Baudrate antwortet. Ehe der Interrupt-Service angesprungen ist, 
vergehen erstmal 6 Clocks und dann sichert die Service Routine auch erst 
ein paar Register, bevor Du dann mit Deinem Receiver aktivieren dran 
bist. Kommt aber auf den Anwendungszweck an. Oder man muss den Slave 
halt bewusst bremsen.

von Wusel D. (stefanfrings_de)


Lesenswert?

> So, so, dann wurde RXEN und TXEN von Atmel also nur zum Spaß vorgesehen...

Oh ja, Du hast Recht. Im Datenblatt steht klar drin, dass die normale 
Funktion des I/O Pins bei TXEN=0 nicht überschrieben wird.

Der Unterschied zwischen ATmega und Xmega besteht wohl darin, dass man 
den Pin beim Xmega als Ausgang konfigurieren muss, auch wenn der 
Transmitter schon enabled ist. Beim ATmega spielt das DDR Bit keine 
Rolle, wenn TXEN=1 ist.

Na dann steht der Urpsrünglichen Idee des TO ja eigentlich nichts im 
Wege, außer eventuell sein Programm-Design.

von Fabian K. (fabian_k)


Lesenswert?

Danke für die vielen Vorschläge.

Ich werds dann wohl so realisieren:
Hardware: Rx und Tx direkt verbinden
Software: Der Receiver bleibt immer aktiv (damit es sicher keine
          zeitlichen Probleme gibt).
          Den Transmitter aktiviere ich vor dem Senden und deaktiviere
          ihn nach dem Sendevorgang wieder (ist ja ziemlich
          zeit-unkritisch, außer der Empfänger hat einen Timer für ein
          Timeout laufen).
          Die Idee für eine mögliche Kollisionserkennung von gfhf werde
          ich auch noch in die Rx-ISR packen.


Noch ein Auszug aus dem Datenblatt (Atmega168PA / S.181):

> The disabling of the Transmitter (setting the TXEN to zero) will not
> become effective until ongoing and pending transmissions are completed,
> i.e., when the Transmit Shift Register and Transmit Buffer Register do
> not contain data to be transmitted. When disabled, the Transmitter will
> no longer override the TxDn pin.

Mein Englisch ist nicht schlecht, also so versteh ich das:
Ich kann den Transmitter direkt nach dem Laden des UDR-Registers wieder 
deaktivieren (TXEN-Bit löschen), da eine Änderung des TXEN-Bit erst nach
dem Abschluss des aktuellen Sendevorgangs wirksam wird.

So könnte ich mir auch noch eine eigene ISR bzw. das Polling des TXC-Bit
für den Transmitter sparen?

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


Lesenswert?

Fabian K. schrieb:
> So könnte ich mir auch noch eine eigene ISR bzw. das Polling des TXC-Bit
> für den Transmitter sparen?

Theoretisch ja, praktisch würde ich immer schauen, ob der Transmitter 
aktiv ist, bvor du TXEN abschaltest, damit ein evtl. noch folgender 
Sendevorgang nicht abgebrochen wird. Allerdings erscheint mir der TXC 
Interrupt als der richtige Platz fürs Abschalten, ich bin allerdings 
auch ein Fan von ISR.

Die Diodenlösung halte ich dann für praktisch, wenn man gleichzeitg den 
Zustand der Leitungen prüfen möchte und einfach gar nicht Abschalten 
möchte. Ein z.B. Kurzschluss auf der Leitung würde eben jedem Sender 
sofort auffallen, wenn kein Echo kommt.

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.