Forum: Mikrocontroller und Digitale Elektronik STM32F103 SPI gibt nur 0 zurück


von Sean G. (atmega318)


Lesenswert?

Hallo
Ich habe wieder mal ein kleines Problem, dass sich einfach nicht lösen 
lassen will:

Es geht um den SPI im STM32f103. TX funktioniert (Oszi) aber RX kommt 
nur 0 zurück. Elektrischer Fehler ist eigentlich ausgeschlossen: wenn 
ich MISO fest auf VCC hänge zeigt GPIOA->IDR zwar eine 1, aber Send() 
gibt 0 zurück!
Code ist nur das hier:
1
GPIO_InitTypeDef GPIO_InitStructure;
2
    SPI_InitTypeDef SPI_InitStructure;
3
    
4
5
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
6
7
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
8
    
9
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
10
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;           
11
    GPIO_Init(GPIOA, &GPIO_InitStructure);
12
13
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
14
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
15
    GPIO_Init(GPIOA, &GPIO_InitStructure);
16
17
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
18
19
    SPI_I2S_DeInit(SPI1);
20
21
    SPI_StructInit(&SPI_InitStructure);
22
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
23
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
24
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
25
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
26
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
27
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
28
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
29
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
30
    SPI_InitStructure.SPI_CRCPolynomial = 7;
31
    SPI_Init(SPI1, &SPI_InitStructure);
32
33
    SPI_Cmd(SPI1, ENABLE);
34
35
    while(1)
36
    {
37
        uint8_t x = Send(SPI1, 123);
38
    }
und die Funktion Send():
1
uint8_t Send(SPI_TypeDef* SPIx, uint8_t data){
2
3
  SPIx->DR = data; // write data to be transmitted to the SPI data register
4
  while( !(SPIx->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete
5
  while( !(SPIx->SR & SPI_I2S_FLAG_RXNE) ); // wait until receive complete
6
  while( SPIx->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore
7
  return SPIx->DR; // return received data from SPI data register
8
}
Weiss da jemand rat? SPI Slave funktioniert Perfekt (sogar mit DMA), nur 
Master RX zickt...
Vielen Dank, Sean

von holger (Gast)


Lesenswert?

>aber Send() gibt 0 zurück!

Lass dir x ml per UART susgeben. Oder mach es volatile.
x wird nirgendwo verwendet und könnte wegoptimiert werden.

von Sean G. (atmega318)


Lesenswert?

holger schrieb:
>>aber Send() gibt 0 zurück!
>
> Lass dir x ml per UART susgeben. Oder mach es volatile.
> x wird nirgendwo verwendet und könnte wegoptimiert werden.

Das ist es nicht, ich habe x mit dem Debugger angeschaut. Zudem habe ich 
es auch mal versucht mit mehreren zugriffen auf x, das ändert nichts. 
Auch SPI1->DR bleibt leer!

von Zur Höxxxx mit Flanders (Gast)


Lesenswert?

Das ist Wasser auf meine Mühlen. Ich hatte genau das gleiche mit einem 
32F3xx. Ich hab irgendwann nach jedem Strohhalm gegriffen und 
angefangen, am Prescaler zu drehen. Bei einer einzigen Einstellung 
klappts. Einen drunter oder drüber ist das Ding tot...
Ich habs nicht weiter verfolgt, weil reines Hobby und keine Zeit.

Versuch mal "SPI_InitStructure.SPI_BaudRatePrescaler = 12;"

von holger (Gast)


Lesenswert?

Nimm mal RCC_APB2Periph_AFIO mit rein und schalte die Clocks auf
BEVOR du irgendwas initialisierst.

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, 
ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 .....

von Sean G. (atmega318)


Lesenswert?

1
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
2
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
3
    
4
5
    GPIO_InitTypeDef GPIO_InitStructure;
6
    SPI_InitTypeDef SPI_InitStructure;
7
    
8
9
10
    
11
12
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
13
    
14
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
15
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;           
16
    GPIO_Init(GPIOA, &GPIO_InitStructure);
17
18
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
19
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
20
    GPIO_Init(GPIOA, &GPIO_InitStructure);
21
22
23
24
    SPI_I2S_DeInit(SPI1);
25
26
    SPI_StructInit(&SPI_InitStructure);
27
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
28
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
29
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
30
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
31
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
32
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
33
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
34
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
35
    SPI_InitStructure.SPI_CRCPolynomial = 7;
36
    SPI_Init(SPI1, &SPI_InitStructure);
37
38
    SPI_Cmd(SPI1, ENABLE);
39
40
    while(1)
41
    {
42
        uint8_t x = Send(SPI1, 123);
43
        delay = x / 2;  //dummy aktion, nur zur sicherheit!
44
    }
So siehts jetzt aus, hat sich aber nichts geändert. Das mit Prescaler = 
12 habe ich auch getestet, gleiches Ergebnis. Trotzdem danke :)

von holger (Gast)


Lesenswert?

>So siehts jetzt aus, hat sich aber nichts geändert.

Ich werde das Gefühl immer noch nicht los das das
nur ein Missverständnis zwischen dir und deinem Debugger ist.

Gib x über UART aus. Da MOSI ja was sendet sollte
das SPI Modul funktionieren. SCK funktioniert auch?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Sean Goff schrieb:
1
 while( !(SPIx->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit  complete
2
 while( !(SPIx->SR & SPI_I2S_FLAG_RXNE) ); // wait until receive complete

 Bist du sicher, dass receive complete nötig ist ?
 SPI ist eigentlich bidirectional, es könnte sein, dass du damit nur
 sein (leeres) SPI-Register empfängst...

: Bearbeitet durch User
von Sean G. (atmega318)


Lesenswert?

Marc Vesely schrieb:
> Sean Goff schrieb:
>
1
>  while( !(SPIx->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit 
2
> complete
3
>  while( !(SPIx->SR & SPI_I2S_FLAG_RXNE) ); // wait until receive 
4
> complete
5
>
>
>  Bist du sicher, dass receive complete nötig ist ?
>  SPI ist eigentlich bidirectional, es könnte sein, dass du damit nur
>  sein (leeres) SPI-Register empfängst...

Dachte ich auch schon, aber in allen Libs wird's so gemacht, und ohne 
ändert sich nichts!

holger schrieb:
>>So siehts jetzt aus, hat sich aber nichts geändert.
>
> Ich werde das Gefühl immer noch nicht los das das
> nur ein Missverständnis zwischen dir und deinem Debugger ist.
>
> Gib x über UART aus. Da MOSI ja was sendet sollte
> das SPI Modul funktionieren. SCK funktioniert auch?

SCK und MOSI funktionieren. Ich kanns mir einfach nicht vorstellen, ich 
habe EXAKT die gleiche Methode beim F4 angewendet. Funktioniert super 
(mit dem Debugger...)
UART müsste ich halt auch zuerst implementieren.

Ich hab aber jetzt mal folgendes gemacht:
1
    WS2812_init();
2
    while(1)
3
    {
4
        uint8_t x = Send(SPI1, 123);
5
        if(x == 0)
6
        {
7
            led[0].r = 3;
8
            led[0].g = 0;
9
            led[0].b = 0;
10
        }
11
        else
12
        {
13
            led[0].r = 3;
14
            led[0].g = 3;
15
            led[0].b = 3;
16
        }
17
        WS2812_update();
18
    }

-leuchtet Rot, nix Weiss!

von holger (Gast)


Lesenswert?

>SCK und MOSI funktionieren.

Bist du sicher das du MISO am richtigen Pin vermutest?
Vieleicht verzählt beim anschliessen?
Irgend sowas banales wird das sein;)

von Sean G. (atmega318)


Lesenswert?

holger schrieb:
>>SCK und MOSI funktionieren.
>
> Bist du sicher das du MISO am richtigen Pin vermutest?
> Vieleicht verzählt beim anschliessen?
> Irgend sowas banales wird das sein;)

Sieht leider für mich nicht so aus, denn erstens ist das ne Platine, die 
garantiert korrekt ist und zweitens wenn ich den Pin auf VCC Brücke sehe 
ich ihn im GPIOA->IDR auf eins gehen (Debugger). Drittens habe ich ihn 
auch schon als Ausgang konfiguriert und zappeln lassen -> Oszi sagt es 
ist der richtige :(

von holger (Gast)


Lesenswert?

Letzter Versuch:

Schalte MISO mal auf GPIO_Mode_IPU und lass ihn offen.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Sean Goff schrieb:
> Dachte ich auch schon, aber in allen Libs wird's so gemacht, und ohne
> ändert sich nichts!
 Probier es mal ganz ohne Flags, etwa so:
1
  SPIx->DR = data;  
2
  while (!(SPIx->SR & RXNE));  // 0x01
3
  return (SPIx->DR);

: Bearbeitet durch User
von Sean G. (atmega318)


Lesenswert?

holger schrieb:
> Letzter Versuch:
>
> Schalte MISO mal auf GPIO_Mode_IPU und lass ihn offen.

Hat nichts gebracht :(

Marc Vesely schrieb:
> Sean Goff schrieb:
>> Dachte ich auch schon, aber in allen Libs wird's so gemacht, und ohne
>> ändert sich nichts!
>  Probier es mal ganz ohne Flags, etwa so:  SPIx->DR = data;
>   while (!(SPIx->SR & RXNE));  // 0x01
>   return (SPIx->DR);

Das akzeptiert der Compiler so nicht (er sagt RXNE sei nicht bekannt.) 
Wenn ich direkt 0x01 nehme, ändert sich am Ergebnis nichts (leuchtet 
rot.)

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Sean Goff schrieb:
> Das akzeptiert der Compiler so nicht (er sagt RXNE sei nicht bekannt.)
> Wenn ich direkt 0x01 nehme, ändert sich am Ergebnis nichts (leuchtet
> rot.)
 Mein letzter Versuch:
 SPI-Mode ändern.

von mal so ins Blaue (Gast)


Lesenswert?

> ich habe EXAKT die gleiche Methode beim F4 angewendet

Haben die beiden die gleiche BUS Matrix? Hast du beim F1 das richtige 
Target im Projekt ausgewählt?

von Sean G. (atmega318)


Lesenswert?

mal so ins Blaue schrieb:
>> ich habe EXAKT die gleiche Methode beim F4 angewendet
>
> Haben die beiden die gleiche BUS Matrix? Hast du beim F1 das richtige
> Target im Projekt ausgewählt?

Mit Methode meinte ich eigentlich eher den Wert per debugger abzufragen, 
ohne ihn sonst zu benutzen. Prozessor stimmt!

von Sean G. (atmega318)


Lesenswert?

Marc Vesely schrieb:
> Sean Goff schrieb:
>> Das akzeptiert der Compiler so nicht (er sagt RXNE sei nicht bekannt.)
>> Wenn ich direkt 0x01 nehme, ändert sich am Ergebnis nichts (leuchtet
>> rot.)
>  Mein letzter Versuch:
>  SPI-Mode ändern.

Wie meinst du das? Auf Slave? Dann funktionierts!

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Sean Goff schrieb:
> Wie meinst du das? Auf Slave? Dann funktionierts!

 War auch so mal ins Blaue.
 Ich dachte wie die Daten eingelesen werden (welche Flanke).

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.