STM32F722ZE SPI-Kommunikation mit LSM6DS33 unter Verwendung von HAL

Ich kann lange Zeit nicht die korrekten Daten aus dem LSM6DS33-Steuerregister (Beschleunigungssensor + Gyroskop) lesen.

Wie ich im Datenblatt gelesen habe, ist die Steuerregisteradresse WHO_I_AM 0x0f. Um die Daten zu lesen muss das MSB auf 1 gesetzt werden, also sende ich schlussendlich 0x8f. Allerdings haben die empfangenen Daten nichts mit dem Erwartungswert 0x69 zu tun, ich bekomme meistens sowas wie 0xff, 0x8f.

Ich überprüfe die Daten im Debug-Modus, ich schaue auch direkt in die DR-Registry. Ich habe alle Kombinationen von CLKPolarity, CLKPhase überprüft und nichts hat geholfen, ich bin überzeugt, dass alles gut verbunden ist.

Ich verwende TrueSTUDIO und das MXCube-Plugin stm32f722ze auf dem Nucleo-Board

/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2018 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f7xx_hal.h"

/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/

SPI_HandleTypeDef hspi1;

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  *
  * @retval None
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI1_Init();
  /* USER CODE BEGIN 2 */
  uint8_t sent,received;
  sent = 0x8f;
  received =0x00;
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
      HAL_GPIO_WritePin(SSPIN_GPIO_Port,SSPIN_Pin,GPIO_PIN_RESET);
      HAL_SPI_Transmit(&hspi1,&sent,1,10);
      HAL_SPI_Receive(&hspi1,&received,1,10);


      HAL_GPIO_WritePin(SSPIN_GPIO_Port,SSPIN_Pin,GPIO_PIN_SET);
      HAL_Delay(500);

  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */

}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

    /**Configure the main internal regulator output voltage 
    */
  __HAL_RCC_PWR_CLK_ENABLE();

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 16;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 216;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Activate the Over-Drive mode 
    */
  if (HAL_PWREx_EnableOverDrive() != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure the Systick interrupt time 
    */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick 
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* SPI1 init function */
static void MX_SPI1_Init(void)
{

  /* SPI1 parameter configuration*/
  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_HIGH;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 7;
  hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

/** Configure pins as 
        * Analog 
        * Input 
        * Output
        * EVENT_OUT
        * EXTI
*/
static void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(SSPIN_GPIO_Port, SSPIN_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin : SSPIN_Pin */
  GPIO_InitStruct.Pin = SSPIN_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  HAL_GPIO_Init(SSPIN_GPIO_Port, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  file: The file name as string.
  * @param  line: The line in file as a number.
  * @retval None
  */
void _Error_Handler(char *file, int line)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  while(1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Willkommen. Was haben Sie versucht, um das Problem einzugrenzen? Funktioniert die SPI-Kommunikation mit einem anderen Chip oder im Loopback-Modus? Haben Sie Zugriff auf Oszilloskop/Logikanalysator?
Leider habe ich aktuell keinen anderen Chip zum Testen. Also habe ich den Loopback-Modus gemacht, die Leitungen MISO und MOSI verbunden, das Programm geändert und es funktioniert. Ich habe versucht, LSM6DS33 mit Raspberry Pi auszuführen, und es funktioniert teilweise, ich bekomme Datentyp 0x69, 0x69, 0x69, 0xff, 0xff, 0x69. Ich habe derzeit keinen Logikanalysator oder Oszilloskop.
Ich verwende das Pololu-Board (Pololu-Artikelnummer: 2736) mit LSM6DS33.
Seltsam. Können Sie bestätigen, dass der SS-Pin korrekt und richtig verdrahtet ist (erzeugen Sie einfach ein "Blinky" an diesem Pin und messen Sie mit dem Voltmeter am LSM6DS33)? Befindet sich LSM6DS33 im SPI-Modus? Sie können auch versuchen, die Uhr zu senken, obwohl es so aussieht, als ob es in Ordnung sein sollte.
Der SS-Pin ist korrekt angeschlossen und ich habe ihn gemäß den Anweisungen überprüft. Im Fall von Himbeer-Pi war wahrscheinlich ein Draht etwas locker, aber jetzt ist es in Ordnung und es liest die Daten 0x69 korrekt ... Auf stm habe ich jedoch auch den SS-Pin überprüft - es funktioniert korrekt, aber die Daten sind völlig zufällig . Wenn sich der SS-Pin im hohen Zustand befindet, befindet sich spi im Leerlaufmodus, wenn sich der SS-Pin im niedrigen Zustand befindet, beginnt SPI mit dem Senden von Daten. Die Spi-Kommunikation kann im angegebenen Modul nicht deaktiviert werden. Es ist möglich, SPI / I2C aktiv (Standard) oder nur aktives SPI.
SPI_NSS_PULSE_ENABLE? Wenn Sie MISO trennen, erhalten Sie immer noch zufällige Daten oder 0xff wie erwartet?
"hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;", ich habe es nicht geändert, es war der Standardwert. Wenn ich MISO spi1 trenne, ist der Registerwert 0x00.
Versuchen Sie, das auf deaktiviert zu ändern, da Sie SS manuell steuern. Wenn das nichts ändert, versuchen Sie, die Uhr niedriger zu stellen?
@R.Griffin - Hallo, vielen Dank, dass Sie zurückgekommen sind, um Ihre Lösung hinzuzufügen. :-) Das Hinzufügen der Lösung zur Frage ist jedoch nicht, wie Antworten auf Stack Exchange-Sites geschrieben werden. Wenn Sie Ihr eigenes Problem gelöst haben, können Sie Ihre eigene Antwort schreiben :-) Können Sie daher bitte Ihre Lösung in Ihre eigene Antwort schreiben und sie dann aus der Frage entfernen? Danke. :-) Abschließend akzeptieren Sie bitte eine der Antworten, damit die Site weiß, dass die Frage gelöst wurde. Es ist möglich, Ihre eigene Antwort zu akzeptieren. Wenn die andere Antwort auch funktioniert hat, würde ich Sie ermutigen, sie zumindest positiv zu bewerten .
Vielen Dank für den guten Rat, es schien seltsam, eine separate Antwort zu schreiben und dann zu akzeptieren :) Wie auch immer, ich habe es so gemacht, wie Sie es empfohlen haben. Leider kann ich nicht upvoten, da ich zu wenige Reputationspunkte habe.

Antworten (2)

STM-Teile erwarten normalerweise gebündelte Lesevorgänge mit dem ersten Wort als Adresse und dem zweiten Byte-Dummy. Versuchen Sie, Ihre TX/RX-Daten in Arrays umzuwandeln, und tun Sie HAL_SPI_TransmitReceive()stattdessen Folgendes:

uint8_t txBuf[2] = {0x8f, 0x00};
uint8_t rxBuf[2] = {0x00, 0x00};
HAL_SPI_TransmitReceive(&hspi1, &txbuf, &rxBuf, 2, 10);

Ihre Antwort sollte sich im zweiten Byte ([1]) des Antwortarrays befinden.

Siehe Abschnitt 6.2.1 des LSM6DS33-Datenblatts

Es funktioniert, aber meine Lösung sollte auch funktionieren, da SSPIN immer noch in einem niedrigen Zustand ist.
Theoretisch ja. In der Praxis könnte der Chip ein internes Frame-Wait-Timeout haben. D. h., wenn der nächste Takt nicht innerhalb von 2–4 vollen Taktperioden ankommt, betrachten Sie den vorherigen Burst als erledigt oder so ähnlich. Um Einzelheiten darüber zu erfahren, wenden Sie sich bitte an den Hersteller. Ich habe im Datenblatt nachgesehen und keine Informationen zur Gültigkeitsdauer eines einzelnen Frames gefunden.

Es hat geholfen, den CPOL auf „niedrig“ zu setzen. Ich weiß nicht, warum es beim ersten Mal nicht funktioniert hat, aber dieses Mal habe ich den Sensor auf der anderen Seite (an männlichen Stiften) angeschlossen.