cancel
Showing results for 
Search instead for 
Did you mean: 

Problem Sending CAN Message

andy2399
Senior
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

25 REPLIES 25
T J
Lead
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
Senior
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

andy2399
Senior
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

andy2399
Senior
Posted on April 16, 2018 at 10:55

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

andy2399
Senior
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
Senior
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

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)

    
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);
Posted on April 16, 2018 at 11:10

I use the interrupts for the RX side.

only enable it once at startup