c++ 将枚举类与std::bitset一起使用并组合位集

djmepvbi  于 2023-03-20  发布在  其他
关注(0)|答案(1)|浏览(139)

我正在尝试编写一个与器件(ADS 1115)进行I2C通信的代码。通信使用不同的位数组来执行命令和发送数据,其中大多数位或位组具有不同的含义。因此,我做了我想到的自然事情,编写了如下的枚举类:

enum class latching_comparator : bool
{
    non_latching= false,    //default
    latching    = true
};
enum class comparator_polarity : bool
{
    low = false,        //default
    high= true
};

我知道我可以从8位和16位实体的uint8_t和uint16_t派生枚举类,但我不需要它们,我需要的是2位和3位实体,但我不能这样做:

typedef std::bitset<2> twobits;
enum class comperator : twobits
{
...
}

有没有一种方法可以像这样对位进行分组,并使编写进一步的代码变得容易?有没有一种方法可以用这种方法合并并恢复位/位组?
也欢迎提出任何其他方法的建议。

b4lqfgs4

b4lqfgs41#

你可以在一个结构体中使用位宽来完成这个任务,根据你的操作,你可能需要使用#pragma pack来解决对齐问题。

enum class latching_comparator : bool
{
    non_latching= false,    //default
    latching    = true,
};

enum class comparator_polarity : bool
{
    low = false,        //default
    high= true,
};

#pragma pack(push, 1)  
typedef struct
{
    comparator_polarity polarity        : 1;
    latching_comparator latching        : 1;
    uint8_t test                        : 3;
} comparator_t;
#pragma pack(pop)

这意味着结构体中的每个枚举只使用1位。测试成员使用3位,可以是3位值或标志成员,只是作为示例。这将只为两个枚举使用一个字节。技术上它只使用5位,但8位arch技术上不能更低,所以您总是使用至少8位。如果您在结构体中使用9位,它将使用2个字节,因为您移动到另一个字节中用于第9位。

std::cout << sizeof(comparitor_t) << std::endl;

将打印1,因为它只使用一个字节来完成此操作。
我没有读过你要接口的硬件的文档,但是最好围绕你要配置的寄存器来设计整个结构体。寄存器中的每个配置的位宽会有所不同,但是通常我为每个寄存器编写一个结构体,操作结构体,然后我只需要将结构体的字节直接输出到通信接口中,而不需要位移位等麻烦。
编辑:今天我感觉很慷慨,所以这里有一些代码来处理芯片的配置寄存器(阅读或写)。寄存器中有更多的配置,所以你仍然需要完成它,但它给了你一个直接的例子,我在谈论什么。

typedef enum
{
    ADS115_CONFIG_COMP_QUE_ASSERT_ONE           = 0b00,
    ADS115_CONFIG_COMP_QUE_ASSERT_TWO           = 0b01,
    ADS115_CONFIG_COMP_QUE_ASSERT_FOUR          = 0b10,
    ADS115_CONFIG_COMP_QUE_ASSERT_DISABLE       = 0b11
} ads115_config_comp_que_t;

typedef enum
{
    ADS115_CONFIG_COMP_LAT_NONLATCHING          = 0b0,
    ADS115_CONFIG_COMP_LAT_LATCHING             = 0b1
} ads115_config_comp_lat_t;

typedef enum
{
    ADS115_CONFIG_COMP_POL_ACTIVE_LOW           = 0b0,
    ADS115_CONFIG_COMP_POL_ACTIVE_HIGH          = 0b1,
} ads115_config_comp_pol_t;

typedef enum
{
    ADS115_CONFIG_COMP_MODE_TRADITIONAL         = 0b0,
    ADS115_CONFIG_COMP_MODE_WINDOW              = 0b1
} ads115_config_comp_mode_t;

typedef enum
{
    ADS115_CONFIG_DR_8_SPS                      = 0b000,
    ADS115_CONFIG_DR_16_SPS                     = 0b001,
    ADS115_CONFIG_DR_32_SPS                     = 0b010,
    ADS115_CONFIG_DR_64_SPS                     = 0b011,
    ADS115_CONFIG_DR_128_SPS                    = 0b100,
    ADS115_CONFIG_DR_250_SPS                    = 0b101,
    ADS115_CONFIG_DR_475_SPS                    = 0b110,
    ADS115_CONFIG_DR_860_SPS                    = 0b111,
} ads115_config_dr_t;

typedef enum
{
    ADS115_CONFIG_MODE_CONTINUOUS               = 0b0,
    ADS115_CONFIG_MODE_ONESHOT                  = 0b1,
} ads115_config_mode_t;

#pragma pack(push, 1)
typedef struct
{
    ads115_config_comp_que_t comp_que           : 2;
    ads115_config_comp_lat_t comp_lat           : 1;
    ads115_config_comp_pol_t comp_pol           : 1;
    ads115_config_comp_mode_t comp_mode         : 1;
    ads115_config_dr_t dr                       : 3;
    ads115_config_mode_t mode                   : 1;
    // @TODO: other configurations
} ads115_reg_config_t;
#pragma pack(pop)

相关问题