Hallo,
ich habe einen 24Bit wert den ich seriell senden möchte. Mit einer
For-Schleife gehe ich bit für Bit durch den uint32_t "code" (in dem die
24Bit liegen) durch. Allerdings scheint er nur mit 16Bit klar zu kommen.
Denn meine "Prüf-Variable" ist auf den ersten 16 bit immer 0xffff (und
das gesendete auch, dort natürlich nur 0xff)
for (cnt=0; cnt<rept; cnt++){ //how often to repeat the send cycle
17
rfm12_ask_trigger(1, synchi);
18
rfm12_ask_trigger(0, synclo);
19
for (bit=24; bit>0; bit--){ //24Bits to send send highest bit first
20
if ( (code & (uint32_t)(1<<(bit-1))) > 0 ){
21
if (test > 0){
22
rfm12_ask_trigger(1, onehi);
23
rfm12_ask_trigger(0, onelo);
24
ret|=(1<<(bit-1));
25
}
26
else{
27
rfm12_ask_trigger(1, zerohi);
28
rfm12_ask_trigger(0, zerolo);
29
}
30
}//cycle for
31
} //rept for
32
return(ret);
33
}
Eigentlich würde ich erwarten, dass ret = code ist am Ende (außer auf
den ersten 8 Bit, wo es 0 sein müsste).
Es ist aber 0xffff000000 | code. Also wenn code = 0x12345678 dann ist
ret 0xffff5678. Hat jemand eine Idee wo das Problem liegt?
Compiler ist avr-gcc 4.5.3 auf Ubuntu 12.04LTS.
Dirk H. schrieb:> if ( (code & (uint32_t)(1<<(bit-1))) > 0 ){
Auf welcher HW bist du unterwegs? Kleiner 32 Bit? dann schreib einmal
if ( (code & (uint32_t)((uint32_t)1<<(bit-1))) > 0 ){
^^^^^^^^^^
Oh,
die Hardware habe ich vergessen hinzuschreiben.
Es ist ein ATMega64, also ein 8-Bitter.
Der Cast steht tatsächlich an der falschen Stelle, er muss zur 1 vor dem
shift left. Der cast davor ist dann nicht mehr nötig.
Also genau wie PeterII gesagt hat.
Danke!!
Bei der Variante mit dem union/bit-fields sollte man schon sehr gut
wissen , was man tut.
Die Implementierung von Bitfields und union sind C Compiler
implementationsabhängig. d.h. Das reale Placement und Alignment können
je nach Compiler, Architektur (8/16/32/64? bit) und eingestellten
Optionen (wie packing, Optimierung) variieren.
In dem speziellen gezeigten Fall mag es funktionieren.
Adib.
Wenn der Compiler nicht meckert gehe ich davon aus, dass er das so
umsetzt, wie ich mir das gedacht habe.
Speziell bei union mit bit-fields oder überlaufender signed Variablen
ist das aber nicht im Standdard definiert, was da rauskommt. Dann hängt
das vom eingesetzten System ab. Also Vorsicht. Heisst jetzt nicht, dass
ich das niemals nie benutze. Man muss halt die Randbedingungen kennen.
Grüße, Adib.
Adib schrieb:> Wenn der Compiler nicht meckert gehe ich davon aus, dass er das so> umsetzt, wie ich mir das gedacht habe.
Du hast ja ein sonniges Gemüt..
Nee, beim GCC darf man getrost davon ausgehen, daß irgendein Teil
(Compiler, Assembler, Linker) keinen Versuch ungenutzt läßt, den
Programmierer gezielt anders zu verstehen als selbiger es sich gedacht
hat.
W.S.
W.S. schrieb:> Nee, beim GCC darf man getrost davon ausgehen, daß irgendein Teil> (Compiler, Assembler, Linker) keinen Versuch ungenutzt läßt, den> Programmierer gezielt anders zu verstehen als selbiger es sich gedacht> hat.
Er verläßt sich halt darauf, daß der Programmierer auch das
hingeschrieben hat, was er sich gedacht hat. Diese Eigenschaft von
Compilern nervt mich auch immer wieder. Der kann sich doch denken, was
ich eigentlich meine.
Rolf Magnus schrieb:> Er verläßt sich halt darauf, daß der Programmierer auch das> hingeschrieben hat,...
Oh ja. Kenne ich.
Unsereiner schreibt
.thumb
und anschließend Assembler eben in thumb und GCC assembliert das auch
ordentlich. Aber die dort enthaltenen Labels werden als ARM labels und
nicht als THUMB labels zum Linker exportiert, der daraufhin zwischen
thumb und thumb nen Interworkingcode setzt -> Absturz.
Sowas war, ist (und wird sein) ein faustdicker Bug, der obendrein den
Leuten von Stallman seit Jahren bekannt ist. Aber anstatt selbigen zu
beheben, haben sie nen zusätzlichen Qualifier (.thumblabel oder so
ähnlich) als Workaround kreiert.
So, du Schlaumeier, meinst du, daß man als logisch denkender
Programmierer wissen muß, daß der GCC bei korrekt vereinbartem und auch
richtig vorhandenem thumb code noch lange nicht daran denkt, daß
selbiger auch dem Linker als thumb bekanntgegeben werden sollte? he?
Beispiel aus dem Handwerk: "Meister, mit den Fenstern streichen bin ich
jetzt fertig. Soll ich nun auch die Rahmen streichen?"
W.S.
Dirk H. schrieb:> Es ist ein ATMega64, also ein 8-Bitter.
Generell solltest du dir am AVR Sachen wie " 1<<(bit-1) " (also Shifts
um eine Variable Bitanzahl) genau überlegen.
Das kann der AVR nämlich nicht in einem Schritt berechnen, deshalb mach
der Compiler aus diesem unscheinbaren Codeschnipsel eine "for (int i =0;
i<bit-1; ++i)" -Schleife.
Bei deinem Code gibt das dann den (Am Oszi lustig anzusehenden) Effekt,
dass die ersten Bits auf der Leitung "kürzer" sind als die späteren.
W.S. schrieb:> Nee, beim GCC darf man getrost davon ausgehen, daß
Compiler, Linker und Assembler die geltenden C-Spezifikation umsetzen
(so gut es eben geht). Alles, was ausserhalb er Sprachdefinition an
prozessorspezifischen Sonderanforderungen rumgeistert, ist, nun ja,
irrelevant, und erfordert dann auch schon mal workarounds.
Wie bei allen open-source-Projekten hilft dagegen kein rummaulen,
sondern nur anpacken und selber ändern.
In diesem Sinne
Oliver
Oliver schrieb:> Wie bei allen open-source-Projekten hilft dagegen kein rummaulen,> sondern nur anpacken und selber ändern.
O ja. Hab ich gemacht, das Kind mit dem Bade ausgeschüttet und den Keil
angeschafft. Fertig.
W.S.