|
|
  |
дефайны засунуть в массив и вызывать |
|
|
|
Sep 12 2016, 07:07
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
Есть некоторые дефайны: Код #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 надо в цикле по очереди их вызывать. Как это делается обычно? Может в массив затолкнуть и по элементам идти?
|
|
|
|
|
Sep 12 2016, 08:42
|
Профессионал
    
Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079

|
не хочет проглатывать там дальше Код #define LN8_Pin GPIOA, GPIO_PIN_2, H мне в коде надо подставлять, например Код on(LED_0); А не хочет проглатывать, т.к. тип LED_0 вовсе не char или int. Надо может в enum затолкать и тип enum дать, но ругается на такие энумы, т.к. уже определены в дефайне.
|
|
|
|
|
Sep 12 2016, 10:11
|
Гуру
     
Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954

|
в этом случае с макросами Волкова не очень красиво получается, так как там в одном месте через запятую перечислены указатель на порт 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);
|
|
|
|
|
Sep 13 2016, 18:43
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046

|
Лет 6 работаю с gpio только на шаблонах(compile-time) и интерфейсах (рантайм). Compile-time: CODE 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: CODE 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(); }
В итоге при переходе на совершенно другой контроллер софт править не нужно, правится только платформо-зависимый код драйвера.
|
|
|
|
|
Sep 14 2016, 06:28
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(Метценгерштейн @ Sep 12 2016, 10:07)  Есть некоторые дефайны: . . . надо в цикле по очереди их вызывать. Как это делается обычно? Может в массив затолкнуть и по элементам идти? Вот была аналогичная задача, добрые люди здесь подсказали. "Номер" с массивом. Код 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 - Sep 14 2016, 09:35
|
|
|
|
|
Sep 14 2016, 07:43
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046

|
Кода будут пины из разных портов, (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(); } И то, это довольно длинный код, я обычно делаю гораздо короче. Просто привел, чтобы сама суть была понятна.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|