Forum: Mikrocontroller und Digitale Elektronik [c] Bitmuster verdreht?!


von Draco (Gast)


Lesenswert?

Hiho,

habe da ein kleines Problem. Wenn ich mir eine Schleife baue und mit 
einer mit einer Hex gefütterten Variable etwas an einen Sensor schicken 
mag, dann ist das Bitmuster verkehrt, ich muß die Variable quasi von 
hinten auslesen, aber wie?!

- MicroC
- Atmega16

So sollte es gehen - tut es aber nicht:
1
   WTR_hex = 0xD5;
2
   
3
   for(i=0;i<8;i++)
4
   {
5
     SCL = 0;                                           
6
     if((WTR_hex >> i) & 1)  DIN = 1; else DIN = 0;     
7
     SCL = 1;                                          
8
   }

So funktioniert es aber:
1
   for(i=8;i>0;i--)
2
   {
3
     SCL = 0;                                            
4
     if((WTR_hex >> (i-1)) & 1)  DIN = 1; else DIN = 0;      
5
     SCL = 1;                                            
6
   }

Nun kann ich ihn ja problemlos so beschreiben, ist umständlich aber 
funktionert, jedoch ist nun mein Problem: Wierum lese ich nun meine 
Daten aus diesem Sensor wieder richtigrum ein damit ich damit rechnen 
kann?!
1
  for(i=0;i<16;i++)
2
  {
3
     SCL = 1;  asm nop;
4
     if(DOT == 1) Word1 |= ((unsigned long)1 << i);
5
     SCL = 0;  asm nop;
6
  }

oder so:
1
  for(i=16;i>0;i--)
2
  {
3
     SCL = 1;  asm nop;
4
     if(DOT == 1) Word1 |= ((unsigned long)1 << (i-1));
5
     SCL = 0;  asm nop;
6
  }

Da es sich dort um 16Bit kalibrationsdaten handelt kann ich nicht genau 
sagen in welchen Bereich diese liegen müssen?!

von Peter (Gast)


Lesenswert?

Draco schrieb:
1
 for(i=8;i>0;i--)
2
    {
3
      SCL = 0;                                            
4
      if((WTR_hex >> (i-1)) & 1)  DIN = 1; else DIN = 0;      
5
      SCL = 1;                                            
6
    }

also das ergibt schon mal überhaupt kein sinn. Das ; vor dem ist 
garantiert flasch.

im Welchen Prozessor geht es überhaupt, bei den Atmels ist das schieben 
wo die weite in einer Variable steht nicht sehr sinnvoll. Auch ein nop 
fürs timing verwenden ist nicht die feine art.

von Peter (Gast)


Lesenswert?

Nachtrag:

oh der Prozessor stand ja da, also ist es nicht sehr sinnvoll so zu 
schieben.


warum nicht so in der art

unsigned long x = 0;
for ( .... ) {
  x = x << 1
  x |= (DOT & 1 )
}

von Draco (Gast)


Lesenswert?

Peter schrieb:
> also das ergibt schon mal überhaupt kein sinn. Das ; vor dem ist
> garantiert flasch.

Vor welchem was?

Peter schrieb:
> im Welchen Prozessor geht es überhaupt,

Steht im ersten Post: Ein Atmega16

Peter schrieb:
> bei den Atmels ist das schieben
> wo die weite in einer Variable steht nicht sehr sinnvoll.

Wie kann ich sonst an meine HEX Werte kommen? Bin da für jeden Tipp 
dankbar!

Peter schrieb:
> Auch ein nop
> fürs timing verwenden ist nicht die feine art.

Nuja, ist ein nop... da es sich nicht um eine extreeeemst Zeitintensive 
Aplikation handelt, kann ich dem 16er ruhig mal ein taktzyklus wegnehmen 
um den PinState etwas luft zu geben ;)

von Peter (Gast)


Lesenswert?

Draco schrieb:
>> also das ergibt schon mal überhaupt kein sinn. Das ; vor dem ist
>> garantiert flasch.
> Vor welchem was?
oh, es ist scheinbar schon spät

DIN = 1; else DIN = 0;

das ; ist bestimmt falsch.

von Draco (Gast)


Lesenswert?

Peter schrieb:
> warum nicht so in der art
>
> unsigned long x = 0;
> for ( .... ) {
>   x = x << 1
>   x |= (DOT & 1 )
> }

Danke, werd ich mal näher beschauen, da wird jedenfalls immer nur 1 bit 
geschoben....

Dennoch bleibt das Problem mit den verdrehten Bitmustern :/

von Peter (Gast)


Lesenswert?

Draco schrieb:
> Dennoch bleibt das Problem mit den verdrehten Bitmustern :/

dann schiebe halt in die andere richtung >>

es muss doch im datenblatt stehen in welcher reihenfolge die bits bei 
dir ankommen, die reihenfolge vom Atmel steht auch im Datenblatt. Damit 
sollte es genau 1 Möglichkeit geben wie es richtig ist.

von Walter (Gast)


Lesenswert?

dann schieb die bits doch einfach von der anderen Seite rein

von Draco (Gast)


Lesenswert?

Na die Reihenfolge der Bits des Sensor sind ja klar. Mir geht es nur um 
die

So einfach mit "von der anderen Seite Schieben" bekomme ich leider nicht 
hin :/ Ich habe mir das hier durchgelesen: 
http://www.mikrocontroller.net/articles/Bitmanipulation

Jedoch finde ich nichts womit ich die Daten von rechts schieben kann. x 
|= (1 << i) funktioniert irgendwie nicht.

Wenn mir der Sensor folgendes Vorgibt:

0110 1101 0111 1010 = 0x6D7A

und ich von links schiebe kommt das bei raus:

0101 1110 1011 0110 = 0x5EB6

Aber ich bekomme das mit rechts schieben nicht hin :/

von Peter (Gast)


Lesenswert?

Draco schrieb:
> Jedoch finde ich nichts womit ich die Daten von rechts schieben kann. x
> |= (1 << i) funktioniert irgendwie nicht.

es gibt doch nur 2 Möglichkeiten

nach rechts:

var = var >> 1
jetzt noch das höchste bit setzen (bei 16bit) var |= 0b100000000000000

oder nach links

var = var << 1
jetzt das kleinste bit setzen     var |= 1;

> Wenn mir der Sensor folgendes Vorgibt:
> 0110 1101 0111 1010 = 0x6D7A
> und ich von links schiebe kommt das bei raus:
> 0101 1110 1011 0110 = 0x5EB6
dann muss irgendwo ein fehler in den code sein, hast du den fehler mit 
den ; behoben.
Zeige doch noch mal den code der nicht geht (vollständig!)

von Stefan E. (sternst)


Lesenswert?

Peter schrieb:
> hast du den fehler mit den ; behoben.

Da ist kein solcher Fehler. Das Semikolon vor dem "else" ist völlig 
korrekt.

von David M. (md2k7)


Lesenswert?

Mit deiner als 2. geschriebenen Lesevariante müsste es doch gehen...

Ansonsten (ist aber funktional gleich, wie deine Lösungen), für die CPU 
Befehls-sparsamer - dafür weniger lesbar:
1
uint16_t i;
2
3
for(i = 1; i != 0; i <<= 1)
4
  // schiebe i immer um 1 bit weiter, von (1 << 0) bis (1 << 15)

bzw. für die andere Richtung
1
uint16_t i;
2
3
for(i = (uint16_t) 0x8000; i != 0; i >>= 1)
4
  // schiebe i immer um 1 bit weiter, von (1 << 15) bis (1 << 0)

IMHO wäre etwas mehr Info zu deinem Sensor angebracht, da dein Code 
stimmen dürfte. Könnte ja auch was mit Timing oder SPI-Polarität zu tun 
haben.

Gruß
David

von Draco (Gast)


Lesenswert?

1
  unsigned short hb;
2
  unsigned short i;
3
4
  for(i=0;i<8;i++)
5
  {
6
     SCL = 1;  asm nop;                //CLK high 
7
     if(DOT == 1)                      //Wenn Pin High
8
     {
9
        hb |= (1 << i);                //Dann schiebt er nach links 
10
        UART1_Write_text("1");         //Über UART den Vergleichswert wenn 1
11
     } else {
12
        UART1_Write_text("0");         //Über UART den Vergleichswert wenn 0
13
     }
14
     SCL = 0;  asm nop;                //CLK low
15
  }
16
  
17
  UART1_Write(hb);                     //1Byte auf UART ausgeben zum Vergleich

Ich probiere das man nach deinem Beispiel umzuschreiben:
1
  
2
  for(i=0;i<8;i++)
3
  {
4
     hb = hb >> 1;                     //Einmal rechts schieben
5
  
6
     SCL = 1;  asm nop;                //CLK high 
7
     if(DOT == 1)                      //Wenn Pin High
8
     {
9
        
10
        hb |= 0b10000000;               //Höchsten Bit setzen - 8Bit
11
        UART1_Write_text("1");         //Über UART den Vergleichswert wenn 1
12
     } else {
13
        UART1_Write_text("0");         //Über UART den Vergleichswert wenn 0
14
     }
15
     SCL = 0;  asm nop;                //CLK low
16
  }
17
  
18
  UART1_Write(hb);                     //1Byte auf UART ausgeben zum Vergleich

Dort bringt er mir ebenfalls alles verdreht... zum Verrücktwerden ist 
das :D

1101 1100 - via direkten Pin lesen.
0011 1101 - Via geschriebenen Bit in hb

von Draco (Gast)


Lesenswert?

David Madl schrieb:
> Mit deiner als 2. geschriebenen Lesevariante müsste es doch gehen...
>
> Ansonsten (ist aber funktional gleich, wie deine Lösungen), für die CPU
> Befehls-sparsamer - dafür weniger lesbar:
> uint16_t i;
>
> for(i = 1; i != 0; i <<= 1)
>   // schiebe i immer um 1 bit weiter, von (1 << 0) bis (1 << 15)
>
> bzw. für die andere Richtung
> uint16_t i;
>
> for(i = (uint16_t) 0x8000; i != 0; i >>= 1)
>   // schiebe i immer um 1 bit weiter, von (1 << 15) bis (1 << 0)
>
> IMHO wäre etwas mehr Info zu deinem Sensor angebracht, da dein Code
> stimmen dürfte. Könnte ja auch was mit Timing oder SPI-Polarität zu tun
> haben.
>
> Gruß
> David

Ja wie gesagt, geht ja auch, nur war ich wirklich nicht sicher ob die 
Bits nun stimmten so rum oder so rum :D

Es handelt sich um einen MS5534C Baro Sensor. Dieser übermittelt mir 4x 
16Bit als Calibrationsdaten - diese muß ich dann mit den ausgelesenen 
Daten für Druck/Temp verrechnen. Es handelt sich dabei um ein 4-Wire 
Interface (MCL, SCL, DIN, DOUT)

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.