STM32 SPI Init

Gast #2843690
Hallo,

ich versuche grade die SPI Schnittstelle von dem STM32F407 zum laufen zu 
bringen. Eig. möchte ich dann eine SD Karte ansteuern. Nur leider kommt 
noch nicht mal ein Takt Signal heraus. Vielleicht könnt ihr euch mal den 
Code ansehen.
1
#include "stm32f4xx.h"
2

3
void SDCard_InitLowLevel(void);
4
void SDCard_Init(void);
5

6
uint16_t response;
7

8
int main(void)
9
{
10
  SystemInit(); // 8MHz extern -> PLL -> 168MHz
11

12
  response = 0x00;
13

14
  SDCard_InitLowLevel();
15

16
    while(!response)
17
    {
18
      SDCard_Init();
19
    }
20

21
    response = response; // Breakpoint
22

23
    //while(1);
24

25
    return 1;
26
}
27

28
void SDCard_InitLowLevel(void)
29
{
30
  GPIO_InitTypeDef GPIO_InitStruct;
31
  SPI_InitTypeDef SPI_InitStruct;
32

33
  /*
34
   * Clocks
35
   */
36
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
37
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
38

39
  /*
40
  * DeInit
41
  */
42
  SPI_I2S_DeInit(SPI1);
43

44
  /*
45
   * Alternate Function
46
   */
47
  GPIO_PinAFConfig(GPIOA, GPIO_Pin_5, GPIO_AF_SPI1);
48
  GPIO_PinAFConfig(GPIOA, GPIO_Pin_6, GPIO_AF_SPI1);
49
  GPIO_PinAFConfig(GPIOA, GPIO_Pin_7, GPIO_AF_SPI1);
50

51
  /*
52
   * GPIO Init
53
   * PA5 (SCK) to SD card pin 5 (SCLK)   PP NOPULL
54
   * PA6 (MISO) to SD card pin 7 (DO)  PP UP
55
   * PA7 (MOSI) to SD card pin 2 (DI)  PP UP
56
   * PA8 (NSS) to SD card pin 1 (CS)  PP UP
57
   */
58
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
59
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
60
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8;
61
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
62
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
63
  GPIO_Init(GPIOA, &GPIO_InitStruct);
64

65
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
66
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
67
  GPIO_Init(GPIOA, &GPIO_InitStruct);
68

69
  GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET);
70

71
  /*
72
   * SPI1 Init
73
   */
74
  SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
75
  SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
76
  SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;
77
  SPI_InitStruct.SPI_CRCPolynomial = 0;
78
  SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
79
  SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
80
  SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
81
  SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
82
  SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;
83
  SPI_Init(SPI1, &SPI_InitStruct);
84

85
  SPI_Cmd(SPI1, ENABLE);
86
}
87

88
void SDCard_Init(void)
89
{
90
  uint16_t CMD0[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95};
91

92
  for(uint16_t i = 0; i < 100; i++); // min. 74 Takte an SCK warten
93

94
  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
95

96
  GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_RESET);
97
  for(uint8_t i = 0; i < 6; i++)
98
  {
99
    SPI_I2S_SendData(SPI1, CMD0[i]);
100
  }
101
  GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET);
102

103
  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
104

105
  response = SPI_I2S_ReceiveData(SPI1);
106
}

Moritz
Gast
>  for(uint16_t i = 0; i < 100; i++); // min. 74 Takte an SCK warten

Das wird sicher keine 74 SCK warten. Es kommt kein SCK
ohne das man Bytes schreibt. Die Schleife optimiert dir
sowieso der Compiler weg weil sie nichts tut.

>    SPI_I2S_SendData(SPI1, CMD0[i]);

Schau dir mal an was die Routine macht. Die prügelt Daten
ins Dataregister, mehr nicht. Du schreibst also sechs mal
schnell hintereinander Daten ohne zu warten ob die schon
gesendet wurden.
Gast
Hallo,

vielen Dank für die Antwort. Selbst wenn ich immer nur ein Byte senden 
will und warte bis SPI_I2S_FLAG_BSY gelöscht ist, kommt kein Takt raus.

>  Ich glaube du musst noch die AFIO-Geschichte mit einem Takt versorgen

Bei den F4ern gibt es das nicht.

Moritz
Auf den ersten Blick sieht für mich fast alles OK aus.
Ich würde aber den CS-Pin nicht als AF-Pin initialisieren, sondern als 
OUT (bei NSS-Soft).
Wenn es wirklich nicht funktionieren will, kannst du ja mal alles exakt 
so wie in den Beispielen von ST machen, d.h. z.B. Pull-Down und nicht 
Up.
Oder du versuchst gleich das Beispiel von ST zum laufen zu bringen.
Gast
Hallo,

ja das mit AF ist mir schon aufgefallen. Macht aber auch keinen 
Unterschied für SPI. Wenn ich UP in Down ändere passiert auch nichts 
anderes

Moritz
Gast
Hallo nochmal.

Könnte es sein, das der SCK Prescaler vielleicht falsch eingestellt ist.
(SCK = APB2 / Prescaler)? Ich hab HCLK = 168MHz APB1 = 42MHz APB2 = 
84MHz

Also müsste doch SCK eig. 84MHz / 256 = 328,8125kHz sein oder?

Moritz
Gast
>vielen Dank für die Antwort. Selbst wenn ich immer nur ein Byte senden
>will und warte bis SPI_I2S_FLAG_BSY gelöscht ist, kommt kein Takt raus.

Woher weisst du das da kein Takt rauskommt?
Hoffentlich hast du da ein Osci dran. Aus SCK kommt kein
Takt wenn du nicht sendest. Also senden, senden, senden, senden...
Nicht nur ein popeliges Byte.
Gast
Hallo,

ja ich hab nen Oszi dran. Und ich sende immer 100x 0b10101010 direkt 
hintereinander.
Ich hab das ganze mal auf SPI2 umgeändert. Das Problem ist jetzt, dass 
wenn ich den MISO Pin(PB14) auf SPI2 mittels GPIO_PinAFConfig() remappen 
möchte, in der Funktion GPIO_PinAFConfig() an der Stelle:
1
GPIOx->AFR[GPIO_PinSource >> 0x03] &= ~((uint32_t)0xF << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)) ;

der Defaul-Handler angesprungen wird.

Moritz
Gast
Es gibt im www ein deutsches Tutorial wo alles beschrieben wird. Is 
total genial, nur leider hab ich den Link nicht zur Hand. SPI is da auch 
beschrieben!


Ingo
Gast
Hier nochmal mein Code mit SPI2:
1
#include "stm32f4xx.h"
2

3
void SDCard_InitLowLevel(void);
4
void SDCard_Init(void);
5

6
int main(void)
7
{
8
  SystemInit();
9

10
  SDCard_InitLowLevel();
11

12
    while(1)
13
    {
14
      SDCard_Init();
15
    }
16

17
    return 1;
18
}
19

20
void SDCard_InitLowLevel(void)
21
{
22
  GPIO_InitTypeDef GPIO_InitStruct;
23
  SPI_InitTypeDef SPI_InitStruct;
24

25
  /*
26
   * Clocks
27
   */
28
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
29
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB, ENABLE);
30

31
  /*
32
  * DeInit
33
  */
34
  SPI_I2S_DeInit(SPI2);
35

36
  /*
37
   * Alternate Function
38
   */
39
  GPIO_PinAFConfig(GPIOB, GPIO_Pin_10, GPIO_AF_SPI2);
40
  //GPIO_PinAFConfig(GPIOB, GPIO_Pin_14, GPIO_AF_SPI2);
41
  GPIO_PinAFConfig(GPIOB, GPIO_Pin_15, GPIO_AF_SPI2);
42

43
  /*
44
   * GPIO Init
45
   * PB10 (SCK) to SD card pin 5 (SCLK)   PP UP AF
46
   * PB14 (MISO) to SD card pin 7 (DO)  PP UP AF
47
   * PB15 (MOSI) to SD card pin 2 (DI)  PP UP AF
48
   * PA8 (NSS) to SD card pin 1 (CS)    PP UP OUT
49
   */
50
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
51
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
52
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | /*GPIO_Pin_14 |*/ GPIO_Pin_15;
53
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
54
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
55
  GPIO_Init(GPIOB, &GPIO_InitStruct);
56

57
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
58
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
59
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
60
  GPIO_Init(GPIOA, &GPIO_InitStruct);
61

62
  GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET);
63

64
  /*
65
   * SPI2 Init
66
   */
67
  SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
68
  SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
69
  SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;
70
  SPI_InitStruct.SPI_CRCPolynomial = 7;
71
  SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
72
  SPI_InitStruct.SPI_Direction = SPI_Direction_1Line_Tx;
73
  SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
74
  SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
75
  SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;
76
  SPI_Init(SPI2, &SPI_InitStruct);
77

78
  SPI_Cmd(SPI2, ENABLE);
79
}
80

81
void SDCard_Init(void)
82
{
83
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
84

85
  GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_RESET);
86

87
  for(int i = 0; i < 1000; i++)
88
  {
89
    SPI_I2S_SendData(SPI2, 0b10101010);
90

91
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
92
  }
93

94
  GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET);
95
}

Moritz
Gast
>Hier nochmal mein Code mit SPI2:

Hör auf im dunkeln rumzustochern.

In der StandardPeripheralLib zum STM32F4 ist ein Beispiel
für ein SPI Flash. Da ist alles drin was du brauchst.

Vergiss das hier:

    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);

RXNE ist das was du abfragen musst. SPI_I2S_FLAG_BSY kommt in dem
Code überhaupt nicht vor. Im Datenblatt steht warum.
Gast
>ja den Code hab ich mir schon x-mal angesehn und nichts gefunden.

Nicht ansehen, benutzen.

Im Anhang mal meine Routinen für SPI1.
Die funktionieren, sind also über jeden Zweifel erhaben;)

Deine CS Leitung musst du noch selber initialisieren.
Angehängte Dateien:
Ich habe es mal kurz mit meinem Code verglichen und auf die Schnelle 
folgende Unterschiede gefunden:

- GPIO_Speed_100MHz und GPIO_PuPd_UP
- SPI_BaudRatePrescaler_256
- beim Senden teste ich auf:
    while (SET != SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE));
- ganz am Anfang der Initialisierung:
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, DISABLE);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2); //sck
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2); //mosi

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 14 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.