Forum: Mikrocontroller und Digitale Elektronik UART Einsteiger braucht etwas Hilfe/Erfahrung


von Martin (Gast)


Lesenswert?

Guten morgen zusammen,

ich habe gestern meine ersten Zeichen per UART an HTerm gesendet 
(Controller Atmega88 mit einem FT232RL USB->Serial Konverter).
Mein eigentliches Ziel ist es, Daten von einem Programm am PC (zunächst 
erstmal manuell von HTerm) an den µC zu senden und dort dann in das 
EEPROM zu speichern. Gesendet werden soll 1 Array mit 200 Stellen 
(Variablen darin 16-bit signed) und ein paar kleine Konfig-Variablen 
(8-bit unsigned)

Der UART kann ja nur 8-bit in einem Rutsch übertragen. Also muss ich die 
Variable zerlegen durch maskieren und immer erst das MSB oder LSB senden 
und dann eben das andere und am µC in der richtigen Reihenfolge durch 
8faches schieben wieder durch Veroderung der beiden zusammenbasteln in 
eine Variable. Soweit habe ich das aus der Suche mal verstanden. Der 
Empfang geschieht natürlich per Interrupt, um nichts zu verpassen. Ich 
dachte ich puffere dies und schreibe es im Hauptprogramm dann in das 
EEPROM, da die Schreibzugriffe hier ja nicht sonderlich schnell sind.

Jetzt ist meine Frage, wie baue ich das Protokoll auf. Habe ich der 
Suche ebenfalls richtig entnommen, dass man eine 8-bit Zahl am besten in 
ein ASCII-Zeichen konvertiert, welche dann als 1 Zeichen gesendet werden 
kann und der µC das wieder rückkonvertiert zu einer Zahl und diese 
speichert?

Wie stelle ich fest, dass keine Zahl verloren geht bzw. wäre es ja 
fatal, wenn beispielsweise ein MSB verloren geht, dann verschiebt sich 
ja alles um 1 Byte. Ich habe leider keinen Portpin mehr frei um das im 
Handshake zu machen, daher wäre hier enie Software Prüfung besser. Wie 
macht man das in der Regel, sendet man 1 Character der signalisiert das 
nächste Byte ist MSB und einen anderen der signalisiert das nächste ist 
LSB?
Wie trage ich dafür sorge, dass alles an der richtigen Stelle im EEPROM 
gespeichert wird? Schickt man die Stelle irgendwie passend zur Variable 
mit (den Array zählt man sinnvollerweise durch hätte ich gesagt, aber 
wie macht man es bei den Konfig-Variablen, die teilweise nicht 
nacheinander im EEPROM liegen)?

Ich weiß, das sind jetzt vielleicht ein paar viele Fragen, aber 
vielleicht hat der ein oder andere ein bisschen Zeit hier Erfahrung zu 
teilen.

Danke.

von spontan (Gast)


Lesenswert?

Zahlen nach ASCII zu konvertieren ist Blödsinn, es sei denn, Du willst 
sie auf einem PC in einem terminal-Programm anschauen.

Übertrage das Array so wie es ist. Als Kontrolle kannst Du die Länge des 
Arrays mitübertragen, eine Checksum über alle Bytes anhängen, denk Dir 
einfach was sinnvolles aus.

Eine Steinzeitmethode wäre z.B. ein Byte zu senden, der µC muß es 
zurücksenden, danach wird erst das nächste Byte gesendet. Geht ist 
langsam, aber wenns Du Angst vor Datenverlusten hast (wieso eigentlich, 
wenn das Design gut ist?), dann wär das eine Methode, die beruhigt.

von Dietrich L. (dietrichl)


Lesenswert?

Hier mal zum Vergleich 2 Varianten:

1. ASCII-Kodierung
Vorteil: es lässt sich einfach ein relativ sicheres Protokoll 
realisieren, da Du eindeutige Steuerzeichen zur Verfügung hast (z.B. STX 
als Beginn usw.).
Nachteil: >= doppelte Länge des Datensatzes

2. Code-Transparent
Vorteil: kleine Datensatzlänge
Nachteil: ein Protokoll ist schwieriger zu realisieren. Erkennung von 
Beginn des Datensatzes oder Verlust von Daten muss z.B. durch Messung 
der Zeiten zwischen 2 UART-Zeichen erfolgen. Das bedeutet dann für den 
Sender: zwischen 2 Datensätzen ist immer eine Pause erforderlich, 
innerhalb des Datensatzes ist keine oder nur ein deutlich kleinere Pause 
erlaubt.

In beiden Fällen ist aber immer eine Time-Out-Erkennung nötig, um eine 
Unterbrechung des Datenstroms zu erkennen.

Weiter Datensicherungen sind dann nach Bedarf und Geschmack: Checksum 
gegen Bitverfälschungen, Quittung gegen Datenverlust ... Das hängt dann 
davon ab, wie störanfällig die Übertragung ist und welche Ansprüche an 
die Datensicherheit gestellt werden.
Problematisch ist in jedem Fall eine variable Datensatzlänge, da Fehler 
schwieriger zu erkennen sind. Sie sollte daher nach Möglichkeit 
vermieden werden.

Gruß Dietrich

von Jürgen S. (jurs)


Lesenswert?

Martin schrieb:
> Jetzt ist meine Frage, wie baue ich das Protokoll auf. Habe ich der
> Suche ebenfalls richtig entnommen, dass man eine 8-bit Zahl am besten in
> ein ASCII-Zeichen konvertiert, welche dann als 1 Zeichen gesendet werden
> kann und der µC das wieder rückkonvertiert zu einer Zahl und diese
> speichert?

Ja, am besten denkst Du Dir ein "Message" basiertes Protokoll aus, wobei 
diese Message in sich geprüft werden kann. Wenn Du beispielsweise ein 
Array  mit 200 Integer-Werten übertragen möchtest, könnte eine zu 
übertragende Message z.B. so aussehen:

Startbytes   - 2 Bytes (zwei beliebige Werte nach Deiner Wahl)
Messagelänge - 2 Bytes (die Anzahl der nachfolgenden Bytes als Integer)
Nutzbytes    - 400 Bytes (die 200 zu übertragenden Integer-Werte)
Prüfsumme    - z.B. 4 Bytes (die 200 Integer-Werte als Long-Integer 
aufsummiert)

Die Empfangsroutine lauert in Sendepausen nun immer darauf, ob die 
beiden Startbyte ankommen, und danach müssen in schneller Folge alle 
anderen Bytes eintreffen. Tritt ein Timeout auf, lauert der Empfänger 
einfach wieder auf die nächsten Startbyte nach einer Sendepause.

Programmlogik des Empfängers dann etwa so:
- Empfange erstes Startbyte
- Wenn erstes Startbyte OK, weitermachen, sonst zurück auf Anfang
- Empfange zweites Startbyte
- Wenn zweites Startbyte OK, weitermachen, sonst zurück auf Anfang
- Empfange Längenwert und fange an zu zählen bei 0
- Empfange Nutzbytes und zähle die Zahl der empfangenen Bytes mit
- Empfange Prüfsumme und zähle die Zahl der empfangenen Bytes mit
- Wenn alle Bytes entsprechend der Länge empfangen, prüfe die Prüfsumme
- Wenn Prüfsumme OK, dann Daten einwandfrei empfangen
- Wenn Prüfsumme nicht OK oder ein Timeout beim Empfangen auftrat ==> 
Daten verwerfen

Falls irgendwo beim Messageempfang ein Timeout auftritt: Zurück auf 
Anfang.

Du müßtest dann eben nur die beiden Startbytes festlegen, die Art wie 
die Prüfsumme (oder ein CRC-Wert) gebildet wird und wie lang der 
zeitliche Abstand zwischen zwei Bytes innerhalb eines Message-Blocks 
sein darf (Timeout-Zeit).

von Rene (Gast)


Lesenswert?


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.