STM32F429 biblioteca HAL CAN_Transmit timeout

2

Tengo un pequeño problema con el ejemplo de ST32CubeF4 v1.13.0 de una red CAN. Estoy utilizando una placa de descubrimiento STM32F429, pero he transferido el ejemplo de la red CAN desde la placa STM324x9_EVAL. Construí un bus de transceptor CAN utilizando MCP2551 . Usé el complemento gnu-arm-eclipse para generar el código base para mi proyecto.

Siempre que quiera usar la función HAL_CAN_Transmit (), siempre devuelve "HAL_CAN_STATE_TIMEOUT". Logré rastrear el origen del problema hasta el archivo stm32f42xx_hal_can.c y este fragmento de código:

/* 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;
     fprintf(stderr, "Error flag in CAN_Transmit");
     /* Process unlocked */
     __HAL_UNLOCK(hcan);
     return HAL_TIMEOUT;
    }
  }
}

Parece que el indicador de transmisión nunca se establece y el dispositivo siempre se apaga. He leído en otros foros en los foros de ST que potencialmente es un error en las bibliotecas HAL.

¿Hay alguna manera de evitar esto? Mi registro ESR también registra este código de error: 16253015, del cual no estoy seguro de qué hacer.

Aquí está el reloj y el código de inicio de CAN en mi main.c:

static void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;

  /* Enable Power Control clock */
  __HAL_RCC_PWR_CLK_ENABLE();

  /* The voltage scaling allows optimizing the power consumption when the device is
     clocked below the maximum system frequency, to update the voltage scaling value
     regarding system frequency refer to product datasheet.  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /* Enable HSE Oscillator and activate PLL with HSE as source */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 25;
  RCC_OscInitStruct.PLL.PLLN = 360;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  HAL_RCC_OscConfig(&RCC_OscInitStruct);

  /* Activate the Over-Drive mode */
  HAL_PWREx_EnableOverDrive();

  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
     clocks dividers */
  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
}

static void CAN_Config(void)
{
  CAN_FilterConfTypeDef sFilterConfig;
  static CanTxMsgTypeDef TxMessage;
  static CanRxMsgTypeDef RxMessage;

  /*##-1- Configure the CAN peripheral #######################################*/
  CanHandle.Instance = CAN1;
  CanHandle.pTxMsg = &TxMessage;
  CanHandle.pRxMsg = &RxMessage;

  CanHandle.Init.TTCM = DISABLE;
  CanHandle.Init.ABOM = DISABLE;
  CanHandle.Init.AWUM = DISABLE;
  CanHandle.Init.NART = DISABLE;
  CanHandle.Init.RFLM = DISABLE;
  CanHandle.Init.TXFP = DISABLE;
  CanHandle.Init.Mode = CAN_MODE_NORMAL;
  CanHandle.Init.SJW = CAN_SJW_1TQ;
  CanHandle.Init.BS1 = CAN_BS1_6TQ;
  CanHandle.Init.BS2 = CAN_BS2_8TQ;
  CanHandle.Init.Prescaler = 2;

  if(HAL_CAN_Init(&CanHandle) != HAL_OK)
  {
    /* Initialization Error */
    fprintf(stderr, "Error_Handler active in CAN Config Init");
    Error_Handler();
  }

  /*##-2- Configure the CAN Filter ###########################################*/
  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 = 0;
  sFilterConfig.FilterActivation = ENABLE;
  sFilterConfig.BankNumber = 14;

  if(HAL_CAN_ConfigFilter(&CanHandle, &sFilterConfig) != HAL_OK)
  {
    /* Filter configuration Error */
    fprintf(stderr, "Error_Handler active CAN Config Filter");
    Error_Handler();
  }

  /*##-3- Configure Transmission process #####################################*/
  CanHandle.pTxMsg->StdId = 0x321;
  CanHandle.pTxMsg->ExtId = 0x01;
  CanHandle.pTxMsg->RTR = CAN_RTR_DATA;
  CanHandle.pTxMsg->IDE = CAN_ID_STD;
  CanHandle.pTxMsg->DLC = 2;
}

Además de dónde están mis principales llamadas a HAL_CAN_Transmit y Receive:

int main(void)
{
  /* STM32F4xx HAL library initialization:
       - Configure the Flash prefetch, instruction and Data caches
       - Configure the Systick to generate an interrupt each 1 msec
       - Set NVIC Group Priority to 4
       - Global MSP (MCU Support Package) initialization
     */
  HAL_Init();

  /* Configure the system clock to 180 MHz */
  SystemClock_Config();

  BSP_LED_Init(LED3);
  BSP_LED_Init(LED4);

  /* Configure Key Button */
  BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_GPIO);

  /*##-1- Configure the CAN peripheral #######################################*/
  CAN_Config();
  /*##-2- Start the Reception process and enable reception interrupt #########*/
  if(HAL_CAN_Receive_IT(&CanHandle, CAN_FIFO0) != HAL_OK)
  {
    fprintf(stderr, "Error_Handler active in CAN_Receive");
    Error_Handler();
  }

  /* Infinite loop */
  while(1)
  {
    while(BSP_PB_GetState(BUTTON_KEY) == KEY_PRESSED)
    {
      if(ubKeyNumber == 0x4)
      {
        ubKeyNumber = 0x00;
      }
      else
      {
        LED_Display(++ubKeyNumber);

        /* Set the data to be transmitted */
        CanHandle.pTxMsg->Data[0] = ubKeyNumber;
        CanHandle.pTxMsg->Data[1] = 0xAD;

        /*##-3- Start the Transmission process ###############################*/
        if(HAL_CAN_Transmit(&CanHandle, 10000) != HAL_OK)
        {
          /* Transmition Error */
            fprintf(stderr, "Error_Handler active in CAN Transmit");
          Error_Handler();
        }
        HAL_Delay(10);

        while(BSP_PB_GetState(BUTTON_KEY) != KEY_NOT_PRESSED)
        {
        }
      }
    }
  }
}

EDITAR:

Encontré una solución, aunque no la ideal. Bajé la velocidad en baudios de CAN aumentando el prescaler a 80 en CAN_Config. Esto ha resultado en una comunicación CAN exitosa.

El problema fue más probable con mi bus CAN. La longitud del bus CAN podría haber sido demasiado corta (meros centímetros) para usar las resistencias de terminación de 120 ohmios y el bit de derecha a alta para usar el bus sin ellas.

    
pregunta Mic De Duiwel

0 respuestas

Lea otras preguntas en las etiquetas