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
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.
Komisch! Wenn ich mir Deinen Quellcode ansehe, scheint alles in Ordnung zu sein. Ausnahme ist Zeile 42, da fehlt wohl eine Klammer.
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.
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.
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.
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.
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
Du weisst schon, daß man USB-UART Adapter ganz einfach durch eine Loop-Back Verbindung (Rx mit Tx verbinden) testen kann?
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.