STM32 H7 - SPI "echo" funktioniert nicht

OP #5966265
Lesenswert?
• ▲
▼
Hallo Forum,

ich möchte auf einem STM32H750 Mikrocontroller ein simples SPI-Slave 
"echo" ans laufen bekommen. Dafür sollen über SPI ein Zeichen über 
Interrupt empfangen werden und dann direkt wieder über SPI 
herausgeschrieben werden soll. Zur Zeit kommt allerdings nur ein 0x00 
zurück. Was schon funktioniert:

- Der RX-Interrupt wird korrekt ausgelöst und empfängt die Zeichen.
- Physikalisch ist die Verbindung zwischen Slave und Master in Ordnung 
(Ich habe den Pin manuell auf high gezogen und 0xFF empfangen).

Ich habe etwas ähnliches schon auf dem STM32F767 implementiert, aber 
irgendwie scheint das SPI Interface anders zu ticken. Ich vermute, dass 
das Problem mit den TSIZE und CSTART-Variablen / Flags zusammenhängt.

Vielleicht hat ja schonmal jemand so was ähnliches gehabt - danke für 
die Hilfe!

Hier ist der Code:
1
void SPI1_IRQHandler(void) {
2

3
    /* Check RXP flag value in ISR register */
4
    if(LL_SPI_IsActiveFlag_RXP(SPI1) && LL_SPI_IsEnabledIT_RXP(SPI1))
5
    {
6
      uint8_t dataecho;
7
      dataecho = LL_SPI_ReceiveData8(SPI1);
8
      LL_SPI_TransmitData8(SPI1, dataecho);
9
    }
10
}
11

12
static void GPIOPins_SPI1_Config(void)
13
{
14
  /* (1) Enables GPIO clock and configures the SPI1 pins ********************/
15
  /* Enable the peripheral clock of GPIOE */
16
  LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOA);
17

18
  /* SPI1 SCK GPIO pin configuration*/
19
  GPIO_InitStruct.Pin       = LL_GPIO_PIN_4 | LL_GPIO_PIN_5 | LL_GPIO_PIN_6 | LL_GPIO_PIN_7;
20
  GPIO_InitStruct.Mode      = LL_GPIO_MODE_ALTERNATE;
21
  GPIO_InitStruct.Pull      = LL_GPIO_PULL_DOWN;
22
  GPIO_InitStruct.Speed     = LL_GPIO_SPEED_HIGH;
23
  GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
24
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
25

26
  /* (2) Configure NVIC for SPI4 transfer complete/error interrupts **********/
27
  /* Set priority for SPI4_IRQn */
28
  NVIC_SetPriority(SPI1_IRQn, 0);
29
  /* Enable SPI1_IRQn           */
30
  NVIC_EnableIRQ(SPI1_IRQn);
31
}
32

33
static void SPI1_Config (void)
34
{
35
  /* Configure SPI SLAVE *****************************************************/
36
  /* Enable SPI4 Clock */
37
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
38

39
  /* Configure the SPI4 parameters */
40
  SPI_InitStruct.BaudRate          = LL_SPI_BAUDRATEPRESCALER_DIV2;
41
  SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
42
  SPI_InitStruct.ClockPhase        = LL_SPI_PHASE_1EDGE;
43
  SPI_InitStruct.ClockPolarity     = LL_SPI_POLARITY_LOW;
44
  SPI_InitStruct.BitOrder          = LL_SPI_MSB_FIRST;
45
  SPI_InitStruct.DataWidth         = LL_SPI_DATAWIDTH_8BIT;
46
  SPI_InitStruct.NSS               = LL_SPI_NSS_HARD_INPUT;
47
  SPI_InitStruct.CRCCalculation    = LL_SPI_CRCCALCULATION_DISABLE;
48
  SPI_InitStruct.Mode              = LL_SPI_MODE_SLAVE;
49
  LL_SPI_Init(SPI1, &SPI_InitStruct);
50

51
// Set FIFO threshold
52
  LL_SPI_SetFIFOThreshold(SPI1,LL_SPI_FIFO_TH_01DATA);      
53

54
  /* Lock GPIO for master to avoid glitches on the clock output */
55
  LL_SPI_DisableGPIOControl(SPI1);
56
  LL_SPI_DisableMasterRxAutoSuspend(SPI1);
57

58
  /* Set number of data to transmit */
59
  LL_SPI_SetTransferSize(SPI1, 1);
60

61
  /* Enable SPI1 */
62
  LL_SPI_Enable(SPI1);
63

64
  /* Enable RXP Interrupt */
65
  LL_SPI_EnableIT_RXP(SPI1);
66
}
Gast #5966878
Lesenswert?
• ▲
▼
Wenn der Master 1 Byte an den Slave sendet, muss der Master noch ein 
weiteres (dummy) Byte senden, damit der Slave antworten kann, denn der 
Master gibt den Takt vor. Hast du das berücksichtigt?
OP #5966987
Lesenswert?
• ▲
▼
Ich habe die Lösung gefunden. Das Problem ist, dass beim ersten Empfang 
ein Transmit Underrun auftritt. Sobald dieser Underrun einmal auftritt, 
dann wird der Transmitter abgeschaltet und auch nicht wieder 
angeschaltet, wenn Daten vorhanden sind. Erst wenn man das Flag wieder 
löscht, dann geht die Übertragung weiter. Die ISR muss also 
folgendermaßen geändert werden:
1
void SPI1_IRQHandler(void) {
2

3
    /* Check RXP flag value in ISR register */
4
    if(LL_SPI_IsActiveFlag_RXP(SPI1) && LL_SPI_IsEnabledIT_RXP(SPI1))
5
    {
6
      uint8_t dataecho;
7
      dataecho = LL_SPI_ReceiveData8(SPI1);
8
      LL_SPI_TransmitData8(SPI1, dataecho);
9
      LL_SPI_ClearFlag_UDR(SPI1);
10
    }
11
}

Vielleicht hilft's ja jemandem.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

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.