Forum: Mikrocontroller und Digitale Elektronik STM32 HAL SPI nur 18 Bits senden oder Bitbanging?


von Ralph (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Zusammen,

ich möchte gerne ein Baustein (HMC6300) via SPI konfigurieren (siehe 
Anhang). Leider umfasst das Register des Bausteins nur 18 Bits. Ein 
Versuch mit der HAL_SPI_TransmitReceive() Funktion 24 Bits (um 5 
führende Nullen ergänzt, welche ggf. durch das FIFO gelatched werden) zu 
übertragen schlug fehl.

Gibt es eine Möglichkeit nur die benötigten 18 Bits zu senden?

Falls nur Bitbanging möglich ist, wie kann ich geschickt auf die 
GPIO-Pins zugreifen? Die bestehende SPI Konfiguration kann nicht ohne 
weiteres geändert werden, da auf dem SPI-BUS noch andere Bausteine sind, 
welche konfiguriert werden müssen.

Wäre sowas in der Art möglich:
void Bitbanging_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t 
*pTxData, uint8_t *pRxData, uint8_t HMC630x_NUM_TX_BITS, uint8_t 
HMC630x_NUM_RX_BITS)
{
//Default Bitbanging
...

//Pseudocode für GPIO-Zugriff über SPI-Handler
HAL_GPIO_WritePin(hspi.MOSI_Port, hspi.MOSI_PIN, MOSI_PIN_SET);
}

Vielen Dank,

Ralph

von Frickelfritze (Gast)


Lesenswert?

Ralph schrieb:
> Ein
> Versuch mit der HAL_SPI_TransmitReceive() Funktion 24 Bits (um 5
> führende Nullen ergänzt, welche ggf. durch das FIFO gelatched werden) zu
> übertragen schlug fehl.

Nach Adam Riese (und Eva Zwerg) müssten 6 führende Nullen ergänzt
werden damit 24 Bits aufgefüllt werden.

Aber ich behaupte dass du etwas anderes falsch machst. Es ist
offensichtlich dass die Vorgeschichte (was vor den 18 Bits
passiert) unerheblich ist, was sich aus dem aus dem Datenblatt
zitierten Absatz (speziell der zweite Teil) entnehmen lässt:

--------------------------------------------------------------
After the 18th clock pulse of the write operation, the ENABLE
line returns high to load the register array on the IC; prior
to the rising edge of the ENABLE line, no data is written to
the array.
--------------------------------------------------------------

Also nur die steigende Flanke der ENABLE Leitung entscheidet
was in die Register geschrieben wird.

Entweder ist deine SPI falsch konfiguriert (Clock Polarität,
Clock Phase) oder die Ausrichtung deiner Daten in den 24 Bit
ist nicht korrekt.

von Frickelfritze (Gast)


Lesenswert?

Ralph schrieb:
> Gibt es eine Möglichkeit nur die benötigten 18 Bits zu senden?

Beachte auch dass (eher ungewöhnlich) die Bits vom nieder-
wertigsten zuerst bis zum höchstwertigen gesendet werden.
Das ist eher die Analog Devices Manier, während man bei
(ehemals) Hittite "immer" MSB zuerst überträgt / übertragen hat.

von Peter D. (peda)


Lesenswert?

Die Datenlänge ist beim STM32F303 von 4-16 Bits konfigurierbar. Also 
einfach 2*9 Bit senden und schon hast Du die 18 Bits.

SPI control register 2 (SPIx_CR2)
Bits 11:8 DS [3:0]: Data size
These bits configure the data length for SPI transfers:
1000: 9-bit

von Ralph (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Zusammen,

zunächst einmal vielen Dank für eure hilfreichen Antworten.

@Frickelfritze
Du hast natürlich recht, es müssen 6 führende Nullen sein. Die 
Problematik mit dem LSB first habe ich abgehandelt und der Vereinfachung 
nicht erwähnt. Falls es wen interessiert, dass Datenwort erzeuge ich wie 
folgt:
1
 ...
2
  /* SPI1 parameter configuration*/
3
  hspi1.Instance = SPI1;
4
  hspi1.Init.Mode = SPI_MODE_MASTER;
5
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
6
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
7
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
8
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
9
  hspi1.Init.NSS = SPI_NSS_SOFT;
10
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
11
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; //Kompatiblität mit anderen Bausteinen
12
 ...
13
14
 ...
15
uint32_t volatile TxWord, RxWord;
16
  
17
TxWord = (ADDRESS_BIT << HMC630x_ADDRESS_BIT_OFFSET) | (R_W_Bit << HMC630x_R_W_Bit_OFFSET) | (REG_CTRL_Bit << HMC630x_REG_CTRL_BIT_OFFSET) | (Value << HMC630x_VALUE_BIT_OFFSET);  
18
19
TxWord = (TxWord << 6); //führende Nullen anhängen
20
TxWord = Swap4Bytes(TxWord); //Byteweise Swappen
21
TxWord = reverse32(TxWord); //alles Bits reversen
22
23
HAL_SPI_TransmitReceive(hspi, (uint8_t *)&TxWord, (uint8_t *)&RxWord, HMC630x_WORD_WIDTH_BYTES, HAL_MAX_DELAY);
24
 ...

Prinzipell kann ich jetzt das gewünschte Bitpattern senden. Bei 
Anschluss des HMC6300 wird jedoch die Clk und MOSI Leitung auf high 
gezogen, ggf. ist dies noch ein Hardwareproblem bei dem ich bei muss. 
Jedenfalls antwortet der HMC6300, was er eigentlich bei gesetztem 
Write-Bit nicht machen sollte (siehe Timing Diagramm in meinem ersten 
Post).

Hier ein beispielhaftes Bitpattern an den HMC6300 gesendet (lsb first, 
ohne die 6 führende Nullen):
011100000011110000

Anbei die zugehörige Ausgabe auf dem Logikanalyser.

@Peter D.
Ich nutze einen STM32L052K8U. Mir ist noch nicht klar, wie ich die 
Datensize geschickt unter Kompatiblität zu CubeMX ändern kann. Kann ich 
die Datensize auf zur Laufzeit ändern? Wie erwähnt hängen noch andere 
Bausteine mit an dem Bus und müssen konfiguriert werden.

von Peter D. (peda)


Lesenswert?

Ralph schrieb:
> hspi1.Init.DataSize = SPI_DATASIZE_8BIT;

Ich würde da einfach ne 9 eintragen und schauen, ob der Compiler 
meckert.

Ralph schrieb:
> Kann ich
> die Datensize auf zur Laufzeit ändern?

Du kannst das SPI jederzeit umkonfigurieren, wenn ein Transfer beendet 
ist.

von Johnny B. (johnnyb)



Lesenswert?

Ralph schrieb:
> Ich nutze einen STM32L052K8U. Mir ist noch nicht klar, wie ich die
> Datensize geschickt unter Kompatiblität zu CubeMX ändern kann.

Das kannst Du ja in CubeMX einstellen, siehe Anhang. (ich sehe aber 
gerade, dass der STM32L052 wohl nur 8- und 16-bit unterstützt)

: Bearbeitet durch User
von Ralph (Gast)


Lesenswert?

Hm oky also kann ich via Hardware nur 8 oder 16 Bit ausgeben. Schade.

Besteht die Möglichkeit die SPI-Pins ans Port A zur Laufzeit auch via 
Bitbanging zu bedienen?

von Peter D. (peda)


Lesenswert?

Johnny B. schrieb:
> ich sehe aber
> gerade, dass der STM32L052 wohl nur 8- und 16-bit unterstützt

So siehts aus.
Daher sollte man das konkrete Target immer als erstes angeben.

von Stefan F. (Gast)


Lesenswert?

Ralph schrieb:
> Besteht die Möglichkeit die SPI-Pins ans Port A zur Laufzeit auch via
> Bitbanging zu bedienen?

Natürlich, das geht immer.

von Ralph (Gast)


Angehängte Dateien:

Lesenswert?

Hm, wie den? Ich kann in CubeMX die Pins als Hardware-SPI ODER als GPIO 
Input/Output konfigurieren . Beides geht nicht bzw. wüsste ich nicht 
wie. Kann ich trotz Hardware-SPI Konfiguration eine Art 
HAL_GPIO_WritePin(SPI_MOSI_GPIO_Port, SPI_MOSI_Pin, GPIO_PIN_SET); 
aufrufen?

Um weiter zu kommen habe ich mal Hardware-SPI durch Bitbanging ersetzt 
und getestet (zwar unschön aber naja.. ).
1
void Bitbanging_SPI_Transmit(uint32_t TxWord)
2
{
3
   for (uint8_t i = 0; i < 18; i++)
4
   {
5
       if (TxWord & 0x1)
6
           HAL_GPIO_WritePin(SPI_MOSI_GPIO_Port, SPI_MOSI_Pin, GPIO_PIN_SET);          
7
       else
8
           HAL_GPIO_WritePin(SPI_MOSI_GPIO_Port, SPI_MOSI_Pin, GPIO_PIN_RESET);
9
10
       HMC630x_Delay();
11
       HAL_GPIO_WritePin(SPI_CLK_GPIO_Port, SPI_CLK_Pin, GPIO_PIN_SET);
12
       HMC630x_Delay();
13
       HAL_GPIO_WritePin(SPI_CLK_GPIO_Port, SPI_CLK_Pin, GPIO_PIN_RESET);
14
       HMC630x_Delay();
15
16
       TxWord >>= 1;
17
   }
18
  
19
   HAL_GPIO_WritePin(SPI_MOSI_GPIO_Port, SPI_MOSI_Pin, GPIO_PIN_RESET);
20
}

Die Ausgabe funktioniert laut Logicanalyser (siehe Anhang). Leider 
antwortet der HMC6300 an MISO, was er bei einem Write nicht machen 
sollte.

Nach meinem Verständnis endspricht die Ausgabe jetzt der des 
Datenblattes. Etwas unsicher bin ich mir bei der TX-Adresse: "the Tx 
Chip Address 110, LSB first)." -> Verstehe ich so, dass ich erst die 
Null sende und dann die beiden Einsen.

von Stefan F. (Gast)


Lesenswert?

Niemand zwingt dich dazu, die Konfiguration der I/O Pins ausschließlich 
über Cube MX zu machen. Dein Programm kann sie zur Laufzeit beliebig 
umkonfigurieren.

Falls Dir das dann in Kombination mit Cube MX zu kompliziert wird - 
willkommen im Club. Ich benutze die ganze HAL gar nicht, CMSIS und ein 
paar Zeilen eigener Code genügen mir.

von Johnny B. (johnnyb)


Lesenswert?

Zwischenfrage; Elektrisch ist das SPI vom HMC6300 richtig angeschlossen, 
d.h. mit 1.2V Pegelwandler?

von Ralph (Gast)


Angehängte Dateien:

Lesenswert?

@Stefanos
Oky danke. Dann werde ich sobald das Bitbanging funktioniert, versuchen 
den Code zusammenzuführen. Schade, dass dann wahrscheinlich die 
Kompatiblität zu CubeMX verloren gehen wird. Bis jetzt konnte ich immer 
in CubeMX neuen Code generieren und nahtlos in den bestehenden 
einsetzen.

@Johnny B.
Ja genau, ich verwende Pegelwandler (MAX3392EEUD+).
Ich habe anbei drei Screenshots vom Oszilloskope beigefügt (Übersicht, 
Zoom, noch mehr Zoom). Das Oszilloskope ist hinter den Pegelwandlern, 
direkt am HMC6300 angeschlossen. Man sieht relativ starkes 
Überschwingen, ggf. wäre eine Serienterminierung sinnvoll. Was meint 
Ihr?

Ich glaube trotzdem nicht, dass dies der Grund dafür ist, dass der 
HMC6300 nicht funktioniert. Aktuell gehen mir die Ideen etwas aus.

von pegel (Gast)


Lesenswert?

Gesund sehen die Signale nicht aus und 1,2V Pegel haben die auch nicht 
wirklich, jedenfalls nicht für lange.

Ausserdem funkt schon nach 16 Takten das CS dazwischen, so kommt es 
nicht zu Übernahme der 18 bit.

von pegel (Gast)


Lesenswert?

Den zweiten Satz nehme ich zurück.
Da muss ich mich vorhin irgendwie verguckt haben.

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.