Guten Morgen,
hab folgendes Problem. Ich hab ein Array[] in das ich Hex Werte also
Bytes empfange. Es ist wie folgt definiert.
1
unsignedcharARRAY[248];//248bytes gross
In das Array bekomme ich, in die ersten zwei Bytes ein uint16_t mit der
Wertigkeit 11 bzw. als Hex "B" geschrieben und in die letzten zwei ein
uint16_t mit der Wertigkeit 47 welches 2F als Hex entspricht.
ich wuerde nun gerne diese beiden Werte aus dem Array extrahieren bzw.
deseriallsieren um zu vergleichen ob die Zahlen stimmen.... so als Check
ob die Inhalte des Bytes vollstaendig sind.
so irgendwie waere:
1
//Eine Art parsing funktion so z.b.
2
uint16_tStartID=ByteToUINT16(ARRAY,0)
3
uint16_tEndeID=ByteToUINT16(ARRAY,256)
4
5
//oder gibts ein weg das es so geht?
6
uint16_tStartID=ARRAY[0];
7
uint16_tEndeID=ARRAY[255];
In c# gabs eine tolle Funktion da konnte man direkt das gewuenschte aus
einem Array rausparsen, gibt es sowas fuer embedded c? Oder vielleicht
eine andere Moeglichkeit?
Spaeter muessen noch andere Werte aus dem ARRAY raus und zwar ein paar
int32[] Arrays etc.
1
typedefstruct
2
{
3
uint16_tPOSStartSign;// muss 11 sein bzw in hex B
4
uint16_tID;
5
uint16_tSchrauben;
6
7
int32_tPOS01[3];
8
int32_tPOS02[3];
9
int32_tPOS03[3];
10
int32_tPOS04[3];
11
int32_tPOS05[3];
12
int32_tPOS06[3];
13
int32_tPOS07[3];
14
int32_tPOS08[3];
15
int32_tPOS09[3];
16
int32_tPOS10[3];
17
int32_tPOS11[3];
18
int32_tPOS12[3];
19
int32_tPOS13[3];
20
int32_tPOS14[3];
21
int32_tPOS15[3];
22
int32_tPOS16[3];
23
int32_tPOS17[3];
24
int32_tPOS18[3];
25
int32_tPOS19[3];
26
int32_tPOS20[3];
27
uint16_tPOSEndSign;// hier muss 47 bzw hex 2F rein
28
29
}SCHR_POS;//TOTAL = 248byte
Ich hab dazu auch ein Strukt erstellt, in der Hoffnung, ich koennte
meine empfangenen Bytes direkt in meine Struktur reinladen.
Hat jemand eine Idee?
Vielen Dank!
Timo
Ich kenn das hier:
uint32 deserialize_uint32(unsigned char *buf)
{
uint32 *x = (uint32*)buf;
return *x;
}
unsigned char * deserialize_uint32B(unsigned char *buffer, uint32*
value)
{
*(uint32*)buffer = *value;
return buffer;
}
Ich weis nicht ob es der optimalse Weg ist und ich hab leider keine
Ahnung wie man das mit Arrays bewerkstelligt.
cya
Sven
PS.
jetzt gehts erstmal nach Malle ! :)
Hallo Timo,
wenn Du nichts gegen Pointer hast, dann leg doch noch einen Pointer vom
Typ SCH_POS an und initialisiere ihn mit der Adresse von ARRAY.
SCH_POS *pSchPos = &ARRAY;
Dann kannst Du mit z.B.
pSchPos-> POSStartSign
oder
pSchPos->POS01[0]
direkt auf die Werte zugreifen. Also quasi das 'ARRAY' für die Funktion
benutzen, die das Teil Byteweise befüllt und pSchPos für den Zugriff
auf die 2- bzw. 4-Byte großen Datenzugriffe.
Danke Michael,
das ist ja praktisch wenn ich das so wie du beschreibst machen kann.
Muesste ich dann nicht im Strukt alle Elemente auch noch als Pointer
schreiben? :
Timo schrieb:> *sharedPosData &RXBUFF;
Das muss so lauten:
sharedPosData = &RXBUFF;
Also vorne den Stern weg und dann noch das = für die Zuweisung rein.
Die Struktur muss übrigens so bleiben; also keine zusätzlichen Pointer
innerhalb der Struktur.
Der Grund: Deine "Füllfunktion" schreibt in die Struktur ja sicherlich
die blanken Daten rein und nicht die Adressen, wo die Daten dann zu
finden wären.
Was evtl. noch sein "könnte": Evtl. gibt es noch ein
Big-/Little-Endian-Problem.... Kommt drauf an, wie Deine Plattform 16
und 32 Byte Werte interpretiert...
Michael B. schrieb:> Was evtl. noch sein "könnte": Evtl. gibt es noch ein> Big-/Little-Endian-Problem.... Kommt drauf an, wie Deine Plattform 16> und 32 Byte Werte interpretiert...
Siehe hierzu auch: http://de.wikipedia.org/wiki/Byte-Reihenfolge
Viel Erfolg :-)
Hi Michael!
Danke für die Hilfe!
ja das big und little endian problem hatte ich. Ich hab das dann auf der
Hostmaschine (win pc) geändert um mir die arbeit am Pc zu sparen.
Viele Gruesse
Timo
Hi Michael,
der compiler sagt :
..\main.c(303): error: #513: a value of type "unsigned char (*)[248]"
cannot be assigned to an entity of type "SCREW_POS *"
Woran koennte das liegen?
Viele Gruesse
Timo
Kann es sein das du eher sowas machen musst?
Also die Variablen so initialisieren bzw beladen ?
sharedPosData->POSStartSign = (uint16_t)RXBUFF[0];
sharedPosData->ID = (uint16_t)RXBUFF[2];
sharedPosData->Schrauben = (uint16_t)RXBUFF[4];
..
.
.
Bringts was?
Funny hab das gleiche Problem wie Timo.
Ich arbeite ebenfalls gerade an einer deserializierung meiner daten die
ich als byte erhalte.
unsigned char Buffer[48]; da sind meine Daten drin.
Mein XMEGA schickt dem STM32F103 per UART serialisierte Daten, 12x
int16.
Ich will die jetzt ebenfalls aus dem byte array in meine int's parsen.
Aber wie?
Eine Struktur habe ich jetzt nicht erstellt, brauch ich auch nich.
MfG
Sven.
Hallo Timo,
das hier:
Timo schrieb:> ..\main.c(303): error: #513: a value of type "unsigned char (*)[248]"> cannot be assigned to an entity of type "SCREW_POS *"
bekommst Du mit einem cast weg:
sharedPosData = (SCREW_POS*)&RXBUFF;
Allerdings ist die struct etwas kritisch...
Es könnte sein, dass Dein Compiler das Teil etwas "optimiert", weil das
Teil 2 Byte, 2 Byte, 2 Byte, dann lauter 4 Byte Variablen hat und am
Ende wieder eine 2 Byte-Variable hat... Stichwort "struct Alignment"
Wenn Du eine Chance hast, Dir den Speicher anzuschauen, dann schau mal,
wie das erste POS01 aussieht...
Am einfachsten füllst Du das Array vielleicht einfach mal mit einer
einfachen for-Schleife wie z.B.
for (int i = 0; i < 248; i++)
{
RXBUFF[i] = i;
}
Dann sollte Dein POS01[0] den Wert 0x09080706 haben (bzw. 0x06070809 -->
Little-Big-Endian; vielleicht sagst Du auch einfach mal, welche
Plattform Du benutzt, dann ist es etwas einfacher :-))
Sollte POS01[0] allerdings sowas wie 0x0B0A0908 sein, dann hat Dir der
Compiler aus Performance-Gründen noch ein paar Bytes dazu geschustert,
damit die POSXX-Teile auf "besseren" Speicheradressen liegen...
Bei 32-Bit Maschinen wird sowas z.B. oft gemacht, wenn die entsprechende
Optimierung zuschlägt...
Es gibt auch irgendeine Möglichkeit, so ein umsoriteren auszuschalten,
aber da weiß ich gerade nicht, wie das geht...
Schau mal, ob das bei Dir überhaupt der Fall ist, dann kann ich mal
googlen...
Es handelt sich um einen STM32 .. ich glaub die haben big endian.
mit dem :
int32 mynumber1 = *((int32 *)&RXBUFFER[0]);
hab ich das Problem das einfach nur das erste byte in das int32 mynumber
kopiert wird nicht aber alle 4 bytes, weil ja das int32 auf 4 bytes
besteht.
... also doch keine lösung.
nehmen wir an
2F 00 AA BB ist RXBUFFER[0] bis [3]
unnd daraus müsste das int32 geparsed/convertiert werden.
Aber so eine Funktion gibts so nicht ... also ByteToInt32 oder
ByteToUInt32
Das Endian Problem kann ich aber auch mit meiner Funktion ArrayReverse()
beseitigen der macht mir dann aus einem big endian ein little endian.
Im momentan passt es mit der Endianness.
Ich will nur aus dem Byte-Stream mein int raus holen und dann das
nächste.. :(
Mist, in C# geht das so einfach!
O.k., für STM müsste vielleicht noch ein anderer helfen... Da kenne ich
den Compiler nicht... Aber der sollte sicherlich auch eine Möglichkeit
haben, das Alignmemt zu deaktivieren.
Aber wenn Du das mit dem cast nicht magst (was aber völlig o.k. und
üblich ist), dann kannst Du ja auch eine eigene Funktion dafür schreiben
(z.B. FillStruct()) und darin dann jede Variable einzeln mit Shifterei
füllen... Etwas viel Aufwand, wenn es doch sonst in einer Zeile geht,
aber durchaus möglich.... Oder Du schreibst zwei Funktionen für die
Konvertieretei (eine für int16, eine für int32) und gibst als Parameter
den Offset an. Den kannst Du ja auch als define anlegen und grob so
nennen, wie die entsprechende Variable im struct. Also z.B.
#define OFFSET_POSStartSign 0
...
#define OFFSET_POS01_0 6
#define OFFSET_POS01_1 10
...
Gibt viele Wege... Wo liegt den jetzt genau Dein Problem?
Hi Michael,
also ich probiere das gleich mal mit dem Cast in das Struct erneut.
Das wäre ja der optimalste Weg.
Ansonsten muss ich jede einzelene Variable durch das verschieben der
Bytes aus dem Array erzeugen. - Das wäre der zweite Weg , welchen du ja
jetzt auch beschrieben hast (mit den offset's etc.)
(Übrigens hier mal der Bitconverter den ich sonst am PC nutze ...
einfacher gehts nicht
http://msdn.microsoft.com/de-de/library/bb384066.aspx)
Übrigens ich benutze den Keil Compiler und soeben habe ich
herausgefunden, das man das byte alignment abschalten kann in dem man
scheinbar die optimierungsstufe von -3 auf 0 setzt. (gut zu wissen!)
Ich hab gerade noch was interessantes gefunden:
Michael es hat geklappt, in dem ich was geaendert habe !
1. unsinged char array zu einem uint8_t array
dann die funktion abgeandert
uint32_t* mynumber1 = (uint32_t *)&RXBUFFER[0];
uint32_t* mynumber2 = (uint32_t *)&RXBUFFER[4];
So gehts super! Ist aber halt BigEndian.
Ich schau mal ob es jetzt auch mit dem Strukt geht.