【问题标题】:How to combine #define macros in c++?如何在 C++ 中组合#define 宏?
【发布时间】:2020-09-26 02:27:35
【问题描述】:

我知道,上面有很多帖子,但我还是不明白。 我想用#define 简化对微控制器的端口处理。通常你会这样做

DDRA |= (1 << PORTA0)  // set pin 0 at port A as OUTPUT
PORTA |= (1 << PORTA0) // set pin 0 at port A

“PORTA”、“DDRA”和“PORTA0”是 avr/io.h 扩展为数字的宏。

目前我喜欢这样:

// pinControl.h
#define setPin(port, pin)       (port |= (1 << pin))
#define setOutput(ddr, pin)     (ddr |= (1 << pin))

// some other file.h
#define myPinPort  PORTA
#define myPinDDR   DDRA
#define myPin      PORTA0

setOutput(myPinDDR, myPin)
setPin(myPinPort, myPin)

现在,如果端口更改并且我有很多引脚,我需要始终将每个 DDRA 和 PORTA 更改为例如到 DDRB 和 PORTB。 我想像这样简化它:

// pinControl.h
#define stringify1(x)   #x
#define stringify(x)    stringify1(x)

#define setPin(port, pin)      (stringify(PORT)##port |= (1 << stringify(PORT)##port##pin))
#define setOutput(port, pin)   (stringify(DDR)##port |= (1 << stringify(PORT)##port##pin))


// some other file.h
#define myPinPort   A
#define myPin       0

setOutput(myPinPort, myPin); // shall expand to "DDRA |= (1 << PORTA0)";
setPin(myPinPort, myPin);    // shall expand to "PORTA |= (1 << PORTA0);"

我真的对得到这个结果的语法感到困惑:(:(

【问题讨论】:

    标签: po


    【解决方案1】:

    stringify 操作是死路一条,一旦将某些内容转换为字符串,就无法将其恢复为标识符名称的一部分。

    由于您希望避免生成像 PORTmyPinPort 这样的标识符,因此您需要预处理器进行额外的评估级别,将 myPinPort “解压缩”到 A 中。对此的常用策略是定义一个仅返回其参数值的VALUE 宏,但在扩展该VALUE 宏的过程中,该参数也被扩展。

    现在对于令牌粘贴,由于评估顺序,该方法不起作用,因此另一种常见的方法是在另一个宏中进行令牌粘贴,通常命名为 PASTE

    从记忆中,我认为标准说为两个以上的标记粘贴标记是未指定的或可能未定义的,因此更正确的方法可能是嵌套 PASTE2 调用,但在测试 PASTE3 时有效。可能是 gcc 扩展。

    以下测试代码为 f1 和 f2 生成完全相同的汇编代码。

    int PORTA;
    int DDRA;
    int PORTA0;
    
    #define VALUE(v_) v_
    #define PASTE2(a_, b_) a_##b_
    #define PASTE3(a_, b_, c_) a_##b_##c_
    
    #define setPin(port, pin)      PASTE2(PORT, port) |= (1 << PASTE3(PORT, port, pin))
    #define setOutput(port, pin)   PASTE2(DDR, port) |= (1 << PASTE3(PORT, port, pin))
    
    #define myPinPort   A
    #define myPin       0
    
    void f1()
    {
        setPin(myPinPort, myPin);
        setOutput(myPinPort, myPin);
    }
    
    void f2()
    {
        PORTA |= (1 << PORTA0);
        DDRA |= (1 << PORTA0);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多