Книга: Программируем Arduino. Профессиональная работа со скетчами.

2. Под капотом

2. Под капотом

Самое замечательное в Arduino — в большинстве случаев нет необходимости знать, что происходит за кулисами после того, как вы выгрузите скетч. Но так как вы собираетесь вникнуть в особенности работы Arduino и узнать больше о ее возможностях, вы должны знать чуть больше о происходящем в ее глубинах.

Краткая история Arduino

Первая плата Arduino была создана в 2005 году в итальянском Институте проектирования взаимодействий (Interaction Design Institute) в городе Ивреа, близ Турина. Целью было создание недорогого и простого в использовании инструмента для обучения студентов искусству проектирования интерактивных систем. Программное обеспечение для Arduino, которое обеспечило этой плате значительную долю успеха, является доработкой открытого фреймворка с названием Wiring, созданного студентом этого же института.

Доработанная версия для Arduino получилась очень близкой к оригиналу Wiring, а среда разработки Arduino IDE написана с использованием фреймворка Processing, старшего брата Wiring, способного работать на PC, Mac и других персональных компьютерах. Вам стоит обратить внимание на Processing, если вы работаете над проектом, в котором плата Arduino должна обмениваться информацией с PC через USB или Bluetooth.

Аппаратура Arduino все эти годы продолжала развиваться, но современные платы Arduino Uno и Leonardo сохранили форму и набор контактов, доставшиеся от оригинала.

Устройство Arduino

На рис. 2.1 изображена структурная схема платы Arduino Uno. Модель Leonardo имеет схожее устройство, но интерфейс USB в ней интегрирован в чип микроконтроллера. Похожее устройство имеет и модель Due, но в ней используется процессор с напряжением питания 3,3 В вместо 5 В.


Рис. 2.1. Устройство платы Arduino Uno

Во многих отношениях Arduino — не более чем микроконтроллер с небольшим количеством поддерживающих компонентов. В действительности вполне можно создать Arduino на макетной плате, добавив микропроцессор и несколько дополнительных компонентов, или создать свою печатную плату, взяв за основу плату Arduino. Готовые платы Arduino избавляют от такой необходимости, но вообще можно повторить любую плату Arduino, используя микроконтроллер и несколько действительно необходимых компонентов. Например, если ваша разработка предназначена только для одной цели, есть смысл отказаться от интерфейса USB, так как программы можно выгружать в микросхемы памяти на плате Arduino, а затем переносить их на свои платы.

Далее в книге будет показано, как можно программировать платы Arduino непосредственно через последовательный интерфейс внутрисхемного программирования ICSP (In Circuit Serial Programming).

Процессоры AVR

Во всех платах семейства Arduino используются микроконтроллеры, производимые компанией Atmel. Все они имеют схожую аппаратную архитектуру и, за исключением микроконтроллера, используемого в модели Due (SAM3X8E ARM Cortex-M3 CPU), схожую конструкцию.

ATmega328

В Arduino Uno и ее предшественнице Duemilanove используется микроконтроллер ATmega328. Фактически первые версии Arduino комплектовались микроконтроллером ATmega168, который, по сути, является полным аналогом ATmega328, но имеет в два раза меньше памяти каждого вида.

На рис. 2.2 изображена функциональная схема ATmega328 из технического описания микроконтроллера. Полное описание можно найти по адресу www.atmel.com/Images/doc8161.pdf. Вам стоит просмотреть ее, чтобы лучше понимать, как действует это устройство.

Центральный процессор — то место, где выполняются все операции. Процессор читает инструкции (скомпилированный код скетча) из флеш-памяти по одной за раз. Этот процесс отличается от обычного для компьютеров, где программы хранятся на диске и перед выполнением загружаются в оперативное запоминающее устройство (ОЗУ). Переменные, используемые в программе, хранятся отдельно, в статическом ОЗУ. В отличие от флеш-памяти, где хранится код программы, ОЗУ является энергозависимым и теряет свое содержимое при выключении питания.


Рис. 2.2. ATmega328

Для данных, которые должны сохраняться даже после выключения питания, следует использовать память третьего типа — электрически стираемую программируемую постоянную память (Electrically Erasable Programmable Read-Only Memory, EEPROM).

Еще одна интересная область — сторожевой таймер и устройство управления питанием. Они открывают для микроконтроллера множество дополнительных возможностей, обычно скрытых за уровнем упрощения Arduino, в том числе перевод микропроцессора в экономичный режим с последующей установкой таймера для периодического перевода в нормальный режим. Этот трюк может пригодиться для создания приложений с низким энергопотреблением. Подробнее об этом рассказывается в главе 5.

Все остальное на рис. 2.2 так или иначе связано с аналого-цифровым преобразователем, портами ввода/вывода и последовательными интерфейсами трех типов, поддерживаемыми микроконтроллером: УСАПП, ППИ и ДПИ.

ATmega32u4

Микроконтроллер ATmega32u4В используется в моделях Arduino Leonardo и LilyPad USB, а также Micro и Nano. Он похож на ATmega328, но имеет более современный чип с несколькими дополнениями, отсутствующими в ATmega328:

• со встроенным интерфейсом USB, благодаря чему отпала необходимость в дополнительных аппаратных компонентах поддержки USB;

• с большим числом контактов с возможностью ШИМ;

• с двумя последовательными портами;

• с отдельными контактами интерфейса I2C (в Arduino эти контакты также играют роль аналоговых входов/выходов);

• с объемом статического ОЗУ больше на 0,5 Кбайт.

В модели Leonardo используется микроконтроллер в корпусе для поверхностного монтажа, то есть он припаивается непосредственно к плате, тогда как ATmega328 выпускается в корпусе с двумя рядами контактов, вставляемом в панель для интегральных микросхем, как на плате Arduino Uno.

ATmega2560

Микроконтроллер ATmega2560 используется в моделях Arduino Mega 2560 и Arduino Mega ADK. Он не быстрее других микроконтроллеров ATmega, но имеет больше памяти каждого типа (256 Кбайт флеш-памяти, 8 Кбайт статического ОЗУ и 4 Кбайт ЭСППЗУ), а также намного больше контактов ввода/вывода.

AT91SAM3X8E

Этот микроконтроллер является сердцем Arduino Due. Он существенно быстрее других микроконтроллеров ATmega, упоминавшихся ранее, и работает на тактовой частоте 84 МГц против обычных для ATmega 16 МГц. Имеет 512 Кбайт флеш-памяти и 96 Кбайт статического ОЗУ. Данный микроконтроллер не имеет ЭСППЗУ. Поэтому для долговременно хранения данных требуется использовать дополнительные устройства, такие как держатели карт памяти или устройства с флеш-памятью или ЭСППЗУ. Сам микроконтроллер обладает множеством дополнительных особенностей, включая два аналоговых выхода, делающих его идеальным инструментом для генерации звуков.

Arduino и Wiring

Фреймворк Wiring включает простые в использовании функции управления контактами на плате Arduino, однако основная его часть написана на языке C.

До недавнего времени в каталоге установки Arduino IDE можно было найти файл WProgram.h (программа Wiring). Теперь его замещает похожий файл с именем Arduino.h, что свидетельствует о постепенном отдалении Arduino от первоначального проекта Wiring.

Заглянув в каталог установки Arduino IDE, можно увидеть папку hardware, внутри нее — папку arduino, а внутри этой папки — папку cores. Обратите внимание на то, что в Mac в эту папку можно попасть, только если щелк­нуть правой кнопкой на ярлыке приложения Arduino, выбрать в контекстном меню пункт View Package Contents (Показать содержимое пакета) и затем перейти в папку Resources/Java/.

Внутри папки cores находится еще одна папка с именем arduino, в которой вы найдете множество заголовочных файлов на языке C с расширением .h и файлов реализации на языке C++ с расширением .cpp (рис. 2.3).


Рис. 2.3. Внутри папки cores

Открыв Arduino.h в текстовом редакторе, вы увидите, что он состоит из множества инструкций #include. Они подключают определения из других заголовочных файлов в папке cores/arduino в процессе компиляции (преобразования скетча в форму, пригодную для записи во флеш-память микроконтроллера).

Там же можно увидеть определения констант, например:

#define HIGH 0x1

#define LOW  0x0

#define INPUT 0x0

#define OUTPUT 0x1

#define INPUT_PULLUP 0x2

Они немного похожи на переменные в том смысле, что, обратившись к имени HIGH, например, программа получит значение 1. Значение определено как 0x1, а не как 1, потому что в этом файле все значения определяются в шестнадцатеричном формате (в системе счисления с основанием 16). Эти определения в действительности не являются переменными — их называют директивами препроцессора C, то есть когда ваш скетч будет преобразован в формат, пригодный для записи во флеш-память микроконтроллера, все слова HIGH, LOW и другие автоматически будут преобразованы в соответствующие числа. Это дает определенные преимущества перед использованием переменных, так как не требуется выделять память для их хранения.

Так как эти константы являются числовыми, вы можете, например, перевести контакт 5 в режим OUTPUT, как показано далее, но все же лучше пользоваться символическими именами на тот случай, если разработчики Arduino решат изменить значения констант. Кроме того, использование имен упрощает чтение программного кода.

setMode(5, 1);

setMode(5, OUTPUT);

Также в файле arduino.h присутствует множество сигнатур функций, например таких:

void pinMode(uint8_t, uint8_t);

void digitalWrite(uint8_t, uint8_t);

int digitalRead(uint8_t);

int analogRead(uint8_t);

void analogReference(uint8_t mode);

void analogWrite(uint8_t, int);

Они предупреждают компилятор о функциях, которые фактически реализуются где-то в другом месте. Возьмем, для примера, первую сигнатуру. Она сообщает, что функция pinMode принимает два аргумента (которые, как вы уже знаете, представляют номер контакта и режим) типа uint8_t. Команда void говорит, что после вызова функция ничего не возвращает.

Вам может показаться странным, почему для параметров выбран тип uint8_t, а не int. Обычно, определяя номер контакта, вы указываете значение типа int. На самом деле int — это универсальный тип, широко используемый в скетчах. Он избавляет пользователей от проблемы выбора из большого разнообразия доступных типов. Но в диалекте языка C для Arduino тип int представляет 16-битные целые значения со знаком в диапазоне между –32 768 и 32 767. Однако номер контакта не может быть отрицательным, и вам едва ли когда-нибудь попадется плата Arduino с 32 767 контактами.

Тип uint_8 намного точнее определяет диапазон допустимых значений, потому что вообще в языке C тип int может представлять значения с разрядностью от 16 до 64 битов в зависимости от конкретной реализации C. Имя типа uint_8 читается так: символ u говорит, что это беззнаковый (unsigned) тип, int сообщает, что это целочисленный тип, и, наконец, число после символа подчеркивания (_) сообщает количество битов. То есть тип uint_8 представляет 8-битные целые числа без знака в диапазоне между 0 и 255.

Вы свободно можете использовать в своих скетчах эти более строгие типы, что некоторые и делают. Но помните, что это сделает ваш код чуть труднее для понимания теми, кто не искушен в программировании для Arduino.

Возможность использования обычного типа int, представляющего 16-битные целые числа со знаком, вместо типа unit_8, например, объясняется способностью компилятора автоматически выполнять необходимые преобразования. Использование переменных типа int для хранения номеров контактов приводит к напрасному расходованию памяти. Поэтому вам придется искать компромисс между объемом памяти для хранения данных и удобочитаемостью кода. Как правило, в программировании предпочтение отдается простоте чтения кода, если только вы не собираетесь создать нечто очень сложное, способное превысить ограничения микроконтроллера.

Здесь можно провести аналогию с грузовиком, который вы собираетесь использовать для доставки чего-то кому-то. Если требуется перевезти большой объем груза, вам придется подумать, как упаковать и расположить его, чтобы он уместился весь. Если груз занимает лишь малую часть площади кузова, нет смысла тратить много времени на его упаковку и размещение.

Также в папке arduino можно найти файл main.cpp. Открыв его, вы увидите кое-что интересное.

int main(void)

{

    init();

#if defined(USBCON)

    USBDevice.attach();

#endif

    setup();

    for (;;) {

        loop();

        if (serialEventRun) serialEventRun();

    }

    return 0;

}

Если прежде вам доводилось программировать на языке C, C++ или Java, вы должны быть знакомы с идеей функции main. Эта функция автоматически вызывается в момент запуска программы. Функция main — это главная точка входа в программу. Это утверждение справедливо и для программ Arduino, только скрыто от глаз разработчиков скетчей, которые обязаны реализовать в своих скетчах две функции — setup и loop.

Если вчитаться в файл main.cpp, пропустив пока первые несколько строк, можно заметить, что функция main вызывает setup() и затем входит в бесконечный цикл for, где вызывает функцию loop.

Команда for(;;) — это, пусть и малопонятный, способ записи while (true). Обратите внимание на то, что кроме вызова функции loop внутри цикла for имеется также команда if, которая проверяет поступление сообщений в последовательный порт и обслуживает их.

Вернувшись в начало файла main.cpp, можно увидеть, что в первой строке находится команда include, подключающая все определения из заголовочного файла arduino.h, о котором я говорил прежде.

Далее находится определение функции main, которая начинается с вызова функции init(). Если поискать, ее можно найти в файле wiring.c, она вызывает функцию sei, разрешающую прерывания.

Строки

#if defined(USBCON)

    USBDevice.attach();

#endif

являются еще одной директивой препроцессора C. Данный код действует подобно команде if, которую вы можете использовать в своих скетчах, но выполняется она не тогда, когда скетч уже работает в Arduino. Проверка условия в директиве #if происходит во время компиляции скетча. Данная директива дает отличную возможность включать и выключать фрагменты кода в зависимости от конкретного типа платы. В данном случае, если Arduino поддерживает интерфейс USB, в программу включается код, подключающий (инициализирующий) его, в противном случае нет никакого смысла компилировать его.

Из скетча в Arduino

Теперь, когда вы узнали, откуда берется весь этот магический код, когда пишется даже самый простой скетч для Arduino, можно посмотреть, как этот код попадает во флеш-память микроконтроллера на плате Arduino, когда вы щелкаете на кнопке Upload (Загрузить) в Arduino IDE.

На рис. 2.4 показано, что происходит после щелчка на кнопке Upload (Загрузить).


Рис. 2.4. Комплект инструментов Arduino

Скетчи для Arduino хранятся в виде текстовых файлов с расширением .ino в папке с тем же именем, но без расширения.

Когда пользователь пытается выгрузить скетч в плату, в дело включается среда разработки Arduino IDE, которая управляет множеством вспомогательных программ, выполняющих основную работу. Сначала компонент Arduino IDE, который я (за неимением лучшего названия) называю препроцессором (Arduino IDE preprocessor), собирает файлы, составляющие скетч. Обратите внимание на то, что обычно скетч состоит из единственного файла. При желании в папку скетча можно добавить другие файлы, правда, при этом для их создания придется использовать другой редактор.

Если в папке присутствуют другие файлы, они также будут включены в процесс сборки. Файлы с программным кодом на языках C и C++ компилируются отдельно друг от друга. В начало главного файла скетча добавляется строка, подключающая arduino.h.

Так как существует множество разных моделей плат Arduino, использующих разные микроконтроллеры с разными наименованиями контактов, Arduino IDE должна выбрать правильные их определения. Если заглянуть в папку hard-ware/arduino/variants, можно увидеть отдельные папки для всех моделей плат Arduino, в каждой из которых хранится свой файл pins_arduino.h. Этот файл содержит имена контактов для своей платформы.

После объединения файлов вызывается компилятор GCC. Это компилятор C++, распространяемый с открытым исходным кодом и входящий в состав дистрибутива Arduino. Он принимает скетч, заголовочный файл и файлы реализации с исходным кодом на C и преобразует их в код, который может выполняться микроконтроллером на плате Arduino. Этот компилятор выполняет следующие шаги.

1. Препроцессор интерпретирует все команды #if и #define и определяет, какой код должен быть скомпилирован.

2. Затем выполняются компиляция и компоновка кода в единственный файл, пригодный для выполнения процессором на плате.

3. Когда компилятор завершит свою работу, запускается открытый программный компонент с названием avrdude, который пересылает в плату выполняемый двоичный код в шестнадцатеричном формате через последовательный интерфейс USB.

Теперь мы в царстве Arduino. В плате Arduino имеется небольшая резидентная программа, устанавливаемая в каждый микроконтроллер. Эта программа называется загрузчиком (bootloader). Загрузчик выполняется каждый раз, когда происходит сброс платы Arduino. Именно поэтому, когда происходит передача данных по последовательному интерфейсу, аппаратура связи в Arduino Uno производит принудительный сброс платы, чтобы дать загрузчику возможность проверить входящие скетчи.

Если был получен скетч, плата Arduino программирует сама себя, распаковывая шестнадцатеричное представление программы в двоичное и сохраняя его во флеш-памяти. Когда в следующий раз произойдет сброс платы, после обычной проверки на наличие нового скетча загрузчик автоматически запустит программу, хранящуюся во флеш-памяти.

Возникает естественный вопрос: почему компьютер не может запрограммировать микроконтроллер напрямую, минуя такую сложную процедуру? Причина в том, что для программирования микроконтроллера требуется специальная аппаратура, использующая другой способ связи с платой Arduino (кто-нибудь из вас спрашивал себя, зачем на плате колодка с шестью контактами?). Благодаря загрузчику, постоянно прослушивающему последовательный порт, мы можем программировать Arduino через USB без использования специальной аппаратуры.

Однако если у вас есть такой программатор, например AVRISPv2, AVRDragon или USBtinyISP, с его помощью вы сможете программировать Arduino напрямую, в обход загрузчика. Фактически, как будет показано далее в этой главе, в роли такого программатора можно использовать вторую плату Arduino.

AVR Studio

Тертые инженеры-электронщики могут выразить свое презрение к Arduino IDE, заявив, что она не имеет никаких преимуществ перед инструментами компании Atmel для программирования всего семейства микроконтроллеров AVR. С технической точки зрения это верно. Но при этом не учитывается, что Arduino помогает раскрыть все тайны процесса использования микроконтроллеров и выйти из-под контроля таких экспертов. Действительно, многое из того, что делает нас поклонниками Arduino, можно считать дилетантством, и в ответ на это я могу только сказать: «Ну и что!»

AVR Studio — это лицензионное программное обеспечение, предоставляемое производителем для программирования микроконтроллеров, на основе которых сконструированы платы Arduino. Его можно использовать вместо Arduino IDE. Однако в этом случае вам придется смириться со следующими ограничениями.

• Работа возможна только в окружении Windows.

• Программирование выполняется с использованием специального оборудования вместо USB.

• Среда разработки сложнее в использовании.

Возможно, вам захочется узнать, почему может возникнуть желание использовать эту среду. Вот некоторые веские причины.

• Чтобы избавиться от загрузчика (в модели Uno он занимает 500 байт), например из-за нехватки флеш-памяти или желания обеспечить более быстрый запуск программы после сброса.

• Чтобы использовать микроконтроллеры, отличные от тех, что применяются в стандартных платах Arduino, например маленькие и недорогие микроконтроллеры семейства ATtiny.

• Просто чтобы освоить что-то новое.

Все платы Arduino снабжаются колодкой с шестью контактами, которые можно использовать для непосредственного программирования Arduino с применением AVR Studio. Фактически некоторые модели имеют две такие колодки: одна связана с основным процессором, а другая — с интерфейсом USB, поэтому будьте внимательнее при выборе нужной.

На рис. 2.5 показано, как выглядит пользовательский интерфейс программы AVR Studio 4.

Изучение AVR Studio выходит за рамки этой книги. Однако, как можно видеть на рис. 2.5, скетч Blink не стал длиннее, но определенно выглядит намного сложнее! И в результате его компиляции выполняемый код занимает намного меньше места во флеш-памяти в сравнении с его аналогом в Arduino.

На рис. 2.6 изображена плата Arduino, подключенная к программатору AVR Dragon. Это очень гибкое и мощное устройство, позволяющее в пошаговом режиме отлаживать программы, фактически выполняющиеся на микроконтроллере ATmega.

В главе 4 мы рассмотрим непосредственное взаимодействие с портами, реализацию которого можно видеть на рис. 2.5. Этот прием позволяет улучшить производительность ввода/вывода и продолжать пользоваться преимуществами Arduino IDE.


Рис. 2.5. AVR Studio


Рис. 2.6. Плата Arduino, подключенная к программатору AVR Dragon

Установка загрузчика

Установка загрузчика в плату Arduino может потребоваться по нескольким причинам. Например, вы могли по неосторожности повредить извлекаемый микроконтроллер ATmega328 на плате Arduino Uno и решили заменить его новым ATmega328, приобретенным без загрузчика. Или, занимаясь собственными разработками, вы решили взять микроконтроллер ATmega328 из платы Arduino и вставить его в плату собственной конструкции.

В любом случае имеется возможность установить загрузчик в «чистый» микроконтроллер ATmega328, используя любой из программаторов, упоминавшихся в предыдущем разделе, или с помощью второй платы Arduino.

Установка загрузчика с помощью AVR Studio и программатора

В папке установки Arduino IDE имеются шестнадцатеричные файлы загрузчиков, которые можно записать в ATmega328 с помощью AVR Studio. Эти файлы находятся в папке hardware/arduino/bootloaders. Там вы найдете шестнадцатеричные файлы для всех видов микроконтроллеров. Если вам требуется установить загрузчик в модель Uno, используйте optiboot_atmega328.hex в папке optiboot (рис. 2.7).

Но имейте в виду следующее: при установке загрузчика есть вероятность того, что ваш микроконтроллер превратится в «кирпич». Микроконтроллеры имеют то, что называют битами защиты, которые можно неправильно запрограммировать без возможности восстановления. Они встраиваются для защиты коммерческих интересов, чтобы предотвратить возможность перепрограммирования. Прежде чем сделать решающий шаг, проверьте внимательно, что биты защиты установлены правильно для той платы Arduino, которую вы собираетесь запрограммировать, и подготовьтесь к худшему. На форуме Arduino (www.arduino.cc/forum) [7] вы найдете множество обсуждений этой темы наряду с советами, как избежать неприятностей.

Чтобы записать загрузчик с помощью AVR Studio и программатора AVR Dragon, подключите программатор к колодке с контактами ICSP (рис. 2.6).


Рис. 2.7. Установка загрузчика в плату Uno в среде AVR Studio 4

Обратите внимание на то, что на плате Arduino Uno имеются две такие колодки (вторая используется для программирования интерфейса USB).

В меню Tools (Инструменты) выберите пункт Program AVR (Программировать AVR) и установите соединение с микроконтроллером ATmega328 в плате Arduino. Затем в разделе Flash (Флеш-память) выберите требующийся шестнадцатеричный файл и щелкните на кнопке Program (Программировать).

Установка загрузчика с помощью Arduino IDE и второй платы Arduino

Установка нового загрузчика с другой платы Arduino выполняется очень просто. Этот подход намного проще и безопаснее, чем использование AVR Studio. Среда разработки Arduino IDE включает необходимую функцию. Далее перечислено все, что вам потребуется:

• две платы Arduino Uno;

• 6-проводной шлейф с двумя разъемами «папа–папа» (или шесть изолированных проводов);

• один короткий изолированный провод;

• конденсатор на 10 мкФ и 10 В (также подойдет конденсатор на 100 мкФ).

Сначала нужно соединить платы проводами, как описывается в табл. 2.1.

Таблица 2.1. Соединение контактов двух плат Arduino для записи загрузчика

Плата-программатор Программируемая плата
GND GND
5 V 5 V
13 13
12 12
11 11
10 Reset

Конденсатор емкостью 10 мкФ включите между контактами Reset и GND на программируемой плате Arduino (то есть на плате, куда будет записан загрузчик). Более длинный положительный вывод конденсатора должен быть подключен к контакту Reset.

На рис. 2.8 показаны соединенные платы Arduino. Плата справа выступает в роли программатора. Обратите внимание на то, как контакт 10 платы-программатора соединен изолированным проводом с контактом Reset программируемой платы. Соединение выполнено так, что к одному контакту Reset на программируемой плате одновременно подключены провод и положительный вывод конденсатора.

Имейте в виду, что плата, выступающая в роли программатора, управляет программируемой платой, поэтому к порту USB компьютера должна быть подключена только плата-программатор.

На плату-программатор требуется установить специальный скетч. Его можно найти в меню File—>Examples (Файл—>Примеры). Он называется ArduinoISP и находится в конце раздела Examples (Встроенные примеры).


Рис. 2.8. Программирование с помощью второй платы Arduino

Как обычно, выберите тип платы и порт и выгрузите скетч ArduinoISP в плату-программатор. Затем в меню Tools (Инструменты) перейдите в подменю Programmer (Программатор) и выберите пункт ArduinoISP.

Наконец, выберите в меню Tools (Инструменты) пункт Burn Bootloader (Записать Загрузчик). Процедура записи займет одну-две минуты, в течение которых должны мигать светодиоды Rx и Tx на плате-программаторе и светодиод L на программируемой плате.

Когда процедура завершится, в программируемый микроконтроллер будет установлен новый загрузчик.

В заключение

В этой главе мы заглянули под капот платы Arduino и посмотрели, как она работает в действительности. Я показал вам, что скрывается за фасадом окружения Arduino.

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

Оглавление книги


Генерация: 1.168. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз