在STM32的单个CAN消息中发送不同的数据类型数据

Posted

技术标签:

【中文标题】在STM32的单个CAN消息中发送不同的数据类型数据【英文标题】:Sending different datatype data in single CAN message in STM32 【发布时间】:2021-07-08 12:45:47 【问题描述】:

在 STM32L4 上使用 CAN 时,我尝试发送三种不同数据类型的数据,即浮点、布尔值和浮点值。在一条消息中可以发送 8 个字节,我在一条消息中发送所有三个数据。

我的数据看起来像

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

如果我能得到一些指导,那就太好了,我如何在单个 CAN 消息中组合所有三种数据类型?

到目前为止,我已经尝试使用带有打印格式说明符的sprintf()。并将组合结果存储在char TxData[8]; 但没有得到任何富有成效的结果。

为了发送数据,使用标准HAL_CAN_AddTxMessage()

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

【问题讨论】:

scanf?你是如何使用它的?通常,CAN Bus 中不需要/不需要这样的文本处理功能。请提供有关它的代码 sn-p,以便我们了解您的用例并提出更好的替代方案。 对不起,我写的是'scanf'而不是'sprintf()',我像下面这样打包了我的数据。字符 TxData[8] = 0; sprintf(TxData, 8, "%f%d%d%d", tf, sl, status_tf,status_sl ); HAL_CAN_AddTxMessage(&hcan1, &TxHeader, TxData, &TxMailbox); 这个方法不好,所以我想改成标准包装方法。感谢@chux,我可以将所有数据打包到一个 CAN_message 中。现在我用过; uint8_t TxData[8]=0; memcpy();对于 'float' 和 'uint16_t' 和布尔值,我使用“bytes ^= 0b00000001 【参考方案1】:

如何在单个 CAN 消息中组合所有三种数据类型?

乍一看,人们可能会考虑使用struct 来保存所有数据,然后将其发送。

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

my_data 的大小可能超过 8 个字节,bool 可能超过 1 个字节。

考虑使用memcpy() 来处理对齐问题。一个好的编译器会为这样的小副本发出传出代码。我会将bool 分配给charTxData[6] (& 7) 以应对宽泛的bool。只会分配 0 或 1 的值。

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);

要恢复数据,请反向复制。


迂腐的代码也会检查尺寸:

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

如果uint16_t 和/或floatfloat 编码的字节序可能不同,则需要额外的代码。

【讨论】:

布尔值可能需要更仔细的转换。将有一个协议准确指定它们对应的位,而这不一定对应于 C 程序中 bool 的内部表示。同样,必须注意将较大的数据类型调整为网络字节序 - 您可能无法使用 memcpy。 @Lundin 在标准 C 中使用bool,使用哪个位与charTxData[6] = status_tf; 或相反的status_tf = charTxData[6]; 没有区别。 charTxData[6] 将收到 0 或 1 的值。bool 不是通过 mempy() 复制的。 @Lundin 关于float, uint16_t 的字节顺序问题是正确的。还有float,即使字节序和大小相同,也可能使用不同的编码。 啊,没错。但是使用 2 个字节来存储 2 位似乎是一种浪费。 CAN 带宽总是很紧。关于字节序,那里有各种奇怪的味道。例如,行业标准 CANopen 使用 Big Endian 标识符(根据 CAN 标准的要求),但使用 Little Endian 有效负载。 @Lundin 当然在小端破解鸡蛋是correct choice。

以上是关于在STM32的单个CAN消息中发送不同的数据类型数据的主要内容,如果未能解决你的问题,请参考以下文章

STM32--CAN通讯实验

STM32------- CAN

STM32------- CAN

STM32CAN总线接口发送和接收数据

STM32 HAL CAN TX 邮箱

STM32F407 CAN发送注意事项