Einrichten von SPI zwischen einem STM32F4-Discovery Board und einem MCP4151 Digital Pot

Ich arbeite derzeit an einem Projekt, in dem ich versuche, ein MCP4151-Digitalpotentiometer mit dem STM32F4-Discovery Board unter Verwendung der Mars Eclipse IDE zu verbinden. Ich habe den STM32F4xx HAL heruntergeladen und eingebunden, habe aber Schwierigkeiten, alle Pins und Einstellungen richtig zu bekommen.

Aus dem STM32F407-Datenblatt (Seite 49) konnte ich ableiten, dass ich PA5 und PA7 als Pins für SPI_SCK und SPI_MOSI verwenden möchte. Also habe ich den Code aus diesem Projekt geändert , um diese Pins zu aktivieren:

void SPI_Init(){
   hspi1.Instance = SPI1;
   hspi1.Init.Mode = SPI_MODE_MASTER;
   hspi1.Init.Direction = SPI_DIRECTION_2LINES;
   hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
   hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
   hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
   hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
   hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
   hspi1.Init.NSS = SPI_NSS_SOFT;
   hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;

   HAL_SPI_Init(&hspi1);
   /* Peripheral clock enable */
   __SPI1_CLK_ENABLE();

   GPIO_InitTypeDef GPIO_InitStruct;
   /**SPI1 GPIO Configuration
   PA5 ------> SPI1_SCK
   PA7 ------> SPI1_MOSI
   */
   GPIO_InitStruct.Pin = GPIO_PIN_5 | GPIO_PIN_7;
   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
   GPIO_InitStruct.Pull = GPIO_NOPULL;
   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

   GPIO_InitStruct.Pin = GPIO_PIN_0;                //Chip Select
   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
   GPIO_InitStruct.Pull = GPIO_PULLDOWN;
   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); 

   __HAL_SPI_ENABLE(&hspi1);
}

Damit versuche ich die Werte am Potentiometer zu initialisieren mit:

void SPI_SendData(uint8_t* adress, uint8_t* data, uint16_t size, uint32_t timeout){

   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET);

   HAL_SPI_Transmit(&hspi1, adress, size, timeout);
   while(HAL_SPI_GetState(&hspi1) == HAL_SPI_STATE_BUSY);

   HAL_SPI_Transmit(&hspi1, data, size, timeout);
   while(HAL_SPI_GetState(&hspi1) == HAL_SPI_STATE_BUSY);

   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET);
}

Und dann schreiben:

void POT_Init(){
  uint8_t data = 0x00;
  SPI_SendData(&STATUS_REGISTER_ADDRESS, &data, 8, 100); //Set SREG bit 1 to 0. Device is NOT in shutdown.
  data = 0x0F;
  SPI_SendData(&TCON_BIT_REGISTER_ADDRESS, &data, 8, 100); //Connect Wiper 0
  data = 0x08;
  SPI_SendData(&WIPER_0_REGISTER_ADDRESS, &data, 8, 100);
}

Das Problem ist, dass ich SCK und SDI/PA5 und PA7 sondiere und keine Bewegung über die Leitung sehe. Die beiden Geräte werden wie folgt verbunden:

Schaltplan

Warum sehe ich also nichts? Ich gehe davon aus, dass etwas in meiner Init-Funktion fehlt, aber ich kann es nicht genau sagen und würde mich über einen zweiten Blick freuen.

Antworten (4)

Ich bin mir nicht sicher, ob das hilft, wenn man bedenkt, wie alt dieser Beitrag ist. Mir ist jedoch aufgefallen, dass Sie PA5 und PA7 als alternative Funktion festlegen, aber nicht wirklich angeben, welche alternative Funktion durch eine GPIO_InitStruct.Alternate-Zuweisung erfolgt.

Zunächst müssen Sie die Uhr für das SPI-Peripheriegerät aktivieren, bevor Sie versuchen, sie zu initialisieren. Zweitens, haben Sie auch die Uhr für die GPIO-Peripherie aktiviert?

(Ich habe nur STM32F103 verwendet, was zugegebenermaßen etwas anders sein könnte, aber ich bezweifle es)

+1, Tatsächlich __GPIOA_CLK_ENABLE();und __GPIOC_CLK_ENABLE();Anrufe fehlen.
Sie hatten Recht, und @Bence hatte die richtigen Funktionsaufrufe. Ich habe vergessen, die GPIOA- und GPIOC-Uhren zu aktivieren. Wenn dies aktiviert ist, kann ich jetzt den PC0-Pin verschieben. hurra Aber PA5 und PA7 sind immer noch tot im Wasser.
Wie prüft man diese Pins? Oszilloskop oder nur den Potentiometerausgang, den Sie überprüfen?
Ich habe PC0, PA5 und PA7 an ein Oscope angeschlossen und P0W und P0A an ein Multimeter angeschlossen. Hier ist ein Bild von der Einrichtung . Ignorieren Sie das Takt- und Datensignal, ich habe mit dem manuellen Umdrehen der Pins experimentiert, um meine eigene Version von SPI zu implementieren. Ich würde lieber die echte Version bekommen, obwohl sie funktioniert.
Sie müssen den __SPI1_CLK_ENABLE trotzdem vor HAL_SPI_Init verschieben, sonst wird der SPI-Init nichts tun, weil die Register, in die er schreibt, nicht getaktet sind.

Ich habe diesen Beitrag gefunden, als ich nach einem ähnlichen Beitrag gesucht habe, und festgestellt, dass es keine akzeptierte Antwort gibt, also habe ich beschlossen, eine Antwort zu schreiben (damit jeder mit einem ähnlichen Problem hoffentlich eine Lösung finden kann).

Bevor Sie SPI verwenden, sollten Sie einige Dinge beachten:

  • Die maximale Frequenz des SCLK, mit der Ihr Gerät (MCP4151) funktionieren kann.
  • Der SPI-Modus, in dem Ihr Gerät (MCP4151) funktionieren kann
  • Die Timing-Anforderungen Ihres Geräts (MCP4151)

Allerdings gibt es ein paar Dinge, die ich erwähnen möchte.

Als erstes sehe ich, dass void SPI_SendData(uint8_t* adress, uint8_t* data, uint16_t size, uint32_t timeout)du in deiner Funktion den Chip Select Pin setzt, die Adresse schickst, die Daten schickst und dann resettest. Normalerweise ist der Chip-Select-Pin aktiv niedrig. Damit der SPI funktioniert, müssen Sie den Pin zurücksetzen und danach erneut einstellen.

Außerdem müssen Sie die Frequenz der SPI-Uhr überprüfen. Wenn Ihr Gerät (stm32f4) mit 168 MHz getaktet ist und Sie dies ausgewählt haben, SPI_BAUDRATEPRESCALER_2bedeutet dies, dass Ihr SPI mit 42 MHz getaktet ist, was ziemlich hoch ist, und ich bin mir ziemlich sicher, dass der MCP4151 nicht mit einer so hohen Frequenz arbeiten kann. Um die maximale Frequenz zu finden, die Ihr Gerät verarbeiten kann, müssen Sie im Datenblatt nachsehen.

Zu guter Letzt müssen Sie in Ihrem Datenblatt prüfen, in welchem ​​SPI-Modus der MCP4151 arbeitet. Es gibt 4 verschiedene SPI-Modi, daher kann der ausgewählte Modus falsch sein.

PS Viele Geräte haben strenge Timing-Anforderungen zwischen Lese- und Schreibbefehlen oder zwischen aufeinanderfolgenden Schreib- oder Lesebefehlen.

Ich hatte ein Problem mit SPI auf STM32H7. Das Problem war, dass die Taktimpulse fehlten. Das letzte Byte hatte 4-7 Taktimpulse statt 8. Die Anzahl der Impulse war bei jedem Übertragungszyklus unterschiedlich. Nach einer Untersuchung stellte ich fest, dass dieses Problem nur besteht, wenn SPI-Pins mit GPIO_SPEED_FREQ_LOW konfiguriert sind. Auch bei einer SPI-Frequenz von bis zu 7 kHz. Sobald ich die GPIO-Frequenzeinstellungen auf eine andere (mittel, hoch, sehr hoch) ändere, verschwindet das Problem. Ich habe noch keine Erklärung für das Problem gefunden.