Настройка UART соединения в Ардуино

Рассмотрим что такое и как настроить UART соединение в Ардуино, напишем небольшой скетч для понимания работы.

Определение UART

UART означает Универсальный асинхронный приемник/передатчик. Это аппаратное устройство (или схема), используемое для последовательной связи между двумя устройствами.

Ниже мы обсудим, что такое соединение UART и как оно работает. Мы также напишем простой эскиз, чтобы показать, как использовать UART-интерфейс Arduino Uno.

Из Википедии: Универсальный асинхронный приёмопередатчик (УАПП, англ. Universal Asynchronous Receiver-Transmitter, UART) — узел вычислительных устройств, предназначенный для организации связи с другими цифровыми устройствами. Преобразует передаваемые данные в последовательный вид так, чтобы было возможно передать их по одной физической цифровой линии другому аналогичному устройству.

Соединение UART-устройств

Подключение двух устройств UART друг к другу просто и понятно. На рисунке ниже показана основная схема подключения.

Один конец предназначен для передачи данных (называется TX-контакт), а другой - для приема данных (называется RX-контакт). Мы можем соединить только два UART устройства вместе.

Принцип действия

UART работает путем преобразования данных в пакеты для отправки или восстановления данных из полученных пакетов.

Отправка последовательных данных

Перед отправкой данных устройство UART преобразует байты данных в биты. После преобразования данных в биты устройство UART разбивает их на пакеты для передачи. Каждый пакет содержит стартовый бит, блок данных, бит четности и стоп-биты. На рисунке ниже приведен пример пакета данных.

После подготовки пакета цепь UART отправляет его через Tx-контакт.

Прием последовательных данных

Принимающее устройство UART проверяет принятый пакет (через вывод RX) на наличие ошибок, вычисляя число единиц и сравнивая его со значением бита четности, содержащегося в пакете.

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

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

Параметры UART

UART имеет настройки, которые должны быть одинаковыми на обоих устройствах, чтобы иметь правильную связь. Этими настройками UART являются скорость передачи данных, длина данных, бит четности, количество стоповых битов и управление потоком.

Скорость передачи

Скорость в бодах - это количество битов в секунду (бит/с), которое может передавать/принимать устройство UART. Для правильной передачи данных необходимо настроить оба прибора UART с одинаковой скоростью передачи данных в бодах. Распространенными значениями скорости передачи данных являются 9600, 1200, 2400, 4800, 19200, 38400, 57600 и 115200 бит в секунду.

Длина данных

Длина данных - это количество битов на байт данных.

Бит четности

Бит четности - это бит, добавляемый к передаваемым данным и сообщающий приемнику, является ли число единиц в передаваемых данных нечетным или четным. Возможная настройка для бита четности - "нечетный" (ODD) или "четный" (EVEN).

  • ODD - бит четности равен '1', если в данных присутствует нечетное число 1. В противном случае бит четности устанавливается равным нулю.
  • EVEN - бит четности равен '1', если в данных присутствует четное число единиц. В противном случае бит четности устанавливается равным нулю.

Количество стоп-битов

Приборы UART могут использовать ни одного, один или два стоповых бита для маркировки конца переданного набора битов (так называемых пакетов).

Управление потоком

Flow Control (управление потоком) - это метод, позволяющий избежать риска потери данных при передаче данных через UART. В устройстве UART в качестве управления потоком для запуска/остановки передачи данных используются специальные символы.

Интерфейс Arduino UART

Arduino имеет один или несколько контактов UART в зависимости от платы. Для нашего проекта, мы будем использовать Arduino Uno, который имеет только один UART интерфейс, найденный на контакте 0 (RX0) и контакте 1 (TX0).

Arduino контакты 0 и 1 также используются для связи с Arduino IDE через USB. Так что если вы будете загружать эскизы в UNO, убедитесь, что сначала вы отсоединили любые провода на контактах 0 и 1. На рисунке ниже показано расположение контактов UART TX и RX.

UART логический уровень

Уровни логики UART могут отличаться у разных производителей. Например, Arduino Uno имеет 5В логический уровень, а RS232 порт компьютера имеет +/-12В логический уровень.

Подключение Arduino Uno непосредственно к порту RS232 повредит Arduino. Если оба устройства UART не имеют одинаковых логических уровней, то для подключения устройств необходима подходящая схема преобразователя логического уровня.

Простой проект

Узнав, как работает UART, давайте теперь сделаем простой проект и напишем скетч, демонстрирующий, как использовать коммуникацию UART, используя Arduino Uno.

Наш проект заключается в управлении встроенным светодиодом Arduino дистанционно через UART. Кнопка, подключенная к первой плате Uno, будет управлять встроенным светодиодом второй платы Uno и наоборот.

Компоненты

Для создания нашего проекта нам понадобятся следующие компоненты:

  1. Arduino Uno (2 шт.)
  2. Кнопки (2 шт.)
  3. Макет
  4. Перемычки

Схема соединения

На рисунке ниже показано, как подключить компоненты, используемые в нашем проекте.

Скетч

После подготовки и сборки компонентов, мы готовы программировать наши платы. Для этого проекта обе платы будут иметь одинаковые скетчи.

Сначала, мы устанавливаем режим контакта 8 (кнопка) в INPUT_PULLUP, режим контакта 13 (светодиод) в OUTPUT и устанавливаем начальное состояние контакта 13 в состояние LOW (светодиод выключен).

void setup() {
  pinMode(8, INPUT_PULLUP); // установить контакт кнопки в качестве входа
  pinMode(13, OUTPUT);      // установить светодиодный вывод в качестве выхода
  digitalWrite(13, LOW);    // выключить светодиодный контакт
}

void loop() {

}

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

Serial.begin()

Для связи через UART-интерфейс необходимо сначала его настроить. Самый простой способ настроить UART Arduino - это использовать функцию Serial.begin(speed). Параметр speed ("Скорость") - это скорость передачи данных, с которой мы хотим запустить UART. С помощью этой функции остальные параметры UART будут установлены на значения по умолчанию:

  • Data length = 8 (длина данных)
  • Parity bit = 1 (бит четности)
  • Number of Stop Bits = None (количество стоп-битов = нет)

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

Нижеприведенный код добавляет Serial.begin(9600); внутри setup() для инициализации Arduino Uno UART со скоростью 9600 бит/с и другими параметрами, установленными по умолчанию.

void setup() {
  pinMode(8, INPUT_PULLUP); // установить контакт кнопки в качестве входа
  pinMode(13, OUTPUT);      // установить светодиодный вывод в качестве выхода
  digitalWrite(13, LOW);    // выключить светодиодный контакт

  Serial.begin(9600);       // инициализировать UART со скоростью 9600 бит/с
}

void loop() {

}

Следующая часть кода - это чтение и сохранение значения, полученного из последовательного интерфейса. Для этого мы будем использовать функцию Serial.available() вместе с оператором If, чтобы проверить, не получены ли данные. Затем мы вызовем Serial.read() для получения одного байта полученных данных и сохраним значение в переменную data_rcvd. Значение data_rcvd управляет включением/выключением встроенного светодиода.

Serial.available()

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

Serial.read()

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

void setup() {
  pinMode(8, INPUT_PULLUP); // установить контакт кнопки в качестве входа
  pinMode(13, OUTPUT);      // установить светодиодный вывод в качестве выхода
  digitalWrite(13, LOW);    // выключить светодиодный контакт

  Serial.begin(9600);       // инициализировать UART со скоростью 9600 бит/с
}

void loop() {
  if(Serial.available()) {
    char data_rcvd = Serial.read();   // прочитать один байт из последовательного буфера и сохранить в data_rcvd

    if(data_rcvd == '1') digitalWrite(13, HIGH);  // включить светодиод
    if(data_rcvd == '0') digitalWrite(13, LOW);   // выключить светодиоод
  }
}

Serial.write()

Для отправки данных через контакты Arduino TX0 мы будем использовать функцию Serial.write(val). Параметр val - это байт (или серия байтов), который будет отправлен.

В нашем скетче мы будем посылать значение char в зависимости от состояния контакта 8. Мы отправим значение char '1', если пин 8 HIGH, или значение char '0', если пин 8 LOW.

void setup() {
  pinMode(8, INPUT_PULLUP); // установить контакт кнопки в качестве входа
  pinMode(13, OUTPUT);      // установить светодиодный вывод в качестве выхода
  digitalWrite(13, LOW);    // выключить светодиодный контакт

  Serial.begin(9600);       // инициализировать UART со скоростью 9600 бит/с
}

void loop() {
  if(Serial.available()) {
    char data_rcvd = Serial.read();   // прочитать один байт из последовательного буфера и сохранить в data_rcvd

    if(data_rcvd == '1') digitalWrite(13, HIGH);  // включить светодиод
    if(data_rcvd == '0') digitalWrite(13, LOW);   // выключить светодиоод
  }

  if (digitalRead(8) == HIGH) Serial.write('0'); // отправьте char '0' на последовательный порт, если кнопка не нажата
  else Serial.write('1'); // отправьте char '1' на последовательный порт, если кнопка нажата

}

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

Сохраните скетч как arduino_uart_tutorial.ino. Оставшийся шаг - загрузить эскиз на обе платы Arduino Uno. Пожалуйста, не забудьте отсоединить провода, подключенные к контактам TX0 и RX0, перед загрузкой эскиза. После успешной загрузки переподключите провода к контактам TX0 и RX0.

После загрузки мы можем управлять встроенным светодиодом одной из плат, нажимая кнопку, подключенную к другой плате. Наш эскиз проверяет состояние кнопки и посылает соответствующее значение char "0" или "1" на другую плату для управления встроенным светодиодом.

12 мая 2020 в 15:04 | Обновлено 7 ноября 2020 в 01:19 (редакция)
Опубликовано: | Оригинал
Статьи,

10 комментариев

  1. Владимир
    1 июня 2020 в 16:24

    Спасибо! Всё очень доходчиво. У меня вопрос а как сделать. Что-бы можно было передавать значения с потенциометра с одной дуни. а на другой крутился серво либо менялась яркость светодиода. Если вас не затруднит.

    Ответить
  2. Дмитрий
    20 июля 2020 в 20:16

    Не получается отправлять числа. Пытаясь отправить цифру «1» получаю 49

    Ответить
    1. Qwerty
      3 марта 2021 в 23:20

      Так 49 это и есть 1 по таблице аски, вы наверное байт привели к числу и выводите его как число.
      А надо привести к char и вывести как char.

      Ответить
  3. AlexGyver
    31 октября 2020 в 10:13

    хороший материал. Но есть ошибка.
    Стандарт SERIAL_8N1 (the default)
    Обозначает: «8 бит данных» «нет проверки» «стоповый бит»
    Если не будет стопового бита, то как принимающее устройство поймёт, что данные завершились? А так молодец, всё доходчиво.

    Ответить
    1. Владимир Смирнов
      31 октября 2020 в 23:59

      Спасибо! Очень приятные слова от Гуру.

      Ответить
      1. Виктор
        25 декабря 2020 в 12:04

        Так исправьте ошибку в статье.
        Data length = 8 (длина данных)
        Parity bit = None
        Number of Stop Bits = 1 (количество стоп-битов = 1)

        Ответить
  4. Сергей
    1 ноября 2020 в 03:34

    Спасибо за статью. Оч круто!

    Ответить
  5. Антон
    23 апреля 2021 в 16:54

    Шина постоянно будет забита передачей данных. У Вас Serial.write вызывается в каждой итерации loop. Лучше прерывание на смену уровня пина кнопки.

    Ответить
  6. Boris
    2 февраля 2022 в 19:37

    Вижу что в инете появляются толковые ардуисты.

    Ответить
  7. Саня
    25 февраля 2022 в 11:56

    Хочу купить arduino передача данных по serial

    Ответить

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

Ваш E-mail не будет никому виден. Обязательные поля отмечены *