Forum: Mikrocontroller und Digitale Elektronik STM32 SPI Init


von Moritz M. (Gast)


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

von Moritz M. (Gast)


Lesenswert?

Hallo,

weiß niemand was genaues darüber?

Moritz

von AVerr (Gast)


Lesenswert?

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

von holger (Gast)


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.

von Moritz M. (Gast)


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

von Thomas W. (ratos)


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.

von Moritz M. (Gast)


Lesenswert?

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

von Moritz M. (Gast)


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

von holger (Gast)


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.

von Moritz M. (Gast)


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

von Moritz M. (Gast)


Lesenswert?

Hallo nochmal,

wenn ich MISO einfach weg lasse geht es trotzdem nicht. kein Takt/Daten

Moritz

von Ingo (Gast)


Lesenswert?

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

von Moritz M. (Gast)


Lesenswert?

Hallo,

meinst du vllt. das von Moritz Diller?
Da hab ich schon nachgesehn aber auch nichts gefunden.

Moritz

von Moritz M. (Gast)


Lesenswert?

Hallo,

ich hab grade heraus gefunden das es sich um ein HardFault Exception 
handelt. Weiß jemand was darüber?

Moritz

von Moritz M. (Gast)


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

von holger (Gast)


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.

von Moritz M. (moritz_m72)


Lesenswert?

Hallo,

ja den Code hab ich mir schon x-mal angesehn und nichts gefunden.

Moritz

von holger (Gast)


Angehängte Dateien:

Lesenswert?

>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.

von Michael F. (startrekmichi)


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

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.