2012-02-05 45 views
4

我正在使用帶有ANSI C(gcc;不是C++)的微控制器,並且有很多硬件引腳可供定義。我正在尋找一種方法來使引腳定義更具可讀性。用於定義符號的C宏

我想我會一個宏,將讓我在單行定義每個引腳,像這樣:

PIN(LED_RED, E, 2); 
PIN(LED_YELLOW, B, 3); 
PIN(LED_GREEN, A, 4); 

(這只是一個簡單的例子 - 我有幾十個針腳的定義)。 現在我有難看這樣的代碼:

#define LED_RED   (LATEbits.LATE2) 
#define LED_RED_TRIS  (TRISEbits.TRISE2) 

#define LED_YELLOW  (LATBbits.LATB3) 
#define LED_YELLOW_TRIS (TRISBbits.TRISB3)  

#define LED_GREEN   (LATAbits.LATA4)  
#define LED_GREEN_TRIS (TRISAbits.TRISA4) 

每個引腳都有2個符號;一個讀/寫引腳,另一個設置I/O方向(_TRIS定義)。鎖存器和TRIS定義來自MCU供應商提供的頭文件庫;避免使用它們並不實際。

我相當肯定有可能在C中編寫一個宏來定義這兩個符號,但我對#和##的東西不是很好。這是我的一半嘗試(不起作用):

#define _PIN(id,port,pos) #define ##id (LAT ##port ##bits.LAT ##port ##pos) 
#define _TRIS(id,port,pos) #define ##id _TRIS (TRIS ##port ##bits .TRIS ##port ##pos) 
#define PIN( id,port,pos) _PIN(id,port,pos) _TRIS(id,port,pos) 

有沒有辦法做到這一點?

或者,有沒有另一種方法來簡化我的引腳定義?我想把它弄到一行/每針,並擺脫端口ID(A,B,C等)和位數(2,3,4等)的重複,我有現在;把他們兩次只是要求麻煩。

乾杯,

--Dave

+1

你能澄清你的宏的所有參數會做什麼嗎?現在我不明白預期的行爲應該是什麼。 – templatetypedef 2012-02-05 01:42:29

+2

一個宏不能定義其他的宏。但也許你的問題可以在不同的層面上簡化? – 2012-02-05 01:46:13

+0

當然。第一個參數(例如:「LED_RED」)用於定義兩個符號;一個稱爲「LED_RED」,另一個稱爲「LED_RED_TRIS」(通過追加「_TRIS」)。第二個和第三個參數被替換爲宏替換字符串以形成「LATEbits」。LATE2「(其中E和2來自參數) – 2012-02-05 01:47:10

回答

4

你無法定義的宏宏,但你可以做一些其他技巧。

這是在「相當醜陋的宏觀」領土。

#define MY_CAT(x, y) x ## y 
#define MY_CAT2(x, y) MY_CAT(x, y) 
#define LED(x) (MY_CAT2(MY_CAT2(LAT, PORT_ ## x), bits) \ 
       .MY_CAT2(LAT, MY_CAT2(PORT_ ## x, POS_ ## x))) 

#define PORT_RED E 
#define POS_RED 2 
#define PORT_YELLOW B 
#define POS_YELLOW 3 
#define PORT_GREEN A 
#define POS_GREEN 4 

LED(RED) 
LED(YELLOW) 
LED(GREEN) 

擴展(與gcc -E檢查)是:

(LATEbits .LATE2) 
(LATBbits .LATB3) 
(LATAbits .LATA4) 

只是因爲宏是你的錘子並不意味着這是一個釘子。嘗試用Python或其他東西來生成源代碼,更好。

LEDS = [ 
    ('RED', 'E2'), 
    ('YELLOW', 'B3'), 
    ('GREEN', 'A4'), 
] 
for name, pos in LEDS: 
    print '#define LED_%s (LAT%sbits.LAT%s)' % (name, pos[0], pos) 
    print '#define LED_%s_TRIS (TRIS%sbits.TRIS%s)' % (name, pos[0], pos) 

輸出是:

#define LED_RED (LATEbits.LATE2) 
#define LED_RED_TRIS (TRISEbits.TRISE2) 
#define LED_YELLOW (LATBbits.LATB3) 
#define LED_YELLOW_TRIS (TRISBbits.TRISB3) 
#define LED_GREEN (LATAbits.LATA4) 
#define LED_GREEN_TRIS (TRISAbits.TRISA4) 

那你先走一步,同時檢查腳本,它的輸出到您的版本控制系統。

附錄:我不打算解釋宏觀把戲是如何工作的,因爲我不想很好地學習這個技巧來解釋它。

+0

感謝您的回覆。不幸的是,解決方案只是將複雜度從「LED(紅色)」行移動到了#defines(並且大多數引腳不是LED指示燈 - 它們是開關,輸入和輸出等)如果有的話,我認爲這個結果的可讀性比我開始的要低,但是如何使用##的例子很有價值 - 這是我的感謝。我將看看這個外部預處理器。 – 2012-02-05 15:56:52