STM32 HAL_CAN_Transmit siempre devuelve TIMEOUT (HAL_CAN_STATE_TIMEOUT)

2

Configuración

Estoy usando un STM32F103C8T6 (también conocido como Blue Pill). Con el STM32Cube establecí CAN_RX en PB8 y CAN_TX9 en PB9 (estos son valores predeterminados / no modificables).

Circuito

simular este circuito : esquema creado usando CircuitLab

Componentes en el circuito anterior:

  • STM # 1: STM32F103C8T6
  • STM # 2: STM32F103C8T6
  • Transceptor # 1: Transceptor basado en TJA1050 (consulte TJA 1050 )
  • Transceptor # 2: Transceptor basado en TJA1050 (consulte TJA 1050 )

Descubrí que el TJA1050 funciona en 5V y que los VCC de salida de STM32 son 3.3V, así que usé una fuente de alimentación de tablero para dar 5V al Transceiver 1 y 2 VCC. Supongo que las GND USB están acopladas a las GND de los STM32 (probablemente internamente, ya que no hice ningún cableado específico), al igual que el USB + 5V está acoplado a la VCC de los STM.

Los transceptores ya contienen resistencias de 120 ohmios, por lo que supongo que no necesito más. La distancia actual entre CANL y CANH del transceptor n. ° 1 y n. ° 2 es de aproximadamente 10 cm / 4 "(cable simple). En mi aplicación real, será de aproximadamente 2 metros.

También asumo que el CAN TX debe estar conectado al TX del Tranceiver (y RX a RX).

Configuración de latas

Las configuraciones CAN generadas están abajo. Esto se ejecuta bien.

/* CAN init function */
static void MX_CAN_Init(void)
{

  static CanRxMsgTypeDef CanRX;
  static CanTxMsgTypeDef CanTX;
  CAN_FilterConfTypeDef sFilterConfig;

  hcan.Instance = CAN1;

  hcan.pRxMsg = &CanRX;
  hcan.pTxMsg = &CanTX;

  hcan.Init.Prescaler = 128;
  hcan.Init.Mode = CAN_MODE_NORMAL;
  hcan.Init.SJW = CAN_SJW_1TQ;
  hcan.Init.BS1 = CAN_BS1_12TQ;
  hcan.Init.BS2 = CAN_BS2_5TQ;
  hcan.Init.TTCM = DISABLE;
  hcan.Init.ABOM = DISABLE;
  hcan.Init.AWUM = DISABLE;
  hcan.Init.NART = DISABLE;
  hcan.Init.RFLM = DISABLE;
  hcan.Init.TXFP = DISABLE;
  if (HAL_CAN_Init(&hcan) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sFilterConfig.FilterNumber = 0;
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
  sFilterConfig.FilterIdHigh = 0x0000;
  sFilterConfig.FilterIdLow = 0x0000;
  sFilterConfig.FilterMaskIdHigh = 0x0000;
  sFilterConfig.FilterMaskIdLow = 0x0000;
  sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
  sFilterConfig.FilterActivation = ENABLE;
  sFilterConfig.BankNumber = 14;

  if (HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
  {
      Error_Handler();
  }
}

Programa

(se eliminaron los bloques de comentarios generados por STM)

Transmisor:

int main(void)
{
  ..
  /* USER CODE BEGIN 2 */
  hcan.pTxMsg->StdId = 0x100;
  hcan.pTxMsg->ExtId = 0x01;
  hcan.pTxMsg->RTR   = CAN_RTR_DATA;
  hcan.pTxMsg->IDE   = CAN_ID_STD;
  hcan.pTxMsg->DLC   = 2;

  while (1)
  {
  hcan.pTxMsg->Data[0] = 0x10;
  hcan.pTxMsg->Data[1] = 0x1;

  if (HAL_CAN_Transmit(&hcan, CAN_FIFO0) != HAL_OK)
  {
      Error_Handler();
  }
  HAL_Delay(1000);
  }
}

Receptor (el código de interrupción nunca se llama):

vox RxIntEnable (CAN_HandleTypeDef * CanHandle)

{
    if (CanHandle->State == HAL_CAN_STATE_BUSY_TX)
    {
        CanHandle->State = HAL_CAN_STATE_BUSY_TX_RX0;
    }
    else
    {
        CanHandle->ErrorCode = HAL_CAN_ERROR_NONE;
        __HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_EWG); // Error warning interrupt
        __HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_EPV); // Error passive interrupt
        __HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_BOF); // Bus-off interrupt
        __HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_LEC); // Last error code interrupt
        __HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_ERR); // Error interrupt
    }

    __HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_FMP0); // FIFO0 message pending interrupt
}

void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
{
    if ((CanHandle->pRxMsg->StdId == 0x100) &&
        (CanHandle->pRxMsg->IDE   == CAN_ID_STD) &&
        (CanHandle->pRxMsg->DLC   == 2))
    {
        printf("1");
    }

    RxIntEnable(CanHandle);
}

dentro de main:

if (HAL_CAN_Receive_IT(&hcan, CAN_FIFO0) != HAL_OK)
{
    Error_Handler();
}

Modo de bucle invertido

Cuando uso el modo de bucle invertido:

hcan.Init.Mode = CAN_MODE_LOOPBACK 

en lugar del modo Normal, puedo transmitir y recibir mensajes (y el hcan muestra los datos correctos en el mensaje recibido).

Problema

Sin embargo, en el modo Normal (como se muestra en el fragmento de código anterior), siempre obtengo un tiempo de espera en el siguiente comando:

 if (HAL_CAN_Transmit(&hcan, 10) != HAL_OK)

La función devuelve: HAL_CAN_STATE_TIMEOUT dentro de este fragmento (código HAL predeterminado):

/* Check End of transmission flag */
while(!(__HAL_CAN_TRANSMIT_STATUS(hcan, transmitmailbox)))
{
  /* Check for the Timeout */
  if(Timeout != HAL_MAX_DELAY)
  {
    if((Timeout == 0U) || ((HAL_GetTick()-tickstart) > Timeout))
    {
      hcan->State = HAL_CAN_STATE_TIMEOUT;

      /* Cancel transmission */
      __HAL_CAN_CANCEL_TRANSMIT(hcan, transmitmailbox);

      /* Process unlocked */
      __HAL_UNLOCK(hcan);
      return HAL_TIMEOUT;
    }
  }
}

Toda la inicialización parece estar bien (todas las funciones devuelven HAL_OK).

Análisis

Lo que probé / revisé fue:

  • Usando otro STM32: no hay diferencia
  • Usando otro transceptor: no hay diferencia
  • Jugó un poco con las cantidades de tiempo SJW / BS1 / BS2: no hay diferencia
  • Asegurarse de que las cantidades de tiempo fueran iguales
  • Jugando con diferentes valores de datos y filtros: no hay diferencia
  • Se verificó la salida de PB9 (CAN transmisión): parece que no cambia en absoluto (por lo que esto es un problema): no hay diferencia
  • Eliminando el cable del GPIO PB9 (CAN Tx) al TX de mi transceptor CAN: no hay diferencia.
  • La verificación de la transmisión se canceló (lo cual es necesario y era un error anterior, pero ya fue corregido por la biblioteca HAL que estoy usando).
  • Comprobar la resistencia entre CANL y CANH que se mueve entre 63 y 70 ohmios.
  • Comprobando el voltaje entre CANL y CANH (mientras no se envía después del error). 0 Voltaje; No esperaría esto.

Preguntas

  1. ¿Por qué tengo un tiempo de espera? Me cuesta mucho encontrar más para comprobar lo que ya hice.

Pregunta relacionada:

Actualizar

Esta es una pregunta antigua, pero volver a intentar que CAN funcione con el mismo resultado negativo (timeout). Cambié algunas configuraciones y actualicé la información anterior correspondiente.

    
pregunta Michel Keijzers

2 respuestas

2

Hace mucho tiempo que no uso CAN, pero lo primero que me vino a la mente es que la posibilidad del transmisor está esperando un ACK del receptor para completar la transmisión con éxito. Y la línea que se mantiene a 0 V también me hace pensar en un apretón de manos ACK perdido. Estoy seguro de que ya lo ha comprobado, pero yo vería el indicador de activación de interrupción global en el lado del receptor.

    
respondido por el pacman
1

¿No es tan simple que haya conectado el pin STM32 TX al pin TX del transceptor? El Transceptor está esperando esa señal en el pin RX.

Intercambie el cableado de modo que STM32 TX > > Transceptor RX y viceversa.

Tx aka Transmit es un bus de una sola vía que siempre se alimenta de un pin Rx aka Receive.

    
respondido por el MIL-SPEC

Lea otras preguntas en las etiquetas