cancel
Showing results for 
Search instead for 
Did you mean: 

bxCAN - hold program while message will be sent corrertly

DKarc
Associate II

Hi,

I'm new to STM's. I'm writing program using bxCAN by HAL Layer. I had a problem with sending messages in time interval.

For example I would like to send two messages in every 100ms, but when I'm doing it messages are missing, so I would like to hold the program while message will be sent correctly.

I'm doing it in this way:

for(;;)if(HAL_CAN_AddTxMessage(&hcan, &TxHeader, msg, &MAILBOX) == HAL_OK)break;

It doesn't work, checking the transmit ok flag also doesn't work. Pooling while transmit mailboxes will be freed also doesn't work:

for(;;)if((HAL_CAN_GetTxMailboxesFreeLevel(&hcan)) == 3)break;

Maybe somebody can help, me with solving this problem.

BR, Daniel

5 REPLIES 5
Jack Peacock_2
Senior III

Based on your problem description messages are not arriving at the receiver. Stalling the transmit program won't help in this case. Do you mean none of your messages arrive at the receiver node? Have you checked the filtering on the receiver side? You may be blocking your messages.

The ideal solution would be to queue both messages in transmit mailboxes so they will be sent as soon as the bus is available. If this isn't working you'll need to explain why, since it suggests you are not sending messages at all. You might check the error registers to see if you are even connected to the CAN bus. If the transmit flag isn't working you definitely have either a configuration problem of a hardware problem with your CAN bus. Do you have termination resistors on the bus?

Jack Peacock

Hi Jack,

thanks for your interest.

All messages are arriving, I'm using data logger to see what is happening on the bus. The termination is ok. I can see all the messages on the bus. I'm sending this messages in time interval, for example in every 20 miliseconds. The case is that sometimes messages are simply lost. I also have checked all the errors flags and transmit OK flags.

Everything looks like the CAN peripherals are busy when I'm trying to send second message and message is sometimes aborted, and sometimes not. I'm just looking for simple mechanism to ensure that my message was sent and Transmit mailboxes are free.

This is not my first CAN project, I have lot of them before and everything was working. Now I'm moving for STM's.

I spend two days on this case and I cannot find a simple solution.

Also I went to LL and I have used example from STM's documentation:

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

    {

     CAN->sTxMailBox[0].TDTR = 8;

     CAN->sTxMailBox[0].TDLR = CMD;

     CAN->sTxMailBox[0].TIR = (uint32_t)(CAN_ID << 21

     | CAN_TI0R_TXRQ);

    }

Message is sent, but when I send messages in interval, again there are sometimes lost.

Daniel Karcz

Jack Peacock_2
Senior III

Are you using multiple transmit mailboxes? If TME0 is busy try 1 or 2 instead.

When you say messages are aborted, what's the error? A message is sent when the mailbox goes to empty, that's your verification. If it never goes empty then you have some kind of bus problem since you can't get a time slot to send, assuming CAN is properly configured.

Is there a lot of traffic on the bus, higher priority messages that force your transmitter node to wait indefinitely? CAN messages are prioritized by the ID field, so if some other node is colliding with your's but has a higher priority you can't get the bus long enough to transmit. That would explain why the mailbox never goes empty but you don;t have any errors.

Jack Peacock

DKarc
Associate II

Ok, Jack. You're right.

I have assumed that I had this problem only on loaded bus, and the case is that messages with the higher ID are blocked by the ones with lower ID. When I'm changing ID to lower my problem is gone.

I need to somehow disable this bus arbitration in the way that my messages will be sent in the way like with the lower ID.

I'm searching in the datasheet but I cannot find a solution. Is there any way to do this?

Daniel Karcz

DKarc
Associate II

Hello again, I have solved my problem.

I was always checking error flags, but I missed ALST flags. I've put HAL_CAN_AddTxMessage function in to infinite loop and after sending messages I'm checking all three ALST flags. If all flags are clear I'm breaking the infinite loop.

It is very important to wait for mailboxes are free before checking this flags by using the statement that I had write before:

for(;;)if((HAL_CAN_GetTxMailboxesFreeLevel(&hcan)) == 3)break;

Thank you Jack for your interest and help. Have a good day.

Daniel Karcz