4
\$\begingroup\$

I transmit 3-byte(24-bit) using SPI from this Nucleo board with HAL as follows (SPIoutputBuffer is a char array):

        SPIoutputBuffer[0] = 0b00010000;

        SPIoutputBuffer[1] = (char)(value >> 8);
        SPIoutputBuffer[2] = (char)(value & 0x00FF);

        HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_RESET);

        HAL_SPI_Transmit(&hspi3, (uint8_t *)SPIoutputBuffer, 3, 1);

        HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_SET);

enter image description here

The logic analyzer shows the expected clock and MOSI timing diagrams.

When I try to send another three bytes without using HAL by following method:

        SPIoutputBuffer[0] = 0b00010000;
        SPIoutputBuffer[1] = (char)(value >> 8);
        SPIoutputBuffer[2] = (char)(value & 0x00FF);
        
        GPIOC->ODR &= ~(1<<4); // Reset the Pin PC4
        
        SPI3->DR = SPIoutputBuffer[0];//Send first byte
        while((SPI3->SR & SPI_SR_TXE)!= SPI_SR_TXE);
        
        SPI3->DR = SPIoutputBuffer[1];//Send second byte
        while((SPI3->SR & SPI_SR_TXE)!= SPI_SR_TXE);
        
        SPI3->DR = SPIoutputBuffer[2];//Send third byte
        while((SPI3->SR & SPI_SR_TXE)!= SPI_SR_TXE);

        while((SPI3->SR & SPI_SR_BSY) == SPI_SR_BSY );
        
        GPIOC->ODR |= 1<<4; // Set the Pin PC4

But now the logic analyzer shows the following diagrams:

enter image description here

The second case SPI clock number is doubled and the MOSI line outputs the bytes with one more byte padded zeros: In hex 1000 instead of 10, 0200 instead of 02 and 1100 instead of 11 as you see in the above screen-shot.

What am I doing wrong in the second(non-HAL) case?

edit for an answer:

static void MX_SPI3_Init(void)
{

  /* USER CODE BEGIN SPI3_Init 0 */

  /* USER CODE END SPI3_Init 0 */

  /* USER CODE BEGIN SPI3_Init 1 */

  /* USER CODE END SPI3_Init 1 */
  /* SPI3 parameter configuration*/
  hspi3.Instance = SPI3;
  hspi3.Init.Mode = SPI_MODE_MASTER;
  hspi3.Init.Direction = SPI_DIRECTION_2LINES;
  hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi3.Init.CLKPhase = SPI_PHASE_2EDGE;
  hspi3.Init.NSS = SPI_NSS_SOFT;
  hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi3.Init.CRCPolynomial = 7;
  hspi3.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi3.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
  if (HAL_SPI_Init(&hspi3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI3_Init 2 */
  SPI3->CR2 = (SPI3->CR2 & ~(0x0F << SPI_CR2_DS_Pos)) | (0x07 << SPI_CR2_DC_Pos);
  SPI3->CR1 |= SPI_CR1_SPE;//Enable SPI
  /* USER CODE END SPI3_Init 2 */

}
\$\endgroup\$
3
  • \$\begingroup\$ So have you compared HAL code to yours? \$\endgroup\$
    – Justme
    Commented Apr 5, 2022 at 9:36
  • \$\begingroup\$ Yes HAL works but with too much delay after CS pin low. The non HAL is faster but the bytes are transferred with extra zero bytes. They have the same initialization settings which I did with STM32CubeMX. \$\endgroup\$
    – cm64
    Commented Apr 5, 2022 at 9:39
  • \$\begingroup\$ I meant, have you looked at HAL code to find out what HAL code does differently when it writes to SPI compared to how you write to SPI in your code? \$\endgroup\$
    – Justme
    Commented Apr 5, 2022 at 9:44

2 Answers 2

6
\$\begingroup\$

It looks like that your code does 16-bit writes to SPI data register so SPI peripheral sends out two bytes for each data register write. You likely want to do 8-bit writes to the SPI data register.

The SPI data register is 16 bits wide and since SPI transactions are set to 8 bits, you can write two bytes simultaneously to SPI data register, which your code does, and which is what HAL code also does for all evn number of bytes, until there is only 1 byte left. The final odd byte is separately written as an 8-bit write in the HAL code.

Since you are already using the HAL in your project, just debug the HAL code or open the SPI HAL source code that is in your project and see how the SPI transmit is implemented in the HAL when you tell it to transmit the 3 bytes.

\$\endgroup\$
2
  • \$\begingroup\$ This is confirmed in RM linked by OP. Page 924, Data packing. \$\endgroup\$
    – Rokta
    Commented Apr 5, 2022 at 12:17
  • \$\begingroup\$ My answer was incorrect, I deleted it. Please, post your conclusions under into/under this post. \$\endgroup\$
    – Ilya
    Commented Apr 5, 2022 at 13:56
1
\$\begingroup\$

I ran into the same problem. You need to treat the DR registers as an 8-bit. Use this to access the DR register as an 8-bit entity:

*(volatile uint8_t *)&SPI1->DR = 0x55;
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.