在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
和/或float
或float
编码的字节序可能不同,则需要额外的代码。
【讨论】:
布尔值可能需要更仔细的转换。将有一个协议准确指定它们对应的位,而这不一定对应于 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消息中发送不同的数据类型数据的主要内容,如果未能解决你的问题,请参考以下文章