В данном уроке кратко рассмотрены основные инструменты C/C++ с запускаемыми примерами для Arduino. Каждая глава имеет подробную версию в разделе уроков C/C++ со всей теорией.
Переменные и константы #
Рекомендуется изучить следующие уроки:
Переменная - ячейка памяти, которая имеет имя и может хранить значение указанного типа, создаётся следующим образом: тип имя;
или тип имя = значение
. К переменной можно присвоить значение в процессе работы, в том числе другую переменную или результат вычислений:
void setup() {
Serial.begin(115200);
int a = 0;
int b = 123;
Serial.println(a); // вывод 0
Serial.println(b); // вывод 123
a = b;
b = 456;
Serial.println(a); // вывод 123
Serial.println(b); // вывод 456
}
void loop() {
}
Arduino-типы #
Фреймворк Arduino добавляет два новых типа данных, которые являются синонимами к стандартным типам:
byte
- синонимunsigned char
,uint8_t
boolean
- синонимbool
Математические операции #
Рекомендуется изучить следующие уроки:
Синтаксис и правила математических операций такие же, как "на бумаге":
void setup() {
Serial.begin(115200);
int a = 10;
int b = a * 3;
Serial.println(b); // вывод 30
b = (a + 5) * (a - 5);
Serial.println(b); // вывод 75
b /= 5;
Serial.println(b); // вывод 15
float pi = 3.14;
float r = 10;
float l = 2 * pi * r;
Serial.println(l); // вывод 62.80
}
void loop() {
}
Логика и сравнение #
Рекомендуется изучить следующие уроки:
В программе можно сравнивать значения и выполнять действия по результату логических выражений:
void setup() {
Serial.begin(115200);
int a = 10;
int b = 20;
if (a >= 0) Serial.println("a больше или равно 0");
if (b == 20) Serial.println("b равно 20");
if (a > b) {
Serial.println("a больше b");
} else {
Serial.println("a меньше b");
}
if (a + b == 30) Serial.println("a + b равно 30");
else Serial.println("a + b не равно 30");
Serial.println(a == 10); // вывод 1, если a равно 10, иначе 0
Serial.println(a == 20); // вывод 1, если a равно 20, иначе 0
if (a >= 0 && a <= 10) Serial.println("a в диапазоне от 0 до 10");
if (a == 0 || a == 10) Serial.println("a равно 0 ИЛИ 10");
if (a == 10 && b == 20) Serial.println("a равно 10 И b равно 20");
}
void loop() {
}
Выбор #
Рекомендуется изучить следующие уроки:
Оператор выбора позволяет выбирать, какой код будет выполняться, исходя из переданного значения:
void setup() {
Serial.begin(115200);
int a = 10;
switch (a) {
case 0:
Serial.println("a равно 0");
break
case 10:
Serial.println("a равно 10");
break;
default:
Serial.println("a неизвестно");
break;
}
}
void loop() {
}
Цикл for #
Рекомендуется изучить следующие уроки:
Цикл-счётчик позволяет одной строкой создать блок кода, который будет выполняться согласно заданным условиям:
void setup() {
Serial.begin(115200);
for (int i = 0; i < 5; i++) {
Serial.print(i);
Serial.print(',');
}
// вывод 0,1,2,3,4,
}
void loop() {
}
Цикл while #
Рекомендуется изучить следующие уроки:
Выполняется, пока верно условие:
void setup() {
Serial.begin(115200);
int i = 5;
while (i > 0) {
Serial.print(i);
Serial.print(',');
i--;
}
// вывод 5,4,3,2,1,
}
void loop() {
}
Массивы #
Рекомендуется изучить следующие уроки:
- Массивы - первую половину
Массив - несколько переменных одного типа, объединённых под одним именем. Обращаться к элементам массива нужно через квадратные скобки []
:
void setup() {
Serial.begin(115200);
int arr[] = {1, 2, 3, 4, 5};
// вывод
for (int i = 0; i < 5; i++) {
Serial.print(arr[i]);
}
// печать 01234
Serial.println();
// изменение
for (int i = 0; i < 5; i++) {
arr[i] = i * 2;
// i = 0, 1, 2, 3
// i*2 = 0, 4, 6, 8
}
// вывод
for (int i = 0; i < 5; i++) {
Serial.print(arr[i]);
}
// печать 02468
Serial.println();
// вывод
for (int v : arr) {
Serial.print(v);
}
// печать 02468
Serial.println();
}
void loop() {
}
Функции #
Рекомендуется изучить следующие уроки:
Функция - блок кода, который можно вызвать по имени:
void hello() {
Serial.println("Hello!");
}
void setup() {
Serial.begin(115200);
hello(); // вывод Hello!
hello(); // вывод Hello!
}
void loop() {
}
Функция может принимать аргументы указанного типа:
void print(int x) {
Serial.println(x);
}
void setup() {
Serial.begin(115200);
print(123); // вывод 123
print(3.14); // вывод 3, т.к. автоматически конвертируется в int
}
void loop() {
}
Функция может возвращать данные указанного типа:
int sum(int x, int y) {
return x + y;
}
void setup() {
Serial.begin(115200);
int s = sum(3, 4);
Serial.println(s); // вывод 7
Serial.println(sum(10, 20)); // вывод 30
}
void loop() {
}
define #
Данная команда позволяет определить в программе "константу" и часто используется на практике. Подробнее читайте в уроке про директивы препроцессора.
#define MY_CONST 3
#define MY_CONST_1 123
void setup() {
Serial.begin(115200);
Serial.println(MY_CONST); // вывод 3
int a = MY_CONST_1;
Serial.println(a); // вывод 123
}
void loop() {
}
include #
Данная команда позволяет подключить в программу другой файл. Подробнее читайте в уроке про директивы препроцессора.
#include <math.h> // подключить системную библиотеку math.h
#include <SPI.h> // подключить Arduino-библиотеку SPI.h
void setup() {
}
void loop() {
}
Задержка #
Как обсуждалось ранее, функция loop
вызывается на всём протяжении работы программы. Как часто она это делает? По сути - с максимальной скоростью, на которую способен процессор. Но "вне" этой функции он выполняет некоторые системные задачи, поэтому loop
вызывается с чуть меньшей скоростью - порядка десятков и сотен тысяч раз в секунду. Загрузите следующую программу и откройте монитор порта:
void setup() {
Serial.begin(115200);
}
int x = 0;
void loop() {
Serial.println(x);
x++;
}
В мониторе с большой скоростью побегут числа, увеличивающиеся на единицу. Любой код, добавленный в loop
, имеет конечное время выполнения, в том числе - вывод в Serial. Поэтому в мониторе вы увидите новые числа по сути со скоростью отправки данных, то есть частота вызова loop
уже чуточку снизилась.
Давайте посильнее нагрузим процессор, например работой с дробными числами: пусть в loop
считается сумма синусов 500 случайных чисел:
void setup() {
Serial.begin(115200);
}
void loop() {
float x = 0;
for (int i = 0; i < 500; i++) {
x += sin(random(100));
}
Serial.println(x);
}
Скорость работы снизится очень сильно - до нескольких выводов в секунду!
Для простоты написания синхронного кода в Arduino существует задержка - функция delay(время)
: программа "зависнет" внутри этой функции на указанное время в миллисекундах:
void setup() {
Serial.begin(115200);
}
int x = 0;
void loop() {
Serial.println(x); // вывести
x++; // увеличить на 1
delay(1000); // подождать секунду
}
Данная программа будет выводить увеличивающееся на единицу число раз в секунду (1000 миллисекунд). Задержки позволяют писать визуально очень понятный код, но такая программа по сути сможет делать только одну задачу синхронно - выполнять свои действия и ждать указанное время. Написание асинхронных программ рассмотрим в следующих уроках, пока что в простых программах будем использовать задержки.