Работа с портами Ардуино Uno[1]
Cтандартные для Arduino-версии языка C++ самые распространенные функции pinMode, digitalWrite, digitalRead, analogWrite, analogRead, Serial.print, Serial.println (и другие) — это всего лишь удобные обертки для тех, кто не желает лезть в дебри программирования. Эти функции-обертки содержат определенные механизмы проверок корректности исполнения, которые увеличивают время получения результата в разы!
Исходные коды функций можно найти в папке Arduino\hardware\arduino\avr\cores\arduino в соответствующих файлах:
- pinMode, digitalWrite, digitalRead — файл wiring_digital.c
- analogWrite, analogRead — файл wiring_analog.c
- shiftOut — файл wiring_shift.c
и т.д.
Частота платы Arduino Uno 16 МГц. Это означает, что плата за 1 секунду совершает 16 000 000 тактов. На один такт уходит — 0,0625 мкс (микросекунд, в 1 секунде 1 000 000 микросекунд) — 62,5 наносекунд!
У языка Arduino есть функции по низкоуровневому взаимодействию с пинами микроконтроллера Atmega 328P (в т.ч. Arduino Uno) в обход стандартных функций, но перед тем как к ним перейти нужно рассказать о том как они работают. Чип Atmega имеет 3 порта: B, C, D — каждый отвечает за свою группу пинов:
Каждый порт управляется 3 регистрами:
Для того, чтобы использовать какой-либо регистр необходимо к регистру (DDR, PORT, PIN) добавить букву порта (B, C, D), и полученной переменной присвоить битовое значение (байт), в котором каждый бит будет отвечать за отдельный пин-выход:
DDRD = 0xFF; // все выходы порта D работают на выход
PORTD = 0xFF; //на все выходы порта D подан высокий уровень сигнала
- код становится нечитаемым и сложным в отладке, не говоря уже об изучении вашего кода сторонними программистами
- код становится непереносимым, так как распиновка и расположение регистров и портов может сильно различаться между разными микроконтроллерами — код придется переписывать при смене платформы
- очень опасно (в данном случае) использовать порт D, ведь если случайно назначить 0 пину режим OUTPUT, то вероятно вы уже не сможете заливать скетчи в вашу плату.
Преимущества подхода! Имеет смысл рассмотреть вариант использования этого метода в ряде случаев:
- конечно, первая причина указана в заголовке статьи — это скорость;
- если нужно переключать одновременно пины, принадлежащие одному порту — использование функций digitalWrite() неминуемо вызовет задержку между переключениями пинов, а операции над портом позволят это реализовать;
- если нужно сократить объем программного кода.
[1]Кравченко Виктор "Тюнинг Arduino или ускоряем работу платы"