【问题标题】:Creating C macro: concatenate string and number创建 C 宏:连接字符串和数字
【发布时间】:2021-01-28 07:26:50
【问题描述】:

我想连接一个字符串和一个整数(枚举)来寻址嵌入式系统项目中的端口/引脚。 端口被命名:

M1_MS1_GPIO_Port
M2_MS1_GPIO_Port
M2_MS1_GPIO_Port

... 并且引脚被相应地命名

M1_MS1_GPIO_Pin
M2_MS1_GPIO_Pin
M2_MS1_GPIO_Pin

...

现在我想要一个获取数字并调用 GPIO_Write 函数的函数。 我尝试了类似的东西

#define SETMS1(NUMBER) (HAL_GPIO_WritePin(M##NUMBER##_GPIO_Port ...)

void set_MS1( int M )
{
   SETMS1( M );
}

但是 M 没有被解析为一个数字。有没有办法做到这一点?

【问题讨论】:

  • 几乎没有人在 SO 上发布此类问题,并设法为 GPIO 编写了一个合理的抽象层。所以我的建议只是不要 - 并且放弃ST bloatware。只需直接访问端口寄存器,这与 C 代码的可读性差不多,而且大多数添加抽象的尝试只会使代码变得更糟。
  • 同意@Lundin,与硬件相关的抽象倾向于使代码更便携,但也很臃肿。根据我的经验,这不值得,代码变得太棘手了。

标签: c macros concatenation preprocessor


【解决方案1】:

您可以在运行时“调用”宏函数。宏在编译时被扩展。

选项 1:

您使用switch 语句。

void set_MS1(int m)
{
    switch (m)
    {
    case 1:
        HAL_GPIO_WritePin(M1_MS1_GPIO_Port/*...*/);
        break;
    case 2:
        HAL_GPIO_WritePin(M2_MS1_GPIO_Port/*...*/);
        break;
    default:
        // if applicable, error handling
        break;
    }
}

选项 2:

您使用数组并索引端口和引脚。这只有在端口名称和引脚名称是常量时才有可能。

void set_MS1(int m)
{
    static const int ports[] =
    {
        0,
        M1_MS1_GPIO_Port,
        M2_MS1_GPIO_Port,
    };

    if (m >= 1 && m < sizeof ports / sizeof ports[0])
    {
        HAL_GPIO_WritePin(ports[m]/*...*/);
    }
    else
    {
        // if applicable, error handling
    }
}

最后说明:

我相信还有更多选择。只需查看其他资源并学习。我们都做到了。哦,实验!

【讨论】:

    最近更新 更多