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


von Janis W. (jotwe)


Angehängte Dateien:

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
1
DMA_Cmd(DMA1_Channel2, ENABLE);
2
DMA_Cmd(DMA1_Channel3, ENABLE);
3
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

von Janis W. (jotwe)


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...

von (prx) A. K. (prx)


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.

von Hannes S. (Gast)


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);

von (prx) A. K. (prx)


Lesenswert?

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

von (prx) A. K. (prx)


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.

von Janis W. (jotwe)


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

von (prx) A. K. (prx)


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.

von (prx) A. K. (prx)


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.

von Janis W. (jotwe)


Lesenswert?

Wenn ich das richtig auf der FWLib rauslese:
1
#define SPI_Direction_2Lines_FullDuplex ((uint16_t)0x0000)
2
#define SPI_Direction_2Lines_RxOnly     ((uint16_t)0x0400)
3
#define SPI_Direction_1Line_Rx          ((uint16_t)0x8000)
4
#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...

von (prx) A. K. (prx)


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.

von Hannes S. (Gast)


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...

von Janis W. (jotwe)


Lesenswert?

Ahja, Bit 10 gibt's auch noch... na denn :)

von Janis W. (jotwe)


Lesenswert?

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

1
RCC_APB1PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

hätte

1
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.

von Hannes S. (Gast)


Lesenswert?

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

von Hannes S. (Gast)


Lesenswert?

Sorry.... hab die Zeile bei Dir übersehen und gerade gefunden,

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.