Если вы с языком С до сих пор не знакомы, то учтите, что логики и стройности в нем немного, зато очень много лишнего и непонятного. Не унывайте — чтобы овладеть Arduino, изучать язык досконально не требуется, Processing и был придуман для тех, кто не хочет углубляться в программирование. Нам сейчас будет достаточно следующих элементарных сведений.
Любая программа в среде Arduino состоит из трех основных блоков: блока определений, функции установок и бесконечного цикла, который и составляет собственно программу. Эти блоки полностью аналогичны структуре нашей ассемблерной программы (см. главу 19
, где с блока определений начиналась программа, функция установок у нас следовала за меткой Reset, а бесконечный цикл заключал текст, который выполняется вне прерываний (у нас — то, что между меткой Cykle: и оператором rjmp Cykle). Явное использование прерываний в программах Arduino — скорее исключение, что относится к числу недостатков этой платформы (и мы еще будем об этом говорить).* * *
Подробности
Но было бы ошибкой считать, что прерывания в Arduino не используются вовсе. Например, в Arduino отсчет времени реализован совершенно так же, как мы делали в главе 19
, только не с помощью Time1, как у нас, а через восьмиразрядный Timer0. Здесь тоже устанавливается прерывание таймера по переполнению и тоже с коэффициентом предделителя 64. При обычной тактовой частоте Arduino, равной 16 МГц, прерывания переполнения восьмиразрядного таймера происходят каждые (64/16)·256 = 1024 микросекунды, что позволяет реализовать такие функции, как millis () или delay (). Самый частый отсчет возможен при таком коэффициенте каждые 4 микросекунды, что обуславливает приведенное в справочнике по функциям Arduino максимальное разрешение функции отсчета микросекунд micros (). Любопытно, что задержка в микросекундах (т. е. функция delayMicroseconds ()) при этом реализована в виде простой программной задержки, как мы делали в первом примере главы 19. Функции коммуникационного порта, кстати, также основаны на прерываниях (см. далее).* * *
Блок определений содержит обычные для почти любого языка программирования ссылки на включаемые библиотеки и определения переменных, например:
#include
//подключаем библиотеку для работы со строчным ЖК-индикаторомint i;
//переменная i — 16-разрядный счетчикbyte temp = 0;
//рабочая переменная типа bytefloat temperature;
//переменная — действительное число для значения температурыОпределение наименований выводов, как констант:
#define dataPin 16
//dataPin — цифровой вывод 16[40] (т. е. вывод А2 платы, см. далее)Выводы можно определять и как переменные целого типа:
int ledPin =3;
// цифровой выход управления светодиодомСтрочные и заглавные буквы здесь различаются, например, string ()
и String () — это разные функции (см. справочник по языку на сайте [23]). В языке С любые определения можно делать в любом месте программы, выносить их в начало необязательно. Только стоит учесть, что, например, вызов переменной, определенной внутри некоей функции (локальная переменная), в другой функции вызовет сообщение об ошибке. Для того чтобы переменная действовала для всей программы, она должна быть определена именно в начале, до всех функций (глобальная переменная). Нюанс заключается в том, что глобальная переменная займет ресурсы контроллера на все время работы программы, тогда как локальная освободит их по окончании действия функции. В условиях ограниченных ресурсов МК это может оказаться существенным фактором, влияющим на скорость выполнения программы.Наша процедура Reset
(блок установок) здесь выглядит, как функция setup: