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

Использование макросов с аргументами в Си

Для удобства работы с портами ввода/вывода (на STM32 в Keil) написал небольшой хидер, приведу его часть :

#define SbitP(Port,Nbit)    GPIO##Port->BSRR=GPIO_BSRR_BS##Nbit
#define RbitP(Port,Nbit)    GPIO##Port->BSRR=GPIO_BSRR_BR##Nbit
#define SmbitP(Port,mask)    GPIO##Port->BSRR=(mask)
#define RmbitP(Port,mask)    GPIO##Port->BSRR=(mask)<<16

в программе использую следующие варианты включения макросов:

#define  LCD_dataShift 1


void LCD_wrAdr (u8 Adr)
{
    SmbitP(A,((Adr&0x0f)<<LCD_dataShift)); // выставляем на шину адрес
    RbitP(A,7); // вкл. на запись адреса A0=0
    SbitP(A,5); // вкл.строба записи 
    delay(2000);// Задержка ~ 100нс
    RbitP(A,5); // снимаем строб записи 
    RmbitP(A,(0x0f<<LCD_dataShift)); // Сброс битов шины DBх
    delay(5000);// Задержка ~ 200нс
}

У меня вопрос: на сколько корректно такое применение макросов ? т.к. в случае с RbitP(A,7) в макрос подставляется символ , который при обединение с остальным текстом сам является библиотечным макросом. Т.е. до каких пор происходит раскрытие макроса ?

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


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

Бегло посмотрел. Вроде все нормально.

Макросы тупо подставляют параметры как текст не вычисляя их значение.

Если вы вместо параметра впишите текст и не будет синтаксических ошибок, то все пучком.

 

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


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

Т.е. до каких пор происходит раскрытие макроса ?

До упора :)

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

 

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


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

Не совсем понятен смысл таких макросов.

Если абстрагироваться, то нужно и от пинов, и от портов, и от уровней.

А это - всем известные макросы Аскольда Волкова или их подобие в виде шаблонов с++ (были пара тем)

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


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

Не совсем понятен смысл таких макросов.

Если абстрагироваться, то нужно и от пинов, и от портов, и от уровней.

а смысл - вместо записи GPIOA->BSRR=GPIO_BSRR_BS2 писать SbitP(A,2) помоему так нагляднее , и букф меньше.

Вот по поводу абстрагирования от пинов, добавим еще пару макросов для именования выводов #define LCD_A0 7 и #define LCD_WR1 5 :

#define  LCD_A0    7 // Выбор: Адрес A0=L/ Данные A0=H
#define  LCD_WR1     5 // Запись в модуль: H-активный уровень

#define  LCD_dataShift 1

void LCD_wrAdr (u8 Adr)
{
    SmbitP(A,((Adr&0x0f)<<LCD_dataShift)); // выставляем на шину адрес
    RbitP(A,LCD_A0); // вкл. на запись адреса A0=0
    SbitP(A,LCD_WR1); // вкл.строба записи 
    delay(2000);// Задержка ~ 100нс
    RbitP(A,LCD_WR1); // снимаем строб записи 
    RmbitP(A,(0x0f<<LCD_dataShift)); // Сброс битов шины DBх
    delay(5000);// Задержка ~ 200нс
}

В этом случае получается что перед тем как раскрыть макрос, нужно вместо букв параметра подставить то что означают эти буквы. Как в таком случае поведет себя предпроцессор , корректна ли такая запись с точки зрения стандарта написания макросов ?

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

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


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

Вы не до конца поняли намёк про макросы Аскольда Волкова.

Не поленитесь - погуглите да изучите.

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

По теме: то, что вы изобразили в последнем примере работать не будет. Требуется допиливание макросов. Вот так:

#define _RbitP(Port,Nbit)    GPIO##Port->BSRR=GPIO_BSRR_BR##Nbit
#define RbitP(Port,Nbit)     _RbitP(Port,Nbit)

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


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

Я обычно так делаю

#define LCD_WR1_pin 4
static inline void LCD_wr1(const char value)
{
  GPIOB->BSRR = 1 << (LCD_WR1_pin + value?0:16);
}

Никаких макро и никаких неясных абстракций. Все конкретно.

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


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

#define LCD_WR1_pin 4
static inline void LCD_wr1(const char value)
{
  GPIOB->BSRR = 1 << (LCD_WR1_pin + value?0:16);
}

Всего два вопроса:

  1. А зачем у аргумента функции квалификатор const? Тут же параметр не по ссылке передается, а по значению. :blink:
  2. 1 << (LCD_WR1_pin + value ? 0 : 16); <— Вы тут часом скобочки не забыли? :)

    Я о том, что приоритет операции "+" выше, чем у тернарной операции "?:"

    Надо бы так: 1 << (LCD_WR1_pin + (value ? 0 : 16));

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


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

Ну и если ещё продолжить придираться, то аргумент функции размером меньше int на ARM архитектуре менее оптимален. Так что char'у тут не место....

 

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


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

Скобочки - запросто мог потерять.

Ну и если ещё продолжить придираться, то аргумент функции размером меньше int на ARM архитектуре менее оптимален. Так что char'у тут не место....

 

Если нужны вычисления на этапе выполнения, то для чего вообще эти инлайны? Это несерьезно. В конце концов, bit band существует.

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


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

Я не придраться :(

Просто уже и раньше кое-где встречал наподобие

void func(const int x)
{
     ....
}

Например, в исходниках scmRTOS. Теперь вот и у Паши (уважаемого, надо сказать, человека :)).

Вот я и спрашиваю... Вдруг в этом есть какой-то глубокий смысл, а я и не в курсе... :laughing:

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


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

Вот я и спрашиваю... Вдруг в этом есть какой-то глубокий смысл, а я и не в курсе... :laughing:

Ну, вдруг кто-то (или сам автор) задаст в value переменную. А компилятор - бац - нельзя! :rolleyes:

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


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

Ну, вдруг кто-то (или сам автор) задаст в value переменную. А компилятор - бац - нельзя! :rolleyes:

Шутить изволите? :)

 

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


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

Шутить изволите? :)

По-моему, в книге Шилдта описан этот прием. Для библиотечных функций.

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


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

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

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

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

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

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

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

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

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

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