Перейти к содержанию
    

Сложная автозамена через #define

Пример:

 

сейчас

 

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

 

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

именах регистров, то, наверно, их можно заменить одним дефайном?

 

#define BKLT_TIMER TIMER7

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

 

и т.д. Что нужно дополнительно сделать, чтобы такая замена работала?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

и т.д. Что нужно дополнительно сделать, чтобы такая замена работала?

Так не получится, потому что 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;

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

*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;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

Удобнее подход, когда набор из четырёх регистров таймера описывается как структура. Тогда TIMER7 можно описать как указатель на такую структуру, а к регистрам обращаться как TIMER7->PERIOD.

...

 

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

 

 

#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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нужно ипользовать вложенные макросы.

Т.е. вызов макроса в макросе.

Правда не все компиляторы поддерживают это.

Помнится AVR Studio поддерживала

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Ошибаетесь. При объявлении типа структуры память не расходуется. Зато читаемость кода лучше. И места для багов меньше. При доступе может быть код поболее будет, но не факт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ошибаетесь. При объявлении типа структуры память не расходуется. Зато читаемость кода лучше. И места для багов меньше. При доступе может быть код поболее будет, но не факт.

 

Не. Я не про объявление, а про размер структуры. Иногда не все регистры у конкретного таймера необходимо использовать. А если уж мы создали переменную-структуру, то даже неиспользуемые поля будут место занимать.

Изменено пользователем kolobochishe

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не. Я не про объявление, а про размер структуры. Иногда не все регистры у конкретного таймера необходимо использовать. А если уж мы создали переменную-структуру, то даже неиспользуемые поля будут место занимать.

Нет. Опять не правы. Структура не создаётся. Определяется тип. Это информация только для компилера. Даже указатель на структуру не создается. Всего то что и происходит, это то, что мы говорим компилеру воспринимать цифру начального адреса как указатель на структуру. При обращении к полям структуры компилятор прибавляет к начальному адресу требуемое смещение. Так как и адрес и смещение известны на этапе компиляции, то компилятор скорее всего сразу рассчитает требуемый адрес регистра. Равносильно дефайну на этот регистр.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не...

Вам дело говорят. Посмотрите как это в avr-libc сделано.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А если уж мы создали переменную-структуру, то даже неиспользуемые поля будут место занимать.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо ;) правда непонятно как это работает...

А что именно непонятно?

Как я понял: у Вас есть записи типа *pTIMER7_PERIOD = 0x0000FFFF; и Вы хотите, чтобы конкретный таймер можно было задать где в заголовке дефайном, типа

#define MY_TIMER TIMER7

и чтобы, при необходимости, можно было в одном месте поменять номер таймера не редактируя весь исходник. Это можно сделать макросами как я описал:

#define MY_TIMER TIMER7

...

*concatABC(p, MY_TIMER, _PERIOD) = 0x0000FFFF;

Если Вы хотели нечто другое, то формулируйте вопрос яснее.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А что именно непонятно?

...

 

 

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

 

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

 

Бывают регистры, которые в таймере добавляют какой-то функционал. Например статус, маска прерываний. А мне нужен просто ШИМ выход для подсветки, без всяких статусов. Но это уже неважно. Я понял что никакой переменной-структуры не создается, а определение структуры нужно лишь для задания смещений относительно первого регистра конкретного таймера. Если они все расположены друг за другом (вроде других вариантов пока не встречал), то хороший метод

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Народ! Да выясните наконец подерживает компилятор топикстартера вложенные макросы или нет.

И вопрос будет решен. В ту или иную сторону. Однозначно.

Чего мы мучаетесь - не пойму. Проблема-то яйца выеденного не стоит

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Чего мы мучаетесь - не пойму. Проблема-то яйца выеденного не стоит

5 баллов. Действительно, чего Вы мучаемся? Скучно?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...