Jump to content

    
Sign in to follow this  
ViKo

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

Recommended Posts

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

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

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

Share this post


Link to post
Share on other sites
5 минут назад, Arlleex сказал:

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

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

Share this post


Link to post
Share on other sites
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

 

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

Edited by Darth Vader

Share this post


Link to post
Share on other sites
11 часов назад, Darth Vader сказал:

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

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

Share this post


Link to post
Share on other sites
16 часов назад, Darth Vader сказал:

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

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

 

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

Share this post


Link to post
Share on other sites
// 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);
};

 

Share this post


Link to post
Share on other sites
40 минут назад, slavka012 сказал:

...

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

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

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

Edited by Arlleex

Share this post


Link to post
Share on other sites

 

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

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

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

 

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

Share this post


Link to post
Share on other sites
2 минуты назад, Forger сказал:

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

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

Share this post


Link to post
Share on other sites
19 minutes ago, Arlleex said:

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

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

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

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

Share this post


Link to post
Share on other sites
20 minutes ago, Arlleex said:

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

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

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

 

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

Share this post


Link to post
Share on other sites
7 minutes ago, Arlleex said:

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

 

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

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

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

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

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

Share this post


Link to post
Share on other sites
11 минут назад, Forger сказал:

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

Спасибо!

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

Share this post


Link to post
Share on other sites
25 minutes ago, Arlleex said:

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

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

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

Share this post


Link to post
Share on other sites
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;
};

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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this