mikrocontroller.net

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


Autor: Draco (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
   WTR_hex = 0xD5;
   
   for(i=0;i<8;i++)
   {
     SCL = 0;                                           
     if((WTR_hex >> i) & 1)  DIN = 1; else DIN = 0;     
     SCL = 1;                                          
   }

So funktioniert es aber:

   for(i=8;i>0;i--)
   {
     SCL = 0;                                            
     if((WTR_hex >> (i-1)) & 1)  DIN = 1; else DIN = 0;      
     SCL = 1;                                            
   }

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

  for(i=0;i<16;i++)
  {
     SCL = 1;  asm nop;
     if(DOT == 1) Word1 |= ((unsigned long)1 << i);
     SCL = 0;  asm nop;
  }


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

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

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Draco schrieb:
 for(i=8;i>0;i--)
    {
      SCL = 0;                                            
      if((WTR_hex >> (i-1)) & 1)  DIN = 1; else DIN = 0;      
      SCL = 1;                                            
    }

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.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 )
}

Autor: Draco (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ;)

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Draco (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :/

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Walter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dann schieb die bits doch einfach von der anderen Seite rein

Autor: Draco (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :/

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!)

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter schrieb:
> hast du den fehler mit den ; behoben.

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

Autor: David Madl (md2k7)
Datum:

Bewertung
0 lesenswert
nicht 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:
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

Autor: Draco (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

  unsigned short hb;
  unsigned short i;

  for(i=0;i<8;i++)
  {
     SCL = 1;  asm nop;                //CLK high 
     if(DOT == 1)                      //Wenn Pin High
     {
        hb |= (1 << i);                //Dann schiebt er nach links 
        UART1_Write_text("1");         //Über UART den Vergleichswert wenn 1
     } else {
        UART1_Write_text("0");         //Über UART den Vergleichswert wenn 0
     }
     SCL = 0;  asm nop;                //CLK low
  }
  
  UART1_Write(hb);                     //1Byte auf UART ausgeben zum Vergleich 


Ich probiere das man nach deinem Beispiel umzuschreiben:

  
  for(i=0;i<8;i++)
  {
     hb = hb >> 1;                     //Einmal rechts schieben
  
     SCL = 1;  asm nop;                //CLK high 
     if(DOT == 1)                      //Wenn Pin High
     {
        
        hb |= 0b10000000;               //Höchsten Bit setzen - 8Bit
        UART1_Write_text("1");         //Über UART den Vergleichswert wenn 1
     } else {
        UART1_Write_text("0");         //Über UART den Vergleichswert wenn 0
     }
     SCL = 0;  asm nop;                //CLK low
  }
  
  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

Autor: Draco (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.