CAN a través de SPI a través de STM32F103C8T6

0

Como no pude hacer que CAN funcionara con la CAN interna de un STM32 (F103C8T6), compré algunos tableros CAN que funcionan con SPI, como estos :

Sinembargo,cuandoenvíoalgo,obtengolossiguientesresultadosutilizandounanalizadorlógico:

  • Los canales 1, 2 y 3 son Reloj, MISO y MOSI del SPI receptor
  • Los canales 4, 5 y 6 son Reloj, MISO y MOSI del SPI de transmisión
  • Los canales 6 y 7 son CANH y CANL

Mi código relevante para el lado del remitente:

static void MX_SPI1_Init(void)
{

  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_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

main:

  while (1)
  {
      uint8_t data[] = { 1, 2, 3, 4, 5 };
      if (HAL_SPI_Transmit(&hspi1, data, 5, 100) != HAL_OK)
      {
          Error_Handler();
      }
      HAL_Delay(1000);
}

(tenga en cuenta que no se llama al Error_Handler, por lo que el valor de retorno es HAL_OK.

Código del receptor:

static void MX_SPI1_Init(void)
{

  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_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

main:

while (1)
{
    HAL_SPI_Receive(&hspi1, data, 5, 100);
}

Preguntas:

  1. ¿Por qué no obtengo información del lado receptor? Parece que el SPI de envío está bien, el CANH de envío puede estar bien, pero CANL parece que no.

  2. Hay dos puentes en la PCB CAN, pero no estoy seguro de lo que hacen (cuando coloco puentes, todavía no consigo nada en el lado SPI que recibe).

  3. Puse tanto el Transmisor como el Receptor en el Maestro (porque luego ambos necesitan enviar mensajes). También probé con el transmisor al maestro y el receptor al esclavo, pero de nuevo no hay diferencia. ¿Cuál debería ser la configuración correcta?

pregunta Michel Keijzers

1 respuesta

1

Por lo que he visto hasta ahora en su código, no está intentando comunicarse con sensores o dispositivos específicos, está enviando algunos bytes entre varios nodos STM32 a una distancia relativamente corta.

Si ese es el caso, la solución simple sería colocar transceptores diferenciales en los puertos UART y terminar con ellos. Cualquier interfaz funcionaría, como RS-485, M-LVDS, LVDS en la configuración de OR cableado, etc.

Sin embargo, debe diseñar su propio protocolo para hacer frente a las colisiones, que es algo que PUEDE hacer por usted. Con solo 7 nodos en la red (si recuerdo bien) esto se puede hacer fácilmente usando un nodo como maestro orquestando la comunicación, o usando cualquier tipo de programación, intervalos de tiempo, etc.

ACTUALIZACIÓN

Aquí hay una cosa que debería aclarar la confusión. Todos estos transceptores diferentes no son tan diferentes. De hecho, puede utilizar el transceptor CAN TJA1050 de sus experimentos anteriores y obtener el mismo resultado. Simplemente convierten las señales de un solo extremo a diferencial y viceversa.

Siempre que tenga más de un nodo que pueda iniciar la comunicación, tiene potencial de colisión. La mayoría de estos chips tienen protección, es decir, no se dañarán si dos nodos comienzan a hablar simultáneamente. Pero los datos serán confusos. Algo tiene que hacerse cargo de esto. CAN controlador es exactamente ese "algo". No necesita inventar su propio protocolo, pero el costo es una configuración / comunicación más compleja con el controlador.

Alternativamente, puede omitir el controlador y conectarse al transceptor directamente. Entonces necesitas un mínimo control. Una forma sencilla de hacer esto (utilizada por el controlador CAN, BTW) es usar una conexión eléctrica O cableada, y transmitir y recibir simultáneamente, comparando cada bit transmitido con uno recibido. Si hay una diferencia, significa que alguien también está transmitiendo, por lo que uno de los nodos produce comunicación con el otro y espera hasta que el bus esté inactivo. Para hacer esto en el software necesitas muy MCU rápido.

Puede crear un protocolo simple que no necesite un cableado especial. Por ejemplo, puede pasar "el derecho a transmitir" entre los nodos. Si el nodo no tiene nada que decir, transmite el código "Nodo #n: Ya terminé". Luego el siguiente nodo toma turno, y así sucesivamente. Si el nodo necesita una respuesta, puede transmitir una solicitud y recibir respuesta de inmediato, o puede generar la línea y obtener respuesta cuando el nodo que responde tome su turno.

En resumen: cualquier implementación de red de múltiples niveles requiere codificación. Depende de usted.

Sugiero leer este excelente artículo para comprender mejor la variedad de opciones.

    
respondido por el Maple

Lea otras preguntas en las etiquetas