Hallo zusammen,
ich habe schon mal vor einiger Zeit hier im Forum zu meinen Versuchen
einen Positionssensor mit SSI-Schnittstelle auszulesen Hilfe gefunden:
STM32 SPI im Halbduplex-Betrieb mit DMA. Leider habe ich immer noch
Probleme mit der Aufgabe.
Der Sensor hat ein CSN-, CLK-, und DO-Pin. Diese habe ich bei meinem
STM32F103CB mit SPI1_NSS (PA4). SPI1_SCK (PA5) und SPI1_MISO (PA6)
verbunden.
Ich habe mal neben dem Quellcode die Messung eines Frames per Oszi und
Logic Analyser und das Datenblatt-Diagramm des Sensors angehängt.
1. Frage: Wie man im angehängten Diagramm sieht, fällt die Clk-Leitung
nach jedem Frame in einer schönen (1-e)-Funktion auf Low. Das liegt wohl
daran, dass ich nach jedem Frame die SPI-Schnittstelle deaktiviere, um
den Clk abzustellen. Eigentlich hätte ich gerne, dass die Clk-Leitung in
dieser Zeit Idle High bleibt. Gibt es eine Möglichkeit den SPI Clk
gezielt in Idle zu versetzen?
2. Frage: Ich habe das Problem, dass der DMA-Interrupt nach 3 Byte nicht
aufgerufen wird. Ich habe einen Timeout eingebaut, der nach 200 us den
Frame zwangsweise beendet, wenn er nicht vorher per DMA-Interrupt
deaktiviert wird. Meine DMA-Konfiguration sieht folgendermaßen aus:
Ich aktiviere die DMA-Kanäle nach einer Initialisierungszeit von 10us
pro Frame.
Hat da jemand Ideen zu? Ich komme irgendwie nicht weiter und bin daher
für jede Anregung dankbar :)
Janis
> Ich habe mal neben dem Quellcode die Messung eines Frames per Oszi und> Logic Analyser und das Datenblatt-Diagramm des Sensors angehängt.
Sehe ich das richtig? Dein Highpegel ist nur 0.3V? Oder hast du
uns einen 10:1 Tastkopf verschwiegen?
Wenn letzteres, findest du dein Unterschwingen nicht schon etwas heftig?
> fällt die Clk-Leitung> nach jedem Frame in einer schönen (1-e)-Funktion auf Low.
Das ist nicht schoen. Wieviel Clocks mag dein Device wohl in der Zeit
zaehlen wo du durch seinen Umschaltpunkt laeufst?
> Gibt es eine Möglichkeit den SPI Clk> gezielt in Idle zu versetzen?
Ich kenne deinen Prozessor nicht, aber entweder man hat ein
SPI-Interface das diese Funktionalitaet hat, oder man schaltet auf
Portmodus zurueck und hat den Port dann als Ausgang mit dem Wunschpegel,
oder aber man spendiert einen Widerstand. So wie es jetzt ist geht es
jedenfalls niemals.
Olaf
Janis W. schrieb:> 1. Frage: Wie man im angehängten Diagramm sieht, fällt die Clk-Leitung> nach jedem Frame in einer schönen (1-e)-Funktion auf Low. Das liegt wohl> daran, dass ich nach jedem Frame die SPI-Schnittstelle deaktiviere, um> den Clk abzustellen. Eigentlich hätte ich gerne, dass die Clk-Leitung in> dieser Zeit Idle High bleibt. Gibt es eine Möglichkeit den SPI Clk> gezielt in Idle zu versetzen?
Du lässt das SPI einfach an !
> 2. Frage: Ich habe das Problem, dass der DMA-Interrupt nach 3 Byte nicht> aufgerufen wird.
Logo siehe deine CodeZeile:
Hallo Olaf und Jean Player,
danke für die schnellen Antworten! Ja, ich hatte den Tastkopf
versehentlich auf 10:1 stehen und gar nicht mehr nach der Amplitude
geschaut...
Ich könnte natürlich den Pin immer wieder als normalen Portpin
umkonfigurieren. Aber das muss doch auch anders gehen. Wenn ich den SPI
aktiviert lasse, läuft der Clk immer durch.
Muss bei der Initialisierung
1
DMA_InitStructure.DMA_BufferSize = 2;
sein? Dann hatte ich das wohl falsch verstanden...
Gruß
Janis
Ok, das mit dem Clk liegt wohl an dem Receive-only-Modus:
To start the communication in receive-only mode, configure and enable
the SPI: In master mode, the communication starts immediately and stops
when the SPE bit is cleared and the current reception stops. There is no
need to read the BSY flag in this mode. It is always set when an SPI
communication is ongoing.
Werde das mal auf Full Duplex umbauen und sehen, ob das das Problem
lösen kann...
für 3 Byte lohnt DMA sowiso nicht, der Overhead mit Interrupt ist größer
als die Zeitersparnis durch den DMA, lass das weg. Such dir lieber ein
Beispiel aus den Libraries raus, die haben bei mir alle hervoragend
funktioniert
Naja, inzwischen habe ich es geschafft, dass der Clk zwischen den Frames
in Idle high geht. Allerdings wird der DMA Transfer Complete Interrupt
zu früh geschmissen. Nämlich direkt nachdem ich DMA aktiviert habe. Zu
sehen ist das am In 2 des Logic Analysers (CS). Der wird direkt nach der
Active low durch den Interrupt wieder auf Idle high gesetzt. Und damit
kommen auch keine Daten mehr an, obwohl die Taktleitung schön wackelt...
Das Problem ist nicht der DMA TC Interrupt, sondern die TIM3 Compare
Interrupts. Trotz Deaktivierung per
1
TIM_ITConfig(TIM3, TIM_IT_CC2, DISABLE);
scheinen die CCxIF Flags im TIMx_SR Register gesetzt zu werden. Diese
werden dann beim nächsten Interrupt-Aufruf falscherweise mit
abgearbeitet.
Ich mache zu dem Thema einen neuen Beitrag auf, da das nichts mehr mit
DMA und SPI zu tun hat.
Janis
Hallo Janis,
kann es sein das deine 3 Byte die Du senden möchtest sofort in einen
Hardware-TX-FIFO deiner Schnittstelle gehen und deshalb der
DMA-Interrupt sofort fertig ist?
Gruß
Hallo Felix,
soweit ich mich erinnern kann, lag das am Modus. Mit
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
hat es dann funktioniert. Ich hoffe, das hilf Dir weiter.
Gruß
Janis
Hallo Felix,
Felix S. schrieb:> Hallo Janis>> Wie hast Du es geschafft, dass der Clock im Idle high bleibt?> Ich habe dasselbe Problem mit der gleichen CPU-Famile.
Bei SPI gibt es 4 Modi, die sich darin unterscheiden,
welches die aktive Flanke und welches der CLK Pegel
im Idle ist.
Weiss jetzt nicht auswendig, wie das beim STM32 einzustellen
ist, aber das Datenblatt gibt das sicher Auskunft
Punkt.