#define StartAdc() ADCSRA |= (1<<ADSC)
…
InitAdc(); //обычная функция
StartAdc(); //макрос
Но что делать, если макрос состоит из двух и более инструкций?
#define StartAdc() ADCSRA |= (1<<ADSC); \
asm(“sei”)
В общем случае, можно вызывать этот макрос как обычно.
StartAdc();
Препроцессор заменит макроопределение и точка с запятой окажется после второй строчки.
ADCSRA |= (1<<ADSC);
asm(“sei”);
Но что произойдет, если мы используем макрос там, где ожидается только одна инструкция?
if( … )
StartAdc();
Препроцессор заменит это на
if( … )
ADCSRA |= (1<<ADSC);
asm(“sei”);
Первая строчка макроопределения станет телом оператора if, а вторая в него не попадет, и будет выполняться всегда.
Можно ограничить определение макроса фигурными скобками {}
#define StartAdc() {ADCSRA |= (1<<ADSC); asm(“sei”);}
if( … )
StartAdc();
Препроцессор заменит это на
if( … )
{ADCSRA |= (1<<ADSC); asm(“sei”);};
На помощь приходит оператор do{…}while().
Определяем макрос следующим образом:
#define StartAdc() do{ADCSRA |= (1<<ADSC); asm(“sei”);}while(0)
И вуаля…
if(…)
StartAdc();
else
…
Препроцессор заменит этот макрос и точка с запятой окажется на вполне законном месте – после оператора while.
if(…)
do{ADCSRA |= (1<<ADSC); asm(“sei”);}while(0);
else
#define StartAdc() ADCSRA |= (1<<ADSC); \
asm(“sei”)
if( … ){
StartAdc();
}
Препроцессор заменит это на
if( … ){
ADCSRA |= (1<<ADSC);
asm(“sei”);
}
Comments
и все. Заодно и макрос от функции будет легко отличить.
Code:
#define StartAdc() (ADCSRA |= 1<<ADSC, asm(“sei”))
Ну и что что 5 лет прошло!))
В 80% случаев с ними надобно бороться.
Создал что-то подобное для нескольких своих внутренних переменных. Хотел иметь словные переменные типа unsigned int с возможностью доступа к отдельным байтам и битам.
В полном соответствии с требованиями языка СИ, декларировал объединение, а в нем структуры. Поскольку декларация объединения общая для нескольких переменных, она должна быть именованной. Также структуры должны быть именованными, иначе транслятор Вас не понимает.
Но теперь в описание моих переменных через точку добавляется имя структуры.
Удалить "лишнее имя" удается только путем декларации макроса, аналогичного макросу для SFR.
Если глянуть на любой из файлов с описанием фирменного драйвера (модуля нижнего уровня) обеспечивающего управление, например, SFR регистрами АЦП, большая часть функций этого уровня описана в виде макросов. Каждая из таких функций после трансляции превращается в одну или несколько строчек ассемблерного кода. Поэтому макросы тут - любимый прием.
И то, что Вы рассмотрели в приведенной выше статье - это только верхушка айсберга под названием #define, на который опирается вся система программировани я для встраиваемых систем.
RSS feed for comments to this post