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

...объявить ногу в одном месте, и потом при необходимости в одном месте ее изменить - это гораздо удобнее и ошибкоустойчивее, чем во всем исходнике явно указывать порт и ногу.

 

тогда в *.h файле просто запишите (MCC30):

 

#define MyPin PORTB4 // (например)

 

и потом везде где вам нужно обращаться к PORTB4, будете писать MyPin. Если нужно изменить, будете менять только в хедере.

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


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

это шутка?
Нет, просто не обратил внимания, что он умеет работать с битовыми переменными и что ноги портов объявлены как битовые переменные. Поскольку я пользуюсь компиляторами, в которых нет такого расширения, и часто приходится таскать код между разными платформами - привык пользоваться стандартными конструкциями типа port |= (1 << bit); В случае с битовыми переменными-выводами портов переносимости можно добиться, обернув их в макросы #define on(pin) pin = 1. Возьму на заметку. Но МСС18 использовать все равно не буду - этот проект уже закончен в SDCC, а новых на пиках, надеюсь, не будет. А если и будут - SDCC уже освоен и к эклипсе прикручен.

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


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

Заманчиво, не знал.

Встроенные макросы для прямого побитного объявления портов и других SFR-ов есть и в компиляторах HTPICC, HTPIC18 для ПИКов. Пример:

#define pin_PFail       RB5
#define pin_1w_in       RE2
#define pin_1w_out      RA5

И в ИАРовских компиляторах, в частности IAR AVR 4.21. Пример:

#define poGreenLED      PORTB_Bit6
#define poRedLED        PORTB_Bit7

Вот цитата из файла iom128.h:

/* Examples of how to use the expanded result:
* TCCR2 |= (1<<5); 
* or if ENABLE_BIT_DEFINITIONS is defined   
* TCCR2 |= (1<<COM21);
* or like this:
* TCCR2_Bit5 = 1;
* or like this:
* TCCR2_COM21 = 1;
*/

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


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

И в ИАРовских компиляторах, в частности IAR AVR 4.21.
Да, вспомнил, что мне не понравилось в таком подходе - объявив таким образом конкретный пин, я могу с ним делать только два действия - on и off. А через свои чудо-макросы - on, off, читать, менять направление, читать направление и прочее. При использовании битовых полей универсальности не получается - невозможно будет сделать if(signal(SCLK)) { dir_out(SCLK); off(SCLK); } if(dir(SCLK) { on(SCLK); dir_in(SCLK); } - придется отдельно объявлять SCLK_PIN, SCLK_DIR, SCLK_OUT. В общем: если макросы дают больше удобств - зачем от них отказываться?

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


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

...

Да, к слову, нет ли под рукой ссылочки, где описывается макропроцессор с применением двойных ##.

Сложные макросы никогда не применял и до сих пор не понимаю значения ## :) , хотя они широко применяются в хидерах компиляторов.

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


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

Да, к слову, нет ли под рукой ссылочки, где описывается макропроцессор с применением двойных ##.
Гугля дает много ссылок по запросу "c preprocessor". Я обычно пользуюсь вот этой, разделы 3.4, 3.5

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


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

Гугля дает много ссылок по запросу "c preprocessor". Я обычно пользуюсь вот этой, разделы 3.4, 3.5

Спасибо, теперь буду знать умные слова stringification (#) и token pasting or token concatenation (##).

Раньше мне везде попадалось только описание Traditional macros, ISO макросы всеми замалчивались :)

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


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

Нет, просто не обратил внимания, что он умеет работать с битовыми переменными и что ноги портов объявлены как битовые переменные...

 

Знаете, это не совсем так... Это особенность адресации в майкрочиповских контроллерах - у них каждый пин (вообще бит SFR) имеет свой адрес, как регистр (напр. адрес PORTB4 = @PORTB + 4). Вот поэтому, объявляя "#define MyPin PORTB4", указываете препроцессору, что значение этикетки MyPin будет равно адресу пина PORTB4. Это все равно записать

 

          unsigned char* MyPin;
          MyPin = @PORTB4;// = @PORTB + 4

(только это уже будет переменная в памяти процессора)

 

Пользуясь подобными выражениями (#define ...), можете не только выставлять или обнулять данного пина, но и читать его состояние. Направление пина не можете менять, поскольку в ПИК-е этим обязан совсем другой регистр (TRIS).

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


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

Это особенность адресации в майкрочиповских контроллерах - у них каждый пин (вообще бит SFR) имеет свой адрес,
Это что-то новенькое. С х51 не путаете?

 

А существо вопроса в том, что в макросе я указываю не конкретный регистр (PORTx, TRISx, LATx), а имя порта (A, B, C) и уже внутри макроса из него получается имя нужного регистра в зависимости от необходимого действия. При использовании битовых полей такое невозможно.

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


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

Это что-то новенькое. С х51 не путаете?...

 

Нет не новенькое (наверно я не очень, так, объяснил). У х51 немножко по-другому. У них регистр направления порта нет. Что бы настроит на вход нужно просто на порт выставить 1. В ПИК-ах есть регистр направления - именно TRIS (конечно, это вам хорошо известно). Дело в том, что вы о макросах говорите, а та конструкция, о которой я - обыкновенная директива препроцессора. Объявление константы "MyPin" со значением "адрес PORTB4".

Мне, в принципе, макросы не нравятся, потому что они съедают програмную память. Но это стоит учитывать только на маленьких процессорах. Зато код выполняется (если пользуетесь макросами) быстрее.

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


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

Нет не новенькое (наверно я не очень, так, объяснил). У х51 немножко по-другому. У них регистр направления порта нет.
Это-то понятно. С каких пор у ПИКов каждый бит порта имеет свой адрес?

Мне, в принципе, макросы не нравятся, потому что они съедают програмную память.
Тоже чудеса рассказываете. Используемый мной (приведенный выше) макрос on(LED) преобразуется препроцессором(!) в С-выражение LATx |= ( 1<< bit), что, в свою очередь, компилируется в команду BSF LATx, bit. Где съедание памяти?

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


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

Это-то понятно. С каких пор у ПИКов каждый бит порта имеет свой адрес?

Тоже чудеса рассказываете. Используемый мной (приведенный выше) макрос on(LED) преобразуется препроцессором(!) в С-выражение LATx |= ( 1<< bit), что, в свою очередь, компилируется в команду BSF LATx, bit. Где съедание памяти?

чего-то он путает конечно =) Все там как обычно

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

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


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

Это особенность адресации в майкрочиповских контроллерах - у них каждый пин (вообще бит SFR) имеет свой адрес, как регистр (напр. адрес PORTB4 = @PORTB + 4). Вот поэтому, объявляя "#define MyPin PORTB4", указываете препроцессору, что значение этикетки MyPin будет равно адресу пина PORTB4

Ну, если так рассуждать, то любой бит регистрового файла в пределах одной страницы у ПИК-ов имеет уникальный адрес, состоящий из адресов байта+бита. Это поддерживается на уровне системы команд. Побитовая адресация части SFR-ов на уровне системы команд есть и у AVR и у MCS51 семейства.

 

Но на самом деле адрес регистра и адрес бита находятся в разных адресных пространствах и мешать их нельзя. В ANSI С нет операций с отдельными битами, поэтому разработчики компиляторов изголяются кто как может. Приведенный вами пример с PORTB4 это уже фича компилятора. Например, вот выдержка из мануала на HTPICC:

PICC supports bit integral types which can hold the values 0 or 1. The bit variable facility may be combined with absolute variable declarations (see page 153) to access bits at specific addresses. Absolute bit objects are numbered from 0 (the least significant bit of the first byte) up. Therefore, bit number 3 (the fourth bit in the byte since numbering starts with 0) in byte number 5 is actually absolute bit number 43 (that is 8bits/byte * 5 bytes + 3 bits).

 

For example, to access the power down detection flag bit in the RCON register, declare RCON to be a C

object at absolute address 03h, then declare a bit variable at absolute bit address 27:

 

static unsigned char RCON @ 0xFD0;

static near bit PD @ (unsigned)&RCON*8+2;

 

Note that all standard registers and bits within these registers are defined in the header files provided.

Поэтому, когда мы пишем PORTB4, мы используем встроенный макрос и просто даем прямую команду компилятору применить специфическую для данного процессора команду битовой адресации. В общем случае компилятор имеет право это не поддерживать.

 

Мне, в принципе, макросы не нравятся, потому что они съедают програмную память. Но это стоит учитывать только на маленьких процессорах. Зато код выполняется (если пользуетесь макросами) быстрее.

Вы говорите о inline macro, которые каждый раз, когда встречаются в тексте, заменяются на одинаковые куски кода.

Сергей же приводит пример макросов переопределения синтаксиса. При этом все равно каждая строка транслируется в одну команду работы с портами. Смысл таких макросов в том, что куски кода можно без исправлений переносить с одного компилятора и процессора на другой. Переписать нужно будет только макросы.

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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