Forum: Mikrocontroller und Digitale Elektronik STM32F405 als SPI Slave sendet verwirrende daten


von Stefan (Gast)


Lesenswert?

Hallo liebe Technikfreunde,

ich habe zwei STM32F05 Boards die über SPI Daten austauschen sollen. Das 
eine Board ist als Master konfiguriert, das andere als Slave.

Von Master zu Slave läuft alles super, die Daten kommen korrekt an.
Vom Slave zum Master kommen aber mal korrekte Zeichen, mal Bit-Foo.

Folgendes weiß ich bisher:

-Die Signale sind sauber (keine Verzerrungen, Störungen oder so)

-Auf dem Oszi ist zu sehen, dass das was der Master empfängt auch vom 
Slave genau so gesendet wurde.

-Der Master empfängt zufälligen Bitsalat, aber ab und zu sind ein oder 
zwei korrekte Zeichen an den korrekten Stellen dabei.

-Wenn ich das SPI-DR register vom Slave auf einen konstanten Wert setze 
und den TX-DMA vom Slave abschalte, dann kommt dieser Konstante Wert 
auch korrekt am Master an. (in mehreren Versuchen getestet)

-Wenn der Slave DMA die Sendewerte aus dem tx-Array aus in das SPI-DR 
schreibt, dann kommt da Müll raus

-Das Array wird bei der initialisierung mit Nullen geflutet (habe das 
sehr oft überprüft) und dann in der Sendefunktion befüllt.

Bevor ich den DMA implementiert hab, war das Ganze Interruptgesteuert. 
Gleiches Phänomen. Ich dachte erst der Slave sei einfach zu langsam 
wenns über ISRs läuft, also hab ich den DMA dazugebaut. Aber die 
Veränderung ist leider Null.

Hier ist der Quellcode des Slaves:
1
 void mcu_spi_spc_init_slave(void (*xfer_done)(uint8_t* data, uint32_t dlen))
2
{
3
  spi2_xfer_done = xfer_done;
4
5
  for (int c=0;c<128;c++)
6
  {
7
    spi2_tx_buffer[c] = 0;
8
    spi2_rx_buffer[c] = 0;
9
  }
10
11
  // Enable the SPI2 peripheral clock
12
  RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;
13
14
  // Enable port B Clock
15
  RCC->AHB1ENR |= (1<<1);
16
17
  // Enable DMA1 Clock
18
  RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;
19
20
  // Reset the SPI2 peripheral to initial state
21
  RCC->APB1RSTR |=  RCC_APB1RSTR_SPI2RST;
22
  RCC->APB1RSTR &= ~RCC_APB1RSTR_SPI2RST;
23
24
  /*
25
 * SPC SPI2 SS:    Pin33 PB12
26
 * SPC SPI2 SCK:  Pin34 PB13
27
 * SPC SPI2 MISO:  Pin35 PB14
28
 * SPC SPI2 MOSI:  Pin36 PB15
29
   */
30
31
  // Configure the SPI2 GPIO pins
32
  GPIOB->MODER |= (2<<24) | (2<<26) | (2<<28) | (2<<30);
33
  GPIOB->PUPDR |= (02<<26) | (2<<28) | (2<<30);
34
  GPIOB->OSPEEDR |= (3<<24) | (3<<26) | (3<<28) | (3<<30);    // "very High speed"
35
  GPIOB->AFR[1] |= (5<<16) | (5<<20) | (5<<24) | (5<<28);    // Alternate function 5 (SPI2)
36
37
  //-------------------------------------------------------
38
39
  // Clock Phase and Polarity = 0
40
  // CR1 = LSByte to MSByte, MSBit first
41
  // DFF = 8bit
42
  // 6 MHz Clock (48MHz / 8)
43
  spi_spc->CR1 = (7<<3) | (0<<2) | (0<<1) | (0<<0)  // 0:CPHA, 1:CPOL, 2:MASTER, 3:CLOCK_DIVIDER
44
        | (0<<7) | (0<<11);            // 7:LSB first, 11:DFF(8Bit)
45
46
  spi_spc->CR2 = (0<<2) | (1<<0);      // 2:SSOE, 0:Enable RX DMA IRQ
47
48
  // DMA config  (Stream3:RX p2mem, Stream4:TX mem2p
49
  // DMA for RX Stream 3 Channel 0
50
  DMA1_Stream3->CR &= ~(1<<0);        // EN = 0: disable and reset
51
  while((DMA1_Stream3->CR & (1<<0)) != 0);  // Wait
52
53
  DMA1_Stream4->CR &= ~(1<<0);        // EN = 0: disable and reset
54
  while((DMA1_Stream4->CR & (1<<0)) != 0);  // Wait
55
56
  DMA1->LIFCR = (0x3D<<22);  // clear all ISRs related to Stream 3
57
  DMA1->HIFCR = (0x3D<< 0);  // clear all ISRs related to Stream 4
58
59
  DMA1_Stream3->PAR = (uint32_t) (&(spi_spc->DR));  // Peripheral addresse
60
  DMA1_Stream3->M0AR = spi2_rx_buffer;    // Memory addresse
61
62
  DMA1_Stream3->NDTR = 0xFFFF;  // Datenmenge zum Empfangen
63
64
  DMA1_Stream3->FCR &= ~(1<<2);  // ENABLE Direct mode by CLEARING Bit 2
65
  DMA1_Stream3->CR = (0<<25) |   // 25:Channel selection(0)
66
             (1<<10) |  // 10:increment mem_ptr,
67
             (0<<9) |    // 9: Do not increment periph ptr
68
             (0<<6);    // 6: Dir(P -> Mem)
69
70
  // DMA for TX Stream 4 Channel 0
71
  DMA1_Stream4->PAR = (uint32_t) (&(spi_spc->DR));  // Peripheral addresse
72
  DMA1_Stream4->M0AR = spi2_tx_buffer;    // Memory addresse
73
74
  DMA1_Stream4->NDTR = 1;  // Datenmenge zum Empfangen
75
76
  DMA1_Stream4->FCR &= ~(1<<2);  // ENABLE Direct mode by CLEARING Bit 2
77
  DMA1_Stream4->CR = (0<<25) |   // 25:Channel selection(0)
78
             (1<<10) |  // 10:increment mem_ptr,
79
             (0<<9) |    // 9: Do not increment periph ptr
80
             (1<<6) |    // 6: Dir(Mem -> P)
81
             (1<<4);
82
83
  // Setup the NVIC to enable interrupts.
84
  // Use 4 bits for 'priority' and 0 bits for 'subpriority'.
85
  NVIC_SetPriorityGrouping( 0 );
86
87
  uint32_t pri_encoding = NVIC_EncodePriority( 0, 1, 0 );
88
  NVIC_SetPriority( DMA1_Stream4_IRQn, pri_encoding );
89
  NVIC_EnableIRQ( DMA1_Stream4_IRQn );
90
91
  DMA1_Stream3->CR |= (1<<1);  // Enable DMA1_Stream3 (RX)
92
  spi_spc->CR1 |= (1<<6);    // 6:EnableSPI
93
94
}

Die Slave Sendefunktion:
1
void mcu_spi_spc_send_slave(uint8_t*data, uint32_t dlen)
2
{
3
  if (dlen >= 128)
4
  {
5
    dlen = 128;
6
  }
7
8
  for (uint32_t c = 0; c < dlen; c++)
9
  {
10
    spi2_tx_buffer[c] = data[c];
11
  }
12
13
  if (dlen > 0)
14
  {
15
    DMA1_Stream4->CR &= ~(1<<0);        // Disable stream 4
16
    while((DMA1_Stream4->CR & (1<<0)) != 0);  // Wait till disabled
17
18
    DMA1->HIFCR = (0x3D<< 0);  // clear all ISRs related to Stream 4
19
    DMA1_Stream4->NDTR = dlen;  // Datenmenge zum Senden
20
    DMA1_Stream4->CR |= (1<<0);  // Enable DMA1_Stream4 (TX)
21
    spi_spc->CR2 |= (1<<1);    // SPI TX DMA Request enable
22
  }
23
24
}

Benutzt wird das Ganze in der main (Auszug):
1
volatile uint8_t tx_buffer_slave[] = "test_erfolgreich!";
2
3
void spi_slave_test()
4
{
5
  mcu_spi_spc_init_slave(0);
6
  mcu_spi_spc_send_slave(tx_buffer_slave, 17);
7
  led_blink();
8
9
  while(1)
10
  {
11
    if (rx_buffer_len_slave != 0)
12
    {
13
      led_blink_lang();
14
      if ((rx_buffer_slave[0] == '1') && (rx_buffer_slave[1] == '2') && (rx_buffer_slave[2] == '3') )
15
      {
16
        for (uint8_t c=0;c<3;c++)
17
        {
18
          led_blink();
19
        }
20
21
      }else
22
      {
23
        // Loopback der Empfangenen Daten
24
        mcu_spi_spc_send_slave(rx_buffer_slave, rx_buffer_len_slave);
25
        led_blink_2();
26
      }
27
28
      rx_buffer_len_slave = 0;
29
30
    }
31
    else
32
    {
33
      led_blink_2_lang();
34
    }
35
36
  }
37
38
}
39
40
int main(void)
41
{
42
  init_leds();
43
44
  int i = 0;
45
46
  spi_slave_test();
47
48
  /* Infinite loop */
49
  while (1)
50
  {
51
      i++;
52
  }
53
}

Hat jemand eine Idee was da falsch läuft?

von Stefan (Gast)


Lesenswert?

STM32F405! Sorry für den Tippfehler!

von au weia (Gast)


Lesenswert?

Stefan schrieb:
> Hat jemand eine Idee was da falsch läuft?

Was soll dieses endlos lange gescrolle in so einem Text?

Dein Source-Text gehört in eine Datei als Anhang zum Beitrag.

Siehe:
---------------------------------------------
Wichtige Regeln - erst lesen, dann posten!
    ..........
    Längeren Sourcecode nicht im Text einfügen,
    sondern als Dateianhang
---------------------------------------------

Lesen, verstehen und verinnerlichen.

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.