2016-04-17 58 views
5

问题

为微控制器编程可重复使用的模块(在我的情况下是AVR)需要在通用IO引脚上具有灵活性。每个引脚由一个字母(A-G)和一个数字(0-7)定义。然而,它由三个寄存器中的相同位置的一位控制。因此,配置文件需要包含4个条目(3个指向寄存器+ 1位置的指针),这不是那么优雅。C:通过一个#define传递两个逗号分隔值

简单的解决方法是简单地接受这一点,但由于它是如此普遍的问题,至少应该引起一点关注。


理念

这将是很好,让预编译器做这样的重复性工作:

//CONFIGURATION 
#define IO_NAME B5 

//MACRO 
#define PORT_(ID) 
#define PIN_(ID) 
#define DDR_(ID) 
#define BIT_(ID) 

结果应该是这样的

PORT_(IO_NAME) => PORTB 
PIN_(IO_NAME) => PINB 
DDR_(IO_NAME) => DDRB 
BIT_(IO_NAME) => 5 

结果表达式在AVR Studio中定义。


我已经试过

我无法弄清楚如何忽略无论是字母而不是数字,所以我尝试concatention代替:

#define PORT_(REG, BIT)    PORT_2(REG, BIT) 
#define PIN_(REG, BIT)    PIN_2(REG, BIT) 
#define DDR_(REG, BIT)    DDR_2(REG, BIT) 

#define PORT_2(REG, BIT)   (PORT ## REG) 
#define PIN_2(REG, BIT)    (PIN ## REG) 
#define DDR_2(REG, BIT)    (DDR ## REG) 

#define BIT(REG, BIT)    (BIT) 

额外的层需要使用任何#defined值作为REG或BIT。

下面的代码按预期工作:

#define IO_NAME_REG B 
#define IO_NAME_BIT 5 

PORT_(B, 5)       => PORTB 
PORT_(IO_NAME_REG, IO_NAME_BIT)  => PORTB 


当我尝试但

#define IO_NAME B, 5 
PORT_(IO_NAME) 

它导致错误:

macro "PORT_" requires 2 arguments, but only 1 given 

据我所知,逗号被解释为逗号运算符,因此左值将被忽略。我总结这个从这个实验:

#define comma , 
#define IO_NAME B comma 5 
PORT_(IO_NAME,)      => PORT_5 

导致同样的结果


解决方法

#define IO_NAME B, 5 
PORT_(IO_NAME,)      => PORT_5 


与定义更换逗号

当然,可以将'B'和'5'分成两个独立的定义。虽然这是对四个定义的改进,但它仍然不够舒适。


问题

...是不是stricly局限于称号。任何解决方案比

#define IO_NAME_REG B 
#define IO_NAME_BIT 5 
PORT_(IO_NAME_REG, IO_NAME_BIT)  => PORTB 

是欢迎我。

如果这是不可能的,我想知道原因。

回答

1

这应该做你想要什么:

#include <stdio.h> 

#define IO_NAME B, 5 

#define PORT_(arg) PORT_2(arg) 
#define PIN_(arg) PIN_2(arg) 
#define DDR_(arg) DDR_2(arg) 
#define BIT_(arg) BIT_2(arg) 

#define PORT_2(reg, bit) (PORT ## reg) 
#define PIN_2(reg, bit)  (PIN ## reg) 
#define DDR_2(reg, bit)  (DDR ## reg) 
#define BIT_2(reg, bit)  (bit) 

#define PORTB 1 
#define PINB 2 
#define DDRB 3 

int main() 
{ 
    printf("%d\n", PORT_(IO_NAME)); 
    printf("%d\n", PIN_(IO_NAME)); 
    printf("%d\n", DDR_(IO_NAME)); 
    printf("%d\n", BIT_(IO_NAME)); 

    return 0; 
} 

这将产生以下的输出:

1 
2 
3 
5 

宏机构##使预处理器通过连接操作数来创建新的令牌。

这几乎是你所拥有的。不同之处在于您的顶级宏需要采用单个参数,而次级宏需要两个宏。

+0

当您想要手工指定它们时,如'PORT_(B,5)',不起作用。 – Leandros

+0

@Leandros除非我误解OP的帖子,那不是目标。但是,如果是这样,那么可以使用次要宏。 –

+0

这个问题有很多解释空间,这是真的。 – Leandros

0

您可以使用可变参数宏代替,只需更改即可实现目标。

#define PORT_(...)    PORT_2(__VA_ARGS__) 
#define PIN_(...)    PIN_2(__VA_ARGS__) 
#define DDR_(...)    DDR_2(__VA_ARGS__)