La comunicación SPI entre STM32F4 y Rasberry Pi produce basura

0

Intento establecer una comunicación SPI entre un RPi (como MASTER) y un STM32F410 (como SLAVE, en un tablero Nucleo). Mi PoC es simple, envío 8 bytes desde el Rpi y los imprimo con el UART-over-USB en el Nucleo. Aquí está el código de envío (en Python) que se ejecuta en Rasberry Pi:

spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 8000000
to_send = [1,2,3,4,5,6,7,8]
#spi.writebytes(to_send)
spi.xfer(to_send)

y el código de recepción en el STM32:

while(1) {
    memset(buf, 0, BRAIN_COM_BUF_SIZE);
    HAL_SPI_Receive(&hspi5, (uint8_t*)&buf, BRAIN_COM_BUF_SIZE, HAL_MAX_DELAY);
    sprintf((char*) dbg_buffer, "[%d][%d][%d][%d][%d][%d][%d][%d]\r\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
    HAL_UART_Transmit(&huart2, dbg_buffer, strlen((char const*) dbg_buffer), 1000);
}

y mi código de inicialización SPI (generado por CubeMX):

/* SPI5 init function */
void MX_SPI5_Init(void)
{

  hspi5.Instance = SPI5;
  hspi5.Init.Mode = SPI_MODE_SLAVE;
  hspi5.Init.Direction = SPI_DIRECTION_2LINES;
  hspi5.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi5.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi5.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi5.Init.NSS = SPI_NSS_SOFT;
  hspi5.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi5.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi5.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi5.Init.CRCPolynomial = 15;
  if (HAL_SPI_Init(&hspi5) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
}

Nada lujoso ¿verdad? Esta es una comunicación de uno a uno, pero de todos modos configuré y configuré el pin CS. Mi problema con este código es que funciona como, IDK 5% de las veces, como máximo. El resto del tiempo, tengo basura o, peor aún, parece que la función HAL_SPI_Receive () no obtuvo absolutamente nada.

Ejemplo de comportamiento actual:

envio: [1] [2] [3] [4] [5] [6] [7] [8] y el STM32 recibe: [0] [0] [1] [1] [2] [2] [3] [3]

¡Cualquier pista y / o ayuda para desbloquearme será muy útil, gracias!

    
pregunta MisterPatate

1 respuesta

3

La señal /CS se requiere incluso con un solo periférico, porque es clave para lograr sincronización de palabras entre el remitente y el receptor: la recepción sabe que el primer reloj después de /CS se agota es el que corresponde al primer bit de datos de la palabra. Debido a que SPI es una interfaz synchronous típicamente sin ninguna frecuencia de reloj mínima, sin sincronización, el receptor simplemente interpretará el primer reloj que ve (en el momento en que busca uno) como el comienzo de una palabra.

Los esquemas alternativos en los que el inicio de una palabra se indica con un intervalo de tiempo en la temporización son posibles, pero en realidad no son SPI y su código no intenta implementar tal cosa. De manera crítica, si alguna vez se produce una falta de coordinación, como que el remitente vuelva a transmitir mientras el receptor todavía está ocupado generando una salida en serie o reciclando después de un intento de recepción de tiempo de espera, puede comenzar a recibir bits del ciclo de reloj incorrecto.

E incluso si no terminas con los bits cambiados en una palabra, aún puedes terminar con las palabras cambiadas en un mensaje.

Finalmente, al realizar una comunicación de nivel binario entre distintos sistemas que utilizan diferentes idiomas, debe asegurarse de que utilicen codificaciones de datos compatibles. Python tiene funciones para empaquetar objetos de datos binarios en casi cualquier combinación de tamaño de elemento y endianness que pueda desear, sería bueno usarlos para establecer explícitamente la compatibilidad con el tipo de datos con el que el STM32 interpretará la información recibida.

    
respondido por el Chris Stratton

Lea otras preguntas en las etiquetas