Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Сложная автозамена через #define
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
kolobochishe
Пример:

сейчас

Код
// Запись значений по указателям
*pTIMER7_PERIOD = 0x0000FFFF;
*pTIMER7_WIDTH = 0x00007FFF;


Как сделать такую запись через всего 1 дефайн? Т.к. текст TIMER7 есть во всех
именах регистров, то, наверно, их можно заменить одним дефайном?

Код
#define BKLT_TIMER TIMER7

*pBKLT_TIMER_PERIOD = 0x0000FFFF;
*pBKLT_TIMER_WIDTH = 0x00007FFF;


и т.д. Что нужно дополнительно сделать, чтобы такая замена работала?
SSerge
Цитата(kolobochishe @ Dec 9 2015, 15:59) *
и т.д. Что нужно дополнительно сделать, чтобы такая замена работала?

Так не получится, потому что pBKLT_TIMER_WIDTH для препроцессора уже одна неделимая лексема и всё что он может с ней сделать разве что заменить целиком.
Удобнее подход, когда набор из четырёх регистров таймера описывается как структура. Тогда TIMER7 можно описать как указатель на такую структуру, а к регистрам обращаться как TIMER7->PERIOD.
Где-то так, по примеру CMSIS для кортексов и без учёта особенностей компилятора.
Код
#define     __IO    volatile
typedef struct{
__IO uint16_t CONFIG;
__IO uint32_t COUNTER;
__IO uint32_t PERIOD;
__IO uint32_t WIDTH;
}Timer_TypeDef;
#define TIMER0  ((Timer_TypeDef*)0xFFC01600)
...
#define TIMER7  (TIMER0+7)

#define BKLT_TIMER TIMER7
BKLT_TIMER->PERIOD = 0x0000FFFF;
BKLT_TIMER->WIDTH = 0x00007FFF;


jcxz
Цитата(kolobochishe @ Dec 9 2015, 14:59) *
*pBKLT_TIMER_PERIOD = 0x0000FFFF;
*pBKLT_TIMER_WIDTH = 0x00007FFF;[/code]
и т.д. Что нужно дополнительно сделать, чтобы такая замена работала?

#define concatABC_(a, b, c) a##b##c
#define concatABC(a, b, c) concatABC_(a, b, c)

#define TIMER TIMER7
*concatABC(p, TIMER, _PERIOD) = 0x0000FFFF;
kolobochishe
Цитата(SSerge @ Dec 9 2015, 17:33) *
...
Удобнее подход, когда набор из четырёх регистров таймера описывается как структура. Тогда TIMER7 можно описать как указатель на такую структуру, а к регистрам обращаться как TIMER7->PERIOD.
...


Было такое желание, но мне не хочется создавать лишние структуры. Хоть на нынешнем контроллере можно и истратить лишние байты, но все же, по-моему, лучше экономить память. Вдруг завтра на Attiny что-то придется делать rolleyes.gif


Цитата(jcxz @ Dec 15 2015, 18:48) *
#define concatABC_(a, b, c) a##b##c
#define concatABC(a, b, c) concatABC_(a, b, c)

#define TIMER TIMER7
*concatABC(p, TIMER, _PERIOD) = 0x0000FFFF;


Спасибо wink.gif правда непонятно как это работает...
Флюктуация ваккума
Нужно ипользовать вложенные макросы.
Т.е. вызов макроса в макросе.
Правда не все компиляторы поддерживают это.
Помнится AVR Studio поддерживала
barabek
Цитата(kolobochishe @ Dec 17 2015, 01:42) *
Было такое желание, но мне не хочется создавать лишние структуры. Хоть на нынешнем контроллере можно и истратить лишние байты, но все же, по-моему, лучше экономить память. Вдруг завтра на Attiny что-то придется делать rolleyes.gif

Ошибаетесь. При объявлении типа структуры память не расходуется. Зато читаемость кода лучше. И места для багов меньше. При доступе может быть код поболее будет, но не факт.
kolobochishe
Цитата(barabek @ Dec 17 2015, 03:18) *
Ошибаетесь. При объявлении типа структуры память не расходуется. Зато читаемость кода лучше. И места для багов меньше. При доступе может быть код поболее будет, но не факт.


Не. Я не про объявление, а про размер структуры. Иногда не все регистры у конкретного таймера необходимо использовать. А если уж мы создали переменную-структуру, то даже неиспользуемые поля будут место занимать.
barabek
Цитата(kolobochishe @ Dec 17 2015, 20:12) *
Не. Я не про объявление, а про размер структуры. Иногда не все регистры у конкретного таймера необходимо использовать. А если уж мы создали переменную-структуру, то даже неиспользуемые поля будут место занимать.

Нет. Опять не правы. Структура не создаётся. Определяется тип. Это информация только для компилера. Даже указатель на структуру не создается. Всего то что и происходит, это то, что мы говорим компилеру воспринимать цифру начального адреса как указатель на структуру. При обращении к полям структуры компилятор прибавляет к начальному адресу требуемое смещение. Так как и адрес и смещение известны на этапе компиляции, то компилятор скорее всего сразу рассчитает требуемый адрес регистра. Равносильно дефайну на этот регистр.
demiurg_spb
Цитата(kolobochishe @ Dec 17 2015, 13:12) *
Не...

Вам дело говорят. Посмотрите как это в avr-libc сделано.
barabek
Цитата(kolobochishe @ Dec 17 2015, 20:12) *
А если уж мы создали переменную-структуру, то даже неиспользуемые поля будут место занимать.

Добавлю. Поля структуры это регистры периферии (на сленге : поля замапены на регистры). Если вы какие-то поля (читай - регистры) не используете по прямому назначению, то как вы их еще можете использовать?
jcxz
Цитата(kolobochishe @ Dec 16 2015, 21:42) *
Спасибо wink.gif правда непонятно как это работает...

А что именно непонятно?
Как я понял: у Вас есть записи типа *pTIMER7_PERIOD = 0x0000FFFF; и Вы хотите, чтобы конкретный таймер можно было задать где в заголовке дефайном, типа
#define MY_TIMER TIMER7
и чтобы, при необходимости, можно было в одном месте поменять номер таймера не редактируя весь исходник. Это можно сделать макросами как я описал:
#define MY_TIMER TIMER7
...
*concatABC(p, MY_TIMER, _PERIOD) = 0x0000FFFF;

Если Вы хотели нечто другое, то формулируйте вопрос яснее.
kolobochishe
Цитата(jcxz @ Dec 18 2015, 13:16) *
А что именно непонятно?
...



Непонятно как эта двухуровневая конструкция работает wacko.gif Так то понятно, я это и хотел, но простая конкатенация с одним уровнем не работает. Компилятор сразу подставляет MY_TYMER вместо TIMER7

Цитата(barabek @ Dec 18 2015, 10:32) *
Добавлю. Поля структуры это регистры периферии (на сленге : поля замапены на регистры). Если вы какие-то поля (читай - регистры) не используете по прямому назначению, то как вы их еще можете использовать?


Бывают регистры, которые в таймере добавляют какой-то функционал. Например статус, маска прерываний. А мне нужен просто ШИМ выход для подсветки, без всяких статусов. Но это уже неважно. Я понял что никакой переменной-структуры не создается, а определение структуры нужно лишь для задания смещений относительно первого регистра конкретного таймера. Если они все расположены друг за другом (вроде других вариантов пока не встречал), то хороший метод
Флюктуация ваккума
Народ! Да выясните наконец подерживает компилятор топикстартера вложенные макросы или нет.
И вопрос будет решен. В ту или иную сторону. Однозначно.
Чего мы мучаетесь - не пойму. Проблема-то яйца выеденного не стоит
Herz
Цитата(Флюктуация ваккума @ Dec 18 2015, 16:01) *
Чего мы мучаетесь - не пойму. Проблема-то яйца выеденного не стоит

5 баллов. Действительно, чего Вы мучаемся? Скучно?
jcxz
Цитата(kolobochishe @ Dec 18 2015, 16:28) *
я это и хотел, но простая конкатенация с одним уровнем не работает. Компилятор сразу подставляет MY_TYMER вместо TIMER7

Для того и нужно два уровня, чтобы выполнялась подстановка значений заданных #define.
Dog Pawlowa
Цитата(kolobochishe @ Dec 18 2015, 13:28) *
Если они все расположены друг за другом (вроде других вариантов пока не встречал), то хороший метод

Я встречал, например у Freescale, но это очень просто решается - добавлением "резервных" полей, которые не используются.
GetSmart
В продолжение темы.
В исходниках V-USB часто встречаются макросы (дефайны) с одинаковыми именами/идентификаторами на входе и на выходе макроса. Как компиляторы относятся к этому и что говорит стандарт?

Если компилятору "случайно" второй раз применить этот макрос к результату этого же макроса, то получится билиберда.
AleksBak
Цитата(GetSmart @ Apr 28 2016, 21:28) *
В продолжение темы.
В исходниках V-USB часто встречаются макросы (дефайны) с одинаковыми именами/идентификаторами на входе и на выходе макроса. Как компиляторы относятся к этому и что говорит стандарт?

Если компилятору "случайно" второй раз применить этот макрос к результату этого же макроса, то получится билиберда.

Такие макросы сделаны для "удобства", но главное для улучшения читаемости кода. А применять в итоге их следует с осторожностью. Склейка и вложенные макросы могут по-разному работать у разных компиляторов т.к. не совсем стандартны.
k155la3
Если возникает сомнение в том
- как использовать макроподстановку
- как ОНО будет работать
следует подумать "а не подправить ли что в консерватории"

Для начала следовало бы (IMHO) убрать "повторы", например, то
что подлежит обработке через макрос переименовать в уникальное для данного проекта значение
например TIMER в TiMeR. Это вручную, внимательно - радактором по всему проекту
Сергей Борщ
QUOTE (AleksBak @ Apr 29 2016, 06:17) *
т.к. не совсем стандартны.
Про это можно подробнее? В Стандарте есть раздел 6.10.3.1 Argument substitution.
AleksBak
Цитата(Сергей Борщ @ Apr 29 2016, 10:23) *
Про это можно подробнее? В стандарте есть раздел 6.10.3.1 Argument substitution.

В смысле не все компиляторы могут поддержать. Это имел ввиду.
Сергей Борщ
QUOTE (AleksBak @ Apr 29 2016, 09:55) *
В смысле не все компиляторы могут поддержать. Это имел ввиду.
Если компилятор не выполняет требования Стандарта, то это компилятор "языка, похожего на Си", но никак не компилятор Си. Использовать такой компилятор просто не нужно и уж тем более нет смысла писать код с оглядкой на такие компиляторы.
ViKo
Про особенности #define еще Керниган с Ричи в своей книжке писали. Есть смысл ознакомиться. А компиляторы не при чем, они работают, как надо.
GetSmart
Цитата
The argument list is enclosed in parentheses and must immediately follow the macro name.


Вопрос о допустимости применения macro name в теле того же макроса. Argument substitution, если дословно, то из другой оперы. Очень может быть, что macro name в своём же теле таит какую-то граблю. К тому же, макросы можно переобъявлять. Но пока ещё глубоко не копался.

Язык похожий на Си - забавно. Как права, похожие на права человека. По-американски.
SSerge
Цитата(GetSmart @ May 3 2016, 23:39) *
Вопрос о допустимости применения macro name в теле того же макроса. Argument substitution, если дословно, то из другой оперы. Очень может быть, что macro name в своём же теле таит какую-то граблю. К тому же, макросы можно переобъявлять. Но пока ещё глубоко не копался.

А это раздел 6.10.3.4 Rescanning and further replacement.
В общем, рекурсия в макроопределениях не допускается, но как именно она не допускается - это место в С довольно тёмное, пример в том разделе отлично сносит крышу.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.