cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L476RG - SPI Communication

DivyaJayan
Associate III

Hi, 

I am currently developing a battery management system (BMS) utilizing the STM32L476RG microcontroller (MCU) and the ADBMS6830 as the analog front end (AFE). Communication between the MCU and AFE is established via SPI. Since the AFE supports isoSPI, we are employing the LTC6820 transceiver. During testing, I transmitted the following data: TxData[6] = {0x80, 0x00, 0x00, 0xFF, 0x03, 0x00}, but the received data was RxData[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}.

 Is my SPI configuration is correct or not, did I need to do anything more. Please provide some insight about this.

Here is the code :

 

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi1;

/* USER CODE BEGIN PV */

uint8_t TxData[6] = {0x80, 0x00, 0x00, 0xFF, 0x03, 0x00};
uint8_t Rxdata[6];
/* 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 */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
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 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

	  HAL_SPI_Transmit(&hspi1,(uint8_t*) TxData, sizeof(TxData), HAL_MAX_DELAY);
	  HAL_Delay(500);

	  HAL_SPI_Receive(&hspi1, (uint8_t*)RxData, sizeof(RxData), HAL_MAX_DELAY);
	  HAL_Delay(500);
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSICalibrationValue = 0;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief SPI1 Initialization Function
  * @PAram None
  * @retval None
  */
static void MX_SPI1_Init(void)
{

  /* USER CODE BEGIN SPI1_Init 0 */

  /* USER CODE END SPI1_Init 0 */

  /* USER CODE BEGIN SPI1_Init 1 */

  /* USER CODE END SPI1_Init 1 */
  /* 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_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
  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();
  }
  /* USER CODE BEGIN SPI1_Init 2 */

  /* USER CODE END SPI1_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @PAram None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

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

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  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,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

 

 

The debug terminal :

Screenshot 2025-01-09 153505.png

Please find the attached Oscilloscope images:

SPI.jpg

Blue : MOSI

Yellow : Clk

Pink : MISO

 

 

11 REPLIES 11
TDK
Guru

Received SPI data of all 0xFF suggests the chip is non responsive. Perhaps not powered, perhaps wires are not connected correctly.

Your SPI output of the STM32 is correct so the issue is not likely to be an STM32 configuration issue.

I'd recommend probing signals directly at the ADBMS6830. Verify chip select, clock, MOSI, MISO all look as expected.

If you feel a post has answered your question, please click "Accept as Solution".

Thank you for your reply.

 

 I attempted to interface the AFE (ADBMS6830) with the STM32L476RG Nucleo board. Currently, I am receiving the transmitted data along with additional values. I need to verify if the received data is accurate.

I am attaching the debug terminal screenshots. Please provide technical insights.

 

Screenshot 2025-01-10 150300.png

Screenshot 2025-01-10 150345.png

Screenshot 2025-01-10 150430.png

1. Use TransmitReceive.

2. Read dozens of similar topics in this forum started by beginners having the same problem and look for the explanations.

https://community.st.com/t5/stm32-mcus-products/regarding-function-calls-when-performing-spi-communication-in/m-p/738412#M265178

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
KMill
Senior

I agree with @gbm 

SPI Transmits and receives at the same time. As bytes are being clocked out, response bytes are clock in.

So you need to use the TransmitReceive call to send a packet which expects a response. Check the timing diagram in the datasheet for the device you are inyterfacing too, it will clearly show the expected bit timings, from which you can see excatly where and when the received bytes come in.

Does it look accurate to you? What values do you expect vs what values are you getting? Surely you should be able to tackle this on your own.

If you feel a post has answered your question, please click "Accept as Solution".

Hi,

Thankyou for your reply.

I used an oscilloscope to measure the signals, and I observed that the MISO signal mirrors the MOSI signal. However, the voltage level of the MISO signal is significantly lower. Additionally, the debug terminal consistently outputs 0xFF.

Could you provide some insights into why this might be happening?

 
Media (7).jpg
 
In the above image Pink channel is MOSI & yellow channel is MISO.
 
 

That doesn't look right. If I read your scope properyl that's only about 0.5 volt on the MISO channel.

How are your devices connected? Are they on the same PCB? If not, make sure you have a common GND connection between the two, as well as the MISO, MOSI, SCK and CS lines.

Your scope has a USB socket for capturing screenshots:

AndrewNeil_0-1737374240291.png

This will give you far better results than trying to take photos of the screen!

 

Are you sure your probes and/or scope channels are correctly configured - for x1, x10, etc?

 

PS:

Is this you on the AD forum ?

The MCU and AFE are located on separate boards. However, I have ensured proper connections, including GND, MISO, MOSI, SCK, and CS lines.