C - 使用枚举作为位标志 - 警告:枚举类型与另一种类型混合

Eli*_*ron 6 c enums arm bitflags keil

我将枚举常量作为位标志传递给期望枚举类型作为输入的函数,如下所示:

// Enumeration type
typedef enum
{
    LED_RED    =        (1 << 0),
    LED_GREEN  =        (1 << 1),
    LED_YELLOW =        (1 << 2),
    LED_ORANGE =        (1 << 3),
} LedType;

...

// Function declaration
void setOnLed(LedType led);

...

// Function call
setOnLed(LED_RED | LED_GREEN | LED_YELLOW);
Run Code Online (Sandbox Code Playgroud)

当我调用该函数时,我收到一条警告:

警告:#188-D:枚举类型与另一种类型混合

警告是因为LED_RED | LED_GREEN | LED_YELLOW转换为整数而不是LedType.

我可以通过在LedType枚举中添加 LED 组合来避免警告,但这意味着我必须添加所有可能的组合……如果我向 中添加更多 LED 选项enum,它会变得非常混乱……

我可以使用数组作为函数的输入,但是在调用函数时需要更多的代码,我更喜欢简单的函数调用来设置 LED。

我正在使用 Keil µVision IDE 对基于 ARM 的微控制器 (STM32) 进行编程。

我的问题

是否有一种简单安全的方法来避免此警告或另一种方法将所有 LED 封装在一个有意义的类型/对象中,以便我可以轻松地将它们传递给函数并在循环中处理它们?


完整的故事

我正在为连接到多个 LED 的基于 ARM 的 MCU 编写程序。在程序的许多地方,我们将打开/关闭、切换和闪烁 LED 的不同组合。为了使这个干净和简单,我想编写几个函数,将 LED 的任意组合作为输入,并对所有函数执行相同的操作。

我创建了一个带有 LED 硬件配置的struct命名LedConfig,以及一个LedConfig包含每个 LED 配置的数组:

typedef struct
{
    // Hardware configurations of a LED
    ...
} LedConfig;

...

LedConfig LedArry[LEDS_LED_COUNT] = 
{
    [0] = { /* Red LED config    */ }, 
    [1] = { /* Green LED config  */ }, 
    [2] = { /* Yellow LED config */ }, 
    [3] = { /* Orange LED config */ }
};

Run Code Online (Sandbox Code Playgroud)

现在,我想要一种简单的方法来将几个 LED 传递给一个函数并循环处理它们。

我为每个 LED 创建了许多位标志:

// Number of LED's defined in the system
#define LED_COUNT           4

// LED flags, for usage in LED's function
#define LED_RED             (1 << 0)
#define LED_GREEN           (1 << 1)
#define LED_YELLOW          (1 << 2)
#define LED_ORANGE          (1 << 3)
Run Code Online (Sandbox Code Playgroud)

定义一个函数:

void setOnLed(uint32_t led)
{
    uint32_t bitMask = 1;
    for(int i = 0; i < LED_COUNT; i++)
    {
        if(led & bitMask)
        {
            LedConfig* ledConfig = &LedArry[i];
            // Turn on LED ...
        }
        bitMask <<= 1;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我可以通过按位或操作将 LED 传递给函数:

setOnLed(LED_RED | LED_GREEN | LED_YELLOW);
Run Code Online (Sandbox Code Playgroud)

这工作正常,但是...

我更愿意enum为 LED 标志使用一个而不是定义,以便将主题封装在一个有意义的类型/对象中。

我用枚举替换了定义:

typedef enum
{
    LED_RED    =        (1 << 0),
    LED_GREEN  =        (1 << 1),
    LED_YELLOW =        (1 << 2),
    LED_ORANGE =        (1 << 3),
} LedType;
Run Code Online (Sandbox Code Playgroud)

并修改setOnLed函数输入以获取枚举类型:

void setOnLed(LedType led)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

当我用几个 LED 调用函数时:

setOnLed(LED_RED | LED_GREEN | LED_YELLOW);
Run Code Online (Sandbox Code Playgroud)

我收到警告:

警告:#188-D:枚举类型与另一种类型混合

注意uint32_t来自stdint.h并且是一个无符号的 32 位整数。