0
\$\begingroup\$

I have two STM32 microcontrollers and they have CAN-bus connection with each other. The problem is that when I connect them together, then the transmitter will after a few messages, stop transmitting CAN-bus messages. From the beginning, I need to send about 2-3 messages, until the receiver understand the CAN-message. So I assume that is some problem with the timing.

The main problem why the CAN-transmitter stop sending is that the Tx Mailboxes are full and I get the error message HAL_CAN_ERROR_PARAM back. That means I need to change some parameters at my settings in my STM32CubeIDE.

In this case, I have selected 250 kB/s as the CAN-bus baudrate. But it seems that I have not correctly selected these parameters.

enter image description here

My question for you is that tsr is CAN transmit status register. If that register is not correct for CAN_TSR_TME0, CAN_TSR_TME1 and CAN_TSR_TME2, then I need to change something. What can that be?

HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pHeader, uint8_t aData[], uint32_t *pTxMailbox)
{
  uint32_t transmitmailbox;
  HAL_CAN_StateTypeDef state = hcan->State;
  uint32_t tsr = READ_REG(hcan->Instance->TSR);

  /* Check the parameters */
  assert_param(IS_CAN_IDTYPE(pHeader->IDE));
  assert_param(IS_CAN_RTR(pHeader->RTR));
  assert_param(IS_CAN_DLC(pHeader->DLC));
  if (pHeader->IDE == CAN_ID_STD)
  {
    assert_param(IS_CAN_STDID(pHeader->StdId));
  }
  else
  {
    assert_param(IS_CAN_EXTID(pHeader->ExtId));
  }
  assert_param(IS_FUNCTIONAL_STATE(pHeader->TransmitGlobalTime));

  if ((state == HAL_CAN_STATE_READY) ||
      (state == HAL_CAN_STATE_LISTENING))
  {
    /* Check that all the Tx mailboxes are not full */
    if (((tsr & CAN_TSR_TME0) != 0U) ||
        ((tsr & CAN_TSR_TME1) != 0U) ||
        ((tsr & CAN_TSR_TME2) != 0U))
    {
      /* Select an empty transmit mailbox */
      transmitmailbox = (tsr & CAN_TSR_CODE) >> CAN_TSR_CODE_Pos;

      /* Check transmit mailbox value */
      if (transmitmailbox > 2U)
      {
        /* Update error code */
        hcan->ErrorCode |= HAL_CAN_ERROR_INTERNAL;

        return HAL_ERROR;
      }

      /* Store the Tx mailbox */
      *pTxMailbox = (uint32_t)1 << transmitmailbox;

      /* Set up the Id */
      if (pHeader->IDE == CAN_ID_STD)
      {
        hcan->Instance->sTxMailBox[transmitmailbox].TIR = ((pHeader->StdId << CAN_TI0R_STID_Pos) |
                                                           pHeader->RTR);
      }
      else
      {
        hcan->Instance->sTxMailBox[transmitmailbox].TIR = ((pHeader->ExtId << CAN_TI0R_EXID_Pos) |
                                                           pHeader->IDE |
                                                           pHeader->RTR);
      }

      /* Set up the DLC */
      hcan->Instance->sTxMailBox[transmitmailbox].TDTR = (pHeader->DLC);

      /* Set up the Transmit Global Time mode */
      if (pHeader->TransmitGlobalTime == ENABLE)
      {
        SET_BIT(hcan->Instance->sTxMailBox[transmitmailbox].TDTR, CAN_TDT0R_TGT);
      }

      /* Set up the data field */
      WRITE_REG(hcan->Instance->sTxMailBox[transmitmailbox].TDHR,
                ((uint32_t)aData[7] << CAN_TDH0R_DATA7_Pos) |
                ((uint32_t)aData[6] << CAN_TDH0R_DATA6_Pos) |
                ((uint32_t)aData[5] << CAN_TDH0R_DATA5_Pos) |
                ((uint32_t)aData[4] << CAN_TDH0R_DATA4_Pos));
      WRITE_REG(hcan->Instance->sTxMailBox[transmitmailbox].TDLR,
                ((uint32_t)aData[3] << CAN_TDL0R_DATA3_Pos) |
                ((uint32_t)aData[2] << CAN_TDL0R_DATA2_Pos) |
                ((uint32_t)aData[1] << CAN_TDL0R_DATA1_Pos) |
                ((uint32_t)aData[0] << CAN_TDL0R_DATA0_Pos));

      /* Request transmission */
      SET_BIT(hcan->Instance->sTxMailBox[transmitmailbox].TIR, CAN_TI0R_TXRQ);

      /* Return function status */
      return HAL_OK;
    }
    else
    {
      /* Update error code */
      hcan->ErrorCode |= HAL_CAN_ERROR_PARAM;

      return HAL_ERROR;
    }
  }
  else
  {
    /* Update error code */
    hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED;

    return HAL_ERROR;
  }
}
\$\endgroup\$
2
  • \$\begingroup\$ "From the beginning, I need to send about 2-3 messages" You should only need to send exactly 1 message or something about your CAN implementation is very fishy. \$\endgroup\$
    – Lundin
    Commented Dec 19, 2022 at 9:28
  • \$\begingroup\$ For general trouble-shooting, check out What are the most common causes of CAN bus communication errors? That covers all the FAQ beginner problems such as missing nodes, no ground, wrong timing, wrong termination etc. \$\endgroup\$
    – Lundin
    Commented Dec 19, 2022 at 9:32

1 Answer 1

1
\$\begingroup\$

In bxCAN, when a message is not acknowledged on the bus, the mailbox is not automatically cleared. The controller will continue transmitting the message until it is canceled or acknowledged.

Except when NART (No automatic retransmission) is set to 1.
Which by default it isn't. Because it's unreliable.

If you find yourself looking at the bxCAN controller registers you should always hookup a scope or can protocol analyzer to see what is actually happening on the bus. Especially if you do not own any known good nodes.

\$\endgroup\$
6
  • \$\begingroup\$ Thank you for your reply. Do you think it has to do with the CAN termination resistance to do? I have 60.9 ohm - capacitor - 60.9 ohm resisistance for both units. \$\endgroup\$
    – euraad
    Commented Dec 16, 2022 at 20:21
  • \$\begingroup\$ I tried to remove one termination resistor and now it won't work. So the termination resistors was not the problem. \$\endgroup\$
    – euraad
    Commented Dec 18, 2022 at 14:31
  • \$\begingroup\$ Can it be that my STM32 CAN tranciever do not send an ACK? \$\endgroup\$
    – euraad
    Commented Dec 18, 2022 at 14:32
  • \$\begingroup\$ @euraad is a message is not acknowledged, an error is recorded. Check the error counters. \$\endgroup\$
    – Jeroen3
    Commented Dec 19, 2022 at 6:43
  • \$\begingroup\$ "In bxCAN, when a message is not acknowledged on the bus, the mailbox is not automatically cleared" That's how all CAN controllers work. They will automatically try to resend until there are no error frames and a positive ACK, or alternatively until they go error passive. \$\endgroup\$
    – Lundin
    Commented Dec 19, 2022 at 9:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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