Наткнулся на такую бибилотеку «CyberLib»

Тема в разделе "Arduino & Shields", создана пользователем Максим B, 5 ноя 2014.

  1. Максим B

    Максим B Гуру

  2. lerik2703

    lerik2703 Гик

    смотря для каких целей, что-бы "разогнать" ардуинку ,я бы посоветовал заняться изучением языка С
    вот к примеру (исходя из приведенного)
    Код (Text):
    void setup()
    {
      DDRB |= (1<<PORTB5);
    }

    void loop()
    {

      PORTB |= (1<<PORTB5);
      PORTB &= (~(1<<PORTB5));

    }
    такой код выдает частоту 992.5 кГц размер 472 байта, эквивалент коду

    Код (Text):
    #include "CyberLib.h"
    void setup()
    {
      D13_Out;
    }

    void loop()
    {
      D13_High;
      D13_Low;
    }

    если добавим оператор while
    Код (Text):
    while(1){
      PORTB |= (1<<PORTB5);
      PORTB &= (~(1<<PORTB5));
      }
    получим уже 2646 кГц при том же размере.

    Код (Text):
    int main(void)
    {
      DDRB |= (1<<PORTB5);
      DDRC = 0x00;
      DDRD = 0x00;

      while(1){
        PORTB |= (1<<PORTB5);
        PORTB &= (~(1<<PORTB5));
      }
    }
    ну а такой код выдаст ту же частоту но займет уже 184 байта
     
    Megakoteyka нравится это.
  3. Unixon

    Unixon Оракул Модератор

    Для битового сдвига есть штатный макрос _BV(bit)

    Код (Text):
    void setup()
    {
      DDRB |= _BV(5);
    }

    void loop()
    {
      PORTB |= _BV(5);
      PORTB &= ~_BV(5);

    }
     
    Последнее редактирование: 6 ноя 2014
  4. Unixon

    Unixon Оракул Модератор

    Элементарную работу с портами можно наглядно представить макросами

    Код (Text):

    #define SetOutput(port,bit) DDR ## port |= _BV(bit)
    #define SetInput(port,bit) DDR ## port &= ~_BV(bit)
    #define SetBit(port,bit) PORT ## port |= _BV(bit)
    #define ClearBit(port,bit) PORT ## port &= ~_BV(bit)
    #define WritePort(port,bit,value) PORT ## port = (PORT ## port & ~_BV(bit)) | ((value & 1) << bit)
    #define ReadPort(port,bit) (PIN ## port >> bit) & 1
    #define PullUp(port,bit) { SetInput(port,bit); SetBit(port,bit); }
    #define Release(port,bit) { SetInput(port,bit); ClearBit(port,bit); }
     
    Потом просто пишем
    Код (Text):
    {
    SetOutput(B,7);
    SetBit(B,7);
    SetInput(C,0);
    int x = ReadPort(C,0);
    }
     
    Последнее редактирование: 6 ноя 2014
  5. lerik2703

    lerik2703 Гик

    где-то я уже его видел :)
     
  6. Dima85

    Dima85 Нерд

    Unixon, то есть если я буду использовать этот пример скорость Arduino возрастет?
    Расскажите пожалуйста что такое "B" и что такое "7" в приведенном примере?
     
  7. Unixon

    Unixon Оракул Модератор

    "Скорость Ардуино" - нет, быстродействие программы на элементарных операциях с портами по сравнению с pinMode и digitalRead/Write - да.
    Но если вы используете PWM на ноге или ADC, включать\выключать его тоже придется вручную. :)

    Имя порта и номер бита. Почитайте что-нибудь про архитектуру AVR.
     
  8. Dima85

    Dima85 Нерд

    А почему сам компилятор Arduino не может оптимизировать вот так вот код? Почему это приходится делать самому. Значит наверное есть и какие-то минусы в предоставленном вами примере?
     
  9. Unixon

    Unixon Оракул Модератор

    Это не оптимизация, это совершенно другой код. Функции pinMode, digitalRead/Write делают еще всякие проверки и пересчет номера пина ардуины в номер и бит порта конкретного контроллера и т.д.. Компилятор не может выкинуть этот код. Замедление кода при использовании Wiring - это плата за универсальность.

    Если вам все дополнительные действия функций библиотеки Wiring не нужны, можете пользоваться прямым обращением к портам.
     
  10. Dima85

    Dima85 Нерд

    Расскажите пожалуйста подробней о этих B, C, D насколько я понимаю таким образом указывается сразу несколько pin-ов. Допустим:
    А как быть если я хочу обратиться только к определенному Pin, допустим к 49 и проверить от LOW или HIGH?
     
  11. Unixon

    Unixon Оракул Модератор

    Буквами именуются порты микроконтроллера, каждому порту соответствует три 8-битных регистра PIN, PORT и DDR. Через регистр PIN можно прочитать состояние порта, через PORT записать, а через DDR включить отдельные биты на вход или выход. Для порта A регистры называются PINA, PORTA, DDRA, для B - PINB, PORTB, DDRB, ну и т.д.. Некоторые порты подключены в выводам микроконтроллера, у которых есть своя нумерация по корпусу микросхемы, все или почти все из них подключены к выводам разъемов Arduino, у которых опять своя нумерация. Библиотека Wiring принимает от вашей программы номер вывода разъема Arduino и вычисляет имя порта и номер бита в этом порту, который соответствует указанному выводу.

    Вывод 49 разъема Arduino Mega подключен к выводу микроконтроллера 35, а он в свою очередь подключен внутри микроконтроллера к биту 0 порта L. Следовательно вам нужно считать значение регистра PINL и выделить младший бит.

    byte x = PINL & 1;
     
  12. Dima85

    Dima85 Нерд

    Спасибо за наводку. В интернете нашел вот такую схему. Здесь распиновка всех выходов Mega:
    http://pighixxx.com/megapdf.pdf
    49 pin там указывается как "PL0" Все так как вы и писали. Хорошо. То есть если необходимо сделать условие на проверку выхода он = 0 или 1. Нужно сделать следующее, возьмем для примера выход 31 на схеме он указан как: PC6
    Следовательно:
    Код (Text):
    #define ReadPort(port,bit) (PIN ## port >> bit) & 1
    ***
    if (ReadPort(C,6) == 0) {
    ***
    }
    Unixon, все я правильно делаю?
     
  13. Unixon

    Unixon Оракул Модератор

    Макрос у вас раскроется препроцессором в текст "if ((PINC >> 6) & 1 == 0)". Это будет работать, но лучше писать не так. Вместо "if (x == 0)" лучше использовать "if (!x)" или тогда уже "if (0==x)". Если "x" - это выражение с операторами, приоритет которых вы не помните, заключите его в скобки, например так: "if (0==(x))" или "if (!(x))".
     
  14. Unixon

    Unixon Оракул Модератор

    Можно добавить еще один макрос для большего удобства
    Код (Text):

    #define IsBitClear(port,bit) ((PIN ## port >> bit) & 1) ^ 1
     
     
  15. Unixon

    Unixon Оракул Модератор

    Сходили бы сразу на arduino.cc, чего по всему интернету то рыскать... :)
     
  16. Dima85

    Dima85 Нерд

    Спасибо.
    А можно ли использовать макрос в макросе?
    У меня в начале программы для удобства идут подобные макросы:
    Код (Text):
    #define water 31
    в которых указывается порт, далее в программе к порту обращаюсь только через макрос, т.к. макросы повторяются достаточно часто.

    Первое что приходит в голову это, для water 31 выход:
    Код (Text):
    #define water (PINС >> 6) & 1
    #define waterOut DDR ## PINС |= _BV(6)
    ***
    waterOut;
    ***
    if (!water) {
    ***
    }
    У меня сейчас нет возможности протестировать. Но я предполагаю написал правильно?

    А можно ли сделать что-то подобное? Будит ли работать этот мой пример?
    Код (Text):

    #define water С,6 //31 выход
    #define ReadPort(port,bit) (PIN ## port >> bit) & 1
    #define SetOutput(port,bit) DDR ## port |= _BV(bit)
    ***
    SetOutput(water);
    ***
    if (!ReadPort(water)) {
    ***
    }
     
    Последнее редактирование: 20 ноя 2014
  17. Unixon

    Unixon Оракул Модератор

    Можно, но с некоторыми ограничениями.

    Научитесь нормально именовать идентификаторы. Что такое "water"? Не понятно же совершенно. Назовите PIN_WATER_PUMP хотя бы. Ну и все пины начинайте с префикса PIN_, чтобы сразу ясен был смысл определения.

    Для этого есть функции.

    Нет, вы так разбор параметров макроса ломаете.