Forum: Mikrocontroller und Digitale Elektronik attiny software uart vollduplex


von Matthias T. (mati123)


Lesenswert?

Hi,

ich versuche gerade einen Software-UART auf dem Attiny 2313 vollduplex 
zum Laufen zu bekommen.

Als Basis habe ich
> http://rn-wissen.de/wiki/index.php/Software-UART_mit_avr-gcc
genommen und lediglich für den Attiny 2313 angepasst (sowie das 
veraltete SIGNAL auf ISR() umgeschrieben).

Testweise lasse ich einen while (1) {a=uart_getc_wait (); uart_putc(a);} 
in main laufen und schaue mir das Ergebnis im Terminal bei 9600 bps an.

Das senden und empfangen von einzelnen Zeichen funktioniert fehlerfrei, 
aber im Vollduplex-Betrieb bekomme ich Empfangsfehler auf dem attiny.

Ein testweises Erhöhen der Taktfrequenz von 1,8432 MHz auf 14,7456 MHz 
durch weglassen der CKDIV8 Fuse ändert an dem Verhalten nichts, daran 
scheint es also nicht zu liegen.

Können die ISR(TIMER1_COMPA_vect), ISR (TIMER1_CAPT_vect), ISR 
(TIMER1_COMPB_vect) evtl. nicht unabhängig voneinander gleichzeitig 
aktiv sein? Oder wo könnte ich sonst noch ansetzen?

LG
Matthias

von Matthias T. (mati123)


Lesenswert?

Ergänzung:
Ich habe nun das selbe mit dem Hardware-USART probiert, und auch da habe 
ich Probleme im vollduplex-Betrieb. Zeichen von Hand senden und 
Empfangen geht, auch mit der Tastenwiederholung, aber sobald ich mehrere 
Zeichen unmittelbar nacheinander sende empfängt der Attiny nur noch 
Müll, wenn er gleichzeitig sendet. Dabei soll der USART doch vollduplex 
sein?

Interessanterweise funktioniert die Kombination Hardware-USART senden, 
Software USART empfangen auf dem gleichen Attiny ohne Probleme.

von m.n. (Gast)


Lesenswert?

Komisch! Wenn ich mir Deinen Quellcode ansehe, scheint alles in Ordnung 
zu sein. Ausnahme ist Zeile 42, da fehlt wohl eine Klammer.

von Stefan F. (Gast)


Lesenswert?

Eine Warteschleife die die Fehlerursache.

Bei jedem Schleifendurchlauf liest du ein empfangendes Zeichen aus dem 
Empfangspuffer aus und schreibst es in den Sendepuffer.

Du kannst mit der vollen Übertragungsrate mehrere aufeinanderfolgende 
Zeichen empfangen, da du einen Empfangspuffer hast, der mehrere Zeichen 
puffern kann.

Aber du hast keinen Sendepuffer. Das nächste Zeichen kann erst gesendet 
werden, nachdem das vorherige fertig gesendet wurde. Dazwischen wartet 
das Programm.
1
do
2
{
3
    sei(); nop(); cli(); // yield(); 
4
} while (outframe);

An dieser Stelle wird zwangsläufig immer ein kleines bisschen länger 
gewartet, als notwendig. Dazu kommt auch noch die Zeit für das Auslesend 
es Empfangspuffers.

Es geht hier nur im Bruchteile von Millisekunden, aber die genügen, um 
den von Dir genannten Fehler auszulösen. Du kannst einfach nicht so 
schnell senden, wie du empfangen kannst.

Du kannst ja mal zum Gegenvergleich einfach nur "aaaaaaaaaa..." Senden, 
ohne zu empfangen. Wenn Du Dir das auf dem Oszilloskop anschaust, wirst 
du sehen, daß zwischen jedem Zeichen eine kleine Pause (mehr als 1 
Stop-Bit) liegt.

von c-hater (Gast)


Lesenswert?

Matthias T. schrieb:

> Können die ISR(TIMER1_COMPA_vect), ISR (TIMER1_CAPT_vect), ISR
> (TIMER1_COMPB_vect) evtl. nicht unabhängig voneinander gleichzeitig
> aktiv sein?

Nein, das können sie tatsächlich nicht, niemals. Denn ein AVR8 hat 
nunmal nur eine einzige MCU, jegliche Nebenläufigkeit von Code kann also 
immer nur eine Scheinbare sein.

D.h.: wenn eine ISR zu lange braucht oder zu häufig aufgerufen wird, 
wird eine andere später, gelegentlich zu spät oder eventuell sogar 
praktisch garnicht mehr drankommen.

> Oder wo könnte ich sonst noch ansetzen?

Eine Sprache lernen, die von Hause aus effizienten Umgang mit Interrupts 
ermöglicht, also Assembler...

> 9600 bps
> Taktfrequenz von 1,8432 MHz

Das ist für eine fullduplex-Kommunikation schon eine merkliche 
Herausforderung an die Kompetenz des Programmierers einer 
Software-Lösung, immerhin fast 19,2kHz maximale Interruptrate, also nur 
knapp 100 Takte pro ISR verfügbar. Das reicht zwar locker aus für die 
Funktionalität, aber nur dann, wenn man den µC auch sinnvoll ausnutzt. 
Und das fällt nunmal sehr schwer mit zusammengeklauten C-Code...

Außerdem darf man ja nie vergessen, dass diese Kommunikation ja kein 
Selbstzweck ist, es sollen i.d.R. ja auch noch andere Sachen passieren, 
(quasi) während diese Kommunikation läuft. Man darf die o.g. 100 Takte 
also nicht annähernd ausnutzen, insbesondere, wenn es auch noch andere 
Interrupts im System gibt, die mit der Kommunikation nichts zu schaffen 
haben.

Und übrigens: wenn die massive Erhöhung des Takts das Verhalten nicht 
signifikant verbessert hat (was du ja probiert hast), ist der Code 
definitiv ganz grundsätzlich Scheisse, denn jeder gute Code würde ganz 
automatisch davon profitieren, mehr Rechenzeit verfügbar zu haben, 
insbesondere natürlich auch bezüglich des Hauptproblems der (variablen) 
Interrupt-Latenz.

von Peter D. (peda)


Lesenswert?


von Matthias T. (mati123)


Lesenswert?

Also ich habe nun viele Dinge probiert, aber auch mit dem Hardware-UART 
treten die gleichen Problem im Duplex-Betrieb auf. Auf der Empfangsseite 
kommt Müll an, obwohl der Attiny keinen FrameError oder BufferOverrun 
signalisiert. Da ich die Orginalbeispiele aus dem Datenblatt als 
Programm verwendet habe kann es also auch daran nicht liegen.

Mittlerweile habe ich den USB-Seriellwandler in Verdacht (FTDI Adapter 
FT232RL USB zu TTL Serial), dass der evtl. im Vollduplex-Betrieb fehler 
produziert. Dann würde es gar nicht am Attiny liegen.

von Wolfgang (Gast)


Lesenswert?

Matthias T. schrieb:
> Mittlerweile habe ich den USB-Seriellwandler in Verdacht (FTDI Adapter
> FT232RL USB zu TTL Serial), dass der evtl. im Vollduplex-Betrieb fehler
> produziert. Dann würde es gar nicht am Attiny liegen.

Also klemme den Logikanalysator an und gucke, was auf der Leitung los 
ist.

von Matthias T. (mati123)


Lesenswert?

Wolfgang schrieb:
> Also klemme den Logikanalysator an und gucke, was auf der Leitung los
> ist.

Einen Logikanalysator habe ich leider nicht, auch kein Oszilloskop. Aber 
ich habe nun einen anderen USB-TTL Wandler angeschlossen (diesmal auf 
CP2102 Basis) und alle Fehler sind verschwunden.

Schade, dass ich so lange den Fehler an der falschen Stelle gesucht 
habe. Vielen Dank für die Hinweise hier im Forum.
LG
Matthias

von Stefan F. (Gast)


Lesenswert?

Du weisst schon, daß man USB-UART Adapter ganz einfach durch eine 
Loop-Back Verbindung (Rx mit Tx verbinden) testen kann?

von m.n. (Gast)


Lesenswert?

Schon lustig: zunächst ist von irgendeiner, modifizierten Software die 
Rede, die nur angedeutet aber nie gezeigt wird, und dann kommt auf 
einmal ein USB-Wandler ins Spiel.
Das sind Probleme für eine Glaskugel.

von Mati (Gast)


Lesenswert?

Stefan U. schrieb:
> Du weisst schon, daß man USB-UART Adapter ganz einfach durch eine
> Loop-Back Verbindung (Rx mit Tx verbinden) testen kann?

Das hatte ich natürlich als erstes geprüft. Dabei treten keine Fehler 
auf, offenbar nur bei einem zeitlichen Versatz zwischen Senden und 
Empfangen.

von Florian (Gast)


Lesenswert?

Hallo Matthias,

Du solltest Dir unbedingt ein einfaches Oszilloskope zulegen. Je nach 
Budget würde ich Dir zu einem USB Picospope (ca. 160€) raten, dies kann 
auch eine USART Übertragung dekodieren und die Fehler in den Frames 
anzeigen. Für die Fehlersuche ist das unerlässlich, sonst suchst Du Dir 
nen Wolf!

Gruß
Florian

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.