2012-02-05 44 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