Arduino – Serial – последовательный порт

Каждая платформа Arduino имеет, по крайней мере, один последовательный порт, который обеспечивает передачу данных от микроконтроллера и обратно.

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

Arduino UNO имеет один аппаратный последовательный порт, подключенный к порту USB.  Arduino MEGA имеет три дополнительных последовательных порта, которые можно использовать для своих целей.

Мы ссылаемся на отдельные последовательные порты через последовательные объекты. Во всех системах Arduino реализован объект Serial, который отвечает за передачу данных через первый доступный последовательный порт. В Arduino MEGA дополнительно реализован Serial1, Serial2, Serial3. Все приведенные ниже примеры для Serial также относятся и к Serial1, Serial2 и Serial3.

Функция Serial.begin()

Основным элементом при использовании последовательной передачи данных, является инициализация последовательного порта. Нам необходимо определить скорость передаваемой информации, а также параметры порта. Скорость передачи данных определяется бодами, то есть битами в секунду. Параметры порта определяются количеством переданных битов, четностью и стоп-битами.

Чтобы установить параметры передачи, мы используем функцию Serial.begin(), которая принимает один или два параметра. Первым параметром является скорость передачи данных, второй параметр – параметр порта. Ниже приведен пример использования метода Serial.begin():

void setup()
{
Serial.begin(9600);
Serial2.begin(9600); // Только для версия Arduino MEGA
Serial.begin(1440,SERIAL_8N1);
}

Как вы можете видеть в приведенном выше примере, мы можем инициализировать последовательный порт, используя один или два аргумента. Если второй аргумент не задан, то система по умолчанию устанавливает значение 8N1 (8 бит данных, без четности, 1 стоповый бит).

Стандартная скорость передачи данных составляет: 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600 или 115200. Кроме того, можно задать свою скорость передачи (путем указания ее значения). Допустимыми параметрами порта являются:

  • SERIAL_5N1
  • SERIAL_6N1
  • SERIAL_7N1
  • SERIAL_8N1 (по умолчанию)
  • SERIAL_5N2
  • SERIAL_6N2
  • SERIAL_7N2
  • SERIAL_8N2
  • SERIAL_5E1
  • SERIAL_6E1
  • SERIAL_7E1
  • SERIAL_8E1
  • SERIAL_5E2
  • SERIAL_6E2
  • SERIAL_7E2
  • SERIAL_8E2
  • SERIAL_5O1
  • SERIAL_6O1
  • SERIAL_7O1
  • SERIAL_8O1
  • SERIAL_5O2
  • SERIAL_6O2
  • SERIAL_7O2
  • SERIAL_8O2

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

Насколько важно определить параметры и скорость последовательного порта, мы рассмотрим на следующем примере:

void setup()
{
Serial.begin(9600,SERIAL_7O1);
}
void loop()
{
delay(500);
Serial.println("test");
}

При запуске терминала Arduino IDE мы увидим, что вместо передаваемого текста "test" мы получим непонятный набор символов. Теперь давайте немного изменим программу:

void setup()
{
Serial.begin(9600,SERIAL_8N1);
}
void loop()
{
delay(500);
Serial.println("test");
}

При загрузке исправленного варианта программы в терминале должно отображаться два раза в секунду ожидаемое слово "test".

Теперь измените в терминале скорость передачи данных с 9600 на 19200 бит/с (в правом нижнем углу). Опять же, мы увидим непонятный набор символов вместо "test". Как вы можете видеть, для правильной работы необходима установка идентичных параметров передачи данных.

Функции Serial.print() и Serial.println()

Функция Serial.print() позволяет отправлять информацию через последовательный порт. Можно отправлять как текстовые, так и переменные значения или непосредственно числа. Данные отправляются в кодировке ASCII. Это означает, что число, например, 12, будет отправлено как два символа 1 и 2. Вот типичный синтаксис Serial.print():

Serial.print(78); // число 78
Serial.print(1.23456); // количество 1.23
Serial.print('N'); // символ: N
Serial.print("Hello world."); // текст: Hello world.
Serial.print(78, BIN); // двоичное число: 1001110
Serial.print(78, OCT); // исходное восьмеричное число: 116
Serial.print(78, DEC); // десятичное число: 78
Serial.print(78, HEX); // шестнадцатеричное число: 4E
Serial.println(1.23456, 0); // первая цифра: 1
Serial.println(1.23456, 2); // три первые цифры: 1.23

Мы отправляем отдельные символы, заключая их в апострофы. Тексты размещаем в двойных кавычках. Числа без кавычек. Можно преобразовать числа в соответствующий формат - по умолчанию установлен десятичный формат.

Вариантом Serial.print() является функция Serial.println(), который отличается добавлением символа конца строки в конце сообщения. В следующем примере показаны различия в использовании этих двух функций:

Serial.print('A');
Serial.print('B');
Serial.println('C'); // ABC
Serial.print('D'); // DE
Serial.println('E'); // F
Serial.println('F'); // G
Serial.print('G');

Функция Serial.write()

В отличие от Serial.print() и Serial.println(), функция Serial.write() позволяет отправлять один байт информации (число). Ниже приведен синтаксис Serial.write():

Serial.write (число);
Serial.write ("текст");
Serial.write (массив, длина);

Примеры использования Serial.write():

byte a[]={65,66,67,68,69};
void setup()
{
Serial.begin(9600);
}
void loop()
{
Serial.print(65); // отправляет в терминал два символа 6 и 5
Serial.write(65); // отправляет в терминал код 65 (буква A в кодировке ASCII)
Serial.write(a,3); // отправляет в терминал коды 65, 66, 67 (A, B, C)
delay(800);
}

Как вы можете видеть в данном примере, при отправке числа 65 с помощью Serial.print() в терминале получим два символа 6 и 5, а отправка числа 65 с использованием Serial.write() в терминале будет интерпретироваться как код ASCII 65, т.е «А».

Функция Serial.available()

Функция Serial.available() позволяет проверить, можно ли прочитать данные из последовательного порта. Arduino имеет 64-байтовый буфер последовательного порта. Функция вызывается без параметров, возвращает количество доступных для чтения байт. Serial.available() позволяет исполнить часть программы, которая считывает данные из последовательного порта только при их появлении. Примеры использования Serial.available():

if(Serial.available())
{
//выполнить, если имеются данные
}
--------------------------------------------------------
while(!Serial.available()); // ждать данные с последовательного порта

В первом примере показано использование условия (if) для проверки доступных данных, и если данные прочитаны, выполняется фрагмент кода. Этот синтаксис, помещенный в функцию loop(), не блокирует его выполнение.

Во втором примере программа будет остановлена ​​до тех пор, пока в буфере не появляться данные, прочитанные из последовательного порта. Ниже приведено практическое использование Serial.available():

void setup()
{
Serial.begin(9600);
}
void loop()
{
if(Serial.available())
{
int x=Serial.available();
Serial.println(x);
}
delay(80);
}

Программа проверяет, поступили ли данные из последовательного порта. Если в буфере содержаться информация, то программа проверяет, сколько байтов поступило и отправляет эту информацию на терминал.

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

Функция serialEvent()

Функция serialEvent() - это специальная функция, такая же, как loop() или setup(), которая вызывается в тот момент, когда в буфер последовательного порта попадет информация. Она позволяет выполнять действия независимо от текущего выполнения кода. Как правило, эта функция содержит инструкции для чтения данных из последовательного порта. Пример использования serialEvent() приведен ниже:

void setup()
{
// предварительные настройки
}
void loop()
{
// код программы
}
void serialEvent()
{
// код для выполнения во время приема данных
}

ВНИМАНИЕ!!!: В соответствии с документацией Arduino данная функция не поддерживается в системах Esplora, Leonardo и Micro.

Функция Serial.read()

Данные из буфера последовательного порта считываются при помощи функции Serial.read(). Она извлекает один байт данных, уменьшая количество доступной информации в буфере. Ниже приведен пример использования Serial.read():

void setup()
{
Serial.begin(9600);
}
void loop()
{
if(Serial.available())
{
byte kol = Serial.read(); //чтение количества
Serial.println(kol);
//-------------------------------------------------
char znak=Serial.read(); //чтение кода символа
Serial.println(znak);
}
delay(80);
}

Вышеуказанная программа считывает данные из последовательного порта и отправляет их на терминал. Существует два способа интерпретации данных. В первом случае байт, считанный с порта, рассматривается как число. Терминал отобразит соответствующий символ ASCII, во втором случае прочитанный байт рассматривается как код ASCII. Когда вы запустите программу и введете букву «a» в первом случае, вы получите код «97», а во втором букву «a».

Функция Serial.readBytes()

Функция Serial.readBytes() позволяет читать большее количество байтов из последовательного порта и помещать данные в буфер. Функция Serial.readBytes() завершит работу в момент, когда будет прочитано соответствующее количество байтов или истечет установленное время. Синтаксис Serial.readBytes() показан ниже:

Serial.readBytes(буфер, длина);

Функция возвращает количество байтов, считанных в буфере или ноль, если данных нет.

Функция Serial.readBytesUntil()

Функция Serial.readBytesUntil() считывает данные из последовательного буфера в массив. Функция завершит работу, когда истечет время, либо обнаружит терминальный символ, либо считает данные указанной длинны. Синтаксис Serial.readBytes() показан ниже:

Serial.readBytesUntil (символ, буфер, длина);

Функция возвращает количество байтов, считанных в буфере, или ноль, если данных нет.

Функция Serial.setTimeout()

Функция Serial.setTimeout() позволяет задать время ожидания данных из последовательного порта для Serial.readBytes() и Serial.readBytesUntil(). По умолчанию установлено 1000 мс (1 сек).

Serial.setTimeout(время) // время в миллисекундах (тип long)

Ниже приведен пример использования Serial.readBytes(), Serial.readBytesUntil() и Serial.setTimeout():

void setup()
{
char buf[10];
Serial.begin(9600);
Serial.setTimeout(10000); // лимит времени 10 секунд
while(!Serial.available()); // ждать данные из порта
Serial.println("Start");
int x=Serial.readBytes(buf,4); // считать 4 байта
Serial.print("Polucheno simvolov: ");
Serial.println(x);

while(!Serial.available());
Serial.println("Start ");
x=Serial.readBytesUntil('X',buf,4); // считать 4 байта
Serial.print("Polucheno simvolov: ");
Serial.println(x);
}
void loop(){}

В первой части вышеприведенного примера будут прочитаны четыре байта данных, при условии, что эта операция будет выполнена в течение 10 секунд. Во второй части, помимо этого, чтение может быть прервано, когда в буфере появляется конкретный код (здесь код определен как «X»).

Функции Serial.find() и Serial.findUntil()

Функция Serial.find() считывает содержимое буфера в поисках конкретной строки. Функция возвращает true, когда строка найдена и false, когда данные не найдены. Ниже приведен пример кода программы:

void setup()
{
Serial.begin(9600);
}
void loop()
{
if(Serial.find("test")) Serial.println("ok.");
}

В данном примере программа считывает данные из буфера и когда полученные данные соответствуют строке поиска (test), то отображается сообщение (ok).

Serial.find() ожидает данные в течение времени, определенного с помощью функции Serial.setTimeout(). В случаях, когда в буфере имеется большое количество данных, то их можно обработать почти мгновенно. Когда же буфер пуст, функция ожидает следующую порцию данных в течение некоторого времени и заканчивается, возвращая соответствующее значение.

Serial.findUntil() - это вариант Serial.find(), который отличается от предшественника дополнительным аргументом, позволяющим прервать загрузку буфера последовательного порта. Пример синтаксиса показан ниже:

Serial.findUntil ( "text", "K");

Функция будет считывать данные из последовательного порта, пока не будет найдена строка поиска (text) или прочитан символ «K», или пока не пройдет определенное время (по умолчанию – 1 секунда).

Функция Serial.flush()

Функция Serial.flush() приостанавливает выполнение программы до окончания отправки данных через последовательный порт. Старые версии Arduino IDE одновременно очищали приемный буфер последовательного порта.

Функция Serial.peek()

Функция Serial.peek() позволяет считать еще один байт, расположенный в буфере приема без его удаления. Чтение данных этой функцией вернет тоже значение, что и идущий за ним вызов Serial.read() или производных. Если буфер пуст, функция возвращает -1.

Функция Serial.parseInt()

Функция Serial.parseInt() позволяет прочитать следующее целое число. Если время превышено, значение равно 0.

Функция Serial.parseFloat()

Функция Serial.parseFloat() позволяет считать первое попавшееся число с плавающей точкой. Если время превышено, значение будет равно 0.

редактор

Добавить комментарий

Ваш электронный адрес не будет опубликован.

*