Forum: Mikrocontroller und Digitale Elektronik SPI Konfiguration beim STM32F107


von paul (Gast)


Angehängte Dateien:

Lesenswert?

Hallo alle zusammen,

ich arbeite gerade mit dem STM32F107 und möchte per SPI den Winkelsensor 
AS5040 auslesen.
Das Interface aus dem Datenblatt des Sensors habe ich angehängt. Den 
STM32 habe ich dazu wie folgt konfiguriert:
1
SPI_I2S_DeInit(SPI3);
2
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
3
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
4
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
5
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
6
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
7
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
8
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
9
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
10
SPI_Init(SPI3, &SPI_InitStructure);
11
12
SPI_Cmd(SPI3, ENABLE);

Um den Winkelinformationen auszulesen nutze ich folgende Routine:
1
GPIOA->BRR = GPIO_Pin_4;     // Chip-Select low
2
SPI_I2S_SendData(SPI3, 0x55);     // Dummy-Byte senden
3
while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_BSY) == SET) {}   // warten solange Busy-Flag gesetzt ist
4
GPIOA->BSRR = GPIO_Pin_4;    // Chip-Select high
5
AS_Winkel = SPI_I2S_ReceiveData(SPI3);    // Winkelinfos lesen
6
AS_Winkel >>= 5;    // shiften

An sich funktioniert das Auslesen des Winkels, jedoch müsste ich meiner 
Meinung nach 6 mal shiften, um den Winkel zu haben, da dieser die 
obersten 10 Bit belegt. Den richtigen Winkel bekomme ich jedoch nur, 
wenn ich 5 mal shifte. Das heißt ja eigentlich, dass das letzte Bit 
nicht eingelesen wird.

Würde mich freuen, wenn mir jemand einen Tipp geben kann, an was dies 
liegt oder ob ich ein Fehler in der Konfiguration gemacht hab.

Danke und Gruß
Paul

von Scher (Gast)


Lesenswert?

>SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

Wenn ich Deine Bildchen und das STM32 Datenblatt richtig interpretiere,

sollte das eher

SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;

sein.

Gruss

Scher

von paul (Gast)


Angehängte Dateien:

Lesenswert?

Also ich habs jetzt mal so wie du gesagt hast getestet:
1
SPI_I2S_DeInit(SPI3);
2
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
3
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
4
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
5
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
6
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
7
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
8
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
9
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
10
SPI_Init(SPI3, &SPI_InitStructure);
11
12
SPI_Cmd(SPI3, ENABLE);

Aber egal, ob ich 5 oder 6 mal shifte, kommt trotzdem nicht das richtige 
raus.

Ich hab ein Bild vom Logikanalysator angehängt. Wenn ich das Bild mit 
dem aus dem Datenblatt des AS5040 vergleiche, sieht es aus, als würde 
CSn zu früh auf high gehen. Könnte es daran liegen?

von (prx) A. K. (prx)


Lesenswert?

Wenn du das Bild aus dem Datasheet genau anschaust, dann kannst du 
erkennen, dass es für das letzte Bit zwar eine Taktflanke gibt, durch 
die es ausgelöst wird, aber keine, an der es durch den Controller 
abgetastet werden könnte.

Der Sensor liefert das erste Datenbit so, dass es erst mit der zweiten 
fallenden oder steigenden Taktflanke gesampelt werden kann. Einen 
passenden SPI-Modus für dieses SSI-Protokoll gibt es nicht. Folglich 
landen die Daten um ein Bit verschoben im Register und das letzte Bit 
ist nicht verfügbar.

Wenn du dieses letzte Bit benötigst, dann kannst du nach der Übertragung 
des Datenwortes und vor Deaktivierung des Sensors den Pinzustand 
auslesen.

von Leo B. (luigi)


Lesenswert?

Der AS5040 ist ein ganz gemeiner Hund!
Du musst aufpassen, welchen Pegel der DI-Pin (MOSI) beim Selektieren des 
Device hat. Sonst versetzt du ihn ggf. in den Programmiermodus, was du 
bestimmt nicht willst oder??
Desweiteren ist entscheidend, dass der Sensor wohl einen kompletten 
CLK-Puls benötigt bevor das erste Datenbit rausgetaktet wird, sonst 
liest du das erste Bit immer als eine 1 und der ganze Datenstrom ist um 
ein Bit verschoben... (Parity wird also abgeschnitten.)

von paul (Gast)


Lesenswert?

Vielen Dank für die Tipps.
Also das Parity-Bit benötige ich eigentlich nicht. Wollte nur die 
kompletten 16 Bit auslesen. Die Winkelinfo reicht mir schon, von daher 
werd ich einfach 5 mal shiften.

von Na55im (Gast)


Angehängte Dateien:

Lesenswert?

Hey,
ich weiß der Thread ist alt, aber ich habe ein Problem seit Tagen, 
welches ich mir nicht erklären kann.

Wenn ich den AS5040 über SPI auslesen möchte, fehlen die Datenbits 0-2.

Ich habe den Magneten 3x um 90° gedreht und folgendes erhalten:

Position|tDo|_____D0___|Systeminfos|D0(Dez)|DR(HEX)|DR(Dez)|
______|___|0123456789|__________|_______|_______|_______|
0_____|1__|0000010101|10011_____|21_____|82D3___|33459__|
90____|1__|0001010110|10011_____|86_____|8AD3___|35539__|
180___|1__|0000101010|10011_____|42_____|8553___|34131__|
360___|1__|0000011101|10011_____|29_____|82B3___|33715__|

Aus der Tabelle lässt sich ja erkennen, dass D0,D1,D2 immer Null sind.
In dem angehängtem Bild meines Logikanalyzers, sieht man, der Sensor 
sendet auch genau diese Daten.

Ich weiß also nicht warum der Sensor diese Daten so sendet.

Mein SPI habe ich wie folgt deklariert:
1
  
2
  hspi1.Instance = SPI1;
3
  hspi1.Init.Mode = SPI_MODE_MASTER;
4
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
5
  hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
6
  hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
7
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
8
  hspi1.Init.NSS = SPI_NSS_SOFT;
9
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
10
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
11
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
12
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
13
  hspi1.Init.CRCPolynomial = 7;
14
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
15
  {
16
    _Error_Handler(__FILE__, __LINE__);
17
  }

Die Daten verarbeite ich wie folgt:
1
  GPIOC ->BRR = GPIO_PIN_6;// Start Receiving
2
   HAL_SPI_Receive(&hspi1,(uint8_t *)angle_data, 1, 300);//Receive 1x16Bit
3
   GPIOC ->BSRR = GPIO_PIN_6;// End Receiving
4
   *angle_data&=0x7fff; // cause tD0 broke first bit
5
   *angle_data >>=5; // Shift for getting angular position (first 10 Bit)


Ich hoffe jemand weiß mir zu helfen.

Gruß Nassim

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.