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

Как дефайнами задать порт и бит?

Только что, ViKo сказал:

В-общем, посмотрел показанное, сделал по Сергею Борщу. Проверять не на чем, а специально - нет времени, будущее покажет, должно работать. Спасибо всем! 

Да у меня, в общем-то, похоже на реализацию Сергея. Только еще и результат работы я вывел - поэтому, проверять не обязательно:boast:

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


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

5 минут назад, Arlleex сказал:

Да у меня, в общем-то, похоже на реализацию Сергея. Только еще и результат работы я вывел - поэтому, проверять не обязательно

Да, похоже. Потому и не проверяю. :drinks:

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


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

On 11/28/2018 at 3:23 PM, ViKo said:

Или как-то иначе описать бит порта? Фантазирую

Самый примитивный способ:

Quote

 

// Светодиод RED_LED подключен к выводу 5 порта F

#define RED_LED_PIN_POS  (5)

#define RED_LED_PIN  (1 << RED_LED_PIN_POS)

#define RED_LED_PORT  GPIOF

 

И так для всех интересующих цепей, подключенных к выводам портов микроконтроллера. Далее в тексте программы оперируете лишь этими макроименами. Мне этого вполне хватает.

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

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


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

11 часов назад, Darth Vader сказал:

Мне этого вполне хватает.

Мне, перфекционисту, не хватает. Я уже описал одним дефайном нужные мне PORT, BIT и радуюсь. 

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


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

16 часов назад, Darth Vader сказал:

Самый примитивный способ:

И так для всех интересующих цепей, подключенных к выводам портов микроконтроллера. Далее в тексте программы оперируете лишь этими макроименами. Мне этого вполне хватает.

 

Какой смысл городить такой балаган, если каждый пин легко задаётся одной строкой?

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


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

// in the API .h

#define M_PORT0    0x0000
#define M_PORT1    0x0100
#define M_PORT2    0x0200
#define M_PORT3    0x0300
#define M_PORT4    0x0400

void ConfigPin2(unsigned int PortPin, unsigned int Mode, unsigned int PullUp);

static inline unsigned int ReadPin(unsigned int PortPin) {..};
static inline void SetPin(unsigned int PortPin) {...};
static inline void ClrPin(unsigned int PortPin) {...};
static inline void SetPinOut(unsigned int PortPin) {...};
static inline void SetPinIn(unsigned int PortPin) {...};

///////////////////////////////////////////////////////////////////////////////
// in the code  .c
    #define BUTTON1_PIN (M_PORT0 | 13)
    #define BUTTON2_PIN (M_PORT1 | 30)
    #define BUTTON3_PIN (M_PORT0 | 12)
    #define BUTTON4_PIN (M_PORT1 | 31)

int main() {
   unsigned int PinState = ReadPin(BUTTON1_PIN);
};

 

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


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

40 минут назад, slavka012 сказал:

...

И как сие работает?

BUTTON1_PIN превратится в 0x000D. И что мне с этим делать? Создавать еще функцию, которая будет расшифровывать битовые поля, и исходя из этого устанавливать нужный бит в нужном GPIO - не очень практично, ИМХО.

На мой взгляд, на установку бита в GPIO должно уходить всего пару тактов, чтобы более-менее точно выводить отладочные сигналы на осциллограф или логический анализатор, при необходимости. Либо экзотический интерфейс ногодрыжно запилить, например. Конечно, для измерения точных временных меток такой метод не годится, но во многих случаях он может пригодиться. И поэтому, для меня определяющим фактором является "быстрее - не медленнее". Вместо раздувания вызовов функций и, соответственно, траты процессорного времени, лучше писать сразу в регистр. Не так ли?:smile:

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

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


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

 

Вот мое решение, на примере управления обычным светодиодом:

#include ....
#include <Pin.hpp>

int main()
{
  static Hardware::LedOpenDrain<PE1> ledGreen;
  
  while (true)
  {
      ledGreen.on();
      sleepMs(100);
      ledGreen.off();
      sleepMs(900);
  }
}        
          

 

Даже на ардуине подобный код получается больше и менее читаемый :)

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


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

2 минуты назад, Forger сказал:

Вот мое решение, на примере управления обычным светодиодом:

А можно поинтересоваться, во что превратится ledGreen.on() в итоговом ассемблерном варианте?

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


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

19 minutes ago, Arlleex said:

И как сие работает?

BUTTON1_PIN превратится в 0x000D. И что мне с этим делать?

полагаю взять смещение порта из старшего байта, а номер/маску пина из младшего,

но вместо такой упаковки в одно слово, проще, как макросах Волкова, через запятую всё перечислить, и потом препроцессором разобрать, на стадии компиляции, а не в рантайме.

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


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

20 minutes ago, Arlleex said:

И как сие работает?

BUTTON1_PIN превратится в 0x000D. И что мне с этим делать? Создавать еще функцию, которая будет расшифровывать битовые поля, и исходя из этого устанавливать нужный бит в нужном GPIO - не очень практично, ИМХО.

На мой взгляд, на установку бита в GPIO должно уходить всего пару тактов, чтобы более-менее точно выводить отладочные сигналы на осциллограф или логический анализатор, при необходимости. Либо экзотический интерфейс ногодрыжно запилить, например. Конечно, для измерения точных временных меток такой метод не годится, но во многих случаях он может пригодиться. И поэтому, для меня определяющим фактором является "быстрее - не медленнее". Вместо раздувания вызовов функций и, соответственно, траты процессорного времени, лучше писать сразу в регистр. Не так ли?:smile:

 

Нормально работает. Да, установка бита в коде делается фунцией, что, возможно кто-то сочтет недостатком. Но по факту на большом арме с IO, который сидит на шине, точных времен ногодрыгом все равно не добиться. По мне так удобство и наглядность в моем случае компенсируют потерю производительности.

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


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

7 minutes ago, Arlleex said:

А можно поинтересоваться, во что превратится ledGreen.on() в итоговом ассемблерном варианте?

 

Такой код на уровне оптимизации balanced (arm compiler v6.11)

  while (true)
  {
      ledGreen.on();
      sleepMs(100);
      ledGreen.off();
      sleepMs(900);
  

Экземпляр пина размещен внутри одного из классов, а не статически, как указал в примепе выше, но это ничего не меняет.

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

Безымянный.jpg

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


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

11 минут назад, Forger сказал:

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

Спасибо!

Думалось мне, будет что-то нечто хуже, оказалось все очень неплохо:ok:

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


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

25 minutes ago, Arlleex said:

Думалось мне, будет что-то нечто хуже, оказалось все очень неплохо:ok:

Нужен лишь современный компилятор и немного подтянуть знания по плюсам :acute:

Макросы  - это уже анахронизм, пережиток ушедшей эпохи :don-t_mention:

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


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

5 hours ago, Forger said:

 


#include ....
#include <Pin.hpp>

int main()
{
  static Hardware::LedOpenDrain<PE1> ledGreen;
  
  while (true)
  {
      ledGreen.on();
      sleepMs(100);
      ledGreen.off();
      sleepMs(900);
  }
}        
          

 

Это типичный код в стиле C


В стиле C++ будет так:

// LED1 = P1.18  LED2 = P1.20  LED3 = P1.21  LED4 = P1.23
#define LED_MASK 0x00B40000

PortOut ledport(Port1, LED_MASK);

int main(void)
{
  while (1)
  {
    ledport = LED_MASK;
    wait(1);
    ledport = 0;
    wait(1);
  }
}


class PortOut
{
  public:

    PortOut(PortName port, int mask = 0xFFFFFFFF)
    {
      core_util_critical_section_enter();
      port_init(&_port, port, mask, PIN_OUTPUT);
      core_util_critical_section_exit();
    }

    void write(int value)
    {
      port_write(&_port, value);
    }

    int read(void)
    {
      return port_read(&_port);
    }

    PortOut&operator=(int value)
    {
      write(value);
      return *this;
    }

    PortOut&operator=(PortOut& rhs)
    {
      write(rhs.read());
      return *this;
    }

    operator int(void)
    {
      return read();
    }

  private:
    port_t _port;
};

И не забываем про критические секции. Не все в стиле суперлуп программируют.

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


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

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

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

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

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

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

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

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

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

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