Forum: Mikrocontroller und Digitale Elektronik STM32 - SPI Schnittstelle empfängt mal korrekt und dann wieder nicht


von C. H. (hedie)


Angehängte Dateien:

Lesenswert?

Guten Abend zusammen


Ich habe hier ein merkwürdiges Problem.

An meinem STM32F105RB hängt eine SD-Card am SPI1
Ich verwende den Code von elm-chan.

Nun habe ich ein Problem mit der SPI kommunikation...
Für das Mounten des Volume wird im MBR der Kate nach dem Pattern 0xAA55 
gesucht.

Dazu wird die karte an entsprechender Stelle ausgelesen.
Nun das Problem, mit dem LA überprüft sendet die Karte beim ersten 
Empfang 0x55, der STM empfängt jedoch 0xEB
bei der zweiten Übertragnung zeigt der LA 0xAA, der STM32 ebenfalls 
0xAA.
Dies ist permanent reproduzierbar.

Die kommunikation an anderen Codestellen klappt meines wissens 
eigentlich.

Hier meine SPI Read routine:
1
unsigned char read_spi (SPI_TypeDef* SPIx)
2
{       //msb first
3
  write_spi(SPIx,0xFF);
4
  while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_BSY) == SET);
5
  while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
6
  return SPI_I2S_ReceiveData(SPIx);
7
}
8
9
10
static
11
BYTE rcvr_mmc (void)
12
{
13
  BYTE r;
14
15
  r = read_spi(SPI1);
16
17
  return r;
18
}

aufgerufen wird rcvr_mmc.
Bereits dort hat die Variable r den flaschen Wert.

Anbei noch die 2 logs des LA's

Ich erkenne dort keinen unterschied was das Timing anbelangt. Der LA 
erkennt die gesendeten Bytes ja auch korrekt.

Meine SPI Einstellungen:
230Khz CLK
CPOL = low
CPHA = erste Flanke

Hat jemand eine Idee woran das liegen könnte?

Danke schonmal :)

von Matthias K. (matthiask)


Angehängte Dateien:

Lesenswert?

Schwierig, ohne Dein Programm genau zu kennen.

Ich häng Dir mal funtionsfähigen Low-Level Code für SPI SDCARD an. 
Vielleicht eine Hilfe.

von C. H. (hedie)


Angehängte Dateien:

Lesenswert?

Matthias K. schrieb:
> Schwierig, ohne Dein Programm genau zu kennen.
>
> Ich häng Dir mal funtionsfähigen Low-Level Code für SPI SDCARD an.
> Vielleicht eine Hilfe.

Hallo Matthias
Vielen Dank für deine Antwort....

Was mir auffält, ist dass du nicht bis zum ende des Transmit wartest.
1
/*-----------------------------------------------------------------------*/
2
/* Transmit/Receive a byte to MMC via SPI  (Platform dependent)          */
3
/*-----------------------------------------------------------------------*/
4
static BYTE stm32_spi_rw( BYTE out )
5
{
6
  /* Loop while DR register in not empty */
7
  /// not needed: while (SPI_I2S_GetFlagStatus(SPI_SD, SPI_I2S_FLAG_TXE) == RESET) { ; }
8
9
  /* Send byte through the SPI peripheral */
10
  SPI_I2S_SendData(SPI_SD, out);
11
12
  /* Wait to receive a byte */
13
  while (SPI_I2S_GetFlagStatus(SPI_SD, SPI_I2S_FLAG_RXNE) == RESET) { ; }
14
15
  /* Return the byte read from the SPI bus */
16
  return SPI_I2S_ReceiveData(SPI_SD);
17
}

Ich habe nach meindem SendData ja noch dies hier drinn

1
while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_BSY) == SET);

Du schreibst ja in deinem Kommentar, dass das Warten auf das ende des 
Sendens nicht nötig ist also auf das flag TXE. Weshalb nicht?
Ich hatte ohne das Warten Probleme.

Der STM hatte dann nämlich sein TX Buffer wieder gefüllt obwohl der alte 
noch nicht gesendet war. Mit dem flag TXE konnte ich dies leider nicht 
korrekt erkennen ob er leer war oder nicht.
Nach einigem Googlen hab ich herausgefunden dass anscheinend auch andere 
dieses Problem haben.

Lösen konnte ich es mit der obigen Codezeile. Das Warten auf das BSY 
Flag

Bevor ich jetzt meinen gesamten Code umkremple und mit deinem vereine,
habe ich dir im Anhang noch mein komplettes Projekt angehängt...

Vielleicht siehst du da etwas verdächtiges....

Danke schonmal

von Matthias K. (matthiask)


Lesenswert?

Claudio Hediger schrieb:
> /* Wait to receive a byte */
>   while (SPI_I2S_GetFlagStatus(SPI_SD, SPI_I2S_FLAG_RXNE) == RESET) { ; }

Wenn das Byte empfangen wurde, ist zwangsläufig auch ein Byte gesendet 
wurden. (immer so im SPI Master Betrieb). Deshalb kann man sich das 
zusätzliche warten beim senden sparen.

von C. H. (hedie)


Lesenswert?

So ich konnte das Problem dank Matthias lösen :)
Also an dieser Stelle, Danke Matthias.

Folgendes ist geschehen,

in meiner spi_write funktion lese ich den empfangs puffer nicht ein.
somit bleit nach dem senden eines bytes das RXNE Flag gesetzt.
Dies bedeutet, der Controller bzw. die Software meint es hat etwas im 
empfangs buffer.

Wenn nun nach einem byte Senden ein empfangen kommt, wird zuerst 0xFF 
gesendet und gleich danach überprüft ob etwas empfangen wurde (mit dem 
RXNE Flag).

Da dieses nun ja schon von der vorherrigen write operation gesetzt ist, 
wird der Buffer sofort ausgelesen. Dies noch bevor das neue Byte 
überhaupt eingelesen wurde.

Deshalb war mein Byte welches ich empfangen habe, jenes von einer 
vorherigen transaktion.

Die Lösung:

Wie Matthias in seinem code auch, wird bei mir nach jedem byte senden 
auch eines empfangen.

Dadurch wird das Flag RXNE gelöscht. und alles klappt einwandfrei :)

hier der Code:
1
unsigned char rw_spi (SPI_TypeDef* SPIx, unsigned char data_out)
2
{       //msb first
3
  SPI_I2S_SendData(SPIx,data_out);
4
  while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_BSY) == SET);
5
  while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
6
  return SPI_I2S_ReceiveData(SPIx);
7
}

Danke euch allen :)

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.