Forum: Mikrocontroller und Digitale Elektronik SPI Mode 3 und Beschleunigungssensor


von Marian (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

ich habe mal wieder ein Problem :).
Ich möchte mit einem Atmega32 einen Beschleunigungssensor(SMB360) von
Bosch "auslesen". Das soll per SPI geschehen. In dem Datenblatt des
Sensors steht, das er den SPI Mode 3 nutzt und um einen Wert
vollständig zu übertragen werden 2 "Cycles" benötigt, da der Wert
insgesamt 10 bit groß ist (und 8 werden ja nur auf einmal übertragen).
Jetzt habe ich versucht, mit meinem Atmega diesen Sensor auszulesen
aber leider klappt das nicht. Ich habe laut Manual des Atmega32 das SPI
konfiguriert(also auf Mode 3 gesetzt usw.) und nun kommt mein Problem:
Wie sage ich in C, das er nun die Übertragung starten soll und mir dann
aus den 2 Bytes meinen richtigen Wert zusammenschreibt. Ich habe mal
meinen Code(Mit Fragen und der Problemstellung) angehängt aber da fehlt
noch ne ganze Menge und ich weiß nach langem Suchen nicht mehr weiter.
Kann mir einer von euch helfen?
Falls ihr noch Informationen benötigt um mir helfen zu wollen und zu
können, sagt es bitte.

Danke schonmal im Voraus!

von Wolfram (Gast)


Lesenswert?

unsigned char SPI_Transmit(unsigned char cData)
{
  /* Starte Übertragung*/
  SPDR = cData;
  /* Warte bis Übertragung beendet*/
  while(!(SPSR & (1<<SPIF)));
return(SPDR);
}

SPI schreibt und liest gleichzeitig!
Erst Befehl Schreiben
SPI_Transmit(.. )
dann weiter FF schreiben und gleichzeitig Wert(2 Byte einlesen)
tmp1=SPI_Transmit(0xFF);
tmp2=SPI_Transmit(0xFF);

von Marian (Gast)


Lesenswert?

Danke für deine Antwort!

Leider hat sie mir nicht wirklich weiter geholfen...so wie du es gesagt
hast, habe ich es auch schon probiert. Aber es klappt irgendwie nicht.
Ich müsste eigentlich jeweils einen Wert für jede gemessene Achse
bekomen(also 3 das 3-achsiger beschleunigungsmesser). Komischerweise
bekomme ich für jeden Zyklus einen Wert aber die Werte können nicht
stimmen, da sie immer konstant sind auch wenn ich den BeSe bewege. Ich
habe das jetzt so geschrieben für 3 Werte:
        SPI_Transmit('x');
  Highbyte=SPI_Transmit(0xFF);
  Lowbyte=SPI_Transmit(0xFF);
  acclx = ((Highbyte & 0x7F) << 3) | (Lowbyte & 0x07);
  SPI_Transmit('y');
  Highbyte=SPI_Transmit(0xFF);
  Lowbyte=SPI_Transmit(0xFF);
  accly = ((Highbyte & 0x7F) << 3) | (Lowbyte & 0x07);
  SPI_Transmit('z');
  Highbyte=SPI_Transmit(0xFF);
  Lowbyte=SPI_Transmit(0xFF);
  acclz = ((Highbyte & 0x7F) << 3) | (Lowbyte & 0x07);
  printf("x%i y%i z%i \n\r",acclx,accly,acclz);
Habe ich dich denn überhaupt richtig verstanden? Also ich meine, kann
ich das so machen? Wie ist das eigentlich mit dem SPI Mode 3? Muss man
da nicht den SS irgendwie auf Low ziehen während der Kommunikation? Und
bestimmt mein µC den Takt selbst, also wann steigende Flanke und wann
die fallende kommt? Und wieso muss ich vor dem abrufen der High und
Lowbytes eigentlich vorher nochmal eine einzelne SPI_transmit Funktion
ausführen? Ich finde diese angeblich "simple" SPI ganz schön
verwirrend...

Gruß Marian

von Marian (Gast)


Lesenswert?

Kann es sein das ich mir selbst Werte per SPI schicke? Ich habe jetzt
mal anstatt FF ein 55 und ein AA gesendet und nun bekomme ich auch
andere Werte ausgegeben. Ich verstehe das nicht!

von Christoph (Gast)


Lesenswert?

Hallo,
kannst du jetzt Daten von deinem BeSe empfangen?
Wenn ja, wie hast du das hinbekommen?

gruß
christoph

von Marian (Gast)


Lesenswert?

Hallo Christoph,

ja mittlerweile bekomme ich Daten von dem BeSe aber leider sind sie
sehr komisch. Nach dem umrechnen der 2er Komplementdarstellung in meine
dezimale Darstellung, bekomme ich sehr seltsame Werte. Wenn er ruhig auf
dem Tisch liegt, dann habe ich diese Werte ca.: X -130 Y 30 Z -140

Hast du es denn mittlerweile auch hinbekommen?

Wenn nicht kann ich dir gerne helfen.

Gruß,

Marian

von Christoph (Gast)


Lesenswert?

Leider nicht,

wenn ich die Bits (für 10g Range, Normal mode) setzen will, bleibt mein
programm schon hängen. wie hast du das denn gemacht.
Und das auslesen klapp auch nicht. hast du da eventuell ein beispiel
für mich?

Schon mal vielen dank.

Christoph

von Christoph (Gast)


Lesenswert?

hallo,
die bits setzen hat funktioniert. nur wie hast du die daten ausgelesen?

von Christoph (Gast)


Lesenswert?

kannst du mir weiterhelfen? ich verzweifel völlig. wie hast denn die
lese routine geschrieben? ich bekomme das nicht hin. hab so was acu
noch nie gemacht.
schon mal vielen dank für deine Hilfe!

von Marian (Gast)


Lesenswert?

Die Daten auszulesen ist ganz einfach.
Ich schreibe dir mal den Weg auf wie ich es gemacht habe!(Kein exakter
C-Syntax)
Das ist meine Leseroutine:
uint8_t spi_read_register(uint8_t adress1, uint8_t adress2)
{
 //Hier musst du dein SS auf 0 legen um die Kommunikation zu starten
 spi_putc(adress1)     //In adress1 muss die Adresse stehen um das MSB

 data1=spi_putc(0xFF); //auszulesen + das Readbit(also 0x9A für MSB der

 spi_putc(adress2);    //x_achse). Dann schickst du ein Dummy byte und

 data2=spi_putc(0xFF); //bekommst den X-Werte geliefert
                       //Dann das gleiche nochmal für die 3 LSB(0x9B
//schicken und danach Dummy Byte um den Wert zu bekommen
 //als letztes SS wieder auf High ziehen um den Lesevorgang zu beenden
}

So das machst du jetzt 3 mal(mit den entsprechenden Adresse+ das
Readbit) und schon hast du die Werte.

Alles klar?

Gruß,

Marian

von Christoph (Gast)


Angehängte Dateien:

Lesenswert?

hallo,
danke schon mal. habe isch das so richtig verstanden?

von Marian (Gast)


Lesenswert?

Fast :).

Du musst dir ja die Werte, die du von den Adressen geliefert bekommst,
noch in die Variablen speichern. Im Moment gibt deine Funktion ja nur
das data1(MSB) zurück aber du verwendest diese ja in der Main nicht.
Mache besser aus data1 und data2 globale Variablen und füge sie dann
sofort zu dem Beschleunigungswert zusammen. Wie das geht weißt du
hoffentlich. Also ich meine das so:
spi_lese ((0x9A),(0x9B));
Highbyte=data1;
Lowbyte=data2;
Das machst du für alle 3 Achsen jeweils einmal.

OK?

Gruß,
Marian

von Christoph (Gast)


Angehängte Dateien:

Lesenswert?

Ich verstehe das irgend wie nicht. Wie füge ich denn das MSB und das LSB
zusammen? ich möchte den Wert dann im eeprom speichern, da ich kein
display habe. ich habe die datei mal angehängt!

[Ist das ein scheiß,wenn man keine Ahnung hat, aber es machen muss.
;-)]

von Rahul (Gast)


Lesenswert?

Deine Funktionen sollten ein int und kein Char zurückliefern.
Sprich:
int spi_lese(char adr1, char adr2)
{
 int result;
 // Adresse schreiben und Daten empfangen...
 result = ((int) adr1<<8); // keine Gewähr, ob das wirklich so
funktioniert...
 return (result | adr2);
}

von Christoph (Gast)


Angehängte Dateien:

Lesenswert?

hallo nochmal,

die nervensäge ist wieder da. ich hab maal das programm angehängt. ich
bekomme immer nur eine 0 gespeichert. egal wie ich es mache. vielleicht
habe ich ja schon vorher was falsch gemacht.
vielen dank für eure bemühungen mir zu helfen!

gruß
christoph

von Rahul (Gast)


Lesenswert?

Du kannst immer nur ein "return" angeben.
Vielleicht solltest du dir mal die C-Bibel (Kernighan und Ritchie
"Programmieren in C") antun.
Dir fehlen nämlich eine Menge C-Grundlagen. Da wird es dir auch kaum
helfen, dauernd vorzubringenden, dass du dich um dieses Problem
kümmmern musst.
Um die Lösung Probleme anderer wirst du im Leben nicht herumkommen.
Ich spreche da aus Erfahrung...

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.