"Вы читаете о роботах и программировании и думаете: «Было бы здорово сделать что-то подобное самому!» Теми, кем эта идея овладевает чуть больше просто мыслей смотрят кто и как делал своего робота. Читают статьи, смотрят видео. На картинках все понятно. В видеороликах тоже обычно показываются уже готовые продукты, а также сжато показываются технологии их изготовления. И вроде бы то же всё понятно: отпилил, прикрутил, припаял, соединил, запрограммировал вон на той программе вот этим кодом."

пятница, 19 марта 2021 г.

Компактней и быстрей

 Работа с портами Ардуино 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 или ускоряем работу платы"