cancel
Showing results for 
Search instead for 
Did you mean: 

Resetting SCLK polarity after changing SPI mode through HAL (STM32F7xx)

amarburg
Associate

We're developing for the STM32F767, primarily using the HAL. We have devices on the SPI bus which require different timing clock polarities. Re-configuring the SPI hardware through repeated calls to HAL_SPI_Init works, however, the actual hardware state of the SCLK line does not seem to change during HAL_SPI_Init .... we are only able to get it to reset by clocking out a byte. What's the "right" way to force the SCLK line to the correct polarity?

In pseudo-code, this works, but is obviously ugly:

SpiHandle.Init.CLKPolarity = SPI_POLARITY_HIGH;
 HAL_SPI_Init(&SpiHandle);
 
// Expect SCLK to be high
// (successfully communicate with devices expecting SCLK to idle high)
 
SpiHandle.Init.CLKPolarity = SPI_POLARITY_LOW;
HAL_SPI_Init(&SpiHandle);
 
// !! Expect SCLK to be low, it is actually still high
 
// Sending a "null" transmission resets clock
char txBuffer[1] = '\0';
HAL_SPI_Transmit(&SpiHandle, txBuffer, 1, SPITimeout );
 
// !!! SCLK is now low
 
// (successful communication with devices expecting SCLK to idle low)

4 REPLIES 4
Yevgeni Tunik
Senior

Try to insert HAL_SPI_DeInit(&SpiHandle) before SpiHandle.Init.CLKPolarity = SPI_POLARITY_LOW;

Wdong.2
Associate

1�?you can change spi sck pull mode with the cpol ,pull up with cpol=1,pull down with cpol=0​

2�?another solution,you can set the master_keep_io_state bit

Yevgeni Tunik
Senior

The following endless cycle content is proven with STM32F405ZGT6:

// Start of cyclical code

SPI_ChangeParameters(&hspi3, SPI_DATASIZE_8BIT, SPI_POLARITY_HIGH, SPI_PHASE_2EDGE, 8);

// Insert here some tiny magic delay! HAL_Delay(2) is even overkill

// Insert here your activate CS

// Insert here your chip activity: HAL_SPI_TransmitReceive_IT() or another function

// Wait until HAL_SPI_GetState(&hspi3) == HAL_SPI_STATE_READY

// Insert here your deactivate CS

SPI_ChangeParameters(&hspi3, SPI_DATASIZE_16BIT, SPI_POLARITY_HIGH, SPI_PHASE_2EDGE, 4);

// Insert here some tiny magic delay! HAL_Delay(2) is even overkill

// Insert here your activate CS

// Insert here your chip activity: HAL_SPI_TransmitReceive_IT() or another function

// Wait until HAL_SPI_GetState(&hspi3) == HAL_SPI_STATE_READY

// Insert here your deactivate CS

SPI_ChangeParameters(&hspi3, SPI_DATASIZE_16BIT, SPI_POLARITY_LOW, SPI_PHASE_2EDGE, 4);

// Insert here some tiny magic delay! HAL_Delay(2) is even overkill

// Insert here your activate CS

// Insert here your chip activity: HAL_SPI_TransmitReceive_IT() or another function

// Wait until HAL_SPI_GetState(&hspi3) == HAL_SPI_STATE_READY

// Insert here your deactivate CS

// End of cyclical code

//---------------

  int SPI_ChangeParameters(SPI_HandleTypeDef* hspi, uint32_t dataSize, uint32_t clkPolarity, uint32_t clkPhase, uint32_t baudRatePrescaler)

  {

    __HAL_SPI_DISABLE(hspi);

    hspi->Init.DataSize = dataSize;

    hspi->Init.CLKPolarity = clkPolarity;

    hspi->Init.CLKPhase = clkPhase;

    hspi->Init.BaudRatePrescaler = baudRatePrescaler;

    if (HAL_SPI_Init(hspi) != HAL_OK)

    {

     return FALSE;

    }

    /* Enable SPI peripheral so SPI phase and polarity are changed before SPI peripheral in selected (otherwise trouble!!!) */

    __HAL_SPI_ENABLE(hspi);

    return TRUE;

  }

//--------------- STM32CubeMX: Initialization of Spi3 controller with my addition

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_HIGH;

 hspi3.Init.CLKPhase = SPI_PHASE_2EDGE;

 hspi3.Init.NSS = SPI_NSS_SOFT;

 hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;

 hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;

 hspi3.Init.TIMode = SPI_TIMODE_DISABLE;

 hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

 hspi3.Init.CRCPolynomial = 10;

 if (HAL_SPI_Init(&hspi3) != HAL_OK)

 {

  Error_Handler();

 }

 /* USER CODE BEGIN SPI3_Init 2 */

 // Enable SPI peripheral so SPI phase and polarity are changed before SPI peripheral in selected (otherwise trouble!!!)

 __HAL_SPI_ENABLE(&hspi3);

 /* USER CODE END SPI3_Init 2 */

}

Discard this advice. See the really working code in my separate comment.