Forum: Mikrocontroller und Digitale Elektronik UART Protokoll: Ich tue mir etwas schwer


von Thorben (Gast)


Lesenswert?

Hallo,

ich tue mir gerade etwas schwer mit meinem UART Protokoll.
Nach vielem Lesen von Beiträgen habe ich mich für mein erstes Protokoll 
für ASCII-Format Übertragung entschieden, da es sowieso nicht 
zeitkritisch ist und es  einfacher und lesbar ist. Ich denke für ein 
Anfänger sicherlich nicht verkehrt, da auch alle Steuerzeichen zur 
Verfügung stehen und nichts substituiert werden muss.

Mein Ziel ist es, vom PC aus Daten zu senden per RS232, die 8-bit und 
16-bit Werte sind (natürlich vorher gewandelt in strings). Der µC (AVR 
Atmega88) soll die Daten aufnehmen und ins EEPROM schreiben/speichern.
Implementiert habe ich die UARTlib von Peter Fleury mit FIFO Puffer.

Also Protokoll habe ich mir derzeit folgendes überlegt:
- µC Startet mit XON und gibt somit dem PC frei, dass er Daten senden 
kann.
- Kommandobit: Auch case Unterscheidung, je nach Case, soll der Wert 
einer bestimmten Variable zugeordnet werden, z.B. case(1) = Wert in 
fooByte1, case(2) Wert in fooWord1, case(3) Wert in fooByte2 usw.
- Daten
- PC setzt seinen Status auf XOFF wartet bis er wieder ein XON erhält 
vom µC erhält für den nächsten Datensatz
- µC holt die Daten aus dem Puffer und schreibt sie in das EEPROM. Wenn 
dies beendet ist, sendet er wieder XON

Woher weiß der µC aber, wann aber z.B. das Kommandobit feritg übertragen 
wurde und wann Daten kommen und wann Daten zu Ende sind?

Danke.

von Karl H. (kbuchegg)


Lesenswert?

Thorben schrieb:

> - µC Startet mit XON und gibt somit dem PC frei, dass er Daten senden
> kann.

Das ist eigentlich nicht Sinn der Sache bei XON/XOFF

Warum soll denn der PC nicht ständig senden dürfen? Du hast doch mit der 
Fleury LIb sowieso eine FIFO dazwischen, die in den kurzen Pausen, in 
denen dein µC was anderes macht, die Zeichen zwischenzeitlich aufnimmt.


> - Kommandobit:

Wieso Bit?

> Auch case Unterscheidung, je nach Case, soll der Wert
> einer bestimmten Variable zugeordnet werden, z.B. case(1) = Wert in
> fooByte1, case(2) Wert in fooWord1, case(3) Wert in fooByte2 usw.

Du denkst schon viel zu technisch.

> Woher weiß der µC aber, wann aber z.B. das Kommandobit feritg übertragen
> wurde und wann Daten kommen und wann Daten zu Ende sind?

Du bist nicht mehr mit Commandozeilen aufgewachsen, stimmts?
Da wusste jeder, dass man an der Command-Line ein Kommando eingibt und 
wenn man fertig ist, drückt man auf Return. Return ist ein Zeichen wie 
jedes andere auch. Aber es signalisiert dem empfangenden Programm: Jetzt 
ist meine Eingabe fertig - du kannst anfangen sie auszuwerten.

Der PC sendet zb den 'Text'
Timeout=129<Return>

Der µC sieht sich den Text an (nachdem er die Zeile komplett empfangen 
hat, was er am Erhalt des Return feststellt), zerlegt sie am '=' in 2 
Teile, dem 'Timeout' und dem '129'. Durch Textvergleich findet er raus, 
dass bei 'Timeout' eine bestimmte Variable gemeint ist und dass die 
einen neuen Wert bekommen soll. Also wird der 2.te Text, "129" erst mal 
in eine Zahl umgewandelt 129, und diese Zahl dann an die Variable 
zugewiesen.

Und wenn der PC die LED 5 einschalten will, dann schickt er vielleicht 
den Text
LEDON 5<Return>

etc. etc.
Denk dir was aus, wie die Texte aussehen sollen. Wenn der PC wissen 
will, ob LED 3 eingeschaltet ist oder nicht, dann schickt er vielleicht
? LEDON 3<Return>
Und der µC anwortet mit
ON<Return>
oder
OFF<Return>
oder
0<Return>
oder
1<Return>

oder wie auch immer. Da ist deine Phantasie gefragt.
Ein HP7475 Plotter wird zb so gesteuert
PU;
PA3000,2000;
PD;
PA1000,2000;PA1000,1000;PU;

hier ist also nicht <Return> der Trenner sondern ';'.
PU bedeutet 'Pen Up'
PD bedeutet 'Pen Down'
PA bedeutet 'Position Absolut' wobei 2 Zahlenangaben zu machen sind, 
nämlich die X und die Y Position, an die der Stift fahren soll.

von Thorben (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Warum soll denn der PC nicht ständig senden dürfen? Du hast doch mit der
> Fleury LIb sowieso eine FIFO dazwischen, die in den kurzen Pausen, in
> denen dein µC was anderes macht, die Zeichen zwischenzeitlich aufnimmt.

Weil ich in das EEPROM schreiben will und das 2-4ms in Anspruch nimmt. 
Um einen Array mit 200 Stellen und 16-bit (den ich unter anderem senden 
will) werten zu übertragen, bräuchte ich daher doch einen großen Puffer 
(der PC sendet sicherlich schneller). Um den Überlauf des Puffers zu 
verhindern, wollte ich diese Flusskontrolle integrieren.

Karl Heinz Buchegger schrieb:
> Du bist nicht mehr mit Commandozeilen aufgewachsen, stimmts?
Ja, das stimmt :-)

Das mit Return verstehe ich nicht ganz. Wenn ich doch Variablenwerte 
sende, z.b. ein uint8_t test = 123, dann bekomme ich doch die 
Zeichenfolge '1' '2' '3' '\0' vom UART. Meinst du mit Return die 
abschließende 0?

Wie sollte ich das nun am besten angehen?

von Walleby (Gast)


Lesenswert?

Hey Torben,

durch Return wird das Zeichen angehängt '\r'. Dann einfach das 
Empfangsregister immer nach diesem Zeichen mit if abfragen. Wenn TRUE 
dann weißt du wann er fertig ist.

von Karl H. (kbuchegg)


Lesenswert?

Thorben schrieb:
> Karl Heinz Buchegger schrieb:
>> Warum soll denn der PC nicht ständig senden dürfen? Du hast doch mit der
>> Fleury LIb sowieso eine FIFO dazwischen, die in den kurzen Pausen, in
>> denen dein µC was anderes macht, die Zeichen zwischenzeitlich aufnimmt.
>
> Weil ich in das EEPROM schreiben will und das 2-4ms in Anspruch nimmt.

Ja und?
Dann schickt eben der PC das Kommando weg und wartet auf Antwort vom µC. 
Der PC schickt
Timeout=129<Return>
und der µC muss das Kommando mit einem
OK<Return>
quittieren.
Und solange der PC das OK (oder ein NAK im Fehlerfall) nicht erhält, 
macht er nicht weiter.

von Peter II (Gast)


Lesenswert?

Thorben schrieb:
> dann bekomme ich doch die
> Zeichenfolge '1' '2' '3' '\0' vom UART.

woher soll denn die \0 kommen?

von Karl H. (kbuchegg)


Lesenswert?

Thorben schrieb:

> Um einen Array mit 200 Stellen und 16-bit (den ich unter anderem senden
> will) werten zu übertragen,

Kein Mensch sagt, dass du die 200 Werte in einem Rutsch übertragen 
musst.

> sende, z.b. ein uint8_t test = 123, dann bekomme ich doch die
> Zeichenfolge '1' '2' '3' '\0' vom UART.

Du bekommst kein \0 von der UART.
Woher soll denn die UART wissen, wann eine Übertragung fertig ist? Auch 
eine µC-UART kann nicht in die Zukunft schauen.

> Meinst du mit Return die
> abschließende 0?
\r oder \n

von Thorben (Gast)


Lesenswert?

Ok, soweit alles erst einmal verstanden für den Anfang.
Das quittieren macht natürlich sind.
Danke erstmal, ich versuche das mal so umzusetzen.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Thorben schrieb:
>
>> Um einen Array mit 200 Stellen und 16-bit (den ich unter anderem senden
>> will) werten zu übertragen,
>
> Kein Mensch sagt, dass du die 200 Werte in einem Rutsch übertragen
> musst.

Dann gibt es eben zum Beispiel einen 'Datenblock', der mehrere Werte 
umfassen kann. Zb maximal 16 Werte

Der PC schickt
BLOCK 1; 0, 129, 512, 867, 378, 93, 93, 23, 0, 0, 8, 125, 12, 18, 14, 
18<Return>

Der µC empfängt die Zeile holt sich die Blocknummer vor dem ; raus (hier 
Block 1), extrahiert die 16 Werte und schreibt sie ins EERPOM, wobei ihm 
die Blocknummer sagt, wo die Werte hinmüssen. Wenn er damit fertig ist, 
schickt er ein
OK<Return>
zum PC zurück, woraufhin der ihm den nächsten Block schickt.

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.