реклама на сайте
подробности

 
 
> Использование макросов с аргументами в Си
MaxiMuz
сообщение Nov 28 2013, 07:32
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Для удобства работы с портами ввода/вывода (на 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) в макрос подставляется символ , который при обединение с остальным текстом сам является библиотечным макросом. Т.е. до каких пор происходит раскрытие макроса ?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
_Pasha
сообщение Nov 29 2013, 18:19
Сообщение #2


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Я обычно так делаю
Код
#define LCD_WR1_pin 4
static inline void LCD_wr1(const char value)
{
  GPIOB->BSRR = 1 << (LCD_WR1_pin + value?0:16);
}

Никаких макро и никаких неясных абстракций. Все конкретно.
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Dec 2 2013, 12:14
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(_Pasha @ Nov 29 2013, 21:19) *
Я обычно так делаю
Код
#define LCD_WR1_pin 4
static inline void LCD_wr1(const char value)
{
  GPIOB->BSRR = 1 << (LCD_WR1_pin + value?0:16);
}

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

по порядку:
1) Во первых Keil 4.7 не дает инлайнить функции.
2) Не ясен смысла записи GPIOB->BSRR = 1 << (LCD_WR1_pin + value?0:16); нужно передать в порт фиксированное значение ( номер пина)
3) Нет возможности изменить порт вывода.


И еще , что делает выражение value?0:16 и зачем ? я вообще не понял , возможно это мои пробелы в знаниях Си.

Сообщение отредактировал MaxiMuz - Dec 2 2013, 12:10
Go to the top of the page
 
+Quote Post
winipuh
сообщение Dec 2 2013, 12:34
Сообщение #4


Частый гость
**

Группа: Участник
Сообщений: 127
Регистрация: 31-10-12
Пользователь №: 74 189



Цитата(MaxiMuz @ Dec 2 2013, 16:14) *
по порядку:
1) Во первых Keil 4.7 не дает инлайнить функции.

blink.gif Да? Может у него что-то свое есть специфическое... типа __inline__ и т.п.?

Цитата(MaxiMuz @ Dec 2 2013, 16:14) *
2) Не ясен смысла записи GPIOB->BSRR = 1 << (LCD_WR1_pin + value?0:16);

BSRR - управляет 16-тью пинками GPIO.
Младшие 16 бит отвечают за установку пинов в "1", старшие 16 - за установку в "0".
Можно одной записью одновременно установить и сбросить несколько разных пинов...

А вышеприведенная (и, возможно, местами изъебисто написанная) конструкция буквально означает следующее:
Код
// n - номер GPIO-пина (от 0 до 15)
#define SET_PIN(n)   (0x0001 << (n))
#define CLR_PIN(n)   (0x0100 << (n))      //  ну или так — (0x0001 << ((n) + 16))

// какой-то конкретный пин
#define LCD_wr1_pin   4

// Функция для установки/сброса какого-то конкретного пина
static inline void LCD_wr1(const char value)
{
  if (value)
      GPIOB->BSRR = SET_PIN(LCD_wr1_pin);
   else
      GPIOB->BSRR = CLR_PIN(LCD_wr1_pin);
}


Сообщение отредактировал winipuh - Dec 2 2013, 12:35
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Dec 2 2013, 19:09
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(winipuh @ Dec 2 2013, 15:34) *
blink.gif Да? Может у него что-то свое есть специфическое... типа __inline__ и т.п.?

вот этого я пока не знаю


Цитата(winipuh @ Dec 2 2013, 15:34) *
BSRR - управляет 16-тью пинками GPIO.
Младшие 16 бит отвечают за установку пинов в "1", старшие 16 - за установку в "0".
Можно одной записью одновременно установить и сбросить несколько разных пинов...
все мне известно


но конструкция
Код
static inline void LCD_wr1(const char value)
{
  if (value)
      GPIOB->BSRR = SET_PIN(LCD_wr1_pin);
   else
      GPIOB->BSRR = CLR_PIN(LCD_wr1_pin);
}
подразумевает вычисление или выбор по условию аргумента, а смысл макроса просто подстановка кода с уже готовым аргументом, вот этого я и добиваюсь
Go to the top of the page
 
+Quote Post
winipuh
сообщение Dec 2 2013, 20:00
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 127
Регистрация: 31-10-12
Пользователь №: 74 189



Цитата(MaxiMuz @ Dec 2 2013, 23:09) *
но конструкция ... подразумевает вычисление или выбор по условию аргумента, а смысл макроса просто подстановка кода с уже готовым аргументом

Возможно Вы удивитесь, но на этапе компиляции не то-что инлайн — даже статические функции разворачиваются в конечное выражение не хуже макросов.
Пожалуйста:
Код
// СИ:
extern void my_func(unsigned int x);
static unsigned int my_value(unsigned int n) { return n ? 0x80 : 0x8000; }

void call_func(n) {
    my_func(value(4));    // на самом деле все это вычисляется на этапе компиляции
}

// ASM:
    stmfd    sp!, {r3, lr}
    mov    r0, #128        // и в итоге получается my_func(0x80) ( 0x80 = 128 )
    bl    my_func
    ldmfd    sp!, {r3, lr}
    bx    lr
    .size    call_func, .-call_func
    .ident    "GCC: (Sourcery CodeBench Lite 2013.05-23) 4.7.3"


Ну и наверное сочту своим долгом повторить еще раз то, что Вам уже говорил MrYuran
Цитата
Если абстрагироваться, то нужно и от пинов, и от портов, и от уровней.

А так вот что имеем:
RbitP(A,7); // вкл. на запись адреса A0=0
SbitP(A,5); // вкл.строба записи

Вопрос:
  1. Что будете делать, если Вам потребуется перенести пины с GPIOA на GPIOB?
  2. Что будете делать, если Вам потребуется использовать для строба записи на Pin5, а напр. Pin8?

Правильный вариант — это когда для этого нужно открыть некий h-файл и поправить там несколько строчек.
В вашем случае - править придется все места, где вызываются макросы SbitP, RbitP и т.д. И в этом случае (при всем уважении) Ваши макросы — просто какая-то обертка, чтобы писать меньше букв кода. Преимущество, мягко говоря, весьма сомнительное...
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Dec 3 2013, 04:30
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(winipuh @ Dec 2 2013, 23:00) *
А так вот что имеем:
RbitP(A,7); // вкл. на запись адреса A0=0
SbitP(A,5); // вкл.строба записи

Вопрос:
  1. Что будете делать, если Вам потребуется перенести пины с GPIOA на GPIOB?
  2. Что будете делать, если Вам потребуется использовать для строба записи на Pin5, а напр. Pin8?

Правильный вариант — это когда для этого нужно открыть некий h-файл и поправить там несколько строчек.
В вашем случае - править придется все места, где вызываются макросы SbitP, RbitP и т.д.

Код
#define SbitP(Port,Nbit)    GPIO##Port->BSRR=GPIO_BSRR_BS##Nbit
вместо Port подставляем букву порта, второй параметр - номер пина. И ничего править не надо.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- MaxiMuz   Использование макросов с аргументами в Си   Nov 28 2013, 07:32
- - Tarbal   Бегло посмотрел. Вроде все нормально. Макросы тупо...   Nov 28 2013, 13:15
- - SSerge   Цитата(MaxiMuz @ Nov 28 2013, 14:32) Т.е....   Nov 29 2013, 06:54
- - MrYuran   Не совсем понятен смысл таких макросов. Если абстр...   Nov 29 2013, 11:48
|- - demiurg_spb   Цитата(MrYuran @ Nov 29 2013, 15:48) +1   Nov 29 2013, 12:12
|- - MaxiMuz   Цитата(MrYuran @ Nov 29 2013, 14:48) Не с...   Nov 29 2013, 12:29
|- - demiurg_spb   Цитата(MaxiMuz @ Nov 29 2013, 16:29) Вы ...   Nov 29 2013, 12:52
|- - winipuh   Цитата(_Pasha @ Nov 29 2013, 22:19) Код#d...   Dec 1 2013, 15:37
||- - demiurg_spb   Цитата(winipuh @ Dec 1 2013, 19:37) Ну и ...   Dec 2 2013, 05:39
||- - _Pasha   Скобочки - запросто мог потерять. Цитата(demiurg_...   Dec 2 2013, 06:29
||- - winipuh   Я не придраться Просто уже и раньше кое-где встре...   Dec 2 2013, 08:24
|||- - ViKo   Цитата(winipuh @ Dec 2 2013, 11:24) Вот я...   Dec 2 2013, 08:36
|||- - winipuh   Цитата(ViKo @ Dec 2 2013, 12:36) Ну, вдру...   Dec 2 2013, 09:50
|||- - ViKo   Цитата(winipuh @ Dec 2 2013, 12:50) Шутит...   Dec 2 2013, 10:13
||- - demiurg_spb   Цитата(_Pasha @ Dec 2 2013, 10:29) Это не...   Dec 2 2013, 11:53
|- - winipuh   Цитата(MaxiMuz @ Dec 3 2013, 08:30) Код#d...   Dec 3 2013, 12:23
|- - MaxiMuz   Цитата(winipuh @ Dec 3 2013, 15:23) Имеем...   Dec 11 2013, 07:36
|- - Сергей Борщ   Цитата(MaxiMuz @ Dec 11 2013, 09:36) Един...   Dec 11 2013, 08:02
- - dxp   QUOTE (winipuh @ Dec 1 2013, 22:37) А зач...   Dec 3 2013, 04:24
- - ViKo   Не понимаю, зачем такие "муки творчества...   Dec 11 2013, 08:23
- - Сергей Борщ   Цитата(ViKo @ Dec 11 2013, 10:23) Не пони...   Dec 11 2013, 09:12


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th July 2025 - 16:40
Рейтинг@Mail.ru


Страница сгенерированна за 0.02892 секунд с 7
ELECTRONIX ©2004-2016