Forum: Mikrocontroller und Digitale Elektronik STM32 SPI wartet nicht bis CLK fertig ist


von Holger K. (holgerkraehe)


Angehängte Dateien:

Lesenswert?

Hallo zusammen

Ich benutze folgenden Code für meine SPI Routinen:
1
void write_spi (unsigned char data_out)
2
{       //msb first
3
4
  SPI_I2S_SendData(SPI2,data_out);
5
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
6
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
7
  SPI_I2S_ReceiveData(SPI2);
8
}
9
10
unsigned char read_spi (void)
11
{
12
13
  SPI_I2S_SendData(SPI2,0x00);
14
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
15
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
16
  return SPI_I2S_ReceiveData(SPI2);
17
18
}

NSS ist als Soft konfiguriert.

meine Zugriff sieht etwa wie folgt aus:
1
  cs_0;
2
  read_spi;
3
  cs_1;


Nun ist es leider so, dass CS bereits auf 1 geht, während dem am SPI 
noch die letzte CLK Flanke kommt.
Ja noch schlimmer, CS kann sogar wieder auf low gehen, während dem die 
letzte CLK Flanke der vorherigen Übertragung noch am Pin anliegt.

Siehe dazu die Bilder im Anhang.

Wenn ich vor das CS1 ein Delay einfüge, funktionierts.

Aber weshalb funktioniert der obige SPI code nicht?

Danke

von Holger K. (holgerkraehe)


Lesenswert?

Für alle die es interessiert.
1
void write_spi (unsigned char data_out)
2
{       //msb first
3
4
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
5
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
6
  SPI_I2S_SendData(SPI2,data_out);
7
8
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
9
  SPI_I2S_ReceiveData(SPI2);
10
11
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
12
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
13
}
14
15
unsigned char read_spi (void)
16
{
17
18
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
19
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
20
  SPI_I2S_SendData(SPI2,0x00);
21
22
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
23
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
24
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
25
26
  return SPI_I2S_ReceiveData(SPI2);
27
}

von jibi (Gast)


Lesenswert?

Die Befehle werden parallel abgearbeitet und du hast dir einen 
Pipeline-Hazard gebaut.

Gruß J

von chris (Gast)


Lesenswert?

Und wie stellst du dir mit deinen beiden Funktionen eine funktionierende 
SPI-Kommunikation vor?
SPI braucht eigentlich nur eine einzige Funktion:
1
uint8_t SPI_transfer_byte(uint8_t tx_data);

Senden und Empfangen geht immer gleichzeitig. Wenn man nur Senden will, 
wertet man den Rückgabewert halt einfach nicht aus.

Deine receive-Funktion sendet ja auch wieder ein Dummy-Byte, so dass das 
vorher im RX-Register enthaltene Byte wieder rausfliegt.

von Christian J. (Gast)


Lesenswert?

Kommt mir bekannt vor, gleiches Problem:

Beitrag "STM32F4xx: Kann mal jemand die SPI testen?"

von Christian J. (Gast)


Lesenswert?

Holger K. schrieb:

> SPI_I2S_ReceiveData(SPI2);
>   while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
>   while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);

Nonsense. Schau Dir mal intensiv die Diagramme an, wie die Events da so 
kommen. Das funktoniert mit jedem Dummy Befehl auch. BSY wird nur vor 
Abschalten der SPI angefragt. Delay(2us) reicht aus.

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.