Вам может показаться странным, почему для параметров выбран тип 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.
Читать дальше