Макрос C для определения символов - PullRequest
4 голосов
/ 05 февраля 2012

Я работаю с микроконтроллером с ANSI C (gcc; не 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 символа;один для чтения / записи вывода, а другой для задания направления ввода / вывода (определения _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)

Есть ли способ сделать это?

Или, есть ли другой способ упростить мои определения выводов?Я хотел бы получить его до одной линии / вывода и избавиться от дублирования идентификатора порта (A, B, C и т. Д.) И номера бита (2,3,4 и т. Д.), Которые у меня естьсейчас;ставить их вдвое - это просто напрашиваться на неприятности.

Приветствия,

- Дейв

1 Ответ

4 голосов
/ 05 февраля 2012

Вы не можете определять макросы в макросах, но вы можете делать некоторые другие трюки.

Это на территории "довольно некрасивых макросов".

#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)

Затем вы просто продолжаете и проверяете как скрипт, так и его вывод в свойСистема контроля версий.

Приложение: Я не собираюсь объяснять, как работает макрос трюк, потому что я не хочу изучать трюк достаточно хорошо, чтобы объяснить его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...