www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik STM32 SPI im Halbduplex-Betrieb mit DMA


Autor: Janis W. (jotwe)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich versuche per SPI1 einen Positionssensor mit SSI-Schnittstelle 
auszulesen. 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 verwende, wie in Beitrag "STM32F: SPI "Halbduplex"" 
beschreiben, zwei DMA-Kanäle (DMA1-Channel2 und -Channel3), um 3 Bytes 
vom Sensor zu empfangen. Jede Millisekunde wird über den SysTick die 
Funktion SENSOR_Activate() aufgerufen, die die beiden DMA-Kanäle und 
SPI1 aktiviert. Nach beendeter Übertragung soll über den Transfer 
Complete Interrupt (DMA1_IT_TC2) die Funktion SENSOR_Deactivate() die 
DMA-Kanäle und SPI1 deaktivieren. Bis der nächste Systick alles wieder 
aktiviert usw.

Leider wird aber nie der Transfer Complete Interrupt erreicht. Auf dem 
Oszi sehe ich, dass eigentlich nur der NSS-Pin auf low gezogen wird, 
aber sonst nicht viel passiert - keine Taktausgabe auf SCK und folglich 
auch keine Daten auf MISO.

Sollte mit
DMA_Cmd(DMA1_Channel2, ENABLE);
DMA_Cmd(DMA1_Channel3, ENABLE);
SPI_Cmd(SPI1, ENABLE);

nicht die Übertragung gestartet werden oder fehlt da noch was?

Muss ich für meine Anwendung die SPI_Direction auf 
SPI_Direction_2Lines_FullDuplex oder kann sie auf SPI_Direction_1Line_Rx 
gestellt werden (hatte jetzt keinen Einfluss auf mein Problem)?

Ich bin für jeden Hinweis dankbar. Die Dokumentation von ST ist nicht so 
ganz einfach zu durchschauen ;)

Gruß

Janis

Autor: Janis W. (jotwe)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo A. K.,

danke für die Antwort. Das Problem ist mir bewusst. Das werde ich mit 
einem zusätzlichen Interrupt später lösen. Allerdings scheitert es ja 
schon daran, dass überhaupt etwas über die SPI geht. Wenn nur ein paar 
Bits abgeschnitten werden (CS zu früh), wäre ich schon sehr 
glücklich....

Gruß

Janis

Edit: Hm, jetzt ist sein Beitrag weg...

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
J. W. schrieb:

> Edit: Hm, jetzt ist sein Beitrag weg...

War sozusagen eine Standardantwort, zu schnell, sorry. Aber ich sah erst 
danach, dass du CS erst mit den Rx-DMA-TC abschaltest, nicht mit Tx. Das 
ist korrekt.

Autor: Hannes S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Aktivieren des Clocks für den AFIO hab ich nirgendwo gesehen. Also 
fehlt sowas, glaub ich:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, 
ENABLE);

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da du ausschliesslich empfängst, dann kannst du natürlich auf 2-Line FDX 
stellen und MOSI einfach weglassen.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was CS angeht: Lass das "Hard" weg und geh auschliesslich auf 
Software-CS. Das Hardware-CS vom SPI ist nicht ganz das, was man sich 
drunter vorstellt.

Autor: Janis W. (jotwe)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Hannes: Ich habe es jetzt mal mit RCC_APB2Periph_AFIO probiert. Leider 
keine Änderung. Meine USART funktioniert auch irgendwie ohne die AFIO 
Clock, obwohl das ja auch AFs sind... müsste ich die da eigentlich auch 
aktivieren?

@A.K. Wenn ich auf Soft-CS umstelle, muss ich den Pin dann auch bei 
Übetragungsbeginn manuell auf active low ziehen oder erledigt das die 
Hardware für mich?

Wenn ich auf 1-Line-RxOnly gehe, dann sollte der MOSI-Pin ja für andere 
Funktionen zur Verfügung stehen... daher nehme ich dann wohl lieber 
diese Option.

Gruß

Janis

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
J. W. schrieb:

> @Hannes: Ich habe es jetzt mal mit RCC_APB2Periph_AFIO probiert. Leider
> keine Änderung. Meine USART funktioniert auch irgendwie ohne die AFIO
> Clock, obwohl das ja auch AFs sind... müsste ich die da eigentlich auch
> aktivieren?

Mir spukt vage im Kopf rum, dass man AFIO nur einschalten muss, wenn man 
auch an die ensprechenden Register ran will.

> @A.K. Wenn ich auf Soft-CS umstelle, muss ich den Pin dann auch bei
> Übetragungsbeginn manuell auf active low ziehen oder erledigt das die
> Hardware für mich?

Soft heisst Soft. Vorher aktivieren, nachher deaktivieren. Der Pin hat 
dann auch keine AF Funktion, sondern ist normaler Portpin.

> Wenn ich auf 1-Line-RxOnly gehe, dann sollte der MOSI-Pin ja für andere
> Funktionen zur Verfügung stehen... daher nehme ich dann wohl lieber
> diese Option.

Der Reference vom Controller entnehme ich, dass in den rxonly- und 
bidi-receive-Modi der SPI-Takt völlig ohne Transmitter arbeitet, also 
sofort loslegt sobald SPI aktiviert wird, und erst aufhört wenn SPI 
deaktiviert wird. Folglich werden u.U. mehr als die gewünschten 3 Bytes 
durchgetaktet. Wenn das nicht stört, dann ist das durchaus sinnvoll.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PS: Da ich die FWlib nicht verwende kann ich wenig zum konkreten Code 
sagen. Ein Grund weshalb ich die nicht verwende ist die hier prima 
sichtbare Begriffsverwirrung. Die Chipref spricht von unidirectional und 
bidirectional Modi, die Lib übersetzt das in 1line und 2line. Da ohne 
die Ref zu lesen ohnehin nichts geht macht die Lib das Leben folglich 
nicht einfacher sondern komplizierter, da man gewissermassen 
gleichzeitig mit Chinesisch und Japanisch kämpft, statt sich für eine 
Sprache entscheiden zu können.

Autor: Janis W. (jotwe)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich das richtig auf der FWLib rauslese:
#define SPI_Direction_2Lines_FullDuplex ((uint16_t)0x0000)
#define SPI_Direction_2Lines_RxOnly     ((uint16_t)0x0400)
#define SPI_Direction_1Line_Rx          ((uint16_t)0x8000)
#define SPI_Direction_1Line_Tx          ((uint16_t)0xC000)

dann bedeutet das für das SPI_CR1:

SPI_Direction_2Lines_FullDuplex

Bit 15 BIDIMODE: Bidirectional data mode enable
0: 2-line unidirectional data mode selected
Bit 14 BIDIOE: Output enable in bidirectional mode
0: Output disabled (receive-only mode)

SPI_Direction_2Lines_RxOnly

Bit 15 BIDIMODE: Bidirectional data mode enable
0: 2-line unidirectional data mode selected
Bit 14 BIDIOE: Output enable in bidirectional mode
1: Output enabled (transmit-only mode)

SPI_Direction_1Line_Rx

Bit 15 BIDIMODE: Bidirectional data mode enable
1: 1-line bidirectional data mode selected
Bit 14 BIDIOE: Output enable in bidirectional mode
0: Output disabled (receive-only mode)

SPI_Direction_1Line_Tx

Bit 15 BIDIMODE: Bidirectional data mode enable
1: 1-line bidirectional data mode selected
Bit 14 BIDIOE: Output enable in bidirectional mode
1: Output enabled (transmit-only mode)

Nun ja, ich wollte eigentlich SPI_Direction_2Lines_RxOnly nehmen, aber 
'transmit-only mode' klingt in dem Zusammenhang irgendwie komisch. Dann 
bleibe ich hat bei FullDuplex und verzichte auf den MOSI-Pin...

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
J. W. schrieb:

> _SPI_Direction_2Lines_RxOnly_
>
> Bit 15 BIDIMODE: Bidirectional data mode enable
> 0: 2-line unidirectional data mode selected
> Bit 14 BIDIOE: Output enable in bidirectional mode
> 1: Output enabled (transmit-only mode)

Nope. Nicht Bit 14, sondern Bit 10 = RXONLY. Passt.

Autor: Hannes S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@A.K: In meinem Fall gings nicht ohne RCC_APB2Periph_AFIO, allerdings 
hatte ich auch die Ports remapped. Wahrscheinlich hast Du recht, und man 
braucht das nicht immer.

Ansonsten sehe ich eigentlich fast keine Unterschied zu meinem Code - 
muss aber sagen, ich hab mich nicht allzutief mit SPI damit beschäftigt, 
da das Sample (merkwürdigerweise) fast auf Anhieb geklappt hat...

Autor: Janis W. (jotwe)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ahja, Bit 10 gibt's auch noch... na denn :)

Autor: Janis W. (jotwe)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe einen typischen Copy-Paste-Fehler gefunden ('1' statt '2'):

RCC_APB1PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

hätte

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

sein müssen. Jetzt kommt wenigstens ein CLK-Signal, aber in den 
Interrupt komme ich leider immer noch nicht... aber immerhin.

Autor: Hannes S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht noch Interrupts mit DMA_ITConfig() einschalten? (Habs selbst 
nicht gemacht - auch wenns peinlich ist, Ich hab hier auf DMA Ende 
gepollt...)

Autor: Hannes S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry.... hab die Zeile bei Dir übersehen und gerade gefunden,

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.