Forum: Compiler & IDEs Verständnisprobleme Datenblatt BMA020 und SPI


von Christian T. (johannf)


Lesenswert?

Schönen guten Abend.

Ich habe mir einen 3 Achsigen Beschleunigungssensor von ELV zugelegt und 
wollte ihn an meinem ATMega644P zum laufen bekommen.
Jetzt hab ich jedoch das Problem das ich nicht weiss, wie ich das 
Datenblatt dieses Sensors deuten soll, da ich noch nicht wirklich fit 
mit dem SPI Protokoll bin.
Ich hab mir Grundsätzlich ein Software SPI gebaut das zur Zeit so 
Aussieht:

void soft_spi_init(void)
{
  //Glob SPI Pins
  SPI_DDR|=(1<<SDI)|(1<<SCK);
  //BMA SPI Pins
  SPI_DDR|=(1<<CS_BMA);
  SPI_PORT|=(1<<CS_BMA);      //BMA CS high inactive
}
unsigned short BMA_com(unsigned short wert)
{  unsigned char i;

  cbi(BMA_PORT, CS_BMA);
  for (i=0; i<16; i++)
  {  if (wert&0x8000)
      sbi(BMA_PORT, SDI);
    else
      cbi(BMA_PORT, SDI);
    wert<<=1;
    if (BMA_PIN&(1<<SDO))
      wert|=1;
    sbi(BMA_PORT, SCK);
    asm("nop");
    asm("nop");
    cbi(BMA_PORT, SCK);
  }
  sbi(BMA_PORT, CS_BMA);
  return wert;
}

void BMA_getdata(char *data)
{
   for (int i=0; i<3; i++)
  {
  cbi(BMA_PORT, SDI);
  cbi(BMA_PORT, CS);
  asm("nop");
  while (!(BMA_PIN&(1<<SDO)))
    *data++=BMA_com(0xB000);
  }
}

Aufgerufen zur Zeit in der main:
void BMA_read(void)
{
  char BMA_STR[3];
  BMA_getdata(BMA_STR);
  lcd_setcursor( 0, 1 );
  lcd_string(BMA_STR);
}
Das Datenblatt des Sensors ist zu finden auf:
http://www.mikrocontroller.net/attachment/51241/BMA020_DataSheet_1.1_080114.pdf

Natürlich läuft diese Routine nicht wirklich da ich dem Sensor keinerlei 
Daten schicke. Das ist leider auch schon mein Problem. Über SPI hab ich 
doch keine Adressen usw oder? Ich Aktiviere den Chip über CS low. Wie 
kann ich jetzt die in der Tabelle (S.9) genannten Register ansprechen 
wie zb 0x07h für acc_z?
Oder muss ich da Grundsätzlich anders ran gehen?

Ach ja, den Interrupt Pin vom Sensor hab ich zur Zeit offen hängen. 
Eigentlich sollte doch der SDO unabhängig vom Interrupt pin Arbeiten 
oder seh ich das falsch?

Ich wäre für jede Hilfe dankbar!
Mit freundlichen Grüßen
Johann

von STK500-Besitzer (Gast)


Lesenswert?

sbi und cbi sind völlig überholt.

Johann Forsch schrieb:
> Ich Aktiviere den Chip über CS low.
Damit startest du die Koomunikation.
>Wie kann ich jetzt die in der Tabelle (S.9) genannten Register ansprechen
> wie zb 0x07h für acc_z?

Hast du schon auf Seite 23 des Datenbalttes einen Blick geworfen?
In Punkt 4.1 ist der Ablauf beschrieben.

von Christian T. (johannf)


Lesenswert?

Hallo STK500-Besitzer.
Danke erstmal für die schnelle Antwort.
Das mit cbi und sbi hab ich in ner header definiert aber werds demnächst 
mal in meinem kompletten programm ändern.
Aber zur seite 23!
Genau da liegt mein Problem:

void BMA_getdata(unsigned char *data)
{

   for (int i=0; i<1; i++)
  {
  cbi(BMA_PORT, SDI);
  cbi(BMA_PORT, CS_BMA);
  asm("nop");
  while (!(BMA_PIN&(1<<SDO))){}
    *data++=BMA_com(0x8200);
  }

}
0x82 entspricht soviel wie 0b10000001
Also: Lesen als RW=1 und das Register 01h = acc_x al/ml
Leider hänge ich schon in der Schleife mit dem SDO fest.
Das müsste der sensor mir den doch auf masse ziehen wenn er bereit ist 
oder?
Auskommentiert kommt grad ma garnix in meinen data string.

von Christian T. (johannf)


Lesenswert?

Kann mir sonst keiner nen Tip dazu geben?
Ich bin hier schon am Verzweifeln.

von makefile (Gast)


Lesenswert?

> Das mit cbi und sbi hab ich in ner header definiert aber werds demnächst
> mal in meinem kompletten programm ändern.

Das brauchst du nicht, dafür sind Macros da.

sbi(port, bit) und cbi(port, bit) sind 'syntactic sugar' für
1
(port) |= (1 << (bit))
2
(port) &= ~(1 << (bit))

Wenn dir dieser Syntax besser gefällt, kannst du ihn ruhig benutzen.
Du hast keine Nachteile dadurch. Lass dir nicht einreden, dass das
verboten sei. Wobei aber die Benennung als 'sbi' und 'cbi' ungünstig
ist, da es  suggeriert, dass sie auch auf die gleichnamigen
Assemblerbefehle  abgebildet werden, was nicht zwangsläufig der Fall
ist. Besser wäre dann z.B. die Bezeichnung set_bit und clear_bit.

von Christian T. (johannf)


Lesenswert?

Naja das is ja eher nebensächlich. Tatsächlich sind Sbi für port|=bit 
definiert und cbi für port&=~bit. Aber das is ja nich das Problem an 
meinem Programm oder?
Mein Problem ist das ich einfach nix von meinem Sensor an Daten bekomme.
Wenn ich explizit nach dem Datenblatt gehe dann könnte ich doch rein 
diese 2 Funktionen aufrufen und mir aus meinem aufgerufenen array das 
byte für den X Wert ausgeben lassen oder?
Default Settings auf dem Chip sind alle so gesetzt, das er von Anfang an 
arbeitet und BMA_com(0x8300) sollte für Lesen aus dem Register 03h 
stehen. Das ist laut Datenblatt Tabelle als das Register mit den acc_x 
Werten angegeben. Leider bekomme ich garkeine Werte in mein Array 
übergeben, egal mit welchen Data Registern ich es Probiere. An meinem 
SPI hängt noch ein Funkmodul mit einem anderen CS. Das sollte aber kein 
Problem sein, das selbst Arbeitet ja auch ohne Probleme und ist über ein 
seperates CS aktiv.
Ich hab leider kein Oszi um den Pin Miso zu kontrollieren. Aber 
irgendwie müsste der Fehler doch daran liegen, das mein Sensor den SDO 
Pin nicht verändert und ich deshalb nur 0 empfange.
Der Pin am µC funktioniert einwandfrei.
Desweiteren hab ich beim rumprobieren, seit ich das Modul auf dem Board 
hab ein Paar mal beim Proggen nen Fehler den ich leider aus dem Kopf 
nichtmehr 100% kenne, der jedoch was mit dem Problem zu tun haben 
könnte: Short Circut MOSI oder so ähnlich. Wenn ich ihn wieder bekomme, 
was mit Sicherheit Passieren wird, dann schreib ich ihn nochmal exakt 
hier rein.
Ich kann mir nicht Erklären warum dieser Fehler manchmal kommt. Ist ja 
schliesslich nur manchmal.
Die Datenleitungen hab ich jetzt desöfteren schon kontrolliert und 
sollten alle richtig Angeschlossen sein.
Enable, uPullup und INT hab ich offen als Pins hängen.
Enable und uPullup sollten laut mitgeliefertem Datenblatt des ELV auch 
offen bleiben, wenn ich mit dem internen Pegelwandler arbeite. Interrupt 
brauch ich meines erachtens nicht wenn ich nur festgelegte Byte abfrage 
oder?
UIN und GND sind über 100nF KerKo entstört.
Ist mein Modul vielleicht defekt?????

Ich weiss nicht was ich jetzt noch darüber Schreiben soll. Vielleicht 
war ja was dabei, was bei der Fehleranalyse hilfreich sein kann.

  void BMA_getdata(unsigned char *data)
{
   for (int i=0; i<1; i++)
  {
    *data++=BMA_com(0x8300);
  }
}
unsigned short BMA_com(unsigned short wert)
{  unsigned char i;

  cbi(BMA_PORT, CS_BMA);
  for (i=0; i<16; i++)
  {  if (wert&32768)
      sbi(BMA_PORT, SDI);
    else
      cbi(BMA_PORT, SDI);
    wert<<=1;
    if (BMA_PIN&(1<<SDO))
      wert|=1;
    sbi(BMA_PORT, SCK);
    asm("nop");
    asm("nop");
    cbi(BMA_PORT, SCK);
  }
  sbi(BMA_PORT, CS_BMA);
  return wert;
}

von Christian T. (johannf)


Lesenswert?

Ok hier ist der Fehler ganz genau:
Er kommt beim Flash Read nach dem Proggen
WARNING: FLASH byte adress 0x0000 and 0x00 (shout be 0x0C)..FAILED!

Mit dem Popup Fenster
There seems to be a short circut on the ISP Connector.
The MOSI line(s) seems to be short-circuted.
Operation will be abborted.

Ohne den Sensor hab ich das noch nie gehabt.
Vielleicht Hilft das weiter.

von Christian T. (johannf)


Lesenswert?

Hat diesen Sensor noch keiner hier zum Arbeiten gebracht?
Oder kann mir nen Fehler in meinen Funktionen sagen?

von Stefan E. (sternst)


Lesenswert?

Johann Forsch schrieb:
> Oder kann mir nen Fehler in meinen Funktionen sagen?

Dein SCK-Handling passt auf jeden Fall schon mal nicht zum 
Timing-Diagramm im Datenblatt.

Wieso überhaupt Software-SPI? Wieso nicht Hardware-SPI?

von Christian T. (johannf)


Lesenswert?

Ich hab mitlerweile mein Funkmodul inkulsive Timerinterrupts aus dem 
Receive usw am Software SPI am laufen, und würde sehr gern ohne 
grossartig weitere Pins zu Verschwenden oder mein ganzes 
Funkmodulprogramm umschreiben zu müssen den Sensor dazu hängen. Deswegen 
wollt ich einfach ne Erweiterung an die bestehende Soft SPI dran hängen 
und mit ner anderen SPI kommunikationsfunktion zwischendurch abfragen.

Inwiefern passt das denn nicht? Eigentlich hab ich Versucht exakt nach 
dem Datenblatt zu gehen. Aber das mit meiner Funktion was nich stimmt is 
schonmal nen Hinweis dem ich auf jeden Fall nachgehen kann, danke dir 
dafür!

von Stefan E. (sternst)


Lesenswert?

Johann Forsch schrieb:
> Inwiefern passt das denn nicht?

Die erste fallende SCK-Flanke nach CS-Low fehlt bei dir (die hast du 
dann dafür am Ende "über").

von Christian T. (johannf)


Lesenswert?

Danke für die Info.
Ich hab mich auch gleich dran gemacht, leider immernoch ohne Erfolg.
Hier meine aktuelle Funktion mit vielen unnötigen Delays und bischen 
vielen Kommentaren :)

unsigned short BMA_com(unsigned short wert)
{  unsigned char i;    //Zählwert für Schleife
  sbi(BMA_PORT, SCK);  //Begin mit SCK high
  cbi(BMA_PORT, CS_BMA);  //Aktiviere BMA
  _delay_us(10);    //dummy Delay
  for (i=0; i<16; i++)  //Zählschleife 2 byte
  {
    cbi(BMA_PORT, SCK);    //Falling Edge SCK
    if (wert&32768)      //Write/Read abfrage
      sbi(BMA_PORT, SDI);  //SBI High Write
    else
      cbi(BMA_PORT, SDI);  //SBI Low Read
    _delay_us(10);      //dummy Delay
    wert<<=1;    //Erstes Bit frei machen
    if (BMA_PIN&(1<<SDO))  //SDO Zustand auswerten
      wert|=1;    //Setze Bit wenn SDO High
    sbi(BMA_PORT, SCK);  //Rising Edge SCK
    asm("nop");    //dummy delay
  }
  sbi(BMA_PORT, CS_BMA);  //Deaktiviere BMA
  cbi(BMA_PORT, SCK);  //Ursprungszustand SCK low
  return wert;
}

Das Problem mit dem Short-Circuted MOSI lines hab ich übrigens 
immernoch. Liegt das an der Programmierung oder an der Hardware???
Ignorrieren will ich das ja nur Ungern :I

Grüße
Johann

von Michael M. (koenig_deluxe)


Lesenswert?

Hallo Johann,

läuft dein Programm mittlerweile? Ich kämpfe auch schon seit wochen mit 
dem BMA020 und hab noch garkeinen erfolg gehabt. Ich bekomm einfach 
keine daten aus dem Sensor. Und hab schon die verschiedensten Sachen 
ausprobiert. Hab den Sensor über Flachbandkabel am STK500 an PORTB eines 
Atmega8. INT, ENABLE und UPULLUP sind auch bei mir offen. Ich versuche 
einfach nur die Daten des Sensor auf den LEDs des STK anzuzeigen, das 
würde mir schon helfen. Doch bekomm es nicht hin. Hier mal einer meiner 
vielen fehlgeschlagenen Quellcode Versuchen:


#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
int main(void)
{
    while(1)
    {
    DDRC = 0xFF;  // PORTC als Ausgang
    DDRB = 0xEF;  // PORTB alle Ausgang, außer MISO
        PORTB = 0xFF; // PORTB high
    SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<CPOL)|(1<<CPHA);
    PORTB &= ~(1<<PB2);  // Wähle Sensor aus
    SPDR = 0x15;         // Wähle Register 15h
    while(!(SPSR & (1<<SPIF)));
    SPSR = 0x00;         // Lösche SPIF
    SPDR = 0x08;         // Setze shadow_dis
    while(!(SPSR & (1<<SPIF)));
    PORTB |= (1<<PB2);   // Übertragung an Sensor beendet
    PORTB &= ~(1<<PB2);  // Erneut Sensor wählen
    SPDR = 0x07;         // Wähle acc_z
    while(!(SPSR & (1<<SPIF)));
    SPSR = 0x00;
    SPDR = 0x80;         // MSB high für read befehl Sende dummy Byte
    while(!(SPSR & (1<<SPIF)));
    SPSR = 0x00;
    _delay_ms(20);
    PORTC = SPDR;
    }
}

von PittyJ (Gast)


Lesenswert?

Ich habe auch in letzter Zeit einige ICs über Busse angeschlossen.

Meine Erfahrung dabei war, dass es ohne Oszilloskop nicht geht. Nur so 
kann man vergleichen, ob das angelegte Signal wirklich dem geforderten 
aus dem Datenblatt entspricht.

Einmal hatte ich den Fall, das der Prozessor nach 16 Bits einen kurzen 
Peak auf die CS-Leitung legte, die der Sensor als Endsignal auslegte. 
Das bekommt man nur mit einem Oszilloskop mit. Nach Einlöten eines 
Widerstandes lief dann alles. Nur mit Software alleine wäre ich nicht 
drauf gekommen.

Ich würde investieren. Ist zwar sehr teuer, doch das zahlt sich in 
gesparter Zeit wieder aus.

von Werner B. (werner-b)


Lesenswert?

Messe mal die Versorgungsspannung auf dem ELV Modul.
Bei meinem war da eine Unterbrechung der Leiterbahn. Könnte ja ein 
Serienfehler sein.

Edit:
Zwischen Anschluss und 3.3V Regler meine ich. Im Schaltplan nachsehen.

von Michael M. (koenig_deluxe)


Lesenswert?

Jetzt hab ich mal ne ganz banale Frage. Ich ließ immer wieder im 
Zusammenhang mit dem Sensor BASCOM. Kann es sein das der Sensor nur in 
Basic programmiert werden kann? Oder ich einfach nur einen anderen 
Compiler verwenden muss? Ich verwende den C-Compiler der mit dem AVR 
Studio 5 dabei is.

von STK500-Besitzer (Gast)


Lesenswert?

Michael Maier schrieb:
> Jetzt hab ich mal ne ganz banale Frage. Ich ließ immer wieder im
> Zusammenhang mit dem Sensor BASCOM. Kann es sein das der Sensor nur in
> Basic programmiert werden kann? Oder ich einfach nur einen anderen
> Compiler verwenden muss? Ich verwende den C-Compiler der mit dem AVR
> Studio 5 dabei is.

Jetzt weiß ich auch, woher das "B" in der Bezeichnung kommt.

Nee, Quatsch!
Am Ende kommt da eh Maschinencode raus, egal ob es vorher Basic, C oder 
Ada war.
Vermutlich mussten einfach eine ganze Menge Basic-Programmierer ihr 
Wissen teilen - C-Programmierer sind die stilleren Typen...

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.