C++ C+;中用于mcu寄存器映射的位字段中的并集+;
我一直在为硬件外设开发软件驱动程序,这些硬件外设是在上的现场可编程门阵列中实现的。我一直使用C++编程语言和ARM无EABI GCC编译器。 其中一个外围设备具有以下寄存器映射C++ C+;中用于mcu寄存器映射的位字段中的并集+;,c++,embedded,bit-manipulation,unions,mcu,C++,Embedded,Bit Manipulation,Unions,Mcu,我一直在为硬件外设开发软件驱动程序,这些硬件外设是在上的现场可编程门阵列中实现的。我一直使用C++编程语言和ARM无EABI GCC编译器。 其中一个外围设备具有以下寄存器映射 Register Offset in bytes in Bits description respect to the base address ===============================================
Register Offset in bytes in Bits description
respect to the base address
========================================================================================
REGISTER_0 0x00 0-15
16-31
----------------------------------------------------------------------------------------
REGISTER_1 0x04 0-15
----------------------------------------------------------------------------------------
REGISTER_2 0x08 0-15
----------------------------------------------------------------------------------------
REGISTER_3 0x0C 0-15
16-31
----------------------------------------------------------------------------------------
CONTROL_REG 0x10 0: enable
1: reset
2: mask_00
3: mask_01
4: mask_02
5: mask_03
6: mask_04
7: mask_05
8: mask_06
9: mask_07
----------------------------------------------------------------------------------------
REGISTER_5 0x14 0-15
16-31
----------------------------------------------------------------------------------------
REGISTER_6 0x18 0-15
16
----------------------------------------------------------------------------------------
REGISTER_7 0x1C 0-15
16
----------------------------------------------------------------------------------------
REGISTER_8 0x20 0-31
----------------------------------------------------------------------------------------
对于寄存器控制_REG,我可以方便地同时使用单个掩码位和所有掩码位。所以我决定在位域中使用并集
int main(int argc, char** argv) {
struct ControlReg
{
uint32_t enable_bit: 1;
uint32_t reset_bit: 1;
union
{
struct
{
uint32_t bit_0: 1;
uint32_t bit_1: 1;
uint32_t bit_2: 1;
uint32_t bit_3: 1;
uint32_t bit_4: 1;
uint32_t bit_5: 1;
uint32_t bit_6: 1;
uint32_t bit_7: 1;
}bits;
uint8_t byte;
}mask;
};
ControlReg control_reg;
control_reg.mask.byte = 0xAA;
cout << "Mask bit 0: " << control_reg.mask.bits.bit_0 << endl;
cout << "Mask bit 1: " << control_reg.mask.bits.bit_1 << endl;
cout << "Mask bit 2: " << control_reg.mask.bits.bit_2 << endl;
cout << "Mask bit 3: " << control_reg.mask.bits.bit_3 << endl;
cout << "Mask bit 4: " << control_reg.mask.bits.bit_4 << endl;
cout << "Mask bit 5: " << control_reg.mask.bits.bit_5 << endl;
cout << "Mask bit 6: " << control_reg.mask.bits.bit_6 << endl;
cout << "Mask bit 7: " << control_reg.mask.bits.bit_7 << endl;
}
int main(int argc,char**argv){
结构控制寄存器
{
uint32启用位:1;
uint32重置位:1;
联盟
{
结构
{
uint32位0:1;
uint32位1:1;
uint32位2:1;
uint32位3:1;
uint32位4:1;
uint32第5位:1;
uint32位6:1;
uint32位7:1;
}比特;
uint8_t字节;
}面具;
};
ControlReg CONTROLU reg;
control_reg.mask.byte=0xAA;
寄存器真的可以有一个位,另一个位,然后是8位大小的吗?这就是所显示的代码所描述的,我对此表示怀疑。事实上,您在您的环境中成功地测试了它,这意味着我会信任在该环境中使用它,就像我信任测试它一样(即,可能足够了).但出于可读性目的(即,以人类为目标,而不是以编译器、链接器为目标)我会更改表示。如果您愿意,并且您提供了有关寄存器的足够详细信息,我可以在回答中提出一个替代方案。您的MCU供应商和/或编译器供应商通常会提供一个定义了寄存器和位域访问的头。我强烈建议您使用特定于工具链的头,因为位域排序和打包是由实现定义的,因为定义您自己的代码并引入您自己的错误与使用更多开发人员验证和使用的代码相比没有任何实际好处。上述操作可能会产生您期望的输出,但您的代码实际上并没有将control\u reg
分配给任何物理设备cal寄存器-您如何知道它精确地覆盖了寄存器-编译器如何打包和对齐位字段取决于实现。在任何情况下,这都是一个X-Y问题。告诉我们MCU是什么,可能会提出一个不同的更合适的解决方案。@Clifford感谢您的反应。我一直在为peri开发驱动程序在现场可编程门阵列中实现的pherals。因此,我没有支持的头文件。我将使用placement new构造将控制\u reg分配给物理寄存器。我看不出该并集如何工作。字节成员无法与较大类型的位2到9对齐。