我可以将多个位域结构替换为 C 中的数组吗?
Can i replace multiple bitfield structs as an array in C?
我正在开发一个带有 CAN 通信的微控制器,它有 32 个通信邮箱。
在制造商提供的头文件中,他们有以下声明:
struct CANMSGID_BITS { // bits description
Uint16 EXTMSGID_L:16; // 15:0
Uint16 EXTMSGID_H:2; // 17:16
Uint16 STDMSGID:11; // 28:18
Uint16 AAM:1; // 29
Uint16 AME:1; // 30
Uint16 IDE:1; // 31
};
/* Allow access to the bit fields or entire register */
union CANMSGID_REG {
Uint32 all;
struct CANMSGID_BITS bit;
};
/* eCAN Message Control Register (MSGCTRL) bit definitions */
struct CANMSGCTRL_BITS { // bits description
Uint16 DLC:4; // 3:0
Uint16 RTR:1; // 4
Uint16 rsvd1:3; // 7:5 reserved
Uint16 TPL:5; // 12:8
Uint16 rsvd2:3; // 15:13 reserved
Uint16 rsvd3:16; // 31:16 reserved
};
/* Allow access to the bit fields or entire register */
union CANMSGCTRL_REG {
Uint32 all;
struct CANMSGCTRL_BITS bit;
};
/* eCAN Message Data Register low (MDR_L) word definitions */
struct CANMDL_WORDS { // bits description
Uint16 LOW_WORD:16; // 15:0
Uint16 HI_WORD:16; // 31:16
};
/* eCAN Message Data Register low (MDR_L) byte definitions */
struct CANMDL_BYTES { // bits description
Uint16 BYTE3:8; // 7:0
Uint16 BYTE2:8; // 15:8
Uint16 BYTE1:8; // 23:16
Uint16 BYTE0:8; // 31:24
};
/* Allow access to the bit fields or entire register */
union CANMDL_REG {
Uint32 all;
struct CANMDL_WORDS word;
struct CANMDL_BYTES byte;
};
/* eCAN Message Data Register high (MDR_H) word definitions */
struct CANMDH_WORDS { // bits description
Uint16 LOW_WORD:16; // 15:0
Uint16 HI_WORD:16; // 31:16
};
/* eCAN Message Data Register low (MDR_H) byte definitions */
struct CANMDH_BYTES { // bits description
Uint16 BYTE7:8; // 7:0
Uint16 BYTE6:8; // 15:8
Uint16 BYTE5:8; // 23:16
Uint16 BYTE4:8; // 31:24
};
/* Allow access to the bit fields or entire register */
union CANMDH_REG {
Uint32 all;
struct CANMDH_WORDS word;
struct CANMDH_BYTES byte;
};
struct MBOX {
union CANMSGID_REG MSGID;
union CANMSGCTRL_REG MSGCTRL;
union CANMDL_REG MDL;
union CANMDH_REG MDH;
};
这是针对单个邮箱的,但是有 32 个邮箱,因此邮箱的定义如下:
struct ECAN_MBOXES {
struct MBOX MBOX0;
struct MBOX MBOX1;
struct MBOX MBOX2;
.
.
.
struct MBOX MBOX30;
struct MBOX MBOX31;
};
最后我们有:
extern volatile struct ECAN_MBOXES ECanaMboxes;
其中 'ECanaMboxes' 在链接器命令文件中定义。
我只用以下声明替换了 struct ECAN_MBOXES
:
struct ECAN_MBOXES {
struct MBOX MBOX[32];
};
这是一个有效的更改,还是我们不允许从位域中创建数组?
我已经尝试了两种方式的代码,并且无论哪种方式,代码都运行良好。我更喜欢数组,因为它更容易为特定目的访问特定邮箱,而且所有邮箱的配置可以迭代方式完成。我想知道声明结构体会不会引起什么意外问题?
更改应该没问题,位域在数组中不是特例。
请注意,您需要保留原始代码中该结构 volatile
的实际变量声明。
至于ECAN_MBOXES
,考虑改用联合:
typedef union {
struct // C11 anonymous struct
{
struct MBOX MBOX0;
struct MBOX MBOX1;
...
};
struct MBOX MBOX[32];
}ECAN_MBOXES ;
现在如果你有 ECAN_MBOXES foo
,你可以用 foo.MBOX0
或 foo.MBOX[0]
访问它,它指的是同一个邮箱寄存器。
struct ECAN_MBOXES
是否包含 32 个不同的 struct MBOX
实例或 32 个 struct MBOX
的数组与 struct MBOX
的内部布局方式无关。
后者显然更可取,因为您可以索引数组,但它不会破坏 struct MBOX
的任何内容,无论它是否包含联合和位域。
请注意,您实际上并不是在创建一个位域数组,而是一个包含位域的结构数组。实际的位域数组不是合法的构造,如果您尝试这样做,您的编译器会给您一个错误。
我正在开发一个带有 CAN 通信的微控制器,它有 32 个通信邮箱。 在制造商提供的头文件中,他们有以下声明:
struct CANMSGID_BITS { // bits description
Uint16 EXTMSGID_L:16; // 15:0
Uint16 EXTMSGID_H:2; // 17:16
Uint16 STDMSGID:11; // 28:18
Uint16 AAM:1; // 29
Uint16 AME:1; // 30
Uint16 IDE:1; // 31
};
/* Allow access to the bit fields or entire register */
union CANMSGID_REG {
Uint32 all;
struct CANMSGID_BITS bit;
};
/* eCAN Message Control Register (MSGCTRL) bit definitions */
struct CANMSGCTRL_BITS { // bits description
Uint16 DLC:4; // 3:0
Uint16 RTR:1; // 4
Uint16 rsvd1:3; // 7:5 reserved
Uint16 TPL:5; // 12:8
Uint16 rsvd2:3; // 15:13 reserved
Uint16 rsvd3:16; // 31:16 reserved
};
/* Allow access to the bit fields or entire register */
union CANMSGCTRL_REG {
Uint32 all;
struct CANMSGCTRL_BITS bit;
};
/* eCAN Message Data Register low (MDR_L) word definitions */
struct CANMDL_WORDS { // bits description
Uint16 LOW_WORD:16; // 15:0
Uint16 HI_WORD:16; // 31:16
};
/* eCAN Message Data Register low (MDR_L) byte definitions */
struct CANMDL_BYTES { // bits description
Uint16 BYTE3:8; // 7:0
Uint16 BYTE2:8; // 15:8
Uint16 BYTE1:8; // 23:16
Uint16 BYTE0:8; // 31:24
};
/* Allow access to the bit fields or entire register */
union CANMDL_REG {
Uint32 all;
struct CANMDL_WORDS word;
struct CANMDL_BYTES byte;
};
/* eCAN Message Data Register high (MDR_H) word definitions */
struct CANMDH_WORDS { // bits description
Uint16 LOW_WORD:16; // 15:0
Uint16 HI_WORD:16; // 31:16
};
/* eCAN Message Data Register low (MDR_H) byte definitions */
struct CANMDH_BYTES { // bits description
Uint16 BYTE7:8; // 7:0
Uint16 BYTE6:8; // 15:8
Uint16 BYTE5:8; // 23:16
Uint16 BYTE4:8; // 31:24
};
/* Allow access to the bit fields or entire register */
union CANMDH_REG {
Uint32 all;
struct CANMDH_WORDS word;
struct CANMDH_BYTES byte;
};
struct MBOX {
union CANMSGID_REG MSGID;
union CANMSGCTRL_REG MSGCTRL;
union CANMDL_REG MDL;
union CANMDH_REG MDH;
};
这是针对单个邮箱的,但是有 32 个邮箱,因此邮箱的定义如下:
struct ECAN_MBOXES {
struct MBOX MBOX0;
struct MBOX MBOX1;
struct MBOX MBOX2;
.
.
.
struct MBOX MBOX30;
struct MBOX MBOX31;
};
最后我们有:
extern volatile struct ECAN_MBOXES ECanaMboxes;
其中 'ECanaMboxes' 在链接器命令文件中定义。
我只用以下声明替换了 struct ECAN_MBOXES
:
struct ECAN_MBOXES {
struct MBOX MBOX[32];
};
这是一个有效的更改,还是我们不允许从位域中创建数组? 我已经尝试了两种方式的代码,并且无论哪种方式,代码都运行良好。我更喜欢数组,因为它更容易为特定目的访问特定邮箱,而且所有邮箱的配置可以迭代方式完成。我想知道声明结构体会不会引起什么意外问题?
更改应该没问题,位域在数组中不是特例。
请注意,您需要保留原始代码中该结构 volatile
的实际变量声明。
至于ECAN_MBOXES
,考虑改用联合:
typedef union {
struct // C11 anonymous struct
{
struct MBOX MBOX0;
struct MBOX MBOX1;
...
};
struct MBOX MBOX[32];
}ECAN_MBOXES ;
现在如果你有 ECAN_MBOXES foo
,你可以用 foo.MBOX0
或 foo.MBOX[0]
访问它,它指的是同一个邮箱寄存器。
struct ECAN_MBOXES
是否包含 32 个不同的 struct MBOX
实例或 32 个 struct MBOX
的数组与 struct MBOX
的内部布局方式无关。
后者显然更可取,因为您可以索引数组,但它不会破坏 struct MBOX
的任何内容,无论它是否包含联合和位域。
请注意,您实际上并不是在创建一个位域数组,而是一个包含位域的结构数组。实际的位域数组不是合法的构造,如果您尝试这样做,您的编译器会给您一个错误。