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

дефайны засунуть в массив и вызывать

Есть некоторые дефайны:

 

#define LED_0    LN8_Pin
#define LED_1    LN7_Pin
#define LED_2    LN6_Pin
#define LED_3    LN5_Pin
#define LED_4    LN4_Pin
#define LED_5    LN3_Pin
#define LED_6    LN2_Pin
#define LED_7    LN1_Pin

 

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

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


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

не хочет проглатывать

 

там дальше

#define  LN8_Pin    GPIOA, GPIO_PIN_2, H

 

мне в коде надо подставлять, например

on(LED_0);

 

А не хочет проглатывать, т.к. тип LED_0 вовсе не char или int.

 

Надо может в enum затолкать и тип enum дать, но ругается на такие энумы, т.к. уже определены в дефайне.

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


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

вероятно надо как-то через # и ## действовать, но что-то не соображу как.

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


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

в этом случае с макросами Волкова не очень красиво получается, так как там в одном месте через запятую перечислены указатель на порт volatile void *, маска unsigned short, и активный уровень, который вообще не имеет типа, так как просто приклеивается препроцессором в нужное место.

соответственно последнее сильно мешает, так как засунуть эту H или L из препроцессора в переменную ещё как-то можно, а вот обратно - никак.

препроцессор не может достать значение переменной и вклеить в кусок кода.

 

можно попробовать сделать похожие макросы Волкова, небольшие inline функции,

void on(const tPin &pin){

if (pin.polarity == "H") pin.port|= pin.mask; else pin.port &= ~pin.mask;

}

 

typedef struct{

volatile void * port;

unsigned short mask;

unsigned char polarity;

}tPin;

 

const tPin LED0 = {GPIOA, (1<<5), "H"};

 

и потом уже создавать массив таких стуктур.

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

 

другой тупой способ:

void on_n(int n){

switch(n){

case 0: on(LED0);

case 1: on(LED1);

case 2: on(LED2);

case 3: on(LED3);

...

}

}

 

on_n(i);

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


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

Да, это макросы Аскольда.

Спасибо за подсказку.

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


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

похожие по сути на макросы Волкова вещи ещё легко делаются на шаблонах С++.

http://www.webalice.it/fede.tft/stm32/stm3...rogramming.html

 

ну это если отсутсвуют религиозные убеждения, что плюсам в программах для МК уровня контроллера светодиода делать нечего :)

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


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

Или так на шаблонах (по-русски с подробным объяснением) http://easyelectronics.ru/rabota-s-portami...erov-na-si.html

 

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


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

Лет 6 работаю с gpio только на шаблонах(compile-time) и интерфейсах (рантайм).

Compile-time:

template<char GPN> static inline LPC_GPIO_TypeDef* GetGpioByName();
template<> inline LPC_GPIO_TypeDef* GetGpioByName<'0'>(){ return LPC_GPIO0; }
template<> inline LPC_GPIO_TypeDef* GetGpioByName<'1'>(){ return LPC_GPIO1; }
...
template<char GPN> class GpioPort{
public:
static LPC_GPIO_TypeDef* gpio(){ return GetGpioByName<GPN>(); }

static void set(uint32_t msk){   gpio()->FIOSET = msk; }
static void clear(uint32_t msk){ gpio()->FIOCLR = msk; }
//....
};

template<char PORT, int PIN> class GpioPin{
public:
static LPC_GPIO_TypeDef* gpio(){ return GetGpioByName<PORT>(); }

static void set(){   GpioPort<PORT>::set(msk); }
static void clear(){ GpioPort<PORT>::clear(msk); }
// ....
enum{ Pin=PIN, msk=1<<PIN};
static const char Port = PORT;
};

// usage:
#define LED1_pin GpioPin<'0',10>

LED1_pin::set();
//....
LED1_pin::clear();

 

Runtime:

class IGpioPin{
public:
virtual ~IGpioPin(){}

virtual void set()=0;
virtual void clear()=0;
// ....
};

template<class T> class IGpioPin_T;

template<char PORT, int PIN>
class IGpioPin_T<GpioPin<PORT,PIN> > : public IGpioPin{
public:
virtual void set(){
	GpioPin<PORT, PIN>::set();
};

virtual void clear(){
	GpioPin<PORT, PIN>::clear();
}
// .....
};

// usage:

#define LED1_pin GpioPin<'0',10>
IGpioPin_T<LED1_pin> LED1_pin_rt;
//...

IGpioPin* const array[3] = {&LED1_pin_rt, &LED2_pin_rt, &LED3_pin_rt};
void f(){
for(int i=0; i<3; i++)array[i]->set();
}

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

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


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

Надо может в enum затолкать и тип enum дать, но ругается на такие энумы, т.к. уже определены в дефайне.

массивы и енумы удобно генерировать с помощью

https://en.wikipedia.org/wiki/X_Macro

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


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

Есть некоторые дефайны:

. . .

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

 

Вот была аналогичная задача, добрые люди здесь подсказали.

"Номер" с массивом.

enum
{
LED1,
LED2,
. . . . 
LED_MAX
};

int my_array[] =
{
[LED1] = LED8_Pin, // это можно из деф
[LED2] = LED5_Pin, 
. . . . 
[LED_MAX] = 0
};


for(int i=0; i<LED_MAX; i++) . . . . .

 

ps - это какраз XMacro из предыд. поста.

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

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


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

Кода будут пины из разных портов, (PORTA, PORTB) - у Вас с этими всеми массивами и дефайнами начнется платформозависимый мрак.

А я в то время просто напишу:

#define LED1_pin GpioPin<'А',5> // этот пин GPIOA.5
#define LED2_pin GpioPin<'B',7> // а этот GPIOB.7
...
IGpioPin_T<LED1_pin> LED1_pin_rt;
IGpioPin_T<LED2_pin> LED2_pin_rt;
//...

IGpioPin* const array[xxx] = {&LED1_pin_rt, &LED2_pin_rt, &LED3_pin_rt,...};
void f(){
for(int i=0; i<sizeof(array)/sizeof(array[0]); i++)array[i]->set();
}

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

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


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

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

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

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

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

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

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

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

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

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