Forum: Compiler & IDEs uint32_t bit für bit interpretieren - wahrscheinlich typ problem


von Dirk H. (dirk_h)


Lesenswert?

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)
1
uint32_t 
2
rfm12_ask_bat_sl_send(uint32_t code, uint8_t rept)
3
{
4
  const uint16_t synchi = 380;
5
  const uint16_t synclo = 2260;
6
  const uint16_t onehi = 1163;
7
  const uint16_t onelo = 350;
8
  const uint16_t zerohi = 350;
9
  const uint16_t zerolo = 1163;
10
11
  uint8_t cnt=0;
12
  uint32_t bit=0;
13
  uint32_t ret=0;
14
  uint32_t test;
15
16
  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.

von Peter II (Gast)


Lesenswert?

(uint32_t)(1<<(bit-1)

der cast ist falsch.

((uint32_t)1<<(bit-1)

oder

1ul<<(bit-1)

von Augen offen (Gast)


Lesenswert?

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 ){
                        ^^^^^^^^^^

von Dirk H. (dirk_h)


Lesenswert?

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!!

von holger (Gast)


Lesenswert?

>  uint32_t test;

> if (test > 0){

Die Abfrage kannst du dir sparen weil test einen völlig
undefinierten Wert hat.

von W.S. (Gast)


Lesenswert?

Dirk H. schrieb:
> for (bit=24; bit>0; bit--){  //24Bits to send send highest bit first
>      if ( (code & (uint32_t)(1<<(bit-1))) > 0 ){

Wozu bloß diese Verrenkung?

Meine Version:
long mask;

 mask = 1<<24; //oder wer es unbedingt braucht: mask = 1UL<<24;
 while (mask)
 { if (code & mask) { blabla }
   mask = mask>>1;
 }

Schönen Abend noch.
W.S. (bei nem argentinischen Cabernet Sauvignon, schon  halbleer..)

von Bidiot (Gast)


Lesenswert?

1
  struct _32BIT {
2
  uint32_t  bit0 : 1;
3
  uint32_t  bit1 : 1;
4
  uint32_t  bit2 : 1;
5
...
6
  uint32_t  bit30 : 1;
7
  uint32_t  bit31: 1;
8
};
9
10
union UINT32_TO_BIT {
11
  uint32_t u32;
12
  struct _32BIT bit32;
13
};
14
15
union UINT32_TO_BIT foo32;
16
17
foo32.u32 = 1234567;
18
foo32.bit32.bit30 = foo32.bit32.bit1;

von Adib (Gast)


Lesenswert?

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.

von Bidiot (Gast)


Lesenswert?

Adib schrieb:
>  sollte man schon sehr
> gut
> wissen , was man tut.

Sollte man das nicht immer?

von Adib (Gast)


Lesenswert?

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.

von W.S. (Gast)


Lesenswert?

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.

von Rolf Magnus (Gast)


Lesenswert?

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.

von W.S. (Gast)


Lesenswert?

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.

von Markus (Gast)


Lesenswert?

Der Wein wirkt ja schon... Nett, nett...

von Εrnst B. (ernst)


Lesenswert?

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.

von Oliver (Gast)


Lesenswert?

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

von W.S. (Gast)


Lesenswert?

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.

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.