Hallo zusammen! Ich bin erst kürzlich von Bascom auf Atmel Studio umgestiegen und mein hirninterner Bitschieber ist schwer eingerostet... Ich lese Daten von einem MPU 6050 über i2c. Der MPU stellt je Ache und Funktion die Rohdaten in einem hi und einem lo Register je 7 bit zur Verfügung. Mein Problem ist es die jeweils 7 bit Rohdaten der Register an die richtige Stelle der 8bit Variable zu schieben und beide 8 bits dann zu einem 16bit zusammenzufassen.Data_L und Data_H sind bei mir als int8_t deklariert.So sieht das momentan bei mir aus: i2c_start_wait(MPU6050_ADDRESS); i2c_write(MPU6050_RA_ACCEL_XOUT_L); i2c_stop(); i2c_rep_start(MPU6050_ADDRESS | 1); Data_L = i2c_readAck() << 8; Data_L = Data_L | i2c_readNak(); i2c_stop(); i2c_start_wait(MPU6050_ADDRESS); i2c_write(MPU6050_RA_ACCEL_XOUT_H); i2c_stop(); i2c_rep_start(MPU6050_ADDRESS | 1); Data_H = i2c_readAck() << 8; Data_H = Data_H | i2c_readNak(); i2c_stop(); int16_t accel_x = (Data_H << 8) + Data_L; Das letzte Mal das ich bits hin und hergeschoben hab war mein Rechner noch ein 80286 mit Bernsteinmonitor.... Vielen Dank für Eure Hilfe!
Olaf Breuer schrieb: > Data_L = i2c_readAck() << 8; Ob das geschiebe richtig und notwendig ist,erschließt sich mir aus dem gezeigten Code nicht, aber das hier: > int16_t accel_x = (Data_H << 8) + Data_L; sieht so verkehrt nicht aus. Du solltest aber noch nach 16bit casten. >int16_t accel_x = ((int16_t)Data_H << 8) + Data_L;
beim bitschieben sind int8_t ungeschickt verwende besser uint8_t und co. dann macht der compiler weniger blödsinn, wenn du in den überlauf reinshiftest
Vielen Dank für die Antworten! Das casten habe ich eingefügt. Die Werte aus dem zusammengefügten Registern sollte eine Zahl zwischen -32786 und +32786 zeigen. Wenn ich mir die Data_L und Data_H ausgeben lasse, dann sehe ich dort bei beiden Registern teilweise Vorzeichen. Momentan scheint das noch nicht richtig zu laufen. Ich bekomme aufeinanderfolgend zum Beispiel folgendes: Data_L: 81Data_H: 84accel_x: 21585...Data_L: -90Data_H: -100accel_x: -25690 Der 6050 rauscht zwar ordentlich, aber das ist grad a bisserl viel... Wenn ich mit unsigned arbeite, wie gelange ich dann am Ende wieder zu meinem Vorzeichen?
Olaf Breuer schrieb: > int16_t accel_x = (Data_H << 8) + Data_L; hier wird sicher das ergebnis falsch sein. Mein vorschlag: Caste Data_H auf int16_t und Data_L auf uint8_t
also so?: int16_t accel_x = ((int16_t)Data_H << 8) + (int8_t)Data_L; meine Ergebnisse: Data_L: 1Data_H: 104accel_x: 26625 Data_L: 1Data_H: 44accel_x: 11265 Data_L: 1Data_H: -120accel_x: -30719 Data_L: 1Data_H: 0accel_x: 1 Data_L: 1Data_H: -84accel_x: -21503 Data_L: 1Data_H: -108accel_x: -27647 Data_L: 1Data_H: -48accel_x: -12287 Data_L: 1Data_H: -80accel_x: -20479 Der Sensor ist fest auf meinem Tisch fixiert bei den Messungen...
Hmmm die Ergebnisse des bitschiebens und zusammenführung sahen eigentlich ganz ok aus. Aber die Werte der hi und lowbits änderten sich, als wären hi und lo vertauscht. Tatsächlich sind die Adressen des MPU6050 genau anders herum als beim mpu9150 (der 9150 sollte einen 6050 enthalten) Jetzt funkts einwandfrei. Ich bekomme stabile Werte die im gewünschten Bereich liegen. DANKE FÜR EURE HILFE! Gruss aus Portugal Olaf.
Little Basdart schrieb: > Olaf Breuer schrieb: >> int16_t accel_x = (Data_H << 8) + Data_L; > > hier wird sicher das ergebnis falsch sein. > Mein vorschlag: > Caste Data_H auf int16_t und Data_L auf uint8_t Wird das nicht automatisch vorher nach int promotet?
Könnt Ihr mir bitte kurz erklären was casten und was promoten bedeutet? Es soll ja nicht nur funktionieren, ich muss es auch begreifen... Danke Olaf.
Olaf Breuer schrieb: > Könnt Ihr mir bitte kurz erklären was casten und was promoten bedeutet? > Es soll ja nicht nur funktionieren, ich muss es auch begreifen... > Danke In dem Post von "Little Basdart" wurde vermutet daß beim Schieben eines 8-Bit-Wertes um 8 Bit nach links alle Bits links herausgeschoben würden und somit nur noch 0 stehenbleibt. Das wäre in der Tat der Fall wenn man annehmen würde daß die Schiebeoperation direkt auf die 8-Bit-Variable Data_H angewendet würde. Dem ist aber nicht so. "Little Basdart" schlug aufgrund dieser Befürchtung vor sie zuvor manuell nach uint16 zu casten um auf Nummer Sicher zu gehen und auf jeden Fall das Schieben mit einer 16-Bit breiten Variable durchzuführen die breit genug wäre damit links nichts herausrutschen kann. Aber das macht der Compiler bereits automatisch weil vor solchen Operationen alles was kleiner als int ist ertmal auf int (oder unsigned int, je nachdem) verbreitert (promoted) wird wird und dann erst die Operation durchgeführt wird. Nur wenn der Compiler beweisen kann dass eh nichts rausgerutscht wäre oder das Ergebnis in jedem möglichen Falle identisch wäre dann kann der Compiler das auch bleiben lassen (optimieren), also wenn Du zum Beispiel ein uint8_t um ein paar bit nach links schiebst und gleich wieder in ein uint8_t speicherst dann muss er sich nicht die Mühe machen das vorher auf 16 bit zu verbreitern (ungünstig und teuer auf ner 8-bit CPU) nur um es hinterher sofort wieder abzuschneiden, sowas würde dann im Zuge der Optimierung komplett auf 8 bit belassen. Im oben besprochenen Falle würde ich vom Compiler erwarten daß er vor dem left-shift auf jeden Fall ein unsigned int draus macht, also muss man es nicht explizit selbst machen.
Wow, vielen Dank für die Mühe, die Du Dir gemacht hast.Jetzt bin wieder ein Stückchen weitergekommen. Wo wären wir ohne Foren und LEuten die sich die Mühe machen zu helfen und Wissen weiterzugeben?? Gruss Olaf.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.