Метценгерштейн 0 12 сентября, 2016 Опубликовано 12 сентября, 2016 · Жалоба Есть некоторые дефайны: #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 надо в цикле по очереди их вызывать. Как это делается обычно? Может в массив затолкнуть и по элементам идти? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 52 12 сентября, 2016 Опубликовано 12 сентября, 2016 · Жалоба const char /*int??*/ array[] = {LED_0, LED_1, LED_2, LED_3, LED_4, LED_5, LED_6, LED_7}; PORT = array; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Метценгерштейн 0 12 сентября, 2016 Опубликовано 12 сентября, 2016 · Жалоба не хочет проглатывать там дальше #define LN8_Pin GPIOA, GPIO_PIN_2, H мне в коде надо подставлять, например on(LED_0); А не хочет проглатывать, т.к. тип LED_0 вовсе не char или int. Надо может в enum затолкать и тип enum дать, но ругается на такие энумы, т.к. уже определены в дефайне. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Swup 0 12 сентября, 2016 Опубликовано 12 сентября, 2016 · Жалоба вероятно надо как-то через # и ## действовать, но что-то не соображу как. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 52 12 сентября, 2016 Опубликовано 12 сентября, 2016 · Жалоба в этом случае с макросами Волкова не очень красиво получается, так как там в одном месте через запятую перечислены указатель на порт 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); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Метценгерштейн 0 12 сентября, 2016 Опубликовано 12 сентября, 2016 · Жалоба Да, это макросы Аскольда. Спасибо за подсказку. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 52 12 сентября, 2016 Опубликовано 12 сентября, 2016 · Жалоба похожие по сути на макросы Волкова вещи ещё легко делаются на шаблонах С++. http://www.webalice.it/fede.tft/stm32/stm3...rogramming.html ну это если отсутсвуют религиозные убеждения, что плюсам в программах для МК уровня контроллера светодиода делать нечего :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Slash 0 12 сентября, 2016 Опубликовано 12 сентября, 2016 · Жалоба Или так на шаблонах (по-русски с подробным объяснением) http://easyelectronics.ru/rabota-s-portami...erov-na-si.html Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 13 сентября, 2016 Опубликовано 13 сентября, 2016 · Жалоба Лет 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(); } В итоге при переходе на совершенно другой контроллер софт править не нужно, правится только платформо-зависимый код драйвера. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SSerge 4 14 сентября, 2016 Опубликовано 14 сентября, 2016 · Жалоба Надо может в enum затолкать и тип enum дать, но ругается на такие энумы, т.к. уже определены в дефайне. массивы и енумы удобно генерировать с помощью https://en.wikipedia.org/wiki/X_Macro Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 26 14 сентября, 2016 Опубликовано 14 сентября, 2016 (изменено) · Жалоба Есть некоторые дефайны: . . . надо в цикле по очереди их вызывать. Как это делается обычно? Может в массив затолкнуть и по элементам идти? Вот была аналогичная задача, добрые люди здесь подсказали. "Номер" с массивом. 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 из предыд. поста. Изменено 14 сентября, 2016 пользователем k155la3 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 14 сентября, 2016 Опубликовано 14 сентября, 2016 · Жалоба Кода будут пины из разных портов, (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(); } И то, это довольно длинный код, я обычно делаю гораздо короче. Просто привел, чтобы сама суть была понятна. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться