【问题标题】:Linking two message structures together将两个消息结构链接在一起
【发布时间】:2018-11-20 08:54:38
【问题描述】:

我有两个略有不同的结构,我想以某种方式链接以获得最快的结果。

这是两个结构:

/** 
  * @brief  CAN Tx message structure definition  
  */
typedef struct
{
  uint32_t StdId;    /*!< Specifies the standard identifier.
                          This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF */

  uint32_t ExtId;    /*!< Specifies the extended identifier.
                          This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF */

  uint32_t IDE;      /*!< Specifies the type of identifier for the message that will be transmitted.
                          This parameter can be a value of @ref CAN_Identifier_Type */

  uint32_t RTR;      /*!< Specifies the type of frame for the message that will be transmitted.
                          This parameter can be a value of @ref CAN_remote_transmission_request */

  uint32_t DLC;      /*!< Specifies the length of the frame that will be transmitted.
                          This parameter must be a number between Min_Data = 0 and Max_Data = 8 */

  uint8_t Data[8];   /*!< Contains the data to be transmitted.
                          This parameter must be a number between Min_Data = 0 and Max_Data = 0xFF */

}CanTxMsgTypeDef;

/**
  * @brief  CAN Rx message structure definition
  */
typedef struct
{
  uint32_t StdId;       /*!< Specifies the standard identifier.
                             This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF */

  uint32_t ExtId;       /*!< Specifies the extended identifier.
                             This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF */

  uint32_t IDE;         /*!< Specifies the type of identifier for the message that will be received.
                             This parameter can be a value of @ref CAN_Identifier_Type */

  uint32_t RTR;         /*!< Specifies the type of frame for the received message.
                             This parameter can be a value of @ref CAN_remote_transmission_request */

  uint32_t DLC;         /*!< Specifies the length of the frame that will be received.
                             This parameter must be a number between Min_Data = 0 and Max_Data = 8 */

  uint8_t Data[8];      /*!< Contains the data to be received.
                             This parameter must be a number between Min_Data = 0 and Max_Data = 0xFF */

  uint32_t FMI;         /*!< Specifies the index of the filter the message stored in the mailbox passes through.
                             This parameter must be a number between Min_Data = 0 and Max_Data = 0xFF */

  uint32_t FIFONumber;  /*!< Specifies the receive FIFO number.
                             This parameter can be CAN_FIFO0 or CAN_FIFO1 */

}CanRxMsgTypeDef;

它们是用于 ARM 的 IAR 嵌入式工作台的 ST 驱动程序的一部分,所以我无法更改它们。

我的功能主要是进行过滤,这意味着无论我收到什么,我都需要立即发送。

驱动函数(我也无法更改)只允许传输CanTxMsgTypeDef 类型。所以每次我需要将CanRxMsgTypeDef 变量复制到CanTxMsgTypeDef 变量,这是非常低效的。

我正在寻找最快结果的最佳实践,即以最少的复制粘贴传输CanRxMsgTypeDef 数据。

请注意CanRxMsgTypeDef 仅具有额外数​​据,即所有要在接收到的CanRxMsgTypeDef 变量中传输的信息。

【问题讨论】:

  • 从技术上讲,您需要在两者之间将数据复制到 RAM - 没有办法。您不能将 CAN 寄存器 rx 缓冲区作为地址传递给 CAN tx。因此,即使使用联合版本(您应该这样做),您也会得到 2 个必须处理的硬拷贝。

标签: c embedded can-bus iar type-punning


【解决方案1】:

使用两个structs中的union,您可以根据6.5.2.3p6从公共初始部分访问任何成员:

为了简化联合的使用,我们做了一个特殊的保证:如果联合包含多个共享相同初始序列的结构(见下文),并且如果联合对象当前包含这些结构之一,则允许在联合的完整类型声明可见的任何地方检查它们中任何一个的公共初始部分。如果对应的成员对于一个或多个初始成员的序列具有兼容的类型(并且对于位域,具有相同的宽度),则两个结构共享一个共同的初始序列。

示例代码:

union common
{
    CanRxMsgTypeDef rx;
    CanTxMsgTypeDef tx;
};

void someFunc(CanTxMsgTypeDef arg)
{
    printf("inside func tx.StdId=%d\n",arg.StdId);
    printf("inside func tx.DLC=%d\n",arg.DLC);
}

int main()
{
    /* Assign RX type to the union */
    union common test = {1,2,3,4,5,{0,0,0,0,0,0,0,0},7,8};

    printf("test.tx.StdId=%d\n",test.tx.StdId);
    printf("test.rx.StdId=%d\n",test.rx.StdId);
    printf("test.tx.DLC=%d\n",test.tx.DLC);
    printf("test.rx.DLC=%d\n",test.rx.DLC);
    printf("test.rx.FMI=%d\n",test.rx.FMI);

    /* Use the union as tx type */
    someFunc(test.tx);
    return 0;
}

【讨论】:

  • 是的,这是正确的解决方案。它甚至允许不同类型之间的狂野类型转换(类型双关语)。最好将联合称为CanMsgTypeDef,其中包含rxtx 部分。或者对于那些不被 UnReadAbleCamelCase 卡住的人:union can_msg_t,struct can_txmsg_t 和 struct can_rxmsg_t
  • @Lundin,关于名称 CanMsgTypeDef 的好建议 - CamelCase 应该没问题,因为此代码打算与使用 CamelCase 的原始 ST 库代码和类型一起使用。
  • 谢谢!我会尽快检查的:)
猜你喜欢
  • 2015-10-18
  • 2023-03-19
  • 2011-03-28
  • 1970-01-01
  • 2013-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多