2016-04-17 64 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__)