2021-07-01 10:28 AM
I have a system with an STM32H74A3, which uses one SPI port for different slaves which use different SPI modes.
One Slave needs Mode 3 (Pol.High/2ndEdge) and 8 Bit Data size, the other needs Mode 0 (Pol.Low/1stEdge) and 16 Bit.
Clock Speed is the same for both SPIs.
Init Code for Mode 3:
HandleSpiBMP.Instance = SPI2;
HandleSpiBMP.Init.Mode = SPI_MODE_MASTER;
HandleSpiBMP.Init.Direction = SPI_DIRECTION_2LINES;
HandleSpiBMP.Init.DataSize = SPI_DATASIZE_8BIT;
HandleSpiBMP.Init.CLKPolarity = SPI_POLARITY_HIGH;
HandleSpiBMP.Init.CLKPhase = SPI_PHASE_2EDGE;
HandleSpiBMP.Init.NSS = SPI_NSS_SOFT;
HandleSpiBMP.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
HandleSpiBMP.Init.FirstBit = SPI_FIRSTBIT_MSB;
HandleSpiBMP.Init.TIMode = SPI_TIMODE_DISABLE;
HandleSpiBMP.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
HandleSpiBMP.Init.CRCPolynomial = 0x0;
HandleSpiBMP.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
HandleSpiBMP.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
HandleSpiBMP.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
HandleSpiBMP.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
HandleSpiBMP.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
HandleSpiBMP.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
HandleSpiBMP.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
HandleSpiBMP.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
HandleSpiBMP.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
HandleSpiBMP.Init.IOSwap = SPI_IO_SWAP_DISABLE;
if (HAL_SPI_Init(&HandleSpiBMP) != HAL_OK)
{
Error_Handler();
}
Init Code for Mode 0:
HandleSpiMurataIMU.Instance = SPI2;
HandleSpiMurataIMU.Init.Mode = SPI_MODE_MASTER;
HandleSpiMurataIMU.Init.Direction = SPI_DIRECTION_2LINES;
HandleSpiMurataIMU.Init.DataSize = SPI_DATASIZE_16BIT; // <<
HandleSpiMurataIMU.Init.CLKPolarity = SPI_POLARITY_LOW; // <<
HandleSpiMurataIMU.Init.CLKPhase = SPI_PHASE_1EDGE; // <<
HandleSpiMurataIMU.Init.NSS = SPI_NSS_SOFT;
HandleSpiMurataIMU.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
HandleSpiMurataIMU.Init.FirstBit = SPI_FIRSTBIT_MSB;
HandleSpiMurataIMU.Init.TIMode = SPI_TIMODE_DISABLE;
HandleSpiMurataIMU.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
HandleSpiMurataIMU.Init.CRCPolynomial = 0x0;
HandleSpiMurataIMU.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
HandleSpiMurataIMU.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
HandleSpiMurataIMU.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
HandleSpiMurataIMU.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
HandleSpiMurataIMU.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
HandleSpiMurataIMU.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
HandleSpiMurataIMU.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
HandleSpiMurataIMU.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
HandleSpiMurataIMU.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
HandleSpiMurataIMU.Init.IOSwap = SPI_IO_SWAP_DISABLE;
if (HAL_SPI_Init(&HandleSpiMurataIMU) != HAL_OK)
{
Error_Handler();
}
When setting up the system to use only the first setup with Mode 3, this SPI slave is working perfectly.
When I switch to Mode 0 to support the second slave, this one works too.
But as soon as I switch back to Mode 3 the first slave doesn't deliver correct values.
I call HAL_SPI_DeInit() before HAL_SPI_Init with the alternative setup.
Even a delay of 100 µsec after the new Init is called doesn't help.
Did anyone use this kind of SPI usage? How can I achieve to get this working with both slaves?
Thank you for any assistance.
GS
2021-07-01 10:33 AM
> But as soon as I switch back to Mode 3 the first slave doesn't deliver correct values
What values does it deliver vs what do you expect? If it's off by one bit, you probably are just sending an extra clock since it's idle high.
> HandleSpiBMP.Init.CLKPolarity = SPI_POLARITY_HIGH;
To fix, transfer 1 dummy byte after HAL_SPI_Init prior the pulling the CS line low.
HAL_SPI_Init doesn't actually start the clock.
HAL is built with the assumption that you are using a single handle per peripheral, but a scheme like this should work as long as you take care that only one handle is active at a time.
2021-07-01 10:42 AM
Thank you for your suggestion.
In fact I just found out that the first slave obviously also supports Mode 0. So the only difference then is the 16 Bit value.
Now both slaves are working with correct data.
Anyway your hint will help me the next time as this problem might occur in future again and then maybe no flexible Mode usage is available.