Forum: Mikrocontroller und Digitale Elektronik BMA020 Beschleunigungssensor über SPI auslesen


von Tobi W. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe folgenden Beschleunigungssensor: 
http://www.elv.de/output/controller.aspx?cid=74&detail=10&detail2=28515

Jetzt möchte ich die Beschleunigung in z-Richtung mit einem ATMega644 
über SPI auslesen.

MOSI <=> SDI
MISO <=> SDO
SCK <=> SCK
SS <=> CSB
VCC <=> UIN
VCC <=> UPullup
GND <=> GND


Dazu habe ich das SPI initialisiert;
1
DDR_SPI |= (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS);
2
SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA); // (1<<CPOL)|(1<<CPHA); BMA020 Datenblatt Seite 23


und in einer Endlosschleife sollen die höchsten 8 Bit der Beschleunigung 
in z-Richtung auf einem Display ausgegeben werden. Dazu muss Adresse 7 
ausgelesen werden (DB Seite 9 und 24)
1
while(1)
2
  {
3
    PORT_SPI &=~ (1<<DD_SS);      // Aktiviere Sensor
4
    
5
    SPI_MasterTransmit((1<<7)|(0x07));  // Adresse 7 ansprechen (lesen)
6
    SPI_MasterTransmit(0);        // Dummy Daten rüberschicken um Adresse 7 auszulesen
7
    
8
    
9
    itoa(SPDR,string,10);  // Gebe empfangenes Byte auf Display aus
10
    LCDSetCursorPos(0,0);
11
    LCDWrite(string);
12
    
13
    itoa(i++,string,10);  // Überprüfe ob while-Schleife durchlaufen wird
14
    LCDSetCursorPos(1,0);
15
    LCDWrite(string);
16
    
17
    
18
    PORT_SPI |= (1<<DD_SS);      // Deaktiviere Sensor
19
    
20
    wait_ms(10);
21
  }


Leider kommt immer wieder nur eine 0 an. Kann mir jemand helfen und 
sagen wo der Fehler ist? Danke.

von Tobi W. (Gast)


Lesenswert?

Das Problem schein unabhängig vom Sensor zu sein. Auch wenn ich einen 
ATMega8 als Slave benutze werden die Schleifen nicht weiter 
durchgezählt.


Laut SPI Spezifikation kann der Slave den Master ausbremsen, wenn der 
Slave mit dem Takt nicht hinterherkommt. Das wird wohl der Grund sein 
warum er in der 2. Schleife stehen bleibt (sowohl beim Sensor als auch 
bei Atmega als Slave).

Hier der Code für die Verbindung zum ATMega:
1
void SPI_MasterInit(void)
2
{
3
  /* Set MOSI and SCK output, all others input */
4
  DDR_SPI |= (1<<DD_MOSI)|(1<<DD_SCK);
5
  /* Enable SPI, Master, set clock rate fck/16 */
6
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
7
}
8
9
void SPI_MasterTransmit(char cData)
10
{
11
  /* Start transmission */
12
  SPDR = cData;
13
  /* Wait for transmission complete */
14
  while(!(SPSR & (1<<SPIF)))
15
    SPSR &=~ (1<<SPIF);
16
}
17
18
int main(void)
19
{
20
  char string[20];
21
  uint16_t i=0;
22
23
  LCDInit();
24
  SPI_MasterInit();
25
  DDRB |= (1<<DD_SS);  // SlaveSelect ist ein Ausgang
26
  
27
28
  while(1)
29
  {
30
    PORT_SPI &=~ (1<<DD_SS);  // Aktiviere Slave
31
    
32
    SPI_MasterTransmit(0);    // Sende Dummy Byte um Daten des Slave zu erhalten
33
    
34
    
35
    itoa(SPDR,string,10);    // Gebe Daten auf dem Display aus    
36
    LCDSetCursorPos(0,0);
37
    LCDWrite(string);
38
    
39
    
40
    itoa(i++,string,10);    // Zähle Schleifendurchläufe
41
    LCDSetCursorPos(1,0);
42
    LCDWrite(string);
43
    
44
    
45
    PORT_SPI |= (1<<DD_SS);      // Deaktiviere Sensor
46
    
47
  }
48
  return 0;
49
}


Slave:
1
void SPI_SlaveInit(void)
2
{
3
  /* Set MISO output, all others input */
4
  DDR_SPI = (1<<DD_MISO);
5
  /* Enable SPI */
6
  SPCR = (1<<SPE);
7
}
8
9
char SPI_SlaveReceive(void)
10
{
11
  /* Wait for reception complete */
12
  while(!(SPSR & (1<<SPIF)))
13
    SPSR&=~(1<<SPIF);
14
  /* Return Data Register */
15
  return SPDR;
16
}
17
int main(void) 
18
{  
19
  SPI_SlaveInit();
20
  while(1)
21
  {
22
    SPI_SlaveReceive();
23
    SPDR=20;
24
  }
25
  return 0;
26
}

von Werner B. (werner-b)


Lesenswert?

Das bekannte Kürzel: RTFM

It is not possible to read-out only MSB bytes if shadow_dis=0, an LSB 
byte must first be read out. To be able to read out only MSB byte, 
shadow_dis must be written to 1.

3.1.6 Shadow_dis

BMA020 provides the possibility to block the update of data MSB while 
LSB are read out. This avoids a potential mixing of LSB and MSB of 
successive conversion cycles. When this bit (address 15h, bit 3) is at 
1, the blocking procedure for MSB is not realized and MSB only reading 
is possible.

von Michael M. (koenig_deluxe)


Lesenswert?

Ich beschäftige mich momentan auch zwangsläufig mit dem BMA020. Verwende 
einen Atmega8, ausgelesen werden soll auch über SPI.

Bedeutet der letzte Beitrag also, dass der oben stehende Quellcode nicht 
funktioniert da shadow_dis nicht auf 1 gesetzt wird?

Hab den Quellcode nämlich in mein uC geladen auf dem STK500 und über 
Flachbandkabel den Sensor am PORTB angeschlossen. Ausgeben wollte ich 
die Daten direkt auf den LEDs des STK500. Und es hat sich nichts getan! 
Konnte noch überhaupt keine Daten auslesen. Werde also bei gelegenheit 
das shadow_dis Bit auf 1 setzen und es erneut probieren. Bin da aber 
eher pesimistisch. Bei erneutem Fehlversuch werd ich hier mal mein 
Quellcode reinstellen.

von Michael (Gast)


Lesenswert?

Hallo,
ich weiß das ist schon ein sehr altes Thema, aber habe ein ähnliches 
Problem, wollte fragen ob du evtl deinen Code einstellen könntest mit 
dem du das Auslesen geschafft hast.

Vielen Dank schon mal im voraus

Gruß Michael

von Johannes S. (killertomate)


Lesenswert?

Guten Abend,

ich möchte mich Michael bei der Bitte anschließen:
wenn jemand zur Ansteuerung des BMA020 über SPI Quellcode hat, der 
funktioniert, wäre ich sehr dankbar.

Das Problem bei mir ist, dass ich den Protokollablauf wohl nicht richtig 
verstehe, aber auch Angst habe, meinen Chip zu zerstören :(

Viele Grüße
Johannes

von PittyJ (Gast)


Lesenswert?

>>Das Problem bei mir ist, dass ich den Protokollablauf wohl nicht richtig
>>verstehe, aber auch Angst habe, meinen Chip zu zerstören :(

Das geht?
So rein mit dem SPI-Protokoll kann ich den Chip kaputt machen?

Wieder was gelernt.

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.