Electronic – NAK in CAN bus for STM32F3 uC

ccanhal-librarylogic analyzerstm32

I have a problem with the NAK on the CAN bus. On STM32F303RE I wrote a code for communication via CAN bus with car dashboard (Instrument Panel Cluster). The communication works, I manage to receive frames from the device (e.g. below on the screen – a frame with ID:C194003) but each frame gets at the end of NAK.

enter image description here

I manage to send a signal on CAN bus (I send 0x700 frame) from which sometimes I get ACK and sometimes NAK. I don't know completely why the device doesn't expose the ACK bit. The Cluster Panel instrument has been taken out of the car so I don't think the CAN communication is badly done there. The transmission speed is about (50kbps)

code for clock initialization:

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
//  RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
//  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2;
  PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

CAN parameters:

 hcan.Instance = CAN;
  hcan.Init.Prescaler = 45;
  hcan.Init.Mode = CAN_MODE_NORMAL;
  hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan.Init.TimeSeg1 = CAN_BS1_13TQ;
  hcan.Init.TimeSeg2 = CAN_BS2_2TQ;

  hcan.Init.TimeTriggeredMode = DISABLE;
  hcan.Init.AutoBusOff = DISABLE;
  hcan.Init.AutoWakeUp = DISABLE;
  hcan.Init.AutoRetransmission = DISABLE;
  hcan.Init.ReceiveFifoLocked = DISABLE; // New message will overwrite existing message in FIFO memory
  hcan.Init.TransmitFifoPriority = DISABLE; // Priority driven by the identifier of the message
  if (HAL_CAN_Init(&hcan) != HAL_OK)
  {
    Error_Handler();
  }

CAN Tx function:

void CAN_Tx(uint32_t CanID, uint8_t CanDLC, uint8_t CANmsg[])
{
    uint32_t pTxMailbox;
    CAN_TxHeaderTypeDef CanTxHeader;
    CanTxHeader.DLC = CanDLC;
    CanTxHeader.ExtId = CanID;
    CanTxHeader.IDE = CAN_ID_EXT;
    CanTxHeader.RTR = CAN_RTR_DATA;

    if ((HAL_CAN_AddTxMessage(&hcan, &CanTxHeader, CANmsg, &pTxMailbox)) != HAL_OK )
    {
        Error_Handler();
    }
    while(HAL_CAN_IsTxMessagePending(&hcan, pTxMailbox));
    Print_CAN_Frame("Tx",CanTxHeader.ExtId, CanTxHeader.DLC, CANmsg);

}

Best Answer

I found a solution some time ago, I forgot to describe it. The problem was really on the hardware side but it's quite unusual. The instrument panel cluster from the car I'm connecting to has already 2 resistors built in and is like a separate CAN network. After removing ALL terminations (I soldered out a 120 ohm resistor from the transciver) everything suddenly started to work. To sum up: check the transciver / STM / Arduino documentation to see if you have a 120 ohm resistor and remove it if necessary. The same may apply to other elements taken out of the car :)