Search code examples
floating-pointbooleanstm32bytebuffercan-bus

Sending different datatype data in single CAN message in STM32


While working with the CAN on STM32L4, I am trying to send three different data types of data i.e. float, bool and float value. As in one message 8 byte can be sent, all three data I am sending in single message.

my data looks like

float tf;
uint16_t sl;
bool status_tf;
bool status_sl;

It would be great if I can get some direction, How I can combine all three data type in single CAN message?

Until now, I have tried with sprintf() with print format specifier. and storing combined result in char TxData[8]; But Not getting any fruitful result.

To send the data, standard HAL_CAN_AddTxMessage() used.

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

Solution

  • How I can combine all three data type in single CAN message?

    At first blush, one might consider a struct to hold all the data and then send that.

    // First idea, but is it too big?
    typedef struct {
      float tf;
      uint16_t sl;
      bool status_tf;
      bool status_sl;
    } my_data;
    

    The size of my_data may be more than 8 bytes due to padding and bool may be more than 1 byte.

    Consider using memcpy() to cope with alignment issues. A good compiler will emit efferent code for such small copies. I'd assign the bool to charTxData[6] (& 7) to cope with a wide bool. Only the value of 0 or 1 will assign.

    unsigned char TxData[8];
    
    memcpy(&charTxData[0], &tf, 4);
    memcpy(&charTxData[4], &sl, 2);
    charTxData[6] = status_tf;
    charTxData[7] = status_sl;
    
    HAL_CAN_AddTxMessage(&hcan1, &TxHeader, TxData, &TxMailbox);
    

    To recover the data, reverse the copying.


    Pedantic code would also check sizes:

    _Static_assert(sizeof tf == 4, "Unusual tf size");
    _Static_assert(sizeof sl == 2, "Unusual sl size");
    

    If endian-ness of uint16_t and/or float or float encoding may differ, additional code is warranted.