1
\$\begingroup\$

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);

}
\$\endgroup\$
4
  • \$\begingroup\$ This is done on the CAN controller level so it sounds like a hardware problem. Common problems to check: 1) is there actually another node on the bus running on same baudrate? 2) did you connect signal grounds? 3) termination of 120R in both ends? Also what do you mean "the transmission speed is about 50kbps"? It has to be exactly 50kbps. Maybe your RC oscillator is too inaccurate - they are not recommended to use for CAN. \$\endgroup\$
    – Lundin
    Commented Mar 23, 2020 at 7:59
  • \$\begingroup\$ Decoding of your logic analyzer looks wrong. Where is your 0x700 frame? \$\endgroup\$
    – A.R.C.
    Commented Mar 23, 2020 at 8:36
  • \$\begingroup\$ @Lundin There are 2 nodes on bus. First node is STM32 and second node is instrument panel cluster. I connected all grounds - STM32, IPC and CAN transciver have common ground. On one side CAN transiver have built-in 120 ohm resisotor. On second site i have THT resistor 120 ohm. Nevertheless I tried with 2 resistor, 1 resistor and without them - result is the same. Speed is equal to 50kbps, sorry you are rigth. I use an external oscillator (HSE) instead of (HSI). If there was a problem with the oscillator on the board, no CAN communication would work, I think... \$\endgroup\$
    – Daniel
    Commented Mar 23, 2020 at 19:02
  • \$\begingroup\$ @A.R.C. sorry, here it is: i.sstatic.net/Gz4zX.png \$\endgroup\$
    – Daniel
    Commented Mar 23, 2020 at 19:03

1 Answer 1

1
\$\begingroup\$

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 :)

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.