STM32F4Discovery SPI slave

OP #3496012
Lesenswert?

Hallo,

ich bin dabei das STM32F4Discovery-Board als SPI slave zu nutzen, aber
irgendwie klappt es nicht.

Die Signale liegen alle richtig an, aber leider Springt das Programm
nicht in den Interrupt. Ich denke der Fehler ist irgendwo in der
Initialisierung...
1
#define SPI2_SCK_PIN              GPIO_Pin_13
2
#define SPI2_SCK_GPIO_PORT        GPIOB
3
#define SPI2_SCK_GPIO_CLK         RCC_AHB1Periph_GPIOB
4
#define SPI2_SCK_SOURCE           GPIO_PinSource13
5
#define SPI2_SCK_AF               GPIO_AF_SPI2
6

7
#define SPI2_MOSI_PIN             GPIO_Pin_15
8
#define SPI2_MOSI_GPIO_PORT       GPIOB
9
#define SPI2_MOSI_GPIO_CLK        RCC_AHB1Periph_GPIOB
10
#define SPI2_MOSI_SOURCE          GPIO_PinSource15
11
#define SPI2_MOSI_AF              GPIO_AF_SPI2
12

13
#define SPI2_MISO_PIN             GPIO_Pin_14
14
#define SPI2_MISO_GPIO_PORT       GPIOC
15
#define SPI2_MISO_GPIO_CLK        RCC_AHB1Periph_GPIOB
16
#define SPI2_MISO_SOURCE          GPIO_PinSource14
17
#define SPI2_MISO_AF              GPIO_AF_SPI2
18

19
#define SPI2_CS_PIN               GPIO_Pin_12
20
#define SPI2_CS_GPIO_PORT         GPIOB
21
#define SPI2_CS_GPIO_CLK          RCC_AHB1Periph_GPIOB
22
#define SPI2_CS_SOURCE            GPIO_PinSource12
23
#define SPI2_CS_AF                GPIO_AF_SPI2
24

25
void SPI2_Init (void){
26
/************************************************************************/
27
  SPI_InitTypeDef SPI_InitStructure;
28
  GPIO_InitTypeDef GPIO_InitStructure;
29

30
  GPIO_InitStructure.GPIO_Pin = SPI2_SCK_PIN;
31
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN|GPIO_Mode_AF ;
32
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
33
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
34
  GPIO_Init(GPIOB, &GPIO_InitStructure);
35

36
  GPIO_InitStructure.GPIO_Pin = SPI2_MOSI_PIN;
37
  GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_OUT|GPIO_Mode_AF;
38
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
39
  GPIO_Init(GPIOB, &GPIO_InitStructure);
40

41
  GPIO_InitStructure.GPIO_Pin = SPI2_MISO_PIN;
42
  GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_IN|GPIO_Mode_AF ;
43
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
44
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
45
  GPIO_Init(GPIOB, &GPIO_InitStructure);
46

47
  GPIO_InitStructure.GPIO_Pin = SPI2_CS_PIN;
48
  GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_IN|GPIO_Mode_AF ;
49
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
50
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
51
  GPIO_Init(GPIOB, &GPIO_InitStructure);
52

53
  GPIO_PinAFConfig(SPI2_SCK_GPIO_PORT, SPI2_SCK_SOURCE, SPI2_SCK_AF);
54
  GPIO_PinAFConfig(SPI2_MOSI_GPIO_PORT, SPI2_MOSI_SOURCE, SPI2_MOSI_AF);
55
  GPIO_PinAFConfig(SPI2_MISO_GPIO_PORT, SPI2_MISO_SOURCE, SPI2_MISO_AF);
56
  GPIO_PinAFConfig(SPI2_MISO_GPIO_PORT, SPI2_CS_SOURCE, SPI2_CS_AF);
57

58
  RCC_AHB1PeriphClockCmd(SPI2_SCK_GPIO_CLK, ENABLE);
59
  RCC_AHB1PeriphClockCmd(SPI2_MOSI_GPIO_CLK, ENABLE);
60
  RCC_AHB1PeriphClockCmd(SPI2_MISO_GPIO_CLK, ENABLE);
61
  RCC_AHB1PeriphClockCmd(SPI2_CS_GPIO_CLK, ENABLE);
62

63
/************************************************************************/
64
  // SPI2 configurieren
65
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
66
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
67
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
68
  SPI_InitStructure.SPI_CRCPolynomial = 0;
69
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
70
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
71
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
72
  SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
73
  SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;
74
  SPI_Init(SPI2, &SPI_InitStructure);
75
  SPI_Cmd(SPI2, ENABLE);
76
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
77

78
  NVIC_InitTypeDef NVIC_InitStructure;
79
/* Enable the USARTy Interrupt */
80
  NVIC_InitStructure.NVIC_IRQChannel            = SPI2_IRQn;
81
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
82
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
83
  NVIC_InitStructure.NVIC_IRQChannelCmd         = ENABLE;
84
  NVIC_Init(&NVIC_InitStructure);
85
  SPI_I2S_ITConfig(SPI2, SPI_I2S_FLAG_RXNE,ENABLE);
86
/************************************************************************/
87
  }
88

89

90
void spi_handleSPI2Interrupt(void){
91
  GPIOD->ODR ^= GPIO_Pin_14 ;
92
    }
Vielen Dank für eure Hilfe.

Viele Grüße Tobias
Gast #3496088
Lesenswert?

Tobias S. schrieb:
> #define SPI2_MISO_GPIO_PORT       GPIOC
> #define SPI2_MISO_GPIO_CLK        RCC_AHB1Periph_GPIOB

Passt nicht zusammen. Später wird es auch auf GPIOB initialisiert.

Tobias S. schrieb:
> GPIO_InitStructure.GPIO_Pin = SPI2_MOSI_PIN;
>   GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_OUT|GPIO_Mode_AF;
>   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
>   GPIO_Init(GPIOB, &GPIO_InitStructure);
>
>   GPIO_InitStructure.GPIO_Pin = SPI2_MISO_PIN;
>   GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_IN|GPIO_Mode_AF ;
>   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
>   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
>   GPIO_Init(GPIOB, &GPIO_InitStructure);

MOSI = Master Out, Slave In. Müsste für einen Slave also Input und nicht 
Output sein. Soweit ich weiss kannst du nur einen Pin-Mode gleichzeitig 
nutzen. Also AF oder IN, aber nicht beides zusammen. Bei einer AF 
Konfiguration entscheidet dann die SPI-Initialisierung darüber, ob der 
Pin IN oder OUT ist.

Guck dir mal http://diller-technologies.de/stm32_wide.html#spi als 
Referenz an. Ist zwar für den STM32F3, aber lässt sich fast 1:1 auf den 
STM32F4 übertragen.
OP #3496148
Lesenswert?

Hallo Marcel, danke für deine Antwort. Ich habe mir den Link angeschaut 
und den Code soweit angepasst, jedoch funktioniert es immer noch 
nicht...

Ich habe die Pins jetzt alle auf "AF" gestellt. Werde aber noch mal das 
Manual durchlesen...

Danke für deine Hilfe
1
#define SPI2_SCK_PIN              GPIO_Pin_13
2
#define SPI2_MOSI_PIN             GPIO_Pin_15
3
#define SPI2_MISO_PIN             GPIO_Pin_14
4
#define SPI2_CS_PIN               GPIO_Pin_12
5

6

7
void SPI2_Init (void){
8
/************************************************************************/
9
  // Clock, MOSI und MISO configurieren
10
  SPI_InitTypeDef SPI_InitStructure;
11
  GPIO_InitTypeDef GPIO_InitStructure;
12

13
  GPIO_InitStructure.GPIO_Pin = SPI2_SCK_PIN | SPI2_MISO_PIN| SPI2_MOSI_PIN|SPI2_CS_PIN;
14
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
15
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
16
  GPIO_Init(GPIOB, &GPIO_InitStructure);
17

18
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
19

20

21
/************************************************************************/
22
  /* Enable the SPI2 Interrupt */
23
  NVIC_InitTypeDef NVIC_InitStructure;
24
  NVIC_InitStructure.NVIC_IRQChannel            = SPI2_IRQn;
25
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
26
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
27
  NVIC_InitStructure.NVIC_IRQChannelCmd         = ENABLE;
28
  NVIC_Init(&NVIC_InitStructure);
29
  SPI_I2S_ITConfig(SPI2, SPI_I2S_FLAG_RXNE,ENABLE);
30

31
  // SPI2 configurieren
32
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
33
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
34
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
35
  SPI_InitStructure.SPI_CRCPolynomial = 0;
36
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
37
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
38
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
39
  SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
40
  SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;
41
  SPI_Init(SPI2, &SPI_InitStructure);
42
  SPI_Cmd(SPI2, ENABLE);
43
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
44

45
/************************************************************************/
46
  }
47

48

49
void spi_handleSPI2Interrupt(void){
50
  GPIOD->ODR ^= GPIO_Pin_14 ;
51
    }
OP #3496195
Lesenswert?

Hmm..

ich dachte, das der Interrupt so eingeschaltet wird
1
  /* Enable the SPI2 Interrupt */
2
  NVIC_InitTypeDef NVIC_InitStructure;
3
  NVIC_InitStructure.NVIC_IRQChannel            = SPI2_IRQn;
4
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
5
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
6
  NVIC_InitStructure.NVIC_IRQChannelCmd         = ENABLE;
7
  NVIC_Init(&NVIC_InitStructure);
8
  SPI_I2S_ITConfig(SPI2, SPI_I2S_FLAG_RXNE,ENABLE);
Gast #3496449
Lesenswert?

Damit gibst du die Interrupts des SPI2 frei. Du musst voher noch mit
[c]
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
[\c]
das Interruptsystem aktivieren. Ist wie das sei() beim AVR.
Ich habe selber noch nicht mit den SPI Interrupts gearbeitet, aber bei 
den USART Interrupts musst du noch manuell das entsprechende Status 
Register auswerten, damit du weisst woher der IRQ kam (Senden, 
Empfangen, ...) und das Statusbit auch manuell löschen, damit die 
Interrput-Routine nicht ständig aufgerufen wird.

Nimm dir einen Abend Zeit die ganzen Beispiele von Diller durchzugucken. 
Auch wenn es nicht direkt mit SPI zu tun hat, wird dir das Prinzip klar, 
mit dem die Interrupts auf einem Cortex arbeiten.
(Firma: Reusch Elektronik) #3496829
Lesenswert?

Die Betriebsart eines Pin als Eingang und Alternate Function ("AF") zu 
setzen, dürfte Unsinn sein. Hier mein funktionierender Kode für einen 
STM32F405 als SPI-Slave...

Initialisierung:
  // Taktversorgung der benötigten Peripherie
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);  // nur 
PreemptionPriority ist von Bedeutung

  // SPI-Ports
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 
| GPIO_Pin_15;  // SPI2_NSS, SPI2_SCK, SPI2_MISO, SPI2_MOSI
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  GPIO_PinAFConfig(GPIOB,GPIO_PinSource12,GPIO_AF_SPI2);
  GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2);
  GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_SPI2);
  GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2);

  // SPI2-Schnittstelle
  SPI_InitStruct.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
  SPI_InitStruct.SPI_Mode=SPI_Mode_Slave;
  SPI_InitStruct.SPI_DataSize=SPI_DataSize_8b;
  SPI_InitStruct.SPI_CPOL=SPI_CPOL_Low;
  SPI_InitStruct.SPI_CPHA=SPI_CPHA_1Edge;
  SPI_InitStruct.SPI_NSS=SPI_NSS_Hard;
  SPI_InitStruct.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_8;
  SPI_InitStruct.SPI_FirstBit=SPI_FirstBit_MSB;
  SPI_InitStruct.SPI_CRCPolynomial=7;
  SPI_Init(SPI2,&SPI_InitStruct);
  SPI_I2S_ITConfig(SPI2,SPI_I2S_IT_RXNE,ENABLE);  // Interrupt, wenn 
Daten empfangen
  SPI_Cmd(SPI2,ENABLE);

  // SPI2-Interrupt
  NVIC_InitStructure.NVIC_IRQChannel = SPI2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0A;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x08;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

Interrupt-Routine:

void SPI2_IRQHandler(void)
{
  uint16_t d=SPI2->DR;
}

Wichtig ist, dass in der Interrupt-Routine das DR-Register gelesen wird, 
um das zugehörige Interrupt-Flag zu löschen.

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