Hallo.
Ich lese über SPI eine Bytefolge ein, die in etwa so aussieht:
Byte 1: 0bZZZZXXXX (ZZZZ = Event, XXXX X-touch-point (11:8))
Byte 2: 0bXXXXXXXX (X-touch-point (7:0))
Byte 3: 0bWWWWYYYY (WWWW = ID, YYYY Y-touch-point (11:8))
Byte 4: 0bYYYYYYYY (Y-touch-point (7:0))
Super wär es, direkt auf die Daten (Event, X, ID und Y) zugreifen zu
können.
Folgende Datenstruktur hätte ich anfangs gedacht:
1
// data type for touch point
2
typedefunion
3
{
4
struct__attribute__((packed))
5
{
6
WORDevent:4;
7
WORDxcor:12;
8
WORDid:4;
9
WORDycor:12;
10
};
11
BYTEraw[4];
12
}EP0430M06_TouchPoint;
Das geht aber nicht, da sich die Bits "falsch verteilen".
Auch wenn ich die Felder vertausche sind die Daten falsch:
1
// data type for touch point
2
typedefunion
3
{
4
struct__attribute__((packed))
5
{
6
WORDxcor:12;
7
WORDevent:4;
8
WORDycor:12;
9
WORDid:4;
10
};
11
BYTEraw[4];
12
}EP0430M06_TouchPoint;
Kann man das irgendiwe in dieser Form lösen oder muss ich mir die Daten
nach dem Einlesen aufbereiten?
lg
WRNR schrieb:> Das geht aber nicht, da sich die Bits "falsch verteilen".
Probiere das doch einfach auf dem Trockenen mit Testdaten aus, dann
kannst Du auch sehen, wo genau das Problem liegt.
Als Testdaten bietet sich die Bytefolge 0x12 0x34 0x56 0x78 an.
Wenn Deine Union korrekt funktioniert, müsste ja folgende Zuordnung
herauskommen:
event = 0x1
xkor = 0x234
id = 0x5
ycor = 0x678
Also: Sieh Dir an, was rauskommt, wenn Du definierte Daten reinsteckst.
Hab ich gerade getestet (2. Variante):
Raw-Daten: 0x12 0x34 0x56 0x78
Ergebnis:
Event = 0x03
X = 0x0412
ID = 0x07
Y = 0x856
Irgendwie ergibt das für mich noch keinen Sinn.
Binär sieht das dann so aus:
0001 0010 | 0011 0100 | 0101 0110 | 0111 1000
x(7:0) | EV ,x(11:8) | y(7:0) | ID , y(11:8)
Habe noch keine Idee wie ich das lösen kann...
WRNR schrieb:> Hab ich gerade getestet (2. Variante):>> Raw-Daten: 0x12 0x34 0x56 0x78>> Ergebnis:> Event = 0x03> X = 0x0412> ID = 0x07> Y = 0x856>> Irgendwie ergibt das für mich noch keinen Sinn.
mach mal aus dem WORD ein BYTE
Da hat dich der Byte-Sex gebissen.
Die Reihenfolge der Bytes in einem Word ist nicht definiert und bei dir
offensichtlich anders als das wovon du ausgehst.
Karl Heinz Buchegger schrieb:> mach mal aus dem WORD ein BYTE>> Da hat dich der Byte-Sex gebissen
Geht nicht, da X und Y 12 bit sind.
Erste Variante:
Event = 0x02
X = 0x0341
ID = 0x06
Y = 0x785
WRNR schrieb:> Karl Heinz Buchegger schrieb:>> mach mal aus dem WORD ein BYTE>>>> Da hat dich der Byte-Sex gebissen>> Geht nicht, da X und Y 12 bit sind.
Yep. Habs auch schon gemerkt
Dann musst du das in deinen Zuweisungen zum Byte Array berücksichtigen
und entsprechend "gegensteuern"
raw[1] = 0x12
raw[0] = 0x34
raw[3] = 0x56
raw[2] = 0x78
Aber:
Ist das wirklich so ein Problem sich eine Funktion zu schreiben, die das
Bitschieben erledigt? Um das Geschiebe kommst du sowieso nicht rum. Ob
du das jetzt ausprogrammierst, oder ob es der Compiler macht ist für den
µC einerlei. Die Arbeit hat er auf jeden Fall
Nochmal genauer hingesehen:
> Hab ich gerade getestet (2. Variante):>> Raw-Daten: 0x12 0x34 0x56 0x78>> Ergebnis:> Event = 0x03> X = 0x0412> ID = 0x07> Y = 0x856
Du musst also, bevor Du Deine union befüllst, die Bytes tauschen, das
erste mit dem zweiten und das dritte mit dem vierten:
Raw-Daten: 0x12 0x34 0x56 0x78
Nach Tausch: 0x34 0x12 0x78 0x58
Und Dein Ergebnis sollte
Event = 0x1
X = 0x0234
Id = 0x5
Y = 0x0678
sein.
OK.
Der PIC32 ist Little Endian. Daran habe ich natürlich überhaupt nicht
gedacht. Bei Big Endian hätte ich bei Variante 2 kein problem gehabt und
ich wär ohne Aufbereitung davon gekommen.
Danke für den Tipp mit der Byteorder.
Vielen Dank für die flotten Antworten
Da du zwischen Byte 1 und Byte 2 eine Trennung hast, müsste auch das
funktionieren
1
typedefunion
2
{
3
struct__attribute__((packed))
4
{
5
WORDevent:4;
6
WORDxcor:12;
7
WORDid:4;
8
WORDycor:12;
9
};
10
WORDraw[2];
11
}EP0430M06_TouchPoint;
12
13
14
raw[0]=Byte[0]<<8|Byte[1];
15
raw[1]=Byte[2]<<8|Byte[3];
dann löst der Compiler die Byteorder richtig auf. Das 8 Bit Geschiebe
bzw. die Verorderung sollte ein guter Compiler eigentlich wegoptimieren
und auf Direktzugriffe umändern.
Die Anordnung der Bits in einem Bitfeld ist im C-Standard überhaupt
nicht definiert. Man kann es sicher irgendwie hinfrickeln, dass es mit
dem verwendeten Compiler zusammen klappt, aber portabel ist das nicht.
Ich würde die Werte lieber von Hand per Bitschieben und Ausmaskieren
zusammenbauen. Das funktioniert immer und ist bei einem guten Compiler
auch nicht langsamer. Eventuell ist es sogar schneller, wenn man nicht
vorher die Bytereihenfolge in einem Extra-Schritt tauschen muss.
Fabian O. schrieb:> Die Anordnung der Bits in einem Bitfeld ist im C-Standard überhaupt> nicht definiert.
Die Reihenfolge der Bits ist schon definiert.
Was nicht definiert ist ist, wie sich die Bytes eines Word im Speicher
abbilden.
> Man kann es sicher irgendwie hinfrickeln, dass es mit> dem verwendeten Compiler zusammen klappt, aber portabel ist das nicht.
Das stimmt.
Und genau genommen ist auch der Zugriff in eine Union über 2
verschiedene Member nicht erlaubt. Der Standard sagt, dass man nur dann
definierte Ergebnisse bekommt, wenn man über denselben Member liest,
über den man auch geschrieben hat. Allerdings ist die Sache so, dass es
sich hier um sowas wie die 'normative Kraft des Faktischen' handelt.
Soll heißen, dass selbst die Leute die den C Standard machen, diese
Technik akzeptieren (und in diversen Newsgroups auch propagierten). Sie
können das nicht in den Standard schreiben, weil sie dann eine Byteorder
vorschreiben müssten, was sie nicht tun wollen. Aber die Union Technik
funktioniert seit Anbeginn der C Zeit und es ist kein Compiler bekannt
auf dem sie nicht (mit Ausnahme der Byte-Order) funktionieren würde.
Karl Heinz Buchegger schrieb:> Die Reihenfolge der Bits ist schon definiert.
Der C99-Standard sagt dazu:
An implementation may allocate any addressable storage unit large enough
to hold a bitfield. If enough space remains, a bit-field that
immediately follows another bit-field in a structure shall be packed
into adjacent bits of the same unit. If insufficient space remains,
whether a bit-field that does not fit is put into the next unit or
overlaps adjacent units is implementation-defined. The order of
allocation of bit-fields within a unit (high-order to low-order or
low-order to high-order) is implementation-defined. The alignment of the
addressable storage unit is unspecified.
(§ 6.7.2.1 Abs. 10)
Und dann ist auch noch nicht mal garantiert, dass das mit dem Typ WORD
(schätzungsweise ein Typedef für unsigned short?) überhaupt
funktioniert:
A bit-field shall have a type that is a qualified or unqualified version
of _Bool, signed int, unsigned int, or some other implementation-defined
type.
(§ 6.7.2.1 Abs. 4)
Also alles sehr wacklig. Das einzige, worauf man sich gemäß Standard
wirklich verlassen kann, ist, dass man eine reingeschriebenes Element
wieder über den gleichen Namen auslesen kann. Im Prinzip wie bei der
Union ...
Fabian O. schrieb:> Karl Heinz Buchegger schrieb:>> Die Reihenfolge der Bits ist schon definiert.>> Der C99-Standard sagt dazu:
Vielen Dank für deine Mühe.
Das hatte ich dann wohl komplett falsch in Erinnerung.