2020-05-08 03:12 AM
Hi there,
I am using the STM32H750VB as an SPI Slave in Interrupt mode and it is working but I am not happy with what I see with my analyzer.
SPI is working with Idle-Clock Low and aquiring data at leading edge. LSB first.
That's all how it should be but when you take a closer look at the last bit you see, that MISO is returning to zero just after the rising edge. In my opinion this should happen when the last clock is completed, e.g. falling edge of the clock.
Is there any way to delay this, as my SPI Master decodes the last byte sometimes as 123(0x7B) instead of 251(0xFB) as it reads the level of the MISO "too late".
The spi is working with a clock frequency of 50khz.
Thanks
Best regards,
Thomas
Below my init:
void MX_SPI2_Init(void)
{
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_SLAVE;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_HARD_INPUT;
hspi2.Init.FirstBit = SPI_FIRSTBIT_LSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 0x0;
hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
hspi2.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi2.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi2.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi2.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi2.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi2.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi2.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi2.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
hspi2.Init.IOSwap = SPI_IO_SWAP_DISABLE;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
}
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
GPIO_TypeDef * pAkt_GPIO;
// Port-Pins konfigurieren
pAkt_GPIO = GPIOB;
if(spiHandle->Instance==SPI2)
{
/* USER CODE BEGIN SPI2_MspInit 0 */
/* USER CODE END SPI2_MspInit 0 */
/* SPI2 clock enable */
__HAL_RCC_SPI2_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI2 GPIO Configuration
PC1 ------> SPI2_MOSI
PC2_C ------> SPI2_MISO
PB12 ------> SPI2_NSS
PB13 ------> SPI2_SCK
*/
// Chipselect auf PB12
pAkt_GPIO->MODER &= ~GPIO_MODER_MODE12;
pAkt_GPIO->MODER |= GPIO_MODER_MODE12_1; // Alternate function for SPI Chip-Select
pAkt_GPIO->OSPEEDR |= GPIO_OSPEEDR_OSPEED12; // High Speed on
pAkt_GPIO->AFR[1] |= (uint32_t)GPIO_AF5_SPI2 << 16; // AFRH ==> AF5
// Clock auf PB13
pAkt_GPIO->MODER &= ~GPIO_MODER_MODE13;
pAkt_GPIO->MODER |= GPIO_MODER_MODE13_1; // Alternate function for SPI SCK
pAkt_GPIO->OSPEEDR |= GPIO_OSPEEDR_OSPEED13; // High Speed on
pAkt_GPIO->AFR[1] |= (uint32_t)GPIO_AF5_SPI2 << 20; // AFRH ==> AF5
pAkt_GPIO = GPIOC;
// MOSI auf PC1
pAkt_GPIO->MODER &= ~GPIO_MODER_MODE1;
pAkt_GPIO->MODER |= GPIO_MODER_MODE1_1; // Alternate function for SPI MOSI
pAkt_GPIO->OSPEEDR |= GPIO_OSPEEDR_OSPEED1; // High Speed on
pAkt_GPIO->AFR[0] |= (uint32_t)GPIO_AF5_SPI2 << 4; // AFRL ==> AF5
// MISO auf PC2
pAkt_GPIO->MODER &= ~GPIO_MODER_MODE2;
pAkt_GPIO->MODER |= GPIO_MODER_MODE2_1; // Alternate function for SPI MISO
pAkt_GPIO->OSPEEDR |= GPIO_OSPEEDR_OSPEED2; // High Speed on
pAkt_GPIO->AFR[0] |= (uint32_t)GPIO_AF5_SPI2 << 8; // AFRL ==> AF5
2020-05-08 04:02 AM
Do you use DMA to fill the SPI Tx? If you change the next byte's LSB to 1, will you still see the problem?
Can you please read out and post the SPI registers' content?
JW
2020-05-08 04:38 AM
No I don't use DMA to fill the output buffer.
I use
HAL_SPI_TransmitReceive_IT(&hspi2,(uint8_t *)aTxBuffer , (uint8_t *)aRxBuffer, BUFFERSIZE);
to fill the output register.
The master always clocks out two bytes at once. If the next LSB is 1 I still see the problem. (Screenshot attached)
When do you want me to read out the SPI registers' content? Init, when Interrupt ist called or after "HAL_SPI_TransmitReceive_IT"
Thank you very much
Regards,
Thomas
2020-05-08 05:14 AM
> [when output buffer is filled]
Can you please toggle a pin *before* and *after* calling HAL_SPI_TransmitReceive_IT() and add it to the LA?
> When do you want me to read out the SPI registers' content? Init, when Interrupt ist called or after "HAL_SPI_TransmitReceive_IT"
Any of these (say when interrupt is called), just tell us when whas it.
I just wanted to know how did you set up the SPI. I don't understand the Cube/HAL gibberish.
JW