Mathias hat geschrieben:UCSZ01 wurde anscheinend in der Atmega328p vergessen, ich habe in der Arduino iom328p.h nachgeguckt und hat auch "2", der gleiche Wert wie UCSZ02.
Nein, nicht vergessen, das war nur ein fauler Sack.
![Wink ;-)](./images/smilies/icon_wink.gif)
UCSZ01 und UCSZ00 bilden ja zusammen ein "Doppelbit", binär %11. (1 shl UCSZ01) or (1 shl UCSZ00) ist also gleich (%11 shl UCSZ00), und das ist gleich (3 shl UCSZ00). Man kann also, wenn man beide Bits setzen will (3 shl UCSZ00) schreiben, oder (%11 shl UCSZ00). Wenn man nur das höhere setzen will (2 shl UCSZ00), oder ganz übersichtlich (%10 shl UCSZ00).
Da diese "Einsparmaßnahme an mehreren Stellen in der Unit zum 328p und ich nehme an auch in Units anderer Controller vorkommt, solltest Du Dir das gleich angewöhnen. Hier einfach ein anderes Kürzel zu nehmen - viel Spaß bei der Fehlersuche, wenn Du die Routine mal mit einem anderen Controller verwenden willst, bei dem die Bitfolge anders ist.
Was mich immer noch wundert: Warum setzt Du UMSEL0? Damit schaltest Du synchrone Übertragung ein, das brauchst Du nur, wenn Du das als SPI-Interface nutzen willst.
Mathias hat geschrieben:Was mich verwundert, es wird zum Senden und Empfangen das Register UDR0 benutzt. Ich dachte immer die COM-Schnittstelle sei bilddirektional ?
Ich verweise ja ungern schon wieder auf das Datenblatt, Seite 191. Das sind zwei physische Register, die sich eine Adresse teilen. Genaugenommen ist es noch etwas komplizierter:
Beim Senden wird UDR0 (Byte 1) in ein Shiftregister kopiert und dieses dann rausgeschoben. Währenddessen können wieder Daten (Byte 2) in UDR0 geschrieben werden, müssen dann aber warten, bis die Daten (Byte 1) aus dem Shiftregister komplett raus sind, was bei 9600baud etwa 1msec dauert. Erst dann werden diese Daten (Byte 2) in das Shiftregister kopiert, und Du kannst die nächsten Daten (Byte 3) in UDR0 schreiben. Deswegen musst Du, wenn Du mehrere Bytes hintereinander schreibst immer auf UDRE0 warten.
Beim Empfangen werden die Daten in einem Register gesammelt. Ist das voll (Byte 1), bekommst Du die Meldung, dass Daten empfangen wurden, und die folgenden Daten (Byte 2) werden in einem zweiten Register gesammelt. In der Zeit musst Du die Daten aus dem ersten Register abholen, sonst geht das dritte Byte verloren. Umgeschalten wird immer durch einen Lesevorgang, Du kannst also nicht zweimal das gleiche Byte aus UDR0 auslesen.
Vorteil ist, Du hast immer ein Byte lang Zeit, UDR0 zu lesen, was bei 9600baud 1msec ist. Allerdings hat Deine Leseroutine ReadChar den Nachteil: Kommen keine Daten an, bleibt der Controller an dieser Stelle hängen. Deswegen macht man sowas gern in einem Interrupt, die Daten werden zeitnah ausgelesen, aber der Controller wird nicht blockiert.