Forum: Mikrocontroller und Digitale Elektronik "Befehle" über USART senden


von Roman F. (Gast)


Lesenswert?

Hallo,

bevor ich mit meinen bescheidenen Software-Kenntnissen versuche 
irgendwas zusammen zu wurschteln frage ich lieber einmal nach wie es die 
"Profis" machen würden.

Und zwar möchte ich mit dem PC über USART auf meine Schaltung zugreifen 
können (das funktioniert auch prinzipiell schon) und gewisse Variablen 
lesen und schreiben können.

Folgende Operationen möchte ich dazu durchführen können:

LADE 16Bit Variable X
SCHREIBE 16Bit Variable X
LADE 64Byte Array X
SCHREIBE 64Byte Array X


Mein Problem ist nun wie ich den Befehlssatz am schlausten codieren 
soll. Ich kann ja schlecht 64Byte als ASCII-Zeichen 
empfangen/versenden... aber wenn ich die Werte einfach binär verschicke 
kann ich Anfang und Ende eines Befehls nicht erkennen(?).

Ich wollte die ganzen Befehle µC-Seitig erstmal per RX-Interrupt in 
einen Ringbuffer speichern und dann im Hauptprogramm auswerten. Ist das 
überhaupt Sinnvoll?


Wie würdet ihr das lösen?


Vielen Dank!

Gruß,
Roman

von Peter II (Gast)


Lesenswert?

Roman F. schrieb:
> Ich kann ja schlecht 64Byte als ASCII-Zeichen
> empfangen/versenden...

und warum nicht?

von Roman F. (Gast)


Lesenswert?

Peter II schrieb:
> Roman F. schrieb:
>> Ich kann ja schlecht 64Byte als ASCII-Zeichen
>> empfangen/versenden...
>
> und warum nicht?

Wenn ich mich nicht irre müsste ich ja dann 192Bytes senden... ich 
dachte mir das würde die ganze Sache nur "verkomplizieren", da ich die 
ganzen Werte dann jeweils noch von ASCII in die wirklichen Werte 
umwandeln müsste.

von Peter II (Gast)


Lesenswert?

Roman F. schrieb:
> Wenn ich mich nicht irre müsste ich ja dann 192Bytes senden... ich
> dachte mir das würde die ganze Sache nur "verkomplizieren", da ich die
> ganzen Werte dann jeweils noch von ASCII in die wirklichen Werte
> umwandeln müsste.

aber dafür ist das "Protokoll" einfacher. Wenn du genug ram und zeit 
dafür hast dann mach es als ASCII. Binary ist zwar effizienter aber auch 
schwer umzusetzen.

von Thomas E. (thomase)


Lesenswert?

Roman F. schrieb:
> Wenn ich mich nicht irre müsste ich ja dann 192Bytes senden
Du irrst. Aus einem Binärbyte werden 2 ASCII-Zeichen.

Roman F. schrieb:
> ich
> dachte mir das würde die ganze Sache nur "verkomplizieren", da ich die
> ganzen Werte dann jeweils noch von ASCII in die wirklichen Werte
> umwandeln müsste.
Wahnsinnig kompliziert.
1
unsigned char AsciiToByte(char nH, char nL)
2
{
3
  if(nH > 0x40) nH += 9;
4
  if(nL > 0x40) nL += 9;
5
  return (nH << 4) + (nL & 0x0F);
6
}

mfg.

von icke (Gast)


Lesenswert?

Wenn du 64Byte übertragen willst, musst du 64 Byte übertragen!
Wie du auf 194Byte kommst weiß ich nicht...

Du kannst in deiner Empfangsroutine (im uC) abhängig von dem empfangenem 
Byte deine Variablen verschicken.

Dein PC Programm muss dann nur die empfangenen Bytes in Abhängigkeit von 
der versendeten Nachricht interpretieren.

von icke (Gast)


Lesenswert?

ah ok.
Verstehe das mit den 192Byte...
Das ist aber nicht sehr effizient. Lieber direkt binär übertragen und 
deinen (schnellen) Pc die "Arbeit" übernehemen lassen.

von Roman F. (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Du irrst. Aus einem Binärbyte werden 2 ASCII-Zeichen.

Thomas Eckmann schrieb:
> unsigned char AsciiToByte(char nH, char nL)
> {
>   if(nH > 0x40) nH += 9;
>   if(nL > 0x40) nL += 9;
>   return (nH << 4) + (nL & 0x0F);
> }

Das ist natürlich tricky! Da wäre ich niemals drauf gekommen...



Effizienter erscheint es mir aber trotzdem die Werte direkt in Binärform 
zu übertragen.

Was haltet ihr von der Möglichkeit zuerst eine Art Header zu verschicken 
der z.B. lautet:

"SAVE_ARRAY NAME;"<<Byte1<<Byte2<<...<<Byte64


Beziehungsweise im umgedrehten Fall:

"LOAD_ARRAY NAME;"

der Controller antwortet dann z.B. mit:

Byte1<<Byte2<<...<<Byte64


Das Array ist immer 64Byte groß, man könnte also mit dem µC den String 
bis zum Semikolin auswerten und wüsste, dass danach die 64 Datenbyte 
kommen die abgespeichert werden sollen.

Ich bin mir nur unsicher ob das so überhaupt praktikabel und 
betriebssicher ist oder ob da irgendwelche fiesen Übertragungsfehler 
passieren könnten?


Danke und Gruß,
Roman

von Marcus P. (marc2100)


Lesenswert?

Hi,
das kannst du so machen, für den Fall von einem Übertragungsfehler 
kannst du ja zusätzlich alle 64 Datenbytes zusammen zählen (als uint8_t) 
und das Ergebnis als 65. Byte hinterher schicken, dann kannst du im uC 
prüfen ob da was nicht stimmt. Der uC könnte auch seine errechnete 
Prüfsumme zurück schicken, damit du auch auf PC-Seite weist ob es 
geklappt hat oder nicht.

Zusätlich solltest du dir auch um einen Timeout gedanken machen, nach 
dem der uC die bis dahin empfangenen Zeichen verwirft, falls kein 
Semikolon eingetroffen ist.
Und du musst natürlich den Buffer groß genug machen, den stell dir z.B. 
vor der "Header" wird nicht erkannt (z.B. durch Übertragenungsfehler), 
anschließend werden die 64 Bytes gespeichert, und erst dann kommt der 
nächste "Header"...

Gruß
Marcus

von Martin S. (der_nachbauer)


Lesenswert?

So richtig verstehe ich dein Problem nicht, mag an der Uhrzeit liegen.

Ich an Deiner Stelle würde mir ein einfaches Binärprotokoll definieren:
Byte 0: Kommando, in Deinem Fall z.B 0x1 für schreiben 16bit, 0x2 
schreiben 64 Byte, 0x10 lesen 16bit und 0x11 für lesen 64 Byte ...
Nur im Schreibfall über trägst Du nach dem Kommando weitere Daten, im 
Lesefall war test Du halt direkt auf die Antwort.

Die Sache mit dem Erkennen des Befehls läuft dann über die state 
machine, die Dein Protokoll auswertet - es beginnt also immer mit dem 
Befehlsbyte, was danach passiert hängt vom Befehl ab.

Wirklich "erkennen" müsstest Du den Befehl nur in solchen Protokollen, 
in denen variable Feldgrössen übertragen werden, was aber in dem von Dir 
geschilderten Fall nicht vorkommt.
[FYI: Wenn Du variable Feldgrössen über tragen - z.B. nicht alle 64 
Bytes senden oder lesen willst, ergänzt Du halt das Kommando um die 
Feldgrösse: auf 0x2 0x20 lässt Du dann nur 32 Bytes folgen - wiederum 
sorgt die Implementierung der state machine für die korrekte 
Abarbeitung.]

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.