Skip to main content
Visitor II
December 19, 2019
Question

I would like to make SPI communication with HAL library. I want to read the incoming data with the Receive function, but I cannot get an answer. Is there anyone who can help?

  • December 19, 2019
  • 12 replies
  • 3337 views

SPI

    This topic has been closed for replies.

    12 replies

    Visitor II
    December 24, 2019

    when you choose one of the SPIs, say for example, SPI1, some of the pins are selected as TX, RX and CLK, standing for transmitter, receiver, and clock pins. you can receive the data on the RX pin. the relevant HAL function would be HAL_SPI_Receive().

    Cözde.1Author
    Visitor II
    December 24, 2019

    BSP_LED_Off(LED2);

    HAL_SPI_Transmit(&SpiHandle,&adres,1,HAL_MAX_DELAY);

    HAL_SPI_Receive(&SpiHandle,&data,1,HAL_MAX_DELAY);

    BSP_LED_On(LED2);

    That's part of my code. Sending data via transmit I want to read the data sent by the receiver but it shows 0.

    Visitor II
    December 24, 2019

    are you sure that "data" contains anything? because in the above code I can see nothing... have you initialized "data"?

    Cözde.1Author
    Visitor II
    December 24, 2019

    #include "main.h"

    #define MASTER_BOARD

    SPI_HandleTypeDef SpiHandle;

    uint8_t aTxBuffer = 0x55;

    uint8_t aRxBuffer;

    void SystemClock_Config(void);

    static void Error_Handler(void);

    void spi_Init(void);

    //static uint16_t Buffercmp(uint8_t *pBuffer1, uint8_t *pBuffer2, uint16_t BufferLength);

    int main(void)

    {

     HAL_Init();

     SystemClock_Config();

     spi_Init();

     BSP_LED_Init(LED2);

     // CS5532_Init();

    #ifdef MASTER_BOARD

     SpiHandle.Init.Mode = SPI_MODE_MASTER;

    #else

     SpiHandle.Init.Mode = SPI_MODE_SLAVE;

    #endif

     if(HAL_SPI_Init(&SpiHandle) != HAL_OK)

     {

       Error_Handler();

     }

    /*

    #ifdef MASTER_BOARD

     BSP_PB_Init(BUTTON_USER, BUTTON_MODE_GPIO);

     while (BSP_PB_GetState(BUTTON_USER) != GPIO_PIN_RESET)

     {

       BSP_LED_Toggle(LED2);

       HAL_Delay(100);

      }

     BSP_LED_Off(LED2);

    #endif */

     HAL_SPI_Transmit(&SpiHandle, &aTxBuffer,1, 5000);

    HAL_SPI_Receive(&SpiHandle,&aRxBuffer,1, 5000);

     HAL_Delay(1);

     BSP_LED_Off(LED2);

     while (1)

     {

     }

    }

    static void Error_Handler(void)

    {

     while(1)

     {

       BSP_LED_Toggle(LED2);

       HAL_Delay(1000);

     }

    }

    void SystemClock_Config(void)

    {

     RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

     RCC_OscInitTypeDef RCC_OscInitStruct = {0};

     /* MSI is enabled after System reset, activate PLL with MSI as source */

     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;

     RCC_OscInitStruct.MSIState = RCC_MSI_ON;

     RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;

     RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;

     RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

     RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;

     RCC_OscInitStruct.PLL.PLLM = 1;

     RCC_OscInitStruct.PLL.PLLN = 40;

     RCC_OscInitStruct.PLL.PLLR = 2;

     RCC_OscInitStruct.PLL.PLLP = 7;

     RCC_OscInitStruct.PLL.PLLQ = 4;

     if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

     {

       while(1);

     }

     RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);

     RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

     RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

     RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; 

     RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; 

     if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)

     {

       while(1);

     }

    }

    void spi_Init(void)

    {

      SpiHandle.Instance              = SPIx;

      SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;

      SpiHandle.Init.Direction        = SPI_DIRECTION_2LINES;

      SpiHandle.Init.CLKPhase         = SPI_PHASE_1EDGE;

      SpiHandle.Init.CLKPolarity      = SPI_POLARITY_LOW;

      SpiHandle.Init.DataSize         = SPI_DATASIZE_8BIT;

      SpiHandle.Init.FirstBit         = SPI_FIRSTBIT_MSB;

      SpiHandle.Init.TIMode           = SPI_TIMODE_DISABLE;

      SpiHandle.Init.CRCCalculation   = SPI_CRCCALCULATION_DISABLE;

      SpiHandle.Init.CRCPolynomial    = 7;

      SpiHandle.Init.CRCLength        = SPI_CRC_LENGTH_8BIT;

      SpiHandle.Init.NSS              = SPI_NSS_SOFT;

      SpiHandle.Init.NSSPMode         = SPI_NSS_PULSE_DISABLE;

    }

    /*static uint16_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)

    {

     while (BufferLength--)

     {

       if((*pBuffer1) != *pBuffer2)

       {

         return BufferLength;

       }

       pBuffer1++;

       pBuffer2++;

     }

     return 0;

    } */

    #ifdef USE_FULL_ASSERT

    void assert_failed(uint8_t *file, uint32_t line)

    {

       while (1)

     {

     }

    }

    #endif

    my full code is as follows. can you help

    Graduate II
    December 24, 2019

    Which STM32 part are we talking about?

    I think if you want two way comms you'd do better using the Transmit_Receive function.

    You'd also want to consider how you're driving the chip-select into the unspecified target device.

    Cözde.1Author
    Visitor II
    December 25, 2019

    I use the STM32 l476 card. Cs5532 I want to get information from ADC. For this, I first tried to communicate between 2 stm32. I wonder why the Receive function doesn't work.

    Visitor II
    December 25, 2019

    safe SPI is 4 wires MOSI/MISO/SCK/NSS

    receive and transmit occur at the same time so you need to use transmit_receive

    There are (too) simple examples in Nucleo project folders... to help you get started.

    Cözde.1Author
    Visitor II
    December 25, 2019

    Only transmitreceive is used in the examples I could not see the example related to Receive

    Visitor II
    December 25, 2019

    Still use transmit receive, even if you don't configure all SPI GPIOs.]

    All works fine with STM32L496 SPI master and slave modes.

    Cözde.1Author
    Visitor II
    December 26, 2019

    can you throw sample code

    Visitor II
    December 26, 2019

    My code for SPI is quite rich as it includes a master/slave mode with interrupts and DMA.

    So I'll show here the 5% which is for master mode extract code. 4 wire SPI on L4R5 @12MHz with SYSCLK = 48MHz

    16 bit SPI mode

    HAL_StatusTypeDef SPIP_MasterConfigureSpi(SPI_HandleTypeDef *hspi){
     hspi->Instance = SPI2;
     hspi->Init.Direction = SPI_DIRECTION_2LINES;
     hspi->Init.CLKPhase = SPI_PHASE_1EDGE;
     hspi->Init.CLKPolarity = SPI_POLARITY_LOW;
     hspi->Init.DataSize = SPI_DATASIZE_16BIT;
     hspi->Init.FirstBit = SPI_FIRSTBIT_MSB;
     hspi->Init.TIMode = SPI_TIMODE_DISABLE;
     hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
     hspi->Init.CRCPolynomial = 7;
     hspi->Init.CRCLength = SPI_CRC_LENGTH_8BIT;
     hspi->Init.NSS = SPI_NSS_SOFT;
     hspi->Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
     hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;//16;
     hspi->Init.Mode = SPI_MODE_MASTER;
     return (HAL_SPI_Init(hspi));
    }
     
    void SPIP_MasterConfigureDma(SPI_HandleTypeDef *hspi){
     /* Configure the DMA handler for Transmission process */
     pSPIP->hdma_tx->Instance = DMA1_Channel2;//DMA1_Channel5;
     pSPIP->hdma_tx->Init.Request = DMA_REQUEST_SPI2_TX;//DMA_REQUEST_1;
     pSPIP->hdma_tx->Init.Direction = DMA_MEMORY_TO_PERIPH;
     pSPIP->hdma_tx->Init.PeriphInc = DMA_PINC_DISABLE;
     pSPIP->hdma_tx->Init.MemInc = DMA_MINC_ENABLE;
     pSPIP->hdma_tx->Init.PeriphDataAlignment = /*DMA_PDATAALIGN_BYTE;*/ DMA_PDATAALIGN_HALFWORD;
     pSPIP->hdma_tx->Init.MemDataAlignment = /*DMA_MDATAALIGN_BYTE;*/ DMA_MDATAALIGN_HALFWORD;
     pSPIP->hdma_tx->Init.Mode = DMA_NORMAL;
     pSPIP->hdma_tx->Init.Priority = DMA_PRIORITY_HIGH;
     HAL_DMA_Init(pSPIP->hdma_tx);
     /* Associate the initialized DMA handle to the the SPI handle */
     __HAL_LINKDMA(hspi, hdmatx, *(pSPIP->hdma_tx));
     
     /* Configure the DMA handler for Reception process */
     pSPIP->hdma_rx->Instance = DMA1_Channel1;//DMA1_Channel4;
     pSPIP->hdma_rx->Init.Request = DMA_REQUEST_SPI2_RX;//DMA_REQUEST_1;
     pSPIP->hdma_rx->Init.Direction = DMA_PERIPH_TO_MEMORY;
     pSPIP->hdma_rx->Init.PeriphInc = DMA_PINC_DISABLE;
     pSPIP->hdma_rx->Init.MemInc = DMA_MINC_ENABLE;
     pSPIP->hdma_rx->Init.PeriphDataAlignment = /*DMA_PDATAALIGN_BYTE;*/ DMA_PDATAALIGN_HALFWORD;
     pSPIP->hdma_rx->Init.MemDataAlignment = /*DMA_MDATAALIGN_BYTE;*/ DMA_MDATAALIGN_HALFWORD;
     pSPIP->hdma_rx->Init.Mode = DMA_NORMAL;
     pSPIP->hdma_rx->Init.Priority = DMA_PRIORITY_HIGH;
     HAL_DMA_Init(pSPIP->hdma_rx);
     /* Associate the initialized DMA handle to the the SPI handle */
     __HAL_LINKDMA(hspi, hdmarx, *(pSPIP->hdma_rx));
    }
     
    // this function kicks normally within interrupt for multi-block transfer
    HAL_StatusTypeDef SPIP_MasterSerialTransferStart_ISR(SPIP_t* pSPIP){
     if(HAL_SPI_TransmitReceive_DMA(pSPIP->hspi, pSPIP->pMasterSerialTxBuffer, pSPIP->pMasterSerialRxBuffer, SERIAL_BLOCK_SIZE_WORD) != HAL_OK)
     TrapError();
     return HAL_OK;
    }