Hallo zusammen,
ich habe zwar einen ähnlichen Thread
Beitrag "UART Daten binär übertragen" zu meiner Frage
gefunden, möchte es aber trotzdem fragen.
Ich möchte ein uint16_t Array mit vorerst einem Messwert der eine
Auflösung von 10Bit hat an ein C#-Programm übertragen, womit ich über
die ReadByte-Funktion den Wert wieder in ein Array einfüge. Ich weiß,
dass der Wert aus dem Array byteweise durch die UART gesendet wird.
Muss ich das nun als String (wenn ja per sprintf?) oder reicht es, wenn
ich folgendes mache:
1
uint16_twert[]={gemessenerWert};
2
voidSendUART(charvar);
3
{
4
while(!(Senderegister(1<<Statusbit)));
5
udr=var;
6
}
7
intmain(void)
8
{
9
.
10
.
11
.
12
SendUART(wert);
13
.
14
.
15
.
16
}
Das ist für mich leider alles Neuland. Einfache 1 Bytevariablen habe ich
schon senden und empfangen können. Hierbei steh ich aber auf dem
Schlauch.
Gruß Matt-Eagle
Matthias P. schrieb:> Ich weiß,> dass der Wert aus dem Array byteweise durch die UART gesendet wird.
schon mal gut
> Muss ich das nun als String (wenn ja per sprintf?) oder reicht es, wenn> ich folgendes mache:
nein.
Du musst die 16bit (2byte) erst auf 2 einzelne Bytes aufteilen und diese
dann versenden.
1
uint8_tbyte1=wert>>8;
2
uint8_tbyte2=wert&0xFF;
beim empfangen muss die die 2 Bytes wieder zusammensetzen. Da du damit
aber ein Binäres Übertragung hast muss du dir auch noch Gedanken über
ein Protokoll machen. Woher weisst du wo das Array beginnt und endet?
Matthias P. schrieb:> Muss ich das nun als String
'Müssen' tust du gar nichts.
Wenn du den Zahlenwert in Form eines Textes übertragen möchtest, dann
kannst du das tun.
Willst du das nicht tun (weil du zuerst die Zahl in eine Textform
bringen musst um den Text zu senden, bzw. der Empfänger erst wieder aus
dem Text eine Zahl machen muss), dann kannst du das natürlich auch
lassen und den Binärwert so wie er ist übertragen.
> oder reicht es, wenn> ich folgendes mache:> void SendUART(char var);
Das hier sendet ganz offensichtlich nur 1 Byte. Ein 16-Bit Wert besteht
aber aus 2 Bytes.
Das ist wie wenn du eine Vertrag hast, der aus 2 Blatt beschriebenem
Papier besteht. Wenn du den Vertrag faxen willst, dann musst du eben 2
Blätter übertragen und nicht nur eines. 1 Faxsendung == 1 Blatt Papier.
Hast du mehrere Blätter, dann musst du halt auch mehrere Blätter durch
das Fax lassen. In diesem Sinne ist diese Send Funktion eine Funktion,
die genau 1 Blatt Papier überträgt. Hast du mehrere Blätter, dann musst
du die Funktion eben entsprechend öfter benutzen.
Hast du gar eine Mappe mit vielen Verträgen (ein Array), dann musst du
eben entsprechend oft die Funktion benutzen, die 1 Vertrag (in Form von
2 Blättern) überträgt.
Peter II schrieb:> beim empfangen muss die die 2 Bytes wieder zusammensetzen. Da du damit> aber ein Binäres Übertragung hast muss du dir auch noch Gedanken über> ein Protokoll machen. Woher weisst du wo das Array beginnt und endet?
Erstmal danke, ich kannte noch gar nicht diese Schreibweise um einen
16Bit-Wert aufzusplitten. Das Hilft schon mal ungemein.
Ich habe eine feste Arraygröße, von daher kann ich mit Schleifen
arbeiten. Außer diesem Array wird nichts übertragen, mein Gedanke wäre
noch ein zusätzliches Zeichen das vor der Übertragung gesendet wird und
dann eine FOR-Schleife in meinem C#-Programm auslöst, in der dann die
folgenden Daten in das Zielarray eingespeist werden.
Das muss ich mir aber noch durch den Kopf gehen lassen.
Matthias P. schrieb:> mein Gedanke wäre> noch ein zusätzliches Zeichen das vor der Übertragung gesendet wird
wenn du binär überträgst, wirst du keine zusätzliches Zeichen übrig
haben
Walter S. schrieb:> Matthias P. schrieb:>> mein Gedanke wäre>> noch ein zusätzliches Zeichen das vor der Übertragung gesendet wird>> wenn du binär überträgst, wirst du keine zusätzliches Zeichen übrig> haben
Meinte ein extra Byte z.B. den Hex-Wert von ASCII "!".
Tu dir selbst einen gefallen und übertrag in ASCII (kann ja auch Hex
sein). Spätestens wenn du mit einem Terminal-programm auf Fehlersuche
gehst, wirst du unendlich dankbar sein.
Matthias P. schrieb:>> wenn du binär überträgst, wirst du keine zusätzliches Zeichen übrig>> haben>> Meinte ein extra Byte z.B. den Hex-Wert von ASCII "!".
Ich vermute der Kommentar war so gemeint, dass du durch dein
zusätzliches Zeichen wie "!" nicht identifizieren kannst wo ein neuer
Datenblock beginnt, da ja durch die binären Daten auch dieses (und jedes
andere) Zeichen gesendet werden könnte. Also wird das Ganze eventuell
blöd zu syncronisieren wenn man dein C# Programm erst startet nachdem
dein µC schon Daten sendet.
Oder so?
for (int ix = 0; ix < sizeof(wert); ix++) {
// cast Startadresse des arrays zu dem gewünschten Typ*
// Verwende Zeigerarithmetik für die gewünschte Schrittweite
// und dereferenziere den resultierenden Zeiger
SendUART( *(((uchar*)&wert[0]) + ix) );
}
Schaut vielleicht hässlich bzw. kryptisch aus. Dafür ist aber kompakt
und recht gut portable.
Falls Du z.B. in einer anderen Applikation Byte nach DWord casten
willst, brauchst Du nur die 1 Zeile so ändern:
uint8_t wert[] ....
for (int ix = 0; ix < sizeof(wert) / 4; ix++) {
SendSPI( *(((u32*)&wert[0]) + ix) );
cfgardiner schrieb:> Dafür ist aber kompakt> und recht gut portable.
Portabel ist da leider nichts denn die Reihenfolge in der die Bytes dann
kommen ist je nach Prozessor anders
Die &wert[0] Geschichte kann man sich sparen weil Arrays sowieso zu
Pointern zerfallen. Und das *(ptr + ix) das Gleiche ist wie ptr[ix]
sollte jedem klar sein. Hängt dann aber trotzdem noch von der Byteorder
ab, weshalb ich die Bitshift Variante erstmal vorziehen würde.
Matthias P. schrieb:> Meinte ein extra Byte z.B. den Hex-Wert von ASCII "!".
Woher weiss der Empfänger, dass das nicht das 17 Byte von einem
Datenblock ist? Übliches Verfahren in solchen Fällen ist, ein
Sonderzeichen zu vereinbaren, dass im Datenblock dann nicht (alleine)
übertragen werden darf. Falls das Zeichen nun aber im Datenblock
vorhanden ist, wird das Sonderzeichen doppelt gesendet. Der Empfänger
kann dann zwischen Einzelsonderzeichen (Steuerfunktion) und
Doppelsonderzeichen (Dateninhalt) unterscheiden und schmeißt das
zusätzlich gesendete vorm Ablegen im Datenarray wieder raus.
Wolfgang schrieb:> Matthias P. schrieb:>> Meinte ein extra Byte z.B. den Hex-Wert von ASCII "!".>> Woher weiss der Empfänger, dass das nicht das 17 Byte von einem> Datenblock ist? Übliches Verfahren in solchen Fällen ist, ein> Sonderzeichen zu vereinbaren, dass im Datenblock dann nicht (alleine)> übertragen werden darf. Falls das Zeichen nun aber im Datenblock> vorhanden ist, wird das Sonderzeichen doppelt gesendet. Der Empfänger> kann dann zwischen Einzelsonderzeichen (Steuerfunktion) und> Doppelsonderzeichen (Dateninhalt) unterscheiden und schmeißt das> zusätzlich gesendete vorm Ablegen im Datenarray wieder raus.
Also es wird einen festgelegten Ablauf geben. Das Array das ich
versenden möchte wird auch das einzige sein, das überhaupt zu meiner
Applikation gesendet wird. Es wird eine feste Größe haben und meine
Applikation wird genau diese Menge einlesen und nicht mehr. Bisher hat
mir aber euer Lösungsansatz mit dem splitten des uint16 Werts geholfen.
Falls ich dennoch mit meiner eher einfachen Denkweise bei viel mehr
Werten auf Probleme stoße werde ich wohl doch nicht darum herumkommen,
doch ein Protokoll wie ihr es vorgeschlagen habt anzuwenden.
Ich danke aber auf jeden Fall für die Tipps und für die Hinweise
bezüglich des Protokolls(Falls es zutrifft einmal Kopfzerbrechen gespart
;)).
Ich gebe Rückmeldung ;)
Da die Daten im Array nur 10 bit haben, reichen 5 bit Daten pro Byte.
Dann bleibt wieder genug Luft für Framing, Steuerzeichen und was einem
sonst so einfällt.
Matthias P. schrieb:> Also es wird einen festgelegten Ablauf geben. Das Array das ich> versenden möchte wird auch das einzige sein, das überhaupt zu meiner> Applikation gesendet wird. Es wird eine feste Größe haben und meine> Applikation wird genau diese Menge einlesen und nicht mehr. Bisher hat> mir aber euer Lösungsansatz mit dem splitten des uint16 Werts geholfen.
Du hast wirklich NICHT nachgedacht.
Was ist, wenn irgendwo ein Zeichen verlorengeht oder irgend ein Krempel
davor hinzukommt? Datensalat natürlich.
Also denke dir ein Protokoll aus, wie es dir hier schon mehrfach
angeraten wurde. Nicht umsonst wird weltweit bei allen
Datenübertragungen ein ganz erheblicher Aufwand getrieben, um Daten
mittels geeigneter Protokolle verläßlich zu übertragen - so daß der
Empfänger sich aus den empfangenen Daten selbst synchronisieren und
obendrein auch noch die Daten auf Richtigkeit überprüfen kann.
Das ist alles reine Denkarbeit und hat mit dem Schreiben in irgend einer
Programmiersprache nix zu tun. Und ebensowenig hat es mit irgend einer
internen Darstellung a la uint16_t zu tun. In deinem Falle willst du
Zahlen übertragen und zwar ganze Zahlen im Bereich von 0 bis 1023. Also
benutze deinen Kopf zum Denken. Es ist ja gar nicht schwer.
W.S.