Skip to main content
andy2399
Senior
April 15, 2018
Question

Problem Sending CAN Message

  • April 15, 2018
  • 15 replies
  • 8093 views
Posted on April 15, 2018 at 23:27

I am following the example code found here to send and receive CAN messages:

STM32Cube_FW_F4_V1.21.0\Projects\STM324xG_EVAL\Examples\CAN\CAN_Networking\Src

I can happily receive CAN messages but when I call the following code, the CAN message is never sent.

HAL_CAN_AddTxMessage( &hcan1, &TxHeader, TxData, &TxMailbox );

while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1) != 3) {}

TxHeader is configured as:

TxHeader.StdId = 0x123;

TxHeader.ExtId = 0x01;

TxHeader.RTR = CAN_RTR_DATA;

TxHeader.IDE = CAN_ID_STD;

TxHeader.DLC = 7;

TxHeader.TransmitGlobalTime = DISABLE;

And TxData is filled with seven bytes of data.

HAL_CAN_GetTxMailboxesFreeLevel always returns 2 and I don't see the CAN message on the bus.

Any help or idea would be gratefully appreciated.

Andy

    This topic has been closed for replies.

    15 replies

    T J
    Senior III
    April 15, 2018
    Posted on April 16, 2018 at 01:39

    Hi,

    are you using 2 devices ? on a CanBus ? with a line driver ?

    You can receive but not transmit.

    Are there only two devices on the bus ?

    Did you turn on the ABOM enable ?

    When you transmit, make sure no two devices never transmit the same msgID.

    andy2399
    andy2399Author
    Senior
    April 16, 2018
    Posted on April 16, 2018 at 10:04

    Thank you for your interest in my problem.

    There are two devices on my bus both with line drivers and both ends terminated.

    I am using a STM32F429 device with a SN65HVD230D CAN transceiver connected to a Microchip CAN Bus Analyser box which is configured to have bus termination enabled. I have the bit rate set to 20Kbps.

    I assume ABOM is Auto Bus Off Management, in the latest HAL it is called AutoBusOff. I have that DISABLED however enabling it makes no difference.

    Andy

    T J
    Senior III
    April 16, 2018
    Posted on April 16, 2018 at 10:28

    if you want the CanBs to recover from a hardware error, then best to enable ABOM.

    I poll this code to transmit:

     no interrupts are needed for Tx

                 if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0)                                                         // (1)

                        {

                     

                            

                            CAN->sTxMailBox[0].TDTR = canTxMsgLength[canTxMsgOUT];                               // (2) length

                            CAN->sTxMailBox[0].TDLR = canTxMsgBottomWord[canTxMsgOUT];                        // (3) 4bytes

                            CAN->sTxMailBox[0].TDHR = canTxMsgTopWord[canTxMsgOUT];                          // (3) 4bytes

                            CAN->sTxMailBox[0].TIR  = ((uint32_t)canTxMsgID[canTxMsgOUT] << 21 | CAN_TI0R_TXRQ);        // (4)    // send it now if the line is idle

                    // destroy old data to be sure we only transmit fresh data

                    // not needed

                            canTxMsgLength[canTxMsgOUT]     = 0;            

                            canTxMsgBottomWord[canTxMsgOUT] = 0;     

                            canTxMsgTopWord[canTxMsgOUT]    = 0;         

                            canTxMsgID[canTxMsgOUT++]        = 0;

                        

                            canTxMsgOUT &= 0x3F;                           // 64 buffer elements

                            canTxMsgTableFULL = false;

                            canTxMsgOverrun = false;

                            //canMsgCounter ++;

                    

                        }

                        if ((CAN->TSR & CAN_TSR_TME1) == CAN_TSR_TME1)                                         // (1)

        
    andy2399
    andy2399Author
    Senior
    April 16, 2018
    Posted on April 16, 2018 at 10:41

    Thanks for the code - you are using LL where I am trying to use the HAL but I gave it a go to see if it helped.

    I modified your code to look like this:

    if ( ( hcan1.Instance->TSR & CAN_TSR_TME0 ) == CAN_TSR_TME0 ) // (1)

    {

    hcan1.Instance->sTxMailBox[ 0 ].TDTR = 8;

    hcan1.Instance->sTxMailBox[ 0 ].TDLR = 0x12345678;

    hcan1.Instance->sTxMailBox[ 0 ].TDHR = 0xABCDEF12;

    hcan1.Instance->sTxMailBox[ 0 ].TIR = ( ( uint32_t )0x123 << 21 | CAN_TI0R_TXRQ );

    }

    The first time in, the if statement executes but nothing appears to be launched onto the bus, thereafter, the if statement never becomes true.

    Andy

    T J
    Senior III
    April 16, 2018
    Posted on April 16, 2018 at 10:47

    I do enable interrupts, but dont use any Tx part of it,

    like this : in startup, run only once never enable again

       

        __HAL_CAN_ENABLE_IT(&hcan, CAN_IT_FMP1);

        __HAL_CAN_ENABLE_IT(&hcan, CAN_IT_FMP0);
    andy2399
    andy2399Author
    Senior
    April 16, 2018
    Posted on April 16, 2018 at 10:55

    I have interrupts enabled though I don't use them.

    T J
    Senior III
    April 16, 2018
    Posted on April 16, 2018 at 11:10

    I use the interrupts for the RX side.

    only enable it once at startup

    andy2399
    andy2399Author
    Senior
    April 16, 2018
    Posted on April 16, 2018 at 11:07

    Okay, digging a little deeper (I was able to get a logic analyser on the bus). I do see a message being transmitted after all. However, it seems that it is not being ACK'd because the original message is continually being sent and all the transmit mailboxes are full. So I guess I have to dig a bit deeper into this :(

    Andy

    andy2399
    andy2399Author
    Senior
    April 16, 2018
    Posted on April 16, 2018 at 11:11

    Even more strange, if I disable automatic re transmission it all works fine. The mailboxes never fill up and I see continually changing data in the messages.

    Andy

    T J
    Senior III
    April 16, 2018
    Posted on April 16, 2018 at 11:57

    :

    kgedi
    Associate
    January 27, 2019

    Hi,

    I have same problem about 2 weeks i stuck in here, please can you explain how could you solve this problem?

    Thank you, best regards.

    T J
    Senior III
    January 28, 2019
    I use this, polled in the foreground: I have a set of buffers for TxMsgs[64]; You would be primarily interested in lines (1)(2)(3)(4) As you may see, there are 3 mail boxes all scanned for an empty mailbox. Thereby the received packets are not likely to be in order, since the mailbox 0 has ‘Tx on the wire’ priority. void checkCanTxMsgs(void) { // this is a non-ordered packet transmitter. if(!canTxMsgTableEMPTY) { if ((canTxMsgOUT != canTxMsgIN) || canTxMsgTableFULL) // non-ordered packet transmitter { if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) // (1) { if (showRxCanFrames) sendCanTxFrametoConsole(); CAN->sTxMailBox[0].TDTR = canTxMsgLength[canTxMsgOUT]; // (2) length CAN->sTxMailBox[0].TDLR = canTxMsgBottomWord[canTxMsgOUT]; // (3) 4bytes CAN->sTxMailBox[0].TDHR = canTxMsgTopWord[canTxMsgOUT]; // (3) 4bytes CAN->sTxMailBox[0].TIR = ((uint32_t)canTxMsgID[canTxMsgOUT] << 21 | CAN_TI0R_TXRQ); // (4) // send it now if the line is idle // destroy old data to be sure we only transmit fresh data // not needed canTxMsgLength[canTxMsgOUT] = 0; canTxMsgBottomWord[canTxMsgOUT] = 0; canTxMsgTopWord[canTxMsgOUT] = 0; canTxMsgID[canTxMsgOUT++] = 0; canTxMsgOUT &= 0x3F; // 64 buffer elements canTxMsgTableFULL = false; canTxMsgOverrun = false; } if ((canTxMsgOUT != canTxMsgIN) || canTxMsgTableFULL) if ((CAN->TSR & CAN_TSR_TME1) == CAN_TSR_TME1) // (1) { if (showRxCanFrames) sendCanTxFrametoConsole(); CAN->sTxMailBox[1].TDTR = canTxMsgLength[canTxMsgOUT]; // (2) length CAN->sTxMailBox[1].TDLR = canTxMsgBottomWord[canTxMsgOUT]; // (3) 4bytes CAN->sTxMailBox[1].TDHR = canTxMsgTopWord[canTxMsgOUT]; // (3) 4bytes CAN->sTxMailBox[1].TIR = ((uint32_t) canTxMsgID[canTxMsgOUT] << 21 | CAN_TI1R_TXRQ); // (4) // send it now if the line is idle // destroy old data to be sure we only transmit fresh data // not needed canTxMsgLength[canTxMsgOUT] = 0; canTxMsgBottomWord[canTxMsgOUT] = 0; canTxMsgTopWord[canTxMsgOUT] = 0; canTxMsgID[canTxMsgOUT++] = 0; canTxMsgOUT &= 0x3F; // 64 buffer depth canTxMsgOverrun = false; canTxMsgTableFULL = false; } if ((canTxMsgOUT != canTxMsgIN) || canTxMsgTableFULL) if ((CAN->TSR & CAN_TSR_TME2) == CAN_TSR_TME2) // (1) { if (showRxCanFrames) sendCanTxFrametoConsole(); CAN->sTxMailBox[2].TDTR = canTxMsgLength[canTxMsgOUT]; // (2) length CAN->sTxMailBox[2].TDLR = canTxMsgBottomWord[canTxMsgOUT]; // (3) 4bytes CAN->sTxMailBox[2].TDHR = canTxMsgTopWord[canTxMsgOUT]; // (3) 4bytes CAN->sTxMailBox[2].TIR = ((uint32_t) canTxMsgID[canTxMsgOUT] << 21 | CAN_TI2R_TXRQ); // (4) // send it now if the line is idle // destroy old data to be sure we only transmit fresh data // not needed canTxMsgLength[canTxMsgOUT] = 0; canTxMsgBottomWord[canTxMsgOUT] = 0; canTxMsgTopWord[canTxMsgOUT] = 0; canTxMsgID[canTxMsgOUT++] = 0; canTxMsgOUT &= 0x3F; // 64 buffer elements canTxMsgOverrun = false; canTxMsgTableFULL = false; } if (canTxMsgOUT == canTxMsgIN) canTxMsgTableEMPTY = true; } } }
    kgedi
    Associate
    January 28, 2019

    Thank you so much TJ i tried ​again in debug mode TxMailbox is always equals to 0x00000001 and the txdatas are not written in TxMailbox even if the selected mailbox(0) is empty why behave like this

    Best regards.​

    T J
    Senior III
    January 29, 2019
    Did you try the code snippets ? (1),(2),(3),(4) ?
    HAL is not great sometimes… but useful in initialisation.
    T J
    Senior III
    January 29, 2019
    That code looks odd,
    what values do you have for CAN_TDH0R_DATA(0..7)_Pos ?
    kgedi
    Associate
    January 29, 2019

    ​thank you for your interest...

    I have datas like these;

    TxData[0]​=0x11;

    TxData[1]​=0x12;

    TxData[2]​=0x13;

    ...