3

I am trying loopback in SPI in STM32F411RE, using the STM32 HAL Library. The output in the serial terminal is distorted (Just boxes) I have connected the MOSI, MISO pins of the micro-controller. Could someone help me point out the problem. Thanks:).

void SPI_call()
{
    int i = 0, size = 3;
    uint8_t tx_buffer[3] = {0x10, 0x20, 0x30};
    uint8_t rx_buffer[3] = {0x00, 0x00, 0x00};

    for (i = 0; i < size; i++) {
        HAL_SPI_Receive(&hspi1, &rx_buffer[i], 1, 100);
        HAL_SPI_Transmit(&hspi1, &tx_buffer[i], 1, 100);
        HAL_UART_Transmit(&huart2, &rx_buffer[i], 1, HAL_MAX_DELAY);
    }
    
}

EDIT: Tried using the API HAL_UART_TransmitReceive(), but I was not able to receive the data.

void SPI_call()
{
    uint8_t tx_buffer = 0x20;
    uint8_t rx_buffer;

    HAL_SPI_TransmitReceive(&hspi1, &tx_buffer, &rx_buffer, 1, 1000);
    HAL_UART_Transmit(&huart2, &rx_buffer, 1, HAL_MAX_DELAY);   
}
Paulson Raja L
  • 379
  • 2
  • 11
  • 1
    For loopback, you need both an SPI master and an SPI slave. I assume you have configured `hspi1` as master. So `HAL_SPI_Receive` will never receive any but just time out. Basically, the original data of the `rx_buffer` is sent to the UART, i.e. 0 bytes. – Codo Oct 27 '20 at 12:35
  • @Bence Kaulics, Could you please provide suggestions. – Paulson Raja L Oct 27 '20 at 12:55
  • @ Codo, Could you please provide some suggestions? – Paulson Raja L Oct 27 '20 at 12:57
  • 1
    Use two SPI buses: one configured as master to transmit data and one configured as slave to receive data. – Codo Oct 27 '20 at 13:03
  • With some luck, it might also work to use `HAL_SPI_TransmitReceive` instead (with a single bus configured as master). – Codo Oct 27 '20 at 13:05
  • @Codo , I like to do it on a single bus and also edited the code for the ```HAL_UART_TransmitRecieve```. Could you please tell me what is wrong with the above code, please. – Paulson Raja L Oct 27 '20 at 13:22
  • Have you wired the MOSI pin to the MISO pin? – Codo Oct 27 '20 at 13:24
  • @ Codo, Yes Sir. – Paulson Raja L Oct 27 '20 at 13:25
  • Then it should work. If it doesn't work, the problem is in an area you haven't mentioned or shown in the code. (I wouldn't use 0x20 as a value. That's a space character, i.e. it might be inivisible in your terminal application.) – Codo Oct 27 '20 at 13:39
  • 1
    @codo ***`For loopback, you need both an SPI master and an SPI slave. I assume you have configured hspi1 as master. So HAL_SPI_Receive will never receive any but just time out`*** it is complete nonsense. Please do not comment if you do not know how the SPI works – 0___________ Oct 27 '20 at 14:11
  • 1
    Do include some letters or numbers if you expect them to be printed (0x20 is space, so 0x30 or '0', or 0x41 or 'A' might be a better choice). – domen Oct 27 '20 at 14:25
  • What are you seeing on the scope, please post scope captures. Where are your pull-ups on board or are you hoping for on chip. – old_timer Oct 27 '20 at 14:58
  • whatever you blast out on mosi can come back in to miso but it depends specifically on how the SPI controller works not on the spi protocol, so be very careful with P__J__'s comments, this is not a spi protocol thing, so codo's comment is perfectly valid in general. How it works for this part you should be able to read about in the docs or certainly experiment with against a real spi slave, and further supported with a scope. Any kind of work like this a scope is generally a requirement (i2c or spi) and they are quite inexpensive these days for four channel scopes. – old_timer Oct 27 '20 at 15:05
  • @old_timer ***`mosi can come back in to miso but it depends specifically on how the SPI controller works`*** no it is not the truth. It is a perfect loopback. But there can still be data in the FIFO so it should be purged before strating the transmition. – 0___________ Oct 27 '20 at 17:51
  • @P__J__ your lack of experience with spi controllers is understandable. You are making assumptions about controller designs in general and that is the flaw in your argument. if you are speaking specifically about one controller that is another story, you shound indicate that but the first question that has to be answered when considering looping mosi to miso on the same controller is the controller design. If you cant get past that tnere is nothing else to talk about until that is answered. – old_timer Oct 27 '20 at 19:14
  • 1
    general statements that controller design is part of the spec is counter productive. Also understanding that it is the very rare case that a spi or i2c peripheral or controller conforms to any such spec. You never bother with specs when using these interfaces you use the datasheets for the particular devices, nothing else matters. – old_timer Oct 27 '20 at 19:16

1 Answers1

2

In general, SPI communication needs at least a master and a slave. However, as SPI uses full duplex communication (i.e. it transmits and receives at the same time), it's usually possible to wire MOSI to MISO and achieve loopback communication.

I've tested it on a Nucleo-F411RE and it works.

Using STM32CubeMX I configured a project with the default settings for the Nucleo-F411RE (8 MHz external clock, SWD, UART2 pins suitable for on-board ST-Link etc.). Additionally, I've enabled SPI2. SPI1 is in conflict with the Nucleo board wiring. I've also shorted MOSI and MISO (PC2 and PC3).

The only code I've added is the piece in the while loop:

  while (1)
  {
    /* USER CODE END WHILE */

    HAL_Delay(1000);

    uint8_t tx_buffer[] = { 'H', 'e', 'l', 'l', 'o', '\r', '\n' };
    uint8_t rx_buffer;
    for (int i = 0; i < sizeof(tx_buffer); i++) {
      HAL_SPI_TransmitReceive(&hspi2, tx_buffer + i, &rx_buffer, 1, 100);
      HAL_UART_Transmit(&huart2, &rx_buffer, 1, 100);
    }

    /* USER CODE BEGIN 3 */
  }

The SPI initialization for reference (generated by STM32CubeMX):

  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();
  }
Codo
  • 75,595
  • 17
  • 168
  • 206