Forum: Mikrocontroller und Digitale Elektronik STM32F4: BMA020 per SPI


von Daniel V. (voda) Benutzerseite



Lesenswert?

Hallo Forum,

ich verzweifle an den Bosch BMA020 welche ich gerne mit meinem STM32F446 
auslesen möchte. Takt ist da, nur ich bekomme im DR-Register stets ein 
0xFF. So bin ich vorgegangen:

Ich habe eine bma020.h Datei erzeugt. Dort ist folgendes definiert 
(Auszug):
1
#define RANGE_2g           (0x14|0x00)
2
#define BANDWIDTH_1500hz   (0x14|0x06)
3
#define ONLY_MSB_VALUE     ((0x14)|(1<<3)) 
4
5
#define X_AXIS  0x03
6
#define Y_AXIS  0x05
7
#define Z_AXIS  0x06
8
9
#define SPI_TXE    SPI_I2S_FLAG_TXE
10
#define SPI_RXNE   SPI_I2S_FLAG_RXNE
11
#define SPI_BSY    SPI_I2S_FLAG_BSY
12
13
/************************SENSORANSTEUERUNGEN***************/
14
#define BMA020_NSS_HIGH      GPIOA->BSRRL |= (1<<4);  /*SET*/
15
#define BMA020_NSS_LOW       GPIOA->BSRRH |= (1<<4);  /*RESET*/
16
17
#define BMA020_INT_ON        GPIOC->BSRRL |= (1<<4);     
18
#define BMA020_INT_OFF       GPIOC->BSRRH |= (1<<4);
19
20
#define BMA020_SENSOR_ON     GPIOA->BSRRL |= (1<<11);   
21
#define BMA020_SENSOR_OFF    GPIOA->BSRRH |= (1<<11);

In der bma020.c habe ich folgendes implementiert (ebenfalls Auszug):
1
void bma020_TAKT(void)
2
{
3
 /*APB2 aktiviert und auf 5 MHz eingestellt, Grundtakt ist 80 MHz */
4
5
  RCC->CFGR    |= 0x0000E000; 
6
  RCC->APB2ENR |= (1<<12);     /* SPI1 auf 13*/
7
}
8
void bma020_SPI(void)
9
{
10
/*BMA Datenblatt Figure 4*/
11
SPI_InitTypeDef SPI_Init_BMA020;
12
13
SPI_Init_BMA020.SPI_Direction         = SPI_Direction_2Lines_FullDuplex;
14
SPI_Init_BMA020.SPI_DataSize          = SPI_DataSize_16b;
15
SPI_Init_BMA020.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;  
16
/*DATEN nach der fallenden Flanke*/
17
SPI_Init_BMA020.SPI_CPHA              = SPI_CPHA_2Edge; 
18
/*Datenblatt: GRUNDZUSTAND HIGH*/
19
SPI_Init_BMA020.SPI_CPOL              = SPI_CPOL_High;      
20
SPI_Init_BMA020.SPI_CRCPolynomial     = 0;
21
SPI_Init_BMA020.SPI_FirstBit          = SPI_FirstBit_MSB;  
22
SPI_Init_BMA020.SPI_Mode              = SPI_Mode_Master;
23
SPI_Init_BMA020.SPI_NSS               = SPI_NSS_Soft;
24
SPI_Init(SPI1, &SPI_Init_BMA020);
25
SPI_Cmd(SPI1, ENABLE);
26
}
27
28
/*Meine Sendefunktion und Empfangsfunktion*/
29
uint8_t bma020_SEND(uint8_t data)
30
{
31
  SPI1->DR = data; 
32
  while(!(SPI1->SR & SPI_TXE)); 
33
  while(!(SPI1->SR & SPI_RXNE)); 
34
  while( SPI1->SR & SPI_BSY); 
35
  return SPI1->DR; 
36
}

Nun sagt das Datenblatt, wenn man nur die Werte aus 0x03, 0x05, 0x07 
auslesen möchte, also nur die Werte in x,z und z-Richtung muss ein 
Shadowbit in 0x14 gesetzt werden. Die anderen Bits geben die Bandbreite 
und die Empfindlichkeit ebenfalls im Register 0x14 an. Des Weiteren 
meine ich gelesen zu haben das man zum Empfangen der Daten ein 0x00 
mitsenden muss. Zudem meine ich, das Senden NSS=LOW und Empfangen 
NSS=HIGH ist.

Also ist meine Configroutine in bma020.c:
1
void bma020_CONFIG(void)
2
{
3
  BMA020_NSS_LOW;
4
  bma020_SEND(RANGE_2g);
5
  bma020_SEND(BANDWIDTH_1500hz);
6
  bma020_SEND(ONLY_MSB_VALUE);
7
  BMA020_NSS_HIGH;  
8
}

Nun habe ich noch eine Funktion, welche mir die Beschleunigungswerte aus 
dem Register auslesen und testweise auf eine USART schreiben soll.
1
void bma020_READ(void)
2
{
3
  bma020_SEND(X_AXIS&0x00);
4
  bma020_temp_data= bma020_SEND(X_AXIS&0x00);
5
 
6
  /*Schreibe mir die Daten auf die USART*/  
7
  USART_SendData(USART3, bma020_temp_data);
8
   while(!(USART3->SR & USART_FLAG_TC));
9
}

Meine main.c sieht dann so aus:
1
#include <functions.h>
2
#include <usart.h> 
3
#include <bma020.h>
4
5
6
/*Bibliotheken*/
7
8
int main (void) 
9
{
10
startUp();        /* GPIO-Config, Takt, SystemInit usw. */
11
USART_config();   /* USART-Konfiguration*/
12
bma020_STARTUP(); /* GPIO, TAKT, SPI-Config, Sensor wird mit Spannung versorgt usw */ 
13
bma020_CONFIG();
14
15
   while(1)
16
          {
17
           Run_Idle();    /*Zeitscheibe*/
18
           bma020_READ(); /*Lese die Daten und schreibe auf die USART */
19
          }
20
}

Wie bekomme ich das hin, das ich die Beschleunigungswerte auslesen kann? 
Was mache ich falsch?

Vielen lieben Dank

: Bearbeitet durch User
von TriHexagon (Gast)


Lesenswert?

Hi,

also ohne das Datenblatt groß angeschaut zu haben: Um mit dem SPI Daten 
empfangen zu können, musst du was drauf schreiben, schließlich bist du 
der SPI Master und nur der hat die Gewalt über die Taktleitung. Siehe 
Figure 5. du musst also um ein Byte zu empfangen, zwei Byte senden (die 
Adresse, RW Bit und das Dummy Byte). Das machst du schon mal falsch.

Daniel V. schrieb:
> Zudem meine ich, das Senden NSS=LOW und Empfangen
> NSS=HIGH ist.

NEIN! NSS ist der ChipSelect, du setzt bei demjenigen Slave NSS auf Low 
mit dem du kommunizieren willst, also Senden und Empfangen. Wenn ein 
Slave auf seinem NSS einen High Pegel hat, muss er nach SPI "Standard" 
die Schnauze halten.

Da du das Prinzip von SPI noch nicht richtig verstanden hast, solltest 
du dich damit vertraut machen und vor allem das Datenblatt vom BMA020 
mal ordentlich durchlesen!

von Daniel V. (voda) Benutzerseite


Lesenswert?

TriHexagon schrieb:
> NEIN! NSS ist der ChipSelect, du setzt bei demjenigen Slave NSS auf Low
> mit dem du kommunizieren willst, also Senden und Empfangen. Wenn ein
> Slave auf seinem NSS einen High Pegel hat, muss er nach SPI "Standard"
> die Schnauze halten.

Ich seh gerade, ist kompletter Unsinn was ich geschrieben habe. Die 
Datenübertragung findet bei NSS Low statt. Datenblatt Figure 4, Seite 
24ff. Das wollte ich damit sagen. Der Pegel ist normalerweise HIGH. das 
heißt der Chip wird gerade vom µC (Master) nicht angesprochen

TriHexagon schrieb:
> Siehe
> Figure 5. du musst also um ein Byte zu empfangen, zwei Byte senden (die
> Adresse, RW Bit und das Dummy Byte). Das machst du schon mal falsch.

Ahh, d.h. ich muss ihm erst eine 1 senden, oder?
Datenblatt Seite 26, Figure 7 also 0b10000011 für 0x03?

Danke und Gruß
Daniel

: Bearbeitet durch User
von TriHexagon (Gast)


Lesenswert?

Daniel V. schrieb:
> TriHexagon schrieb:
>> NEIN! NSS ist der ChipSelect, du setzt bei demjenigen Slave NSS auf Low
>> mit dem du kommunizieren willst, also Senden und Empfangen. Wenn ein
>> Slave auf seinem NSS einen High Pegel hat, muss er nach SPI "Standard"
>> die Schnauze halten.
>
> Ich seh gerade, ist kompletter Unsinn was ich geschrieben habe. Die
> Datenübertragung findet bei NSS Low statt. Datenblatt Figure 4, Seite
> 24ff. Das wollte ich damit sagen. Der Pegel ist normalerweise HIGH. das
> heißt der Chip wird gerade vom µC (Master) nicht angesprochen

Genau, NSS ist "active low".

Daniel V. schrieb:
> TriHexagon schrieb:
>> Siehe
>> Figure 5. du musst also um ein Byte zu empfangen, zwei Byte senden (die
>> Adresse, RW Bit und das Dummy Byte). Das machst du schon mal falsch.
>
> Ahh, d.h. ich muss ihm erst eine 1 senden, oder?
> Datenblatt Seite 26, Figure 7 also 0b10000011 für 0x03?

Genau und dann das Dummy Byte, damit der Sensor die Daten auf den Bus 
legen kann.

von Daniel V. (voda) Benutzerseite


Angehängte Dateien:

Lesenswert?

TriHexagon schrieb:
> Genau und dann das Dummy Byte, damit der Sensor die Daten auf den Bus
> legen kann.

Es funktioniert leider nicht :(

Mein derzeitiger Code:

bma020.h
1
/************************Defines**************************/
2
#define RANGE_2g           (0x14|0x00)
3
#define BANDWIDTH_1500hz   (0x14|0x06)
4
#define ONLY_MSB_VALUE     ((0x14)|(1<<3)) 
5
6
#define X_AXIS  0x03
7
#define Y_AXIS  0x05
8
#define Z_AXIS  0x07
9
10
#define SPI_TXE    SPI_I2S_FLAG_TXE
11
#define SPI_RXNE   SPI_I2S_FLAG_RXNE
12
#define SPI_BSY    SPI_I2S_FLAG_BSY

bma020.c
1
/*Sende an BMA020 die Konfigutationseinstellungen*********/
2
3
void bma020_CONFIG(void)
4
{
5
 BMA020_NSS_LOW;
6
 bma020_SEND(0x00|RANGE_2g);
7
 bma020_SEND(0x00|BANDWIDTH_1500hz);
8
 bma020_SEND(0x00|ONLY_MSB_VALUE);
9
 BMA020_NSS_HIGH;  
10
}
11
12
13
void bma020_READ(void)
14
{
15
 BMA020_NSS_LOW;
16
 bma020_SEND(0x01|X_AXIS|0x00);                     /* 0x01|0x02|0x00*/
17
 bma020_temp_data= bma020_SEND(0x01|X_AXIS|0x00);
18
 BMA020_NSS_HIGH;
19
  
20
 USART_SendData(USART3, bma020_temp_data);
21
  while(!(USART3->SR & USART_FLAG_TC));
22
}

main.c
1
#include <functions.h>
2
#include <usart.h> 
3
#include <bma020.h>
4
5
6
/*Bibliotheken*/
7
8
int main (void) 
9
{
10
startUp();
11
USART_config();
12
bma020_STARTUP();
13
bma020_CONFIG();
14
15
while(1)
16
{
17
  Run_Idle();
18
  bma020_READ();
19
20
// sendText("Es tut mir leid Dave, aber das kann ich nicht tun!\n");
21
//for (x = 0; x < 200000;x++);  
22
23
    }
24
}

Verstehe ich nicht. Ich habe stets 0xFF im DR-Register. Pullups sind 
auch gesetzt.

[Edit]: Der Sensor ist ein Bausatz von ELV. Ich habe jetzt mal einen 
anderen eingesetzt und dort ist der Wert 0x01. Hab ich den Sensor von 
meinem Board entfernt, so ist der Registerwert 0xFF. Daraus schließe 
ich, das ein Sensor über die Wupper gegangen ist (ich hatte den mal 
verpolt)

: Bearbeitet durch User
von Daniel V. (Gast)


Lesenswert?

...aber leider kann ich noch immer nicht die Daten auslesen.

von TriHexagon (Gast)


Lesenswert?

Sorry habe den Thread aus den Augen verloren und nicht mehr gefunden. 
Irgendwas ist da faul, ist mit dem SPI Enable die NSS Leitung gemeint? 
Wenn ja läuft da etwas schief, NSS muss vor dem ersten Takt auf Low und 
erst nach dem letzten Takt (also nach dem 16 Bit) auf High. So wie das 
aussieht geschieht das aber nicht. Du kannst im Saleae Logic auch einen 
SPI Decoder setzen, dann siehst du genau was da übertragen wird.

von TriHexagon (Gast)


Lesenswert?

Versuch erst mal die ChipID auszulesen, da weißt du genau was 
zurückkommen soll. Also sende 0x80 0x00, zurück kommen muss XXXXX010.

von Daniel V. (voda) Benutzerseite


Angehängte Dateien:

Lesenswert?

TriHexagon schrieb:
> Sorry habe den Thread aus den Augen verloren und nicht mehr
> gefunden.
> Irgendwas ist da faul, ist mit dem SPI Enable die NSS Leitung gemeint?
> Wenn ja läuft da etwas schief, NSS muss vor dem ersten Takt auf Low und
> erst nach dem letzten Takt (also nach dem 16 Bit) auf High. So wie das
> aussieht geschieht das aber nicht. Du kannst im Saleae Logic auch einen
> SPI Decoder setzen, dann siehst du genau was da übertragen wird.

Hi TriHexagon,

bisher habe ich folgende Erkenntnisse:

Von diesen BMA020-Sensoren waren zwei defekt, ich hatte die mal verpolt 
angeschlossen, da ich aus Faulheit an meinem Board keine 
Aufstecksicherung vorgesehen habe. Ich habe den ENABLE-PIN-Stift 
weggelötet und den dazugehörigen Weibchen zugeklebt. Ein Sensor wurde 
extrem heiß (IR-Kamera zeigte 100 °C) und nahm 0,2 A Strom auf. Der 
andere rührte sich gar nicht. Daher die Registerwerte 0xFF.

Anschießend bin ich nochmals Schritt für Schritt das Datenblatt 
durchgegangen und folgende SPI-Einstellungen habe ich implementiert:

* SPI-Takt auf 5 MHz gesetzt (Der APB2-Takt ist 80 MHz=Systemtakt)
* Datenkommunikation auf NSS=LOW
* Clockphase auf HIGH (fallende Flanke des Clocks)
* Clockpolaritöt auf HIGH

Dies entspricht SPI-Mode 3

* Vollduplex aktiviert
* MSB zuerst
* der STM ist der Master


folgende Einstellungen habe ich gemacht:
1
/*****Initialisierung der SPI-Schnittstelle*************/
2
3
void bma020_SPI(void)
4
{
5
 /*BMA Datenblatt Figure 4*/
6
 SPI_InitTypeDef SPI_Init_BMA020;
7
 SPI_Init_BMA020.SPI_Direction         = SPI_Direction_2Lines_FullDuplex;
8
 SPI_Init_BMA020.SPI_DataSize          = SPI_DataSize_16b;          
9
  
10
 /*teilt das Clocksignal (DILLER TUTORIAL): 80 MHz/32 = 2,5 MHz
11
   Datenblatt BMA020= fmax = 10 MHz  */ 
12
  
13
 SPI_Init_BMA020.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;  
14
   
15
 /*SPI Mode 3 (Artikel mc.net SPI): CPHA=1, CPOL=1 Datenblatt S.23 */
16
 SPI_Init_BMA020.SPI_CPHA              =  SPI_CPHA_2Edg
17
 SPI_Init_BMA020.SPI_CPOL              = SPI_CPOL_High;        
18
 SPI_Init_BMA020.SPI_CRCPolynomial     = 0;
19
 SPI_Init_BMA020.SPI_FirstBit          = SPI_FirstBit_MSB
20
 SPI_Init_BMA020.SPI_Mode              = SPI_Mode_Master;
21
 SPI_Init_BMA020.SPI_NSS               = SPI_NSS_Soft;
22
 SPI_Init(SPI1, &SPI_Init_BMA020);
23
 SPI_Cmd(SPI1, ENABLE);
24
}

Nun habe ich mit meinem Oscar mir die SPI-Signale angeschaut. Sehr 
auffällig ist dass das MOSI-Signal schon wellig ist (wie auch NSS). Auf 
MISO liegen Nullzeichen. Das spricht dafür das irgendwas mit meiner 
Sendesoutine oder allgemeinen Ablauf etwas nicht stimmt.

Meine Senderoutine
1
void bma020_CONFIG(void)
2
{
3
4
  BMA020_NSS_LOW
5
    bma020_SEND(RANGE_4g);
6
    bma020_SEND(BANDWIDTH_1500hz);
7
    bma020_SEND(ONLY_MSB_VALUE);
8
  BMA020_NSS_HIGH;  
9
10
}
11
12
13
void bma020_READ(void)
14
{
15
 BMA020_NSS_LOW;
16
  bma020_SEND(0x01|X_AXIS|0x00);
17
  bma020_temp_data= bma020_SEND(0x01|X_AXIS|0x00); 
18
 BMA020_NSS_HIGH;
19
  
20
 USART_SendData(USART3, bma020_temp_data);
21
  while(!(USART3->SR & USART_FLAG_TC));
22
}
23
24
25
/************Initialisierung aller Funktionen************/
26
void bma020_STARTUP(void)
27
{
28
  bma020_GPIO();
29
  bma020_TAKT();
30
  bma020_SPI();
31
  bma020_CONFIG();
32
}

In der Main ist die bma020_READ in der Schleife
Vielen Dank für Deine Hilfe :)

: Bearbeitet durch User
von Daniel V. (voda) Benutzerseite


Lesenswert?

TriHexagon schrieb:
> Versuch erst mal die ChipID auszulesen, da weißt du genau was
> zurückkommen soll. Also sende 0x80 0x00, zurück kommen muss XXXXX010.

Als Antwort bekomme ich 01000000 (0x40), was ich aber auf dem Oscar 
nicht sehen kann (NUL)

Auch bricht die Datenkommunikation nach einer gewissen Zeit zusammen 
(speise das Board gerade mit der USB-Schnittstelle)

[EDIT] Gerade mal mein Netzteil angehangen, Schaltung zieht 0,023 A und 
ich habe einen Spannungsregler LP2950 drauf der bis 1A Strom liefern 
kann.

: Bearbeitet durch User
von Daniel V. (voda) Benutzerseite


Lesenswert?

So, ich glaube ein Fehler liegt am NSS-Signal. Dieser schlägt extrem 
aus, was im Logicanalyser und auch auf dem Oscar zu sehen ist. Daher 
schwingt dieser zwischen LOW und HIGH und daher ist keine vernünfige 
Kommunikation möglich, da der Sensor einmal angesprochen wird und wieder 
nicht. Also muss dieses Signal geglättet werden. Ich frage mich nun, 
warum dieses Signal so unfassbar unsauber ist...

Auch läuft das NSS-Signal und der Takt gleichzeitig los. Zudem ist das 
MISO-Signal und das Taktsignal identisch... echt seltsam

Gruß
Daniel

: Bearbeitet durch User
von TriHexagon (Gast)


Lesenswert?

Ja die Signale sehen überhaupt nicht gut aus, außer CLK und lila (NSS?). 
Also vom Code her, sehe ich nichts was gegen eine fehlerfreie 
Kommunikation sprechen würde. Irgendwas stört dein Signal. Kannst du den 
SPI Bus mal ohne Sensor abgreifen?

von Daniel V. (voda) Benutzerseite



Lesenswert?

TriHexagon schrieb:
> Ja die Signale sehen überhaupt nicht gut aus, außer CLK und lila
> (NSS?).
> Also vom Code her, sehe ich nichts was gegen eine fehlerfreie
> Kommunikation sprechen würde. Irgendwas stört dein Signal. Kannst du den
> SPI Bus mal ohne Sensor abgreifen?

Ich habe mal ein aktuelles Oszibild mit Sensor.

gelb:       NSS
hellblau:   Clock
Lila:       MISO
dunkelblau: MOSI

Das Signal MOSI und NSS sehen gleich aus... Komisch ist auch, der Oscar 
liest eine 0x00 aus, auf der USART liegt 0x55.


Gruß
Daniel

PS: Die dicke Leitung auf der BOTTOM-Seite wurde gekappt.

: Bearbeitet durch User
von TriHexagon (Gast)


Lesenswert?

Puh vom Platinenlayout habe ich nicht viel Ahnung, aber ich kann mir 
nicht vorstellen, dass es da bei dem Signal ein Problem in der Richtung 
geben kann. Aber man sieht, dass der Takt Einfluss auf MOSI und NSS hat 
(besonders bei den Flanken). Wie sieht den deine GPIO Konfiguration aus? 
Erhöhe mal den Clockdivider und messe nochmal.

von Daniel V. (voda) Benutzerseite


Angehängte Dateien:

Lesenswert?

Mit dem Teiler habe ich jetzt auch gecheckt. Spasseshalber habe ich den 
NSS auf Output gestellt, so das ich im Debug-Mode direkt auf den ODR 
zugreifen kann. Aktiviere ich den ODR ziehe ich gleichzeitig den MOSI 
mit hoch.

Aber warum sieht das Signal von der MOSI und NSS identisch aus?

: Bearbeitet durch User
von TriHexagon (Gast)


Lesenswert?

Tja, mir gehen die Ideen aus. Aktuell würde ich auf das Platinenlayout 
bzw. auf die Platine tippen. CLK kommt ordentlich durch und Pullups sind 
auch vorhanden, am µC kanns irgendwie nicht liegen. Solche Wellen 
bekommt man mit dem so nicht hin, es sei denn die Ausgänge sind defekt, 
ist aber extrem unwahrscheinlich. Hast du noch mal den gleichen µC? Ich 
würde einen Anderen mit dem gleichen Programm testen.

von Daniel V. (voda) Benutzerseite


Lesenswert?

TriHexagon schrieb:
> Tja, mir gehen die Ideen aus. Aktuell würde ich auf das
> Platinenlayout
> bzw. auf die Platine tippen. CLK kommt ordentlich durch und Pullups sind
> auch vorhanden, am µC kanns irgendwie nicht liegen. Solche Wellen
> bekommt man mit dem so nicht hin, es sei denn die Ausgänge sind defekt,
> ist aber extrem unwahrscheinlich. Hast du noch mal den gleichen µC? Ich
> würde einen Anderen mit dem gleichen Programm testen.

Ich vermute es auch, da ich zweimal den Sensor falschherum montiert 
habe, daher kann es gut sein. Leider habe ich gerade keine zur Hand, 
muss ich neu ordern.

Gruß
Daniel

: Bearbeitet durch User
von Felix F. (wiesel8)


Lesenswert?

Hallo,

ich habe hier einen STM32F411. Falls die kompatibel sind, kannst du mir 
mal deine ELF/HEX schicken. Habe auf diesem auch einen funktionierenden 
SPI Treiber, mit dem ich ein RFM-Modul ansteuere.

mfg

von Daniel V. (voda) Benutzerseite


Lesenswert?

Felix F. schrieb:
> ich habe hier einen STM32F411. Falls die kompatibel sind, kannst du mir
> mal deine ELF/HEX schicken. Habe auf diesem auch einen funktionierenden
> SPI Treiber, mit dem ich ein RFM-Modul ansteuere.

Vielen Dank, aber funktioniert das? Ich habe auf der Platine auch einen 
externen Quarz mit 25 MHz und der Controller läuft mit 80 MHz.

Das Pinning sieht hingegen gleich aus (SPI1 auf PA.04 bis PA.07) USART3 
hingegegen fehlt.

Mir fällt aber gerade ein, das ich ja auch noch ein Nuceloboard mit dem 
STM32F446 rumfliegen habe. Damit probiere ich den Code gleich mal aus.

Gruß
Daniel

von Daniel V. (voda) Benutzerseite


Angehängte Dateien:

Lesenswert?

So, ich habe den Code auf den Nucleo getestet. Der Fehler lässt sich 
reproduzieren. Mein NSS-Signal ist identisch mit dem MOSI-Signal.

Kann das an den ELV-Bausatz liegen?

Bei der Bedienungsleitung des ELV-Bausatzes auf Seite 6 heißt es, dass 
die maximale Busfrequenz aufgrund der Pegelwandler 100 kHz betragen 
darf. Ich hab eben das Taktsignal mit meinem Oscar gemessen und habe 
eine Periodenzeit von 22,7 µs, also 44,05 kHz gemessen.

Auch frage ich mich, warum das NSS-Signal so eigenartig aussieht...

Ohne Sensor ist nur das Takt- und MISO-Signal vorhanden.

Jemand Ideen?

Danke und Gruß
Daniel

: Bearbeitet durch User
von Felix F. (wiesel8)


Angehängte Dateien:

Lesenswert?

Das ist meine Implementierung für den F411. Aber mit 16 Bit und CS 
steuere ich manuell an. Für deine Zwecke müsstest du auf jeden Fall noch 
den Prescaler anpassen.

mfg

: Bearbeitet durch User
von Daniel V. (voda) Benutzerseite


Lesenswert?

Geil, danke, das werde ich nun durcharbeiten. Das selbe Phänomen habe 
ich am Bildsensor ADNS3090, mit dem ich Bilddaten per SPI aufnehmen 
möchte. Da sieht ebenfalls das NSS-Signal gleich dem MOSI-Signal aus. 
Auch ist das NSS-Signal sägezahnartig.

Sehr eigenartig, alles

von Daniel V. (voda) Benutzerseite


Lesenswert?

Hallo Felix,

leider verstehe ich den Code noch nicht vollständig. Dieser ist auf Dein 
RFM-Modul ausgerichtet, oder?

Was bedeutet
1
uint8_t bma020_ReadByte(SPI_TypeDef *SPIx, uint8_t _address)
2
{
3
  // Clear MSB -> Read mode
4
  _address &= 0x7F;
5
6
  return bma020_WriteWord(SPIx, _address<<8 & 0xff00);
7
}

Ist die Adresse etwas sensorspezifisches?

Wenn ich z.B die Chip_ID im Register 0x00 auslesen möchte, würde ich 
folgendes auf den Bus legen wollen:

*NSS auf Low ziehen
*0x80|0x00 Senden (0b10000000|0b00000000)

Dabei ist RW 1 = READ ADRESSE 0x00 und das Dummybyte auf SPI1
Wie implementiere ich dies in Deine SPI-Lösung?

also:
1
 void bma020_READ(void)
2
{
3
  bma020_WriteData(SPI1,0x00,0x00);
4
  bma020_ReadByte(SPI1,0x80|0x00|0x00);
5
  bma020_temp_data = bma020_ReadByte(SPI1,0x80|0x00|0x00);
6
    
7
   USART_SendData(USART3, bma020_temp_data);
8
      while(!(USART3->SR & USART_FLAG_TC));
9
}

Leider funktioniert das alles nicht...

Danke und Gruß
Daniel

: Bearbeitet durch User
von Stromverdichter (Gast)


Lesenswert?

Hallo Daniel,
hast du irgendeine funktionierende SPI-Implementierung jemals selbst 
umgesetzt? SPI ist vom Prinzip her sehr einfach. Du solltest zunächst 
herausbekommen, wie du korrekt die Daten heraus-schicken kannst.
Als nächstes schickst du den Lesezeiger deines Sensors erst mal auf die 
null und ließt alle Register die da folgen. Diese packst du dir auf 
deinem Controller in ein Array. Sobald das funktioniert, kannst du 
ordentlich debuggen, weil du jetzt die Änderungen im Sensor verfolgen 
kannst. Du solltest mal einen Schritt zurückgehen und stumpf die 
SPI-Schnittstelle bedienen. Denke dabei nicht darüber nach, was andere 
machen, erst musst du die Schnittstelle verstanden haben. Der Rest kommt 
dann automatisch.

von Felix F. (wiesel8)


Lesenswert?

Hallo,

das RFM-Modul erwartet immer 16 Bit.

Die ersten 8 Bit bezeichnen die Registeradresse. Das MSB davon gibt an, 
ob ich schreiben (1) oder lesen (0) will.
Die nächsten 8 Bit sind die zu schreibenden Daten wenn ich schreiben 
will oder beim Lesen nur Dummy-Cycles, damit das Modul die Daten 
zurückgibt.

In meinem Screenshot wird als erstes 0x8600 geschrieben: Es wird also 
ins Register 0x06 nur 0x00 geschrieben, die 8 ist das Write-Bit.

Wenn der SPI auf 8 Bit eingestellt ist, könnte man alternativ auch 
schreiben:
1
CS_Low;
2
// Schreibbefehl an Register 0x06
3
SPI_Write(SPI1, 0x86);
4
// Schreibe 0x00 in Register 0x06
5
SPI_Write(SPI1, 0x00);
6
CS_High;

mfg

von Stromverdichter (Gast)


Lesenswert?

alternativ könnte man auch
1
CS_Low;
2
// Lesebefehl an Register 0x01
3
SPI_Write(SPI1, 0x01);
4
// lese alle folgenden Register
5
32* SPI_Write(SPI1, 0xFF);
6
CS_High;
erst einmal den ganzen Kram lesen um dann später bei den einzelnen 
Registern weiterzumachen. der Lese-Zeiger wandert ja imho weiter.

von Daniel V. (voda) Benutzerseite


Lesenswert?

Stromverdichter schrieb:
> Hallo Daniel,
> hast du irgendeine funktionierende SPI-Implementierung jemals selbst
> umgesetzt?

Das ist meine erste eigene SPI-Implementierung auf einer ARM-Kiste.

Felix F. schrieb:
> Die ersten 8 Bit bezeichnen die Registeradresse. Das MSB davon gibt an,
> ob ich schreiben (1) oder lesen (0) will.
> Die nächsten 8 Bit sind die zu schreibenden Daten wenn ich schreiben
> will oder beim Lesen nur Dummy-Cycles, damit das Modul die Daten
> zurückgibt

Der BMA020 erwartet auch 16 Bit. Hier ist es so dass das MSB 0 schreiben 
und 1 lesen ist. Die Chip-ID liegt auf Register 0x00 und hinterher muss 
ein Dummybyte mitgesendet werden:

NSS_LOW
auf MOSI->  0x80|0x00
also mit Deiner Lösung habe ich folgende Lösung implementiert
1
void bma020_READ(void)
2
{
3
 BMA020_NSS_LOW;
4
 
5
 bma020_WriteData(SPI1,0x08,0x00);
6
 bma020_ReadByte(SPI1,0x00|0x00);
7
 bma020_temp_data = bma020_ReadByte(SPI1,0x00|0x00);
8
 USART_SendData(USART3, 0xFF);
9
  while(!(USART3->SR & USART_FLAG_TC));
10
11
 BMA020_NSS_HIGH;
12
}

Diese Funktion habe ich in die main.c in die while-Schleife gepackt 
zusammen mit einer anderen Testfunktion um zu sehen ob die Schleife 
läuft.
Nichts tut sich und auf dem Oscar ist auch nichts zu sehen.

Danke und Gruß
Daniel

von Felix F. (wiesel8)


Lesenswert?

Hast du meine Initialisierung übernommen? Dann musst du nämlich deinen 
Sensor auch an den entsprechenden Pins anschließen!

mfg

von Daniel V. (voda) Benutzerseite


Lesenswert?

Felix F. schrieb:
> Hast du meine Initialisierung übernommen? Dann musst du nämlich
> deinen
> Sensor auch an den entsprechenden Pins anschließen!
>
> mfg

Nene, ich habe lediglich die Sende und die Empfangsroutine übernommen. 
Die GPIOs, RCC und SPI-Konfiguration sind jeweils in einer eigenen 
Funktion und fasse diese am Ende in einer StartUp zusammen (natürlich in 
der selben c-Datei) , welche ich in die Main vor der Schleife einlade.

Kommentiere ich die o.a. Funktion aus, läuft die Schleife.

Gruß
Daniel

: Bearbeitet durch User
von Felix F. (wiesel8)


Lesenswert?

Wie sieht den der aktuelle Code aus? Im ersten Post kann ich nicht mal 
eine Initialisierung der Pins etc. sehen.

mfg

von Daniel V. (Gast)


Angehängte Dateien:

Lesenswert?

Felix F. schrieb:
> Wie sieht den der aktuelle Code aus? Im ersten Post kann ich nicht
> mal
> eine Initialisierung der Pins etc. sehen.
>
> mfg

Guten Morgen,

Ich habe die C-Datei mal hochgeladen.

Gruß
Daniel

von Daniel V. (Gast)


Lesenswert?

Ich könnte mir jetzt vorstellen, wo der Fehler liegt. Ich habe ja den 
NSS-Pin als Alternate Function konfiguiert, steuere diesen Pin aber 
selber an.

Bisher bin ich davon ausgegangen, dass ich wenn
1
SPI_Init_BMA020.SPI_NSS               = SPI_NSS_Soft;

gesetzt ist, dieser sich wie ein ganz normaler Pin verhält. Im 
Diller-Tutorial ist der NSS-Pin auch nicht als AF gesetzt, sondern als 
ganz normaler General purpose output mode-Pin.

von Alex W. (a20q90)


Lesenswert?

MISO und /CS ist vertauscht!

von Daniel V. (Gast)


Lesenswert?

Alex W. schrieb:
> MISO und /CS ist vertauscht!

Wie kommst Du jetzt darauf?

von Daniel V. (voda) Benutzerseite


Angehängte Dateien:

Lesenswert?

So, ich habe jetzt nochmal rumprobiert und der SPI-Code von Felix 
funktioniert leider nicht und ich hab auch kein Schimmer mehr woran es 
noch liegen kann.

Das einzige was jetzt klappt ist NSS und der Takt. Der Takt stimmt auch 
überein, was ich auf dem µC eingestellt habe.

Grundtakt: 80 MHz
AHB      : /1
APB1     : /2
APB2     : /16
SPI1/div : /64

Macht f = (80/16*64) = 78,125 kHz. Am Oscar habe ich eine Zeit von 12,8 
µs also 78,125 kHz gemessen. Der NSS und die MISO sind natürlich nicht 
vertauscht.

Ich bekomme keinerlei Daten auf den Bus beschrieben, obwohl ich mich ans 
das Protokoll des Datenblattes gehalten habe.

Kann mir einer vllt noch ein Impuls geben?

Danke und Gruß
Daniel

PS: Bei einem Bild habe ich versehentlich den Schalter an der Messspitze 
1x verschoben.

von Stefan F. (Gast)


Lesenswert?

zeige mal den Schaltplan inklusive Pegelwandler, falls vorhanden.

von Daniel V (Gast)


Lesenswert?

Schau mal in einem der oberen Threads, da ist eine PDF von dem ELV 
Bausatz, da ist der Schaltplan enthalten.

von Stefan F. (Gast)


Lesenswert?

Ach, das ELV Teil. Mit dem war ich auch schonmal verzweifelt. In meinem 
Fall waren die Pull-Ups der Pegelwandler für Lego Mindstorms zu klein. 
Und als ich sie dann vergrößerte, hatte ich ganz ähnliche 
Signalverläufe, wie du.

Ich hatte letztendlich die Pegelwandler ausgebaut. Die I/O Pins des BMA 
Chips sind trotz niedrigerer Spannungsversorgung 3,3V tolerant.

Versuche das mal.

von Christopher C. (trihexagon)


Lesenswert?

Gib uns mal die betreffenden Registerinhalte von SPI und GPIO. Das 
müsste man ja dann reproduzieren können...

von Daniel V. (Gast)


Angehängte Dateien:

Lesenswert?

Stefan U. schrieb:
> Ich hatte letztendlich die Pegelwandler ausgebaut. Die I/O Pins des BMA
> Chips sind trotz niedrigerer Spannungsversorgung 3,3V toleran

Diesen Tipp habe ich an anderer Stelle auch schon bekommen. Ich werde 
dafür einen Sensor opfern.

Christopher C. schrieb:
> Gib uns mal die betreffenden Registerinhalte von SPI und GPIO. Das
> müsste man ja dann reproduzieren können...

Sehr gerne.

von Felix F. (wiesel8)


Lesenswert?

PullUps braucht man beim SPI nicht. Und die Beschaltung des BMA ist auch 
völlig uninteressant, solange am Oszi keine richtigen SPI Signale 
ankommen.
Lade dir mal von ST die SPL oder Cube für den F4 runter. Dort sind für 
jede Peripherie mehrere Beispiele drin. Und damit funktionierts dann 
auch garantiert! Ich (und anscheinend auch kein anderer) habe keine Lust 
mich durch dieses ganze Bitgeschubse durchzuarbeiten, wenn es dafür 
einheitliche, prozessorunabhängige APIs gibt. Vlt. gibts ja Motivierte, 
die das für dich machen.

mfg

von Daniel V. (voda) Benutzerseite


Angehängte Dateien:

Lesenswert?

Normalerweise müsste ich doch ohne Sensor auf der MOSI die Bytes 
0x80|0x00 sehen. Aber leider sehe ich diese nicht. Der Fehler muss im 
Code liegen. Das kann doch nicht sein...

Felix F. schrieb:
> Und die Beschaltung des BMA ist auch
> völlig uninteressant, solange am Oszi keine richtigen SPI Signale
> ankommen.

Es steht in der Anleitung aber expizit drin, das die Pullups aktiviert 
werden sollen. Siehe mein Post vom 01.10.2016 14:49. Natürlich hatte ich 
die Pullups auch schon deaktiviert. Die Timings und NSS funktionieren 
ja, nur die MOSI und MISO nicht.

Kann das nicht an der fehlerhaften Sende/Empfangsroutine liegen? Auf der 
MOSI ist ja einmal ein Peak.

Danke und Gruß
Daniel

: Bearbeitet durch User
von Felix F. (wiesel8)


Lesenswert?

Daniel V. schrieb:
> Es steht in der Anleitung aber expizit drin, das die Pullups aktiviert
> werden sollen.

Ja, aber solange der SPI nicht funktioniert ist es völlig egal was der 
Sensor will.

Mal angenommen der SPI ist richtig initialisiert, dann müsste auch was 
auf MOSI gesendet werden, wenn du ins DR schreibst:
1
SPIx->DR = Data;

Aber solange hierbei nichts auf dem Oszi erscheint, ist der SPI bzw. die 
GPIOs nicht richtig initialisiert!

mfg

: Bearbeitet durch User
von Daniel V. (voda) Benutzerseite


Angehängte Dateien:

Lesenswert?

Felix F. schrieb:
> Daniel V. schrieb:
>> Es steht in der Anleitung aber expizit drin, das die Pullups aktiviert
>> werden sollen.
>
> Ja, aber solange der SPI nicht funktioniert ist es völlig egal was der
> Sensor will.
>
> Mal angenommen der SPI ist richtig initialisiert, dann müsste auch was
> auf MOSI gesendet werden, wenn du ins DR schreibst:SPIx->DR = Data;
> mfg

Ja, das tut er auch. Der Peak ist abhängig von:
1
bma020_Write(SPI1,0x10,0x00);

: Bearbeitet durch User
von Felix F. (wiesel8)


Lesenswert?

Schreib mal FF oder 55 ins DR. Und welches Signal ist welche Farbe? Hast 
du die GPIOs korrekt initialisiert? AF_Funktion?

mfg

von Daniel V. (voda) Benutzerseite


Angehängte Dateien:

Lesenswert?

Felix F. schrieb:
> Schreib mal FF oder 55 ins DR. Und welches Signal ist welche
> Farbe? Hast
> du die GPIOs korrekt initialisiert? AF_Funktion?
>
> mfg

AF gesetzt auf PA.05, PA.06, PA.07 auf AF5 (SPI1). Nun habe ich gesetzt:
1
bma020_Write(SPI1,0xFF,0x00);

Felix F. schrieb:
> Und welches Signal ist welche Farbe?

lila: MOSI    /am Sensor: SDI
blau: MISO    /am Sensor: SDO

also die Verschaltung ist MOSI am µC -> SDI am Sensor und umgekehrt

Danke und Gruß
Daniel

: Bearbeitet durch User
von Felix F. (wiesel8)


Lesenswert?

Bist du sicher, dass du Miso und Mosi nicht vertauscht hast am Oszi?
Konfiguriere Miso (PA6?) mal als Pull DOWN.

mfg

Mosi am besten auch als Pull DOWN.

: Bearbeitet durch User
von Daniel V. (voda) Benutzerseite


Angehängte Dateien:

Lesenswert?

Ich werd bekloppt... Grad mal die Linuxkiste mit Saleae mal 
angeschlossen und siehe da: 0xFF lässt sich lesen. Jetzt bleibt nur noch 
das MISO-Problem.

von Felix F. (wiesel8)


Lesenswert?

Hast du die PINs jetzt als Pull DOWN konfiguriert?

mfg

von Daniel V. (voda) Benutzerseite


Lesenswert?

Ja hab ich, ich wollte es gerade editieren ;)

von Felix F. (wiesel8)


Lesenswert?

Hast du den CS und Miso pin mal überprüft? Die schalten beide im selben 
Moment laut Oszi.

mfg

von Daniel V. (voda) Benutzerseite


Lesenswert?

Ja, die schalten in der Tat im selben Moment. Darauf habe ich jetzt gar 
nicht mehr geachtet. Das ist ja seltsam.

Daher habe ich nochmals die Registerwerte geguckt:

PA.04 normaler Output-Pin
PA.05 Clock
PA.06 MISO
PA.07 MOSI

(wie es im Datenblatt des STM auch steht und auch Cube es mir anzeigt)

PA.04 bis PA.07 sind als Alternate SPI konfiguiert.
Pull-Down auf MOSI

Gruß
Daniel

: Bearbeitet durch User
von Felix F. (wiesel8)


Lesenswert?

Wie sieht es aktuell auf dem Oszi aus?

mfg

von Daniel V. (voda) Benutzerseite


Angehängte Dateien:

Lesenswert?

Felix F. schrieb:
> Wie sieht es aktuell auf dem Oszi aus?
>
> mfg

Habe ich PULL-DOWN aktiv, habe ich auf der MISO starke Verschmutzungen.

Danke und Gruß
Daniel

: Bearbeitet durch User
von Felix F. (wiesel8)


Lesenswert?

Hier muss ein Hardwareproblem vorliegen, es kann nicht sein dass der Pin 
dauerhaft auf High gehalten wird!
Trenne mal die Misoleitung vom Sensor und miss einzeln mit dem Oszi. Am 
STM MUSS dabei Low anliegen, am Sensor normal auch.

mfg

von Daniel V. (voda) Benutzerseite


Angehängte Dateien:

Lesenswert?

Felix F. schrieb:
> Hier muss ein Hardwareproblem vorliegen, es kann nicht sein dass
> der Pin
> dauerhaft auf High gehalten wird!
> Trenne mal die Misoleitung vom Sensor und miss einzeln mit dem Oszi. Am
> STM MUSS dabei Low anliegen, am Sensor normal auch.
>
> mfg

Ist auch so. Ich habe jetzt mal ohne Sensor die Werte mit dem Oszi 
angeguckt. Also ist der BMA020-Sensor über die Wupper gegangen. Werde 
ich gleich mal einen neuen zusammenbauen.

Danke und Gruß
Daniel

[EDIT]: Fehler ist mit einem neuen Sensor reproduzierbar.

: Bearbeitet durch User
von Felix F. (wiesel8)


Lesenswert?

Wie sieht den die Beschaltung des Sensors aus?

mfg

von Daniel V. (voda) Benutzerseite


Lesenswert?

Felix F. schrieb:
> Wie sieht den die Beschaltung des Sensors aus?
>
> mfg

Schau mal, weiter oben, da ist der Schaltplan des ELV-Sensors, als 
pdf-Datei Die Modifikationen die Stefan und ein ein Bekannter von mit 
auch empfohlen haben, werde ich morgen mal bei einem Sensor durchführen.

Bei meinem Board gehen nur die vier Busleitungen an den Controller.

Gruß
Daniel

von Felix F. (wiesel8)


Lesenswert?

Daniel V. schrieb:
> Felix F. schrieb:
>> Wie sieht den die Beschaltung des Sensors aus?
>>
>> mfg
>
> Schau mal, weiter oben, da ist der Schaltplan des ELV-Sensors, als
> pdf-Datei Die Modifikationen die Stefan und ein ein Bekannter von mit
> auch empfohlen haben, werde ich morgen mal bei einem Sensor durchführen.
>
> Bei meinem Board gehen nur die vier Busleitungen an den Controller.
>
> Gruß
> Daniel

Genau das hilft mir doch nicht weiter. Hast du die Leitungen 1:1 
verbunden oder noch irgendeine Schaltung mit Pullups, Cs etc. 
dazwischen??

Da STM und BMA beide mit 3,3V arbeiten, würde ich einfach mal Miso und 
SDO direkt ohne sonst was verbinden. Mosi eigentlich auch. Nur Clk und 
CS sollten mit PullUps High gehalten werden, aber das kann der STM auch 
selbst ohne Hilfe.

mfg

: Bearbeitet durch User
von Daniel V. (voda) Benutzerseite


Lesenswert?

Ach so, nein. Die Leitungen sind vom µC zum Sensor über Buchsen. Im 
selben Post vom 01.10.2016 14:49 wo auch die PDF enthalten war, ist auch 
das Layout meiner Platine enthalten. Ich habe beim Design die Leitung 
extrem kurz gehalten und keinerlei Pullups oder sonstwas 
hinzugefügt.Also µC raus, Sensor-Eingang rein.

Der Sensor selber hat wiederum Pegelwandler, damit man den Sensor in 
einem großen Spannungsbereich einsetzten kann. Diese Flexibilität 
bezahlt man jedoch mit der maximalen Frequenz, welcher der Sensor 
betrieben werden kann.

Die Widerstände die Du unten sieht sind 22R für die USART, die zum FTDI 
gehen, die haben nichts mit dem Bus zu tun.

Danke und Gruß
Daniel

: Bearbeitet durch User
von Felix F. (wiesel8)


Lesenswert?

Setzt bei Miso/Mosi nochmal den Pullup, bzw verbinde Miso aber nicht, 
sondern miss nur den Ausgang beim Sensor mit dem Oszi und schick mal ein 
paar Befehle, ob der Sensor reagiert. Macht der Sensorausgang überhaupt 
was?

mfg

von Reiner.S (Gast)


Lesenswert?

Hast Du den UPULLUP von der Sensorplatine mit den 3,3V vom STM32 
verbunden?

von Daniel V. (Gast)


Lesenswert?

Guten Morgen zusammen,

Felix F. schrieb:
> Setzt bei Miso/Mosi nochmal den Pullup, bzw verbinde Miso aber nicht,
> sondern miss nur den Ausgang beim Sensor mit dem Oszi und schick mal ein
> paar Befehle, ob der Sensor reagiert. Macht der Sensorausgang überhaupt
> was?

Diese Messung werde ich heute Nachmittag direkt durchführen

Reiner.S schrieb:
> Hast Du den UPULLUP von der Sensorplatine mit den 3,3V vom STM32
> verbunden?

Nein, die Lötbrücke auf der Sensorplatine ist offen.

Danke und Gruß
Daniel

von Stefan F. (Gast)


Lesenswert?

Du musst die Pull-Ups mit der Versorgungsspannung verbinden, sonst 
hängen sie in der Luft.

von Daniel V. (Gast)


Lesenswert?

Die Lötbrücke J1 ist offen und nicht an 3,3 des µC angeschlossen. Wenn 
ich gleich zuhause bin, werde ich das schnell mal machen.

Sehr guter Einwand!

Danke und Gruß
Daniel

von Daniel V. (voda) Benutzerseite


Angehängte Dateien:

Lesenswert?

Leute, ich werde verrückt! Es scheint zu funktionieren und zwar mit 
diesem Tipp:

Stefan U. schrieb:
> Du musst die Pull-Ups mit der Versorgungsspannung verbinden, sonst
> hängen sie in der Luft.

Das darf doch wohl nicht wahr sein. Im Datenblatt ist die o.a. 
Verschaltung angegeben und ich bin wieder eine Erfahrung reicher in 
meiner noch sehr jungen Entwicklerlaufbahn...

Ich gebe 0x80|0x00 auf den Bus und als Antwort erhalte ich 0xFF02 was 
0b1111 1111 0000 0010 entspricht, was die Vorgabe im BMA-Datenblatt 
entspricht.

Ich werde das nun mal weitertesten. Wenn ich euch mal irgendwann mal 
persönlich treffen sollte, gebe ich euch ein Bier aus!

Danke und Gruß
Daniel

von Felix F. (wiesel8)


Lesenswert?

Also hast du doch noch eine Beschaltung am Sensor gehabt und nicht nur 
direkt über Buchsenleisten verbunden. Deshalb haben CS und Miso auch im 
selben Moment geschalten, da sie über die Pull Ups verbunden waren.
Und Enable hast du deswegen vmtl auch nicht bestromt...

mfg

: Bearbeitet durch User
von Daniel V. (voda) Benutzerseite


Angehängte Dateien:

Lesenswert?

Felix F. schrieb:
> Also hast du doch noch eine Beschaltung am Sensor gehabt und nicht
> nur
> direkt über Buchsenleisten verbunden. Deshalb haben CS und Miso auch im
> selben Moment geschalten, da sie über die Pull Ups verbunden waren.
> Und Enable hast du deswegen vmtl auch nicht bestromt...
>
> mfg

Ja klar, den Sensor von ELV besitzt einen Pegelwandler. ENABLE zieht den 
auf der Platine verbauten Linearregler auf Masse und wird somit 
ausgeschaltet. Die o.a. Schaltung war in der von mir geposteten pdf.

Jetzt frage ich mich, warum der Sensor bei den Arduino-Leuten ohne zu 
Murren fliegt und hier die Verschaltungsvorgabe aus dem Datenblatt des 
ELV nicht funktioniert...

Danke und Gruß
Daniel

: Bearbeitet durch User
von Daniel V. (voda) Benutzerseite


Angehängte Dateien:

Lesenswert?

Zwei Sachen habe ich:

In meinem Post: www.mikrocontroller.net/topic/407652#4746755 ist in 
einem Bild der Fehlerteufel eingeschlichen. Der Pin Enable wird nicht an 
UIN angeschlossen, sondern UPULLUP. Dies habe ich entsprechend geändert.

Felix, deine Routine
1
uint8_t Spi_ReadByte(SPI_TypeDef *SPIx, uint8_t _address)
2
{
3
  _address &= 0x7F;
4
5
  return Spi_WriteWord(SPIx, _address<<8 & 0x7f00);
6
}

habe ich nach wie vor nicht verstanden. Der Zeiger ist klar, aber die 
Variable _adresse verundest Du das erste Byte mit 1 shiftest diese nach 
links um 8 Bits und verundest diese wieder mit zwei Bytes.

Warum machst Du das?

Leider funktioniert diese Readroutine nicht. Hab ich einen Brett vor 
meinem Kopf (siehe Logic-Bild) :(
1
void bma020_READ_DATA_X(void)
2
{
3
  BMA020_NSS_LOW;
4
    bma020_temp_data_X_value = bma020_Read(SPI1,READ_DATA|DATA_ACC_X);
5
  BMA020_NSS_HIGH;
6
  
7
 USART_SendData(USART3, bma020_temp_data_X_value);
8
   while(!(USART3->SR & USART_FLAG_TC));   
9
 
10
}

Zur Vervollständigung, ein Auszug aus der Headerdatei:
1
/************************SENSORREGISTER*******************/
2
#define REG_CONTROL_15     0x15
3
#define REG_CONTROL_14     0x14    
4
5
/************************DATENREGISTER********************/
6
#define DATA_ACC_X     0x03
7
#define DATA_ACC_Y     0x05
8
#define DATA_ACC_Z     0x07
9
 
10
/************************REGISTERBEFEHLE*******************/
11
#define READ_DATA          0x80
12
13
#define BANDWIDTH_1500Hz   0x06
14
#define ONLY_MSB_VALUE     (1<<3)
15
#define WAKEUP_80ms        0x03

Das Senden funktioniert ohne Probleme und habe die entsprechenden Bits 
im Register 0x14 (Bandbreite) und 0x15 (shadow_dis) gesetzt und dies 
wird auch übertragen.

Danke und Gruß
Daniel

: Bearbeitet durch User
von Daniel V. (voda) Benutzerseite


Angehängte Dateien:

Lesenswert?

Also, die Read-Funktion bringt mich an den Rand des Wahnsinns. Folgendes 
habe ich jetzt implementiert.

Als allererstes habe ich ein Flag definiert. Dieses markiert, ob die 
Startsettings geladen wurden.
1
#define BMA020_SET_SUCCESS  1
2
#define BMA020_SET_FAIL     0

Danach habe ich eine if-Abfrage geschrieben, welcher dieses Flag 
abfragt.
1
void bma020_READ_DATA(void)
2
{
3
  if (bma020_setting_flag == BMA020_SET_FAIL)
4
  {
5
    BMA020_NSS_LOW;
6
    bma020_Write(SPI1,REG_CONTROL_14, BANDWIDTH_1500Hz);
7
    bma020_Write(SPI1,REG_CONTROL_15, ONLY_MSB_VALUE);
8
    BMA020_NSS_HIGH;    
9
    bma020_setting_flag = BMA020_SET_SUCCESS;
10
  }  
11
    
12
  if(bma020_setting_flag == BMA020_SET_SUCCESS)
13
  {     
14
   BMA020_NSS_LOW;
15
   bma020_temp_data_X_value = bma020_Read(SPI1,READ_DATA|DATA_ACC_X);
16
   USART_SendData(USART3, bma020_temp_data_X_value);
17
   while(!(USART3->SR & USART_FLAG_TC)){}; 
18
   BMA020_NSS_HIGH;    
19
  }
20
}

Auch habe ich es geschafft, Felix' seine Routine anzupassen:
1
uint8_t bma020_Read(SPI_TypeDef *SPIx, uint8_t _address)
2
{
3
  //_address |= 0x01;
4
  //_address &= 0x7F;
5
  return bma020_WriteWord(SPIx, _address<<8);
6
}

Es passt auch soweit alles, aber die MISO ist dauerhaft HIGH, er 
überträgt keine Daten, obwohl die Settings korrekt übertragen werden 
(Bandbreite und das gesetzte Shadow-Bit). Normalerweise müsste ich doch 
die Registerwerte auf 0x03 (ACC X) im zweiten Byte auslesen und auf die 
USART schreiben können. Das MSB=1 schicke ich auch mit. Ich verstehe es 
nicht.

Danke und Gruß
Daniel

: Bearbeitet durch User
von Daniel V. (voda) Benutzerseite


Lesenswert?

Keiner eine Idee? Das Dummybyte schick ich auch mit. Keine Reaktion vom 
Sensor.

Danke und Gruß
Daniel

von Marc H. (marchorby)


Angehängte Dateien:

Lesenswert?

Daniel V. schrieb:
> Alex W. schrieb:
>> MISO und /CS ist vertauscht!
>
> Wie kommst Du jetzt darauf?

https://www.mikrocontroller.net/attachment/306522/SPI_BMA020_Logic.png

Wahrscheinlich weil /CS den Chipselect ist und da keine Daten laufen 
sollten:

von Daniel V. (voda) Benutzerseite


Lesenswert?

Gut gesehen :). Ich vermute, dass ich die Messkabel verwechselt habe. 
Den Fehler habe ich schon korrigiert.  Ich bekomme auch Daten gesendet 
und ich kann diese auf der MISO sehen (bei 0x80|0x00) bekomme ich die 
Antwort xxxxxxx10. Nun komme ich aber mit der Read-Routine vom Felix 
nicht weiter (hab vieles schon ausprobiert).

Siehe frühere Posts.

Ich erwarte, wenn ich auf die MOSI (0x15|(1<<3)) für das Shadow-Bit und 
die Bandbbreite (0x14|0x06) anschließend (0x01|0x02 & 0x00) das 
Dummybyte die Daten des Sensors erhalte. Dies macht die Readfunktion 
aber nicht und ich raff es einfach nicht.

Danke und Gruß
Daniel

: Bearbeitet durch User
von Daniel V. (voda) Benutzerseite


Lesenswert?

Leider muss ich dieses Thema nochmal aufwärmen, aber allgemein zu SPI:

Felix F. schrieb:
> CS_Low;
> // Schreibbefehl an Register 0x06
> SPI_Write(SPI1, 0x86);
> // Schreibe 0x00 in Register 0x06
> SPI_Write(SPI1, 0x00);
> CS_High;


Dieser Code funktioniert mit 8 Bit nicht. Hier die jeweiligen Funktionen 
von Felix die ich anderweitig einsetzten wollte (nicht BMA020, der läuft 
einwandfrei)
1
static uint8_t Spi_WriteWord(SPI_TypeDef *SPIx, uint16_t _word)
2
{
3
  // Select chip
4
  GPIO_ResetBits(GPIOC, GPIO_Pin_9);
5
6
  // Loop while DR register is not empty
7
  while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
8
9
  // Send byte through the SPIx peripheral
10
  SPI_I2S_SendData(SPIx, _word);
11
12
  while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
13
14
  // Deselect chip
15
  GPIO_SetBits(GPIOC, GPIO_Pin_9);
16
17
  // Return the byte read from the SPI bus
18
  return (uint8_t)SPI_I2S_ReceiveData(SPIx);
19
}
20
21
uint8_t Spi_ReadByte(SPI_TypeDef *SPIx, uint8_t _address)
22
{
23
  // Clear MSB -> Read mode
24
 _address &= 0x7F;
25
26
 return Spi_WriteWord(SPIx, _address<<8 & 0xff00);
27
}
28
29
void Spi_WriteData(SPI_TypeDef *SPIx, uint8_t _address, uint8_t _data)
30
{
31
 // Set MSB to 1 -> Write mode
32
 _address |= 0x80;
33
34
 Spi_WriteWord(SPIx, _address<<8 | _data);
35
}

Wie bekomme ich das auf 8 Bit umgestellt? Bin ich blind oder sollte ich 
wirklich mal eine Pause machen??

Danke und Gruß
Daniel

: Bearbeitet durch User
von Felix F. (wiesel8)


Lesenswert?

Der Code funktioniert mit 8 bit nicht, weil er für 16 bit geschrieben 
wurde. Deshalb habe ich es auch in meinem ersten Beitrag geschrieben und 
die Funktion !WriteWORD! genannt!

Und daraus eine 8 bit Funktion abzuleiten ist nun wirklich nicht schwer, 
vorausgesetzt man kann ein ganz, ganz kleines bisschen programmieren.
1
uint8_t Spi_ReadByte(SPI_TypeDef *SPIx)
2
{
3
  return Spi_WriteByte(SPIx, 0xFF);
4
}
5
6
uint8_t Spi_WriteByte(SPI_TypeDef *SPIx, uint8_t _data)
7
{
8
  // Loop while DR register is not empty
9
  while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
10
11
  // Send byte through the SPIx peripheral
12
  SPI_I2S_SendData(SPIx, 0xFF & _data);
13
14
  while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
15
16
  // Return the byte read from the SPI bus
17
  return (uint8_t)SPI_I2S_ReceiveData(SPIx);
18
}

mfg

: Bearbeitet durch User
von Daniel V. (voda) Benutzerseite


Lesenswert?

Felix F. schrieb:
> Deshalb habe ich es auch in meinem ersten Beitrag geschrieben und
> die Funktion !WriteWORD! genannt!

Ich sagte ja, ich bin blind... Felix, vielen Dank dafür, manchmal sieht 
man den Wald vor lauter Bäumen mehr...

Gruß
Daniel

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.