Electrical – STM32 SPI SCLK stops ticking

hal-librarymicrocontrollerspistm32

I have STM32L052K8T6 (master) and I am trying to communicate with AD7124-4 ADC (slave) via SPI. My problem is that STM stops transmiting clock pulses on SCLK immediately after it transfers all data from tx buffer (checked on external oscilloscope) and ignores request to wait for answer till timeout expire. Slave has no chance to answer when it has no clock to synchronise.

My init:

void initSPI (void)
{
GPIO_InitTypeDef GPIO_InitStructure;

__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_SPI1_CLK_ENABLE();

//GPIO - MOSI, MISO, CLK
GPIO_InitStructure.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStructure.Alternate = GPIO_AF0_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);

HAL_NVIC_SetPriority(SPI1_IRQn, 1, 1);
HAL_NVIC_EnableIRQ(SPI1_IRQn);

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_HIGH;
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;

if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
    ErrorHandler();
}

HAL_SPI_MspInit(&hspi1);

__HAL_SPI_ENABLE(&hspi1);
}

I am calling this function:

void SendReceiveData ()
{
    uint8_t tx = 64;
    while (hspi1.State != HAL_SPI_STATE_READY);
    HAL_SPI_TransmitReceive(&hspi1, &tx, &rx, 1, 10000);
}

Even when I have a long timeout it is ignored.

HAL_SPI_TransmitReceive() returns HAL_OK.

Is there a problem in my initialization?

Best Answer

I think you misunderstood the functionality of HAL_SPI_TransmitReceive function. It doesn't first transmit tx buffer then receive to rx buffer. It does both at the same time. After all SPI is a full duplex protocol. It can transmit (from MOSI) and receive (MISO) at the same time.

To achieve what you want in a single function call you should use buffers of size 2. Like this:

    HAL_SPI_TransmitReceive(&hspi1, &tx, &rx, 2, 10000);

It doesn't matter what is in the second byte of TX buffer (tx[1]) or what you read in the first byte of RX buffer (rx[0]). Just make sure you put correct data to tx[0] and take received data from rx[1] and ignore the rest.

PS: I haven't checked the datasheet of the slave device you mentioned. Some devices start sending data at the very first clock cycle. Make sure you understand protocol correctly.