Продвинутое препроцессор токенизации в C - PullRequest
1 голос
/ 16 апреля 2011

У меня проблема с построением макроса C для моего PIC.То же самое относится и к другим системам на основе C, поэтому эксперты, не относящиеся к PIC C , также приветствуются.

Предположим, что я определил свой вывод LED_1:

#define LED_1 A1    //A1 as output for LED_1

Поэтому, если я хочу зажечь светодиод, я написал бы:

PORTAbits.RA1 = 1;

И если я хотел бы сделать это, используя мое определение LED_1, я должен добавить еще два макроса:

#define change_PORT_(var) PORTAbits.R##var
#define change_PORT(var) change_PORT_(var

И чтобы использовать это:

change_PORT(LED_1) = 1;

И это работает как шарм.Но проблема в том, что в приведенных выше определениях у меня есть

PORT A бит. ## var

Так что, если я хочу изменить значения PORTB?Мне пришлось бы создавать отдельные макросы для портов A и B. Но это даже близко не является надежным решением.И у меня возникла идея, которая, я не знаю почему, не работает.

#define LED_1 A1
#define LED_2 B1

#define __A1 A   //This would be defined for all PORTA's pins such as A2,A3,A4 etc
#define __B1 B

#define ___change_PORT(var,var2)    PORT##var2 bits.R##var
#define __change_PORT(var,var2)   ___change_PORT(var,var2)
#define _change_PORT(var)    __change_PORT(var,__##var) // creating e.g. __A1
#define change_PORT(var)   _change_PORT(var)

И когда я пытаюсь запустить это:

change_PORT(LED_1);

Компилятор меняется __ ## var до ___ A1 , но никогда не меняется __ A1 на A , поэтому этот MACRO не работает так, как предполагалось.

Я потратил много времени, пытаясь это исправить, поэтому буду признателен за любую помощь :)


EDIT ::


Возможно, я нашел решение своей проблемы:
(LAT - это просто другое имя регистра, но оно работает так же, как PORT, поэтому это изменение имени не имеет значения)

#define ___PORTchange(var,var2) PORT##var2##bits.R##var
#define __PORTchange(var,var2)  ___PORTchange(var,var2)
#define CHANGE_TO_PORT_NAME(var) ___##var
#define _PORTchange(var)    __PORTchange(var,CHANGE_TO_PORT_NAME(var))
#define PORTchange(var) _PORTchange(var)

но я получаю ошибку компилятора:

100: PORTAbits.RA0 = 1;
^ (374) отсутствует базовый тип;int предположил (предупреждение)
^ (983) переопределен класс хранения
^ (984) переопределен тип
^ (239) идентификатор "PORTAbits" переопределен (из строки 3900)
^ (314) ";"ожидаемый

Так что нет, он заменяет его правильно, но я получаю предупреждение компилятора, говорящее мне, что я переопределяю PORTAbits, которые я не могу понять.Я просто хотел, чтобы препроцессор изменил PORTchange (var) на PORTxbits.Rvar , где x - это A или B. Но вместо этого мне кажется, что я что-то переделал.

Я не понимаю.

1 Ответ

2 голосов
/ 16 апреля 2011

Если я препроцессирую (пробовал с несколькими версиями gcc и sun cc)

#define LED_1 A1
#define LED_2 B1

#define __A1 AX
#define __B1 BX

#define ___change_PORT(var,var2)    PORT##var2##bits.R##var
#define __change_PORT(var,var2)   ___change_PORT(var,var2)
#define _change_PORT(var)    __change_PORT(var,__##var)
#define change_PORT(var)   _change_PORT(var)

change_PORT(LED_1);
change_PORT(LED_2);

Я получаю

PORTAXbits.RA1;
PORTBXbits.RB1;

что, очевидно, то, что вы хотите. Ошибка в вашем компиляторе?

...