0

I'm trying to test out a SPI master using HAL_SPI_TransmitReceive() as I will be communicating with an SPI slave. The SPI slave device is not yet available. I have two STM32F4 NUCLEOs that I am using. One that will be the master and one pretending to be the slave device. I've wired them together and am using the following code:

Master_main.c

SPI_HandleTypeDef hspi2;

static void MX_SPI2_Init(void);

uint8_t spi_tx_data[9];
uint8_t spi_rx_data[9];

int main(void)
{
  MX_SPI2_Init();

  spi_tx_data[0] = 0;
  spi_tx_data[1] = 0;
  spi_tx_data[2] = 0;
  spi_tx_data[3] = 0;
  spi_tx_data[4] = 0;
  spi_tx_data[5] = 0;
  spi_tx_data[6] = 0;
  spi_tx_data[7] = 0;
  spi_tx_data[8] = 1;

  while (1)
  {
      static HAL_StatusTypeDef spi_error = HAL_OK;

      static uint32_t PreviousTicks_GreenLight = 0U;
      uint32_t CurrentTicks_GreenLight = HAL_GetTick();
      if((CurrentTicks_GreenLight - PreviousTicks_GreenLight) >= 500u)
      {
          HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
          PreviousTicks_GreenLight = CurrentTicks_GreenLight;
      }

      static uint8_t runonce = 0;
      if (HAL_GPIO_ReadPin(USER_Btn_GPIO_Port, USER_Btn_Pin) != 0) {
          if (runonce != 1){

              HAL_GPIO_WritePin(GPIO_ADR1_GPIO_Port, GPIO_ADR1_Pin, 0);
              HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
              spi_error = HAL_SPI_TransmitReceive(&hspi2,spi_tx_data, spi_rx_data,18,0x01);
              HAL_Delay(1);
              HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
              HAL_GPIO_WritePin(GPIO_ADR1_GPIO_Port, GPIO_ADR1_Pin, 1);

              runonce = 1;
          }
      } else {
          runonce = 0;
      }

      static uint32_t PreviousTicks_RedLight = 0U;
      uint32_t CurrentTicks_RedLight = HAL_GetTick();
      if((CurrentTicks_RedLight - PreviousTicks_RedLight) >= 500u)
      {
          if ( spi_error == HAL_TIMEOUT || spi_error == HAL_ERROR){
              HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
          } else {
              if ( spi_rx_data[8] == 2){
                  HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
              }
          }
          PreviousTicks_RedLight = CurrentTicks_RedLight;
      }
  }
}

static void MX_SPI2_Init(void)
{
  hspi2.Instance = SPI2;
  hspi2.Init.Mode = SPI_MODE_MASTER;
  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_SOFT;
  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi2.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi2) != HAL_OK)
  {
    Error_Handler();
  }
}

Slave_main.c

uint8_t spi_tx_data[9];
uint8_t spi_rx_data[9];

uint8_t rx_cmplt = 0;

void HAL_SPI_RxCpltCallback (SPI_HandleTypeDef *hspi) {
    static uint8_t rx_counter = 0;

    if ( rx_counter == 8 ){
        rx_cmplt = 1;
    } else {
        rx_counter++;
    }
    HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}

int main(void)
{
  MX_SPI2_Init();

  spi_tx_data[0] = 0;
  spi_tx_data[1] = 0;
  spi_tx_data[2] = 0;
  spi_tx_data[3] = 0;
  spi_tx_data[4] = 0;
  spi_tx_data[5] = 0;
  spi_tx_data[6] = 0;
  spi_tx_data[7] = 0;
  spi_tx_data[8] = 2;

  while (1)
  {
      static HAL_StatusTypeDef spi_error = HAL_OK;

      static uint32_t PreviousTicks_GreenLight = 0U;
      uint32_t CurrentTicks_GreenLight = HAL_GetTick();
      if((CurrentTicks_GreenLight - PreviousTicks_GreenLight) >= 1000u)
      {
          HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
          PreviousTicks_GreenLight = CurrentTicks_GreenLight;
      }

      static uint8_t runonce = 0;
      if (HAL_GPIO_ReadPin(GPIO_ADR1_GPIO_Port, GPIO_ADR1_Pin) != 1) {
          if (runonce != 1){

              HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
              //spi_error = HAL_SPI_TransmitReceive_IT(&hspi2, spi_tx_data, spi_rx_data, 18);
              spi_error = HAL_SPI_TransmitReceive(&hspi2,spi_tx_data, spi_rx_data,18,0x01);
              HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);

              runonce = 1;
          }
      } else {
          runonce = 0;
      }

      static uint32_t PreviousTicks_RedLight = 0U;
      uint32_t CurrentTicks_RedLight = HAL_GetTick();
      if((CurrentTicks_RedLight - PreviousTicks_RedLight) >= 500u)
      {
          if ( rx_cmplt == 1 ){
              if (spi_rx_data[8] == 1){
                  HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, 1);
              } else {
                  HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, 1);
              }
          } else {
              if ( spi_error == HAL_TIMEOUT || spi_error == HAL_ERROR){
                  HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
                  if (spi_error == HAL_TIMEOUT){
                      HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
                  }
              }
          }

          PreviousTicks_RedLight = CurrentTicks_RedLight;
      }
  }
}

static 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_SOFT;
  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi2.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi2) != HAL_OK)
  {
    Error_Handler();
  }
}

I stripped out various MCU initialization for simplicity. I had made an attempt to use the IT version of TransmitRecieve at an earlier time, but it didn't successfully transmit. If I use the USER button on my master several times it does manage to activate the appropriate lights on the slave but not on the master.

ConductedForce
  • 194
  • 2
  • 14
  • If I understood your query correctly, the data is not being transmitted and sometimes the LED is not triggering, right? Can you print the data at the time you are receiving the interrupt on the slave side? However, If you are not getting data at any time then you should also check the wired connections and pinmux once. – Harshit Sep 30 '21 at 09:36
  • I believe the data is out of sync given how I call TransmitReceive(). I debugged master and all the entire rx array is filled with 255 in all 9 positions. I can't debug the slave as the debugger won't support two devices being connected. The slave pulls power from the master board in my current config. – ConductedForce Sep 30 '21 at 10:01
  • Using a breakpoint and a data check, I have found that I never have even one moment of good data. Checking my wires because I did have an issue for one of them earlier. – ConductedForce Sep 30 '21 at 10:12
  • Someone recommended a logic analyzer, which is what I've been needing over an oscilloscope, which should be in tomorrow. Should help in viewing the problem more. – ConductedForce Sep 30 '21 at 10:21
  • Correct, the logic analyzer should help here. What I suspect is the length of the SPI lines as well. SPI lines can not be very high in length. Try to reduce the length and check whether the clock signals are proper. – Harshit Sep 30 '21 at 10:28
  • https://www.youtube.com/watch?v=wzOjVhEkk3c Check if this helps. This might not be the same controller, but it should be a good reference. – Harshit Sep 30 '21 at 10:30

1 Answers1

2

I suspect I had some sort of wiring issue. I added a breadboard into the mix and stuck some LEDs in, and somehow after connecting everything up, both master and slave worked correctly. I did change the code around to use some of the STM example for SPI, but that was before the breadboard.

Slave.c

  static uint8_t runonce = 0;
  if (HAL_GPIO_ReadPin(GPIO_ADR1_GPIO_Port, GPIO_ADR1_Pin) != 1) {
      if (runonce != 1){


      switch(HAL_SPI_TransmitReceive(&hspi2, spi_tx_data, spi_rx_data, 9, 5000))
        {
        case HAL_OK:
          /* Communication is completed_____________________________________________*/
          /* Compare the sent and received buffers */
          if(spi_rx_data[8] == 1)
          {
              HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
          }

          break;

        case HAL_TIMEOUT:
          /* A Timeout occurred_____________________________________________________*/
          /* Call Timeout Handler */
            HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
          break;

          /* An Error occurred______________________________________________________*/
        case HAL_ERROR:
          /* Call Timeout Handler */
            HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
          break;

        default:
          break;
        }

      runonce = 1;
  }
  } else {
      runonce = 0;
  }

Master.c

  static uint8_t runonce = 0;
  if (HAL_GPIO_ReadPin(USER_Btn_GPIO_Port, USER_Btn_Pin) != 0) {
      if (runonce != 1){


          HAL_GPIO_WritePin(GPIO_ADR1_GPIO_Port, GPIO_ADR1_Pin, 0);
          HAL_Delay(0x01);

          switch(HAL_SPI_TransmitReceive(&hspi2, spi_tx_data, spi_rx_data, 9, 5000))
            {
            case HAL_OK:
              /* Communication is completed_____________________________________________*/
              /* Compare the sent and received buffers */
              if(spi_rx_data[8] == 2)
              {
                  HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, 1);
              }

              break;

            case HAL_TIMEOUT:
              /* A Timeout occurred_____________________________________________________*/
              /* Call Timeout Handler */
                HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, 1);
              break;

              /* An Error occurred______________________________________________________*/
            case HAL_ERROR:
              /* Call Timeout Handler */
                HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, 1);
              break;

            default:
              break;
            }

          //HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);

          HAL_GPIO_WritePin(GPIO_ADR1_GPIO_Port, GPIO_ADR1_Pin, 1);

          runonce = 1;
      }
  } else {
      runonce = 0;
  }
ConductedForce
  • 194
  • 2
  • 14