Forum: Mikrocontroller und Digitale Elektronik STM32F303 SPI kein SCK- und MOSI-Signal


von Werner R. (wt_r)


Angehängte Dateien:

Lesenswert?

Hallo,

ich möchte ein LCD-Display über SPI an mein Nucleo-64 (STM32F303RET6)
anschliessen. Ich habe die Initialisierung entsprechend Referenzmanual
Seiten 962-1004 ausgeführt (init_io.c).

Wenn ich im main.c ein Testbyte über SPI ausgebe, sehe ich auf dem LA
kein Signal an SCK und MOSI.

Die Steuerbits in den Registern CR1 und CR2 habe ich mit dem Debugger
überprüft und sie entsprechen init_io.c

Wo liegt der Denkfehler ?

Danke und Gruss
Werner

von Stefan F. (Gast)


Lesenswert?

Du sendest nur ein einzelnes Datenbyte, wirst also nur wenige 
Clock-Impulse erhalten. Hast du eventuell erwartet, dass da ein 
fortlaufendes Taktsignal erzeugt wird?

von Werner R. (wt_r)


Lesenswert?

Stefan ⛄ F. schrieb:
> Du sendest nur ein einzelnes Datenbyte, wirst also nur wenige
> Clock-Impulse erhalten. Hast du eventuell erwartet, dass da ein
> fortlaufendes Taktsignal erzeugt wird?

Nein, ich erwarte genau 8 Taktsignale entsprechend 8-Datenbits,
die ich mit dem Logicanalysor aufzeichne. Sowohl SCK als auch MOSI sind
bei Ausgabe des Datenbytes permanent High.

Gruss Werner

von dummschwaetzer (Gast)


Lesenswert?

hast du es mal mit cuve mx und den dort vorhanden HAL-Funktionen 
versucht?

von Stefan F. (Gast)


Lesenswert?

Werner R. schrieb:
> Nein, ich erwarte genau 8 Taktsignale

Dann sehe ich keinen Denkfehler. Sorry.

von Werner R. (wt_r)


Lesenswert?

dummschwaetzer schrieb:
> hast du es mal mit cuve mx und den dort vorhanden HAL-Funktionen
> versucht?

Nein, habe ich nicht, ich bin kein Freund von HAL, ich will verstehen 
was ich mache, Scheitern inbegriffen.

Gruss Werner

von Ben S. (bensch123)


Lesenswert?

Gibt es ein Datasize Register (in CR2)? Wenn ja, konfigurieren!
Für 8-bit: SPI1->CR2 |= (0b0111ul << 8);

Ggf. musst du eine Fifo auf 0 setzen, falls vorhanden?
SPI1->CR2 |= SPI_CR2_FRXTH;

Nur als Hinweis, was auf manchen Controllern gemacht werden muss:
1
uint8_t send(const uint8_t cVal) {
2
  uint8_t u8Result;
3
4
  *(volatile uint8_t*) &SPI1->DR = cVal;
5
  while (!(SPI1->SR & SPI_SR_RXNE));
6
  u8Result = SPI1->DR;
7
8
  return u8Result;
9
}

Und zum Testen eignet sich immer in Dauerschleife zu senden.

: Bearbeitet durch User
von Werner R. (wt_r)


Lesenswert?

Ben S. schrieb:
> Gibt es ein Datasize Register?

Ja, im Controlregister CR2 Bit's 8..11 DS[3:0]= 0x7
>
> Ggf. musst du eine Fifo auf 0 setzen, falls vorhanden?
> SPI1->CR2 |= SPI_CR2_FRXTH;

Habe es soeben ausprobiert, bringt leider keinen Erfolg.
>
> Nur als Hinweis, was auf manchen Controllern gemacht werden muss:uint8_t
> send(const uint8_t cVal) {
>   uint8_t u8Result;
>
>   *(volatile uint8_t*) &SPI1->DR = cVal;
>   while (!(SPI1->SR & SPI_SR_RXNE));
>   u8Result = SPI1->DR;
>
>   return u8Result;
> }

Genau diesen Vorschlag habe ich auch in der STM-Community gefunden
und damit begonnen aber ohne Erfolg.

Trotzdem danke für die Hinweise.

Gruss Werner

von dummschwaetzer (Gast)


Lesenswert?

Takte für Port, SPI, .. sind an?
Kannst du die verwendeten Ports schalten?
ggf HighSpeed im Speed-Register?

von dummschwaetzer (Gast)


Lesenswert?

Die Hal ist aber auch kein Hexenwerk. Da könntest du mal schauen wie 
CUBE-MX den Port und die SPI initialisiert und mit deinenm vergleichen.

von Werner R. (wt_r)


Lesenswert?

dummschwaetzer schrieb:
> Takte für Port, SPI, .. sind an?

Ja, siehe die ersten zwei Anweisungen in init_io.c.

> Kannst du die verwendeten Ports schalten?

Ja, ich kann das Signal CSB(NSS) eindeutig messen

> ggf HighSpeed im Speed-Register?

Habe ich schon probiert, bringt nichts, wäre bei 125KHz-SPI-Takt
auch verwunderlich.

Gruss Werner

von Beo Bachta (Gast)


Lesenswert?

dummschwaetzer schrieb:
> Die Hal ist aber auch kein Hexenwerk. Da könntest du mal schauen wie
> CUBE-MX den Port und die SPI initialisiert und mit deinenm vergleichen.

Es gibt ja auch in CubeMX die Möglichkeit die "althergebrachten"
Low-Level-Treiber zu verwenden.

Der Sinn es Ganzen (eine genormte Schittstelle zu verwenden) wäre
dass man keine Bits irgendwo vergisst zu initialisieren, sofern
man die üblichen Initialisierungen von Clock-System, Peripherieclock,
Peripherie-Enables, Ports, Alternativ-Funktionen (usw.) explizit aus
dem höheren Level aufruft bzw. ausführt.

Da es hier im Forum keinen schnell auffindbaren Link gibt, zeig
ich mal einen von der "Konkurrenz":

https://stackoverflow.com/questions/47972831/how-to-use-ll-low-level-drivers-in-cubemx-stm32

von Werner R. (wt_r)


Lesenswert?

Beo Bachta schrieb:
> Es gibt ja auch in CubeMX die Möglichkeit die "althergebrachten"
> Low-Level-Treiber zu verwenden.
>
> 
https://stackoverflow.com/questions/47972831/how-to-use-ll-low-level-drivers-in-cubemx-stm32

Ich versuche gerade CubeMX zu installieren, Installation wird wegen
falscher Java-Version abgebrochen. Muss mich zuerst schlau machen, wegen
"richtiger" Java-Version.

von Beo Bachta (Gast)


Angehängte Dateien:

Lesenswert?

Werner R. schrieb:
> Ich versuche gerade CubeMX zu installieren

Nachdem du darauf angesprungen bist, hier noch ein Beispiel
(aus der Anwendung der älteren Standard Peripheral Library)
wie ich das mache. Alle Initialisierungen in einer Funktion.
Nicht ganz vollständig da die Bezüge (*.h) fehlen, aber man
sieht wo es lang geht.

In der CubeMX-Libt heissen die Aufrufe natürlich gerigfügig
anders.

Auffällig ist für mich jetzt dass man auch für die
alternativen Peripherie-Funktionalitäten ein zusätzliches
Clock Enable braucht.

von Werner R. (wt_r)


Lesenswert?

Beo Bachta schrieb:

> Auffällig ist für mich jetzt dass man auch für die
> alternativen Peripherie-Funktionalitäten ein zusätzliches
> Clock Enable braucht.

Die von Dir beigefügte Inititialisierungsroutine ist identisch mit 
meiner, mit Ausnahme des Statements

RCC_APB2PeriphClockCmd (RCC_APB2Periph_AFIO, ENABLE);

Im Referenzmanual des STM32F1xx Seite 146 ist das Flag AFIOEN im 
Register
RCC_APB2ENR (Bit0) beschrieben.
Im Referenzmanual meines STM32F303 gibt es dieses Flag AFIOEN nicht, 
aber
im Register RCC_APB2ENR (Bit0) steht dafür das Flag SYSCFGEN (System 
Configuration Controller). Ich habe SYSCFGEN gesetzt aber ohne Erfolg.

Mit dem Flag SYSCFGEN und einem weiteren Flag SPI1_TX_DMA_RMP kann
man DMA-Kanäle ummappen.

Gruss Werner

von Beo Bachta (Gast)


Lesenswert?

Werner R. schrieb:
> Nein, ich erwarte genau 8 Taktsignale entsprechend 8-Datenbits,
> die ich mit dem Logicanalysor aufzeichne. Sowohl SCK als auch MOSI sind
> bei Ausgabe des Datenbytes permanent High.

Dann bleibt natürlich noch die Fehlerquelle dass du aus diesem
singulärem Ereignis es nicht schaffst deine Aufzeichnung darauf
zu triggern. Entweder du triggerst gar nicht oder die Software
des Oszilloskops schafft es nicht das Ereignis "einzufangen".

Eine Loop im 100usec-Takt würde helfen durch die Wiederholung
Ereignisse aufzufangen bzw. die Triggerart und -Level richtig
einzustellen.

von Werner R. (wt_r)


Angehängte Dateien:

Lesenswert?

Beo Bachta schrieb:

> Dann bleibt natürlich noch die Fehlerquelle dass du aus diesem
> singulärem Ereignis es nicht schaffst deine Aufzeichnung darauf
> zu triggern. Entweder du triggerst gar nicht oder die Software
> des Oszilloskops schafft es nicht das Ereignis "einzufangen".
>
> Eine Loop im 100usec-Takt würde helfen durch die Wiederholung
> Ereignisse aufzufangen bzw. die Triggerart und -Level richtig
> einzustellen.

Ich habe jetzt Mal eine do-while Schleife in main.c mit 100us Delay
programmiert. Sowohl das Speicher-Oszi als auch der SALEA Logicanalysor 
eingestellt auf SPI-Protokoll zeichnen jetzt SCK- und MOSI-Signale auf.

Das Problem ist und war folgendes:
Ich habe bisher immer im Einzelschritt (F5) das Programm getestet und
immer HIGH auf SCK und MOSI erhalten, obwohl Oszi und LA getriggert
haben.
Durch die do-while Schleife in main.c habe ich das Programm durchlaufen
lassen und siehe da SCK und MOSI erscheinen an PA5 und PA7.
D. h. die SPI-Schnittstelle verhält sich im Einzelschritt anders
als im Durchlauf. Das beigefügte Bild zeigt einen Einzelshot
mit SCK (gelb) und MOSI (magenta).

Dein Hinweis mit der Schleife war letztlich Gold wert und hat zur 
Problemlösung geführt. Nochmals Danke für Deine Ausdauer.

Gruss Werner

von Beo Bachta (Gast)


Lesenswert?

Werner R. schrieb:
> Das Problem ist und war folgendes:

Verstehe die Symptome zwar nicht ganz, aber danke für die
vorbildliche Rückmeldung!

von Werner R. (wt_r)


Lesenswert?

Beo Bachta schrieb:
> Werner R. schrieb:
>> Das Problem ist und war folgendes:
>
> Verstehe die Symptome zwar nicht ganz, aber danke für die
> vorbildliche Rückmeldung!

Einfach formuliert im Einzelschritt gibt die SPI-Schnittstelle
beim Befehl SPI1->DR = val; keine SCK- und MOSI-Signale aus
im normalen Programmdurchlauf (selbst bei einmaligem Durchlauf, keine 
Schleife)  erscheinen die Signale SCK und MOSI. Frag mich bitte nicht
warum.

Übrigens in dem Oszi-Bild das ich angehängt hatte werden 16 Takte
für ein Byte ausgegeben. Wenn ich den Befehl SPI1->DR = val;
durch  *(volatile uint8_t*) &SPI1->DR = val; ersetze sind es genau 8 
Takte
bei einem Byte als Ausgabe.

Gruss Werner

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.