Forum: Mikrocontroller und Digitale Elektronik STM32 SPI empfängt immer 0


von Max (Gast)


Lesenswert?

Ich bin seit mehreren Tagen daran, über einen STM32L151 (Master) mit 
einem Funkmodul (Slave) per SPI zu kommunizieren. Mit einem Oszi konnte 
ich bereits sicherstellen, dass die Kommunikation standardgemäß abläuft. 
CS, CLK, MOSI und MISO werden von dem STM32 und der Gegenstelle 
(scheinbar) korrekt angesteuert.

Das einzige Problem ist, dass ich beim Empfangen ausschließlich 0 
erhalte, obwohl das Funkmodul die richtigen Datenbits auf MISO gibt. Ich 
habe den Chip bereits erfolglos ausgetauscht.

Hier ist die Initialisierungsroutine:
1
//Pin-Config: PA15 = Chip Select, PA12 = MOSI, PA11 = MISO, PA5 = SCK
2
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1); // SCK
3
GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_SPI1); // MOSI
4
GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_SPI1); // MISO
5
6
// SCK & MOSI
7
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_12;
8
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
9
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
10
GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
11
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
12
GPIO_Init(GPIOA, &GPIO_InitStructure);
13
14
// MISO
15
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
16
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
17
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
18
GPIO_Init(GPIOA, &GPIO_InitStructure);
19
20
// NSS
21
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
22
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
23
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
24
GPIO_Init(GPIOA, &GPIO_InitStructure);
25
26
GPIO_WriteBit(GPIOA, GPIO_Pin_15, SET);
27
28
// Configure SPI
29
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
30
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
31
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
32
SPI_InitStructure.SPI_CRCPolynomial = 0;
33
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
34
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
35
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
36
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
37
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
38
39
SPI_Init(SPI1, &SPI_InitStructure);
40
SPI_Cmd(SPI1, ENABLE);

Und hier ist die Empfangsroutine:
1
uint8_t recvSPI(uint8_t address) {
2
  GPIO_WriteBit(GPIOA, GPIO_Pin_15, RESET);                // NSS off
3
4
  while (!SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE));  // Wait while TX buffer is full
5
  SPI1->DR = address;                                      // Send register address
6
  while (!SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE)); // Wait while RX buffer is empty
7
  SPI1->DR;                                                // Read dummy byte
8
9
  while (!SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE));  // Wait while TX buffer is full
10
  SPI1->DR = 0x00;                                         // Send dummy byte
11
  while (!SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE)); // Wait while RX buffer is empty
12
  uint8_t recv = SPI1->DR;                                 // Receive byte (Hier ist immer recv = 0)
13
14
  while (!SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE));  // Wait while TX buffer is full
15
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY));   // Wait while busy
16
17
  for(int i = 0; i < 20; i++);                             // Delay before NSS
18
  GPIO_WriteBit(GPIOA, GPIO_Pin_15, SET);                  // NSS on
19
20
  return recv;
21
}

von Benjamin S. (recycler)


Lesenswert?

SPI sendet und empfängt gleichzeitig. Ohne dem code für Ablauf, ist es 
schwer raus zufinden, was du machst (Stichwort minimalcode).

Aber wenn du das DR beschreibst und liest, dann ist es null. Les das DR 
mal vorher aus und du solltest nach dem Beschreiben des DR registers 
auch den SPI Transfer starten, sonst ist da nix drinnen.

  SPI1->DR = 0x00;
  uint8_t recv = SPI1->DR;

von Max (Gast)


Lesenswert?

Danke für die Tipps. So wie ich das verstanden habe, wird durch das 
Schreiben in das DR Register bereits das Senden gestartet, siehe 
Refrence Manual:

>– The sequence begins when data are written into the SPI_DR register (Tx buffer).
>– The data are then parallel loaded from the Tx buffer into the 8-bit shift 
register
>during the first bit transmission and then shifted out serially to the MOSI pin.
>– At the same time, the received data on the MISO pin is shifted in serially to 
the 8-
>bit shift register and then parallel loaded into the SPI_DR register (Rx buffer).

von Benjamin S. (recycler)


Lesenswert?

Was passiert, wenn du nach SPI1->DR = 0x00; einfach manuell 200ms 
wartest und dann liest. Dann würde deine Flag Abfrage nicht greifen oder 
die falsche sein oder muss negiert werden.

von Max (Gast)


Lesenswert?

Gute Idee, habe ich gerade getestet. Ich lese selbst dann leider immer 
noch 0.

von Max (Gast)


Lesenswert?

Es klappt. Der MISO GPIO musste als GPIO_Mode_AF, nicht als GPIO_Mode_IN 
initialisiert werden...

Trotzdem vielen Dank für's Mitdenken!

von Benjamin S. (recycler)


Lesenswert?

:)

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.