Forum: Mikrocontroller und Digitale Elektronik SPI empfaengt nur 0xFF


von Matt S. (matze_93)


Angehängte Dateien:

Lesenswert?

Hi Leute,

ich probiere seid ein paar Tagen einen Sensor via SPI auszulesen.
Bei dem Sensor handelt es sich um einen BMP280, der schon auf einer 
Leiterplatte angebracht ist. (siehe Breadboard)
Mittels N-Kanal Mosfet (2N 7000) und 2 10k Pull-Up Widerständen habe ich 
die Logic Level angepasst, da der Sensor mit 3V3 arbeitet.
Der µC ist ein AtMega 328P auf dem Entwicklungsboard xplained mini.
Bis dahin funktioniert auch alles.
Ich kann mit Multimeter die eingestellten Pegel messen.

Leider habe ich kein Oszi.

Software seitig gibt es 2 Dinge die mich stören:

1. Der Debugger zeigt mir im Atmel Studio 7 immer ein leeres SPDR an, 
egal ob ich etwas rein schreibe (SPDR = 0xD0) das SPDR bleibt leer.

2. Wenn ich mein Programm laufen lasse empfange ich als ID 0xFF welche 
eigentlich 0x58 sein sollte. Habe mir nichts weiter dabei gedacht und 
weiter programmiert um die "pressure Werte" auszulesen, MSB und LSB 
bekomme ich auch als 0xFF angezeigt.


Weis jemand wo das Problem liegt? bzw liegen könnte?

hier ist der Code:
main.c:
1
 
2
/*
3
 * BMP280-SPI.c
4
 *
5
 * Created: 17.06.2017 11:45:17
6
 * Author : MattZe
7
 */ 
8
9
#ifndef F_CPU
10
#define F_CPU      16000000UL
11
#endif
12
13
#include <avr/io.h>
14
#include "spi.h"
15
#include <util/delay.h>
16
#include <avr/interrupt.h>
17
18
#define char uint8_t
19
#define unsigned int uint16_t
20
#define IDAddr      0xD0    // see Datasheet BMP280 page 31 & 24 ff.
21
22
23
int main(void)
24
{
25
  DDRC = 0xF0;
26
  PORTC |= (1 << DDC5);
27
28
  uint8_t ID = 0x00;
29
  uint8_t pressMSB = 0x00;
30
  uint8_t pressLSB = 0x00;
31
  uint16_t press = 0x00;
32
  
33
  
34
  //  initialize SPI as Master, MSB first, Interrupt off, clock rate: f(osc)/128, Mode: 00
35
  spi_master_init ();        // SPI wird nicht eingeschaltet (SPE nicht gesetzt)
36
  PORTB |= (1 << DDB2);      // zur Sicherheit nochmal auf VCC ziehen
37
  
38
  SPCR |= (1 << SPE);        // enable SPI
39
  
40
  //  start communication
41
  PORTB &= ~(1<<DDB2);
42
  // get ID
43
  ID = spi_fast_shift (0xD0);
44
  //  determinate Communication
45
  PORTB |= (1<<DDB2);
46
  
47
  spiConfigBMP280 ();
48
  
49
  while (1)
50
  {
51
    /*    write Register-Addr without MSB 
52
        MSB is 1 if read access
53
        MSB is 0 if write access
54
    */
55
    ID = SPIMasterSend (0xD0);
56
    if (ID == 0x00)          //  wurde keine ID gelesen wird die LED an PC5 ausgeschaltet
57
      PORTC &= ~(1 << DDC5);
58
    
59
    press = spiPressBMP280 (pressMSB, pressLSB);
60
    
61
    ID = 0x00;
62
  }
63
  
64
  while (1);
65
  
66
  return 1;
67
}


spi.c
1
#include "spi.h"
2
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
6
#define PORT_SPI    PORTB
7
#define DDR_SPI     DDRB
8
#define DD_MISO     DDB4
9
#define DD_MOSI     DDB3
10
#define DD_SS       DDB2
11
#define DD_SCK      DDB5
12
13
void spi_master_init (void) 
14
{
15
  SPCR = 0x00;                // vorbeugend
16
  DDRB |= ((1<<DD_SCK) | (1<<DD_MOSI) | (1<<DD_SS));  // setze SCK,MOSI,PB2 (SS) als Ausgang
17
  DDRB &= ~(1<<DD_MISO);              // setze MISO als Eingang
18
  PORTB |= ((1<<DD_SCK) | (1<<DD_SS));        // SCK low und PB2 high (ist mit SS am Slave verbunden)
19
  SPCR |= ((1<<MSTR) | (1<<CPHA) | (1<<SPR0) | (1<<SPR1));      //Master, Taktrate fck/128
20
}
21
uint8_t spi_fast_shift (uint8_t data)
22
// Clocks only one byte to target device and returns the received one
23
{
24
    SPDR = data;
25
    while(!(SPSR & (1<<SPIF)));
26
    return SPDR;
27
}
28
29
uint8_t SPIMasterSend(uint8_t data)
30
{
31
  //  start communication
32
  PORTB &= ~(1<<DDB2);
33
  //  send data
34
  SPDR = data;
35
  //  wait for transmition complete
36
  while (!(SPSR &(1<<SPIF)));
37
  //  Empfangene Daten in Variable zurück schreiben
38
  data = SPDR;
39
  //  determinate Communication
40
  PORTB |= (1<<DDB2);
41
  
42
  return data;
43
}

BMP280.c:
1
/*
2
**
3
**
4
*/
5
#define ConfigAddr    0x74    // see Datasheet BMP280 page 31 & 24 ff.
6
#include "spi.h"
7
#include <avr/io.h>
8
9
uint8_t spiConfigBMP280 (void)
10
{
11
  //  start communication
12
  PORTB &= ~(1<<DDB2);
13
  // configure Sensor
14
  spi_fast_shift (ConfigAddr);
15
  spi_fast_shift (0xB7);
16
  //  determinate Communication
17
  PORTB |= (1<<DDB2);
18
  
19
  //  start communication
20
  PORTB &= ~(1<<DDB2);
21
  // configure Sensor
22
  spi_fast_shift (ConfigAddr+1U);
23
  spi_fast_shift (0x10);
24
  //  determinate Communication
25
  PORTB |= (1<<DDB2);
26
  
27
  return 1;
28
}
29
30
uint16_t spiPressBMP280 (uint8_t MSB, uint8_t LSB)
31
{
32
  //  start communication
33
  PORTB &= ~(1<<DDB2);
34
  // get pressure Value
35
  MSB = spi_fast_shift (0xF7);
36
  //  determinate Communication
37
  PORTB |= (1<<DDB2);
38
  
39
  //  start communication
40
  PORTB &= ~(1<<DDB2);
41
  // get pressure Value
42
  LSB = spi_fast_shift (0xF8);
43
  //  determinate Communication
44
  PORTB |= (1<<DDB2);
45
  
46
  return ((MSB<<8U) + LSB);
47
}

das ganze Projekt habe ich nochmals bei Google Drive hoch geladen:
https://drive.google.com/open?id=0B99TRuv5UwfWZzMxSmhVbF9VWVk


ich hoffe ich habe alles einigermaßen verständlich erklärt,
vielen Dank schon mal vor ab

von Erwin D. (Gast)


Lesenswert?

Sieh dir mal die MOSI-Leitung an.
Klingt so, als hättest du einen Schluss gegen HIGH.

von Stefan F. (Gast)


Lesenswert?

Mach erstmal eine LED an MISO, MOSI und CLK, dann takte das Ding so 
langsam wie möglich (am besten so, dass du die Signale an den LED's 
mitlesen kannst).

Kontrolliere anhand der LED's welchers Fehlerbild zutrifft:

a) Kein Takt
b) MOSI sendet nichts.
c) MOSI sendet etwas aber MISO empfängt nichts.
d) CLK, MOSI und MISO sind alle aktiv, aber das SPDR  ist trotzdem immer 
0xFF.

Davon hängt ab, wie man weiter vorgeht.

von Stefan E. (sternst)


Lesenswert?

Deine ganze Kommunikation ist grundlegend falsch. Wie soll der BMP280 
z.B. die ID mit der gleichen SPI-Übertragung raus takten, mit der du den 
Befehl zum Ausgeben der ID rein taktest? Der kann doch nicht Hellsehen.

Die FF werden einfach die Dummy-Daten sein, die der BMP280 beim Empfang 
des Befehls raus taktet.

: Bearbeitet durch User
von Jim M. (turboj)


Lesenswert?

Matt S. schrieb:
> 1. Der Debugger zeigt mir im Atmel Studio 7 immer ein leeres SPDR an,
> egal ob ich etwas rein schreibe (SPDR = 0xD0) das SPDR bleibt leer.

SPDR sollte man niemals im Debugger direkt verwenden. Dies ist eins 
der Hardware Register bei denen das Lesen Nebenwirkungen auslöst.

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.