STM32 SPI Init

Gast #2843690
Lesenswert?

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 #2844065
Lesenswert?

>  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 #2844092
Lesenswert?

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
#2844217
Lesenswert?

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 #2844286
Lesenswert?

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 #2844303
Lesenswert?

>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 #2844327
Lesenswert?

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 #2846400
Lesenswert?

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 #2846420
Lesenswert?

>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.
#2846680
Lesenswert?

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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren