смотря для каких целей, что-бы "разогнать" ардуинку ,я бы посоветовал заняться изучением языка С вот к примеру (исходя из приведенного) Код (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 байта
Для битового сдвига есть штатный макрос _BV(bit) Код (Text): void setup() { DDRB |= _BV(5); } void loop() { PORTB |= _BV(5); PORTB &= ~_BV(5); }
Элементарную работу с портами можно наглядно представить макросами Код (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); }
Unixon, то есть если я буду использовать этот пример скорость Arduino возрастет? Расскажите пожалуйста что такое "B" и что такое "7" в приведенном примере?
"Скорость Ардуино" - нет, быстродействие программы на элементарных операциях с портами по сравнению с pinMode и digitalRead/Write - да. Но если вы используете PWM на ноге или ADC, включать\выключать его тоже придется вручную. Имя порта и номер бита. Почитайте что-нибудь про архитектуру AVR.
А почему сам компилятор Arduino не может оптимизировать вот так вот код? Почему это приходится делать самому. Значит наверное есть и какие-то минусы в предоставленном вами примере?
Это не оптимизация, это совершенно другой код. Функции pinMode, digitalRead/Write делают еще всякие проверки и пересчет номера пина ардуины в номер и бит порта конкретного контроллера и т.д.. Компилятор не может выкинуть этот код. Замедление кода при использовании Wiring - это плата за универсальность. Если вам все дополнительные действия функций библиотеки Wiring не нужны, можете пользоваться прямым обращением к портам.
Расскажите пожалуйста подробней о этих B, C, D насколько я понимаю таким образом указывается сразу несколько pin-ов. Допустим: B (digital pin 8 to 13) C (analog input pins) D (digital pins 0 to 7) http://www.arduino.cc/en/Reference/PortManipulation А как быть если я хочу обратиться только к определенному Pin, допустим к 49 и проверить от LOW или HIGH?
Буквами именуются порты микроконтроллера, каждому порту соответствует три 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;
Спасибо за наводку. В интернете нашел вот такую схему. Здесь распиновка всех выходов 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, все я правильно делаю?
Макрос у вас раскроется препроцессором в текст "if ((PINC >> 6) & 1 == 0)". Это будет работать, но лучше писать не так. Вместо "if (x == 0)" лучше использовать "if (!x)" или тогда уже "if (0==x)". Если "x" - это выражение с операторами, приоритет которых вы не помните, заключите его в скобки, например так: "if (0==(x))" или "if (!(x))".
Можно добавить еще один макрос для большего удобства Код (Text): #define IsBitClear(port,bit) ((PIN ## port >> bit) & 1) ^ 1
Спасибо. А можно ли использовать макрос в макросе? У меня в начале программы для удобства идут подобные макросы: Код (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)) { *** }
Можно, но с некоторыми ограничениями. Научитесь нормально именовать идентификаторы. Что такое "water"? Не понятно же совершенно. Назовите PIN_WATER_PUMP хотя бы. Ну и все пины начинайте с префикса PIN_, чтобы сразу ясен был смысл определения. Для этого есть функции. Нет, вы так разбор параметров макроса ломаете.