Акции
Блог
О 3DiY
  • О компании
  • Реквизиты
  • Партнеры
  • Клиенты
  • Вакансии
Оплата
Доставка
Гос. закупки
Товары под заказ
ВК Видео
Отзывы
Услуги
  • 3D печать
    • 3D печать пластиком FDM/FFF
    • 3D печать фотополимером
Контакты
  • Как до нас добраться
    8 (800) 500-45-93
    8 (800) 500-45-93отдел продаж Россия
    8 (495) 565-35-93отдел продаж Москва
    E-mail
    info@3d-diy.ru — отдел продаж

    print@3d-diy.ru — 3D печать на заказ

    support@3d-diy.ru — тех. поддержка

    buh@3d-diy.ru — Бухгалтерия
    Адрес
    Москва, Павелецкая набережная, 2с1
    Как до нас добраться, см. тут
    Режим работы
    пн - пт 09:00—18:00
    3DIY
    Войти
    0Сравнение
    0Избранное
    0Корзина
    3D принтеры3D сканерыПластик для 3D принтераФотополимерыКомплектующие 3DКомплектующие ЧПУЗапчасти 3D принтеров по брендам3D печать на заказ
    3DIY
    Войти
    0Сравнение
    0Избранное
    0Корзина
    3DIY
    Телефоны
    8 (800) 500-45-93отдел продаж Россия
    8 (495) 565-35-93отдел продаж Москва
    E-mail
    info@3d-diy.ru — отдел продаж

    print@3d-diy.ru — 3D печать на заказ

    support@3d-diy.ru — тех. поддержка

    buh@3d-diy.ru — Бухгалтерия
    Адрес
    Москва, Павелецкая набережная, 2с1
    Как до нас добраться, см. тут
    Режим работы
    пн - пт 09:00—18:00
    0
    0
    0
    • Кабинет
    • 0Сравнение
    • 0Избранное
    • 0Корзина
    • Бренды
    • Акции
    • Услуги
      • Услуги
      • 3D печать
        • 3D печать
        • 3D печать пластиком FDM/FFF
        • 3D печать фотополимером
    • Компания
      • Компания
      • О компании
      • Реквизиты
      • Партнеры
      • Клиенты
      • Вакансии
    • Блог
    • Информация
      • Информация
      • Гарантия на товар
      • Возврат товара
      • Положение о персональных данных
      • Политика конфиденциальности
      • Согласие на получение рекламы
      • Пользовательское соглашение
      • Согласие на обработку персональных данных
      • Использование cookie-файлов
      • Договор-оферта
    • Контакты
      • Контакты
      • Как до нас добраться
    8 (800) 500-45-93отдел продаж Россия
    • Телефоны
    • 8 (800) 500-45-93 отдел продаж Россия
    • 8 (495) 565-35-93 отдел продаж Москва
    • info@3d-diy.ru — отдел продаж

      print@3d-diy.ru — 3D печать на заказ

      support@3d-diy.ru — тех. поддержка

      buh@3d-diy.ru — Бухгалтерия
    • Москва, Павелецкая набережная, 2с1
      Как до нас добраться, см. тут
    • пн - пт 09:00—18:00
    Главная
    Блог
    Модули
    Интерфейс передачи данных - UART

    Интерфейс передачи данных - UART

    Интерфейс передачи данных - UART
    Модули 1 января 2024
    Содержание

    • Назначение и принцип работы,
    • Реализация в Ардуино,
    • Примеры использования,
    • Вывод,
    • FAQ.

    Назначение и принцип работы

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

    Если говорить применительно к Ардуино, то в аппаратном виде у всех плат присутствуют три интерфейса: UART, SPI и I2C. А у некоторых особо продвинутых имеется аж встроенный адаптер CAN-шины. У каждого из перечисленных интерфейсов есть свои преимущества и недостатки, о чем будет упомянуто отдельно, а также свои “клиенты”, то есть устройства, использующие только тот или иной интерфейс для связи с внешним миром. Потому обо всех вариантах надо знать и всеми уметь пользоваться.

    Обязательно к прочтению:Интерфейс передачи данных I2C

    В данной статье чуть подробнее разберем первый интерфейс из нашего списка - UART. Первый он и по другим параметрам: самый простой, понятный и распространенный. С него начинается знакомство начинающего DIY-мастера на тему “межмашинного” общения, даже если бы он выбрал другую последовательность. Все потому, что подключение Ардуино к компьютеру для прошивки программы осуществляется именно через него, родимого - UART. Благодаря специальному встроенному адаптеру он превращается на выходе с платы в более понятный для ПК порт USB. Через него на компьютер посылаются информационные и диагностические сообщения, а также принимаются команды и прочая полезная информация. Таким образом интерфейс этот будет преследовать нас везде и всегда, что, впрочем, и не так уж плохо.

    Итак, UART - Universal Asynchronous Receiver-Transmitter, что в переводе звучит как Универсальный Асинхронный Приемо-Передатчик. Насчет “универсальный” понятно, он широко распространен в электронном мире, его в разных видах используют и большие и малые компьютеры, контроллеры, датчики, средства коммуникации и прочие электронные устройства. Слово “асинхронный” означает то, что прием и передача отдельных битов не выравниваются так называемыми синхроимпульсами, что и хорошо, и плохо одновременно. Единица отличается от нуля исключительно по времени между перепадами уровней сигнала, которое заранее задается скоростью передачи. Для полноты картины следует сказать, что в природе существует версия UART в синхронизацией сигналов - USART, где буква S обозначает Synchronous, но здесь мы ее изучать пока не будем. Чем хороша асинхронная передача данных? Простотой протокола, минимумом проводов и занятых в процессе аппаратных средств, возможность полного дуплекса (одновременной передачи данных в обоих направлениях). В чем ее недостаток? Меньшая помехозащищенность и, как следствие, максимальная скорость и расстояние при тех же остальных условиях. Однако, для 99,5% наших задач скорости и устойчивости асинхронного варианта хватит с большим запасом.

    С “хардовой” стороны UART использует два пина контроллера - RX и TX, где первые буквы обозначают, соответственно, Receiver и Transmitter. Что означают вторые Иксы, не спрашивайте, никто точно не знает, но все пишут именно так и нам советуют. Логично, что для связи двух устройств понадобятся два провода, причем соединять их следует крест-накрест RX первого в TX второго и наоборот. Куда один передает, там другой принимает.

    uart1-uart2.png

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

    У разных плат Ардуино разное количество аппаратных портов UART, чаще всего один, а у огромной Меги аж четыре. Однако, простота этого интерфейса позволяет эмулировать порт программными методами, присваивая RX и TX почти любым пинам на выбор. То есть можно использовать “железные” порты на строго определенных пинах (рекомендуется) или - с некоторыми ограничениями - “программные”, а при необходимости и те, и другие одновременно.

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

    soft.png

    Пока информация не передается, в линии сохраняется высокий уровень (для нашего случая с Ардуино это +5В, так называемая TTL-логика). Спад сигнала - это команда принимающей стороне, что сейчас начнется что-то интересное! И спустя определенное количество времени, зависящее от заранее заданной скорости, начинается обещанное интересное, а именно передача байта в виде ряда нулей и/или единиц с соблюдением тех же, заранее оговоренных, временных отрезков. После восьмого бита следует стоп-сигнал в виде высокого уровня и ситуация повторяется до тех пор, пока не будут переданы все нужные нам байты.

    Так в реальности выглядит в пине TX снятый осциллографом фрагмент сообщения “Hello, World!”:

    hello-word.jpg

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

    protocol.jpg

    Наличие или отсутствие такого бита тоже оговаривается в протоколе заранее, наряду со скоростью и прочими параметрами. Тут нужно понимать, что протокол имеет разновидности и может отличаться у разных устройств в зависимости от условий и предпочтений программистов. Основные параметры таковы: скорость, количество битов, паритет (четность), длина стоп-сигнала. Отсюда вытекает важное условие для работы UART: оба устройства должны быть настроены одинаково, иначе они друг друга не поймут, как случайно встретившиеся в Антарктиде китаец и швед. Опять же, истины ради, стоит упомянуть о возможностях некоторых особо умных устройств понимать, на каком “языке” говорит с ним собеседник и автоматически настраиваться под него, например GPS-модули типа SIM800, но это исключительно заслуга программистов, которые предусмотрели такую функцию и облегчили жизнь своим клиентам. Мы же пока таким заниматься не станем, поэтому будем просто задавать одинаковые параметры на обоих электронных “собеседниках”.

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

    Пример - полный сигнал “Hello, World!” с переводом строки. Хорошо видны информационные биты, отмеченные точкой, и служебные “старт” и “стоп” в начале и в конце каждого байта.

    signal.jpg

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

    znacheniya.jpg

    Чем выше скорость, тем быстрее бегают по проводам данные, но тем больше вероятность ошибок, поэтому рекомендуется не злоупотреблять и соблюдать принцип разумной достаточности. Для большинства случаев рекомендуется скорость 9600 бод, это довольно быстро и весьма надежно даже на приличных дистанциях, байт передается примерно за 1мс. Если этого недостаточно, всегда можно “поддать газу”. Предельно возможная скорость передачи данных на аппаратных UART для плат Ардуино - 250000 бод, на софтовых - 115200. Но, как говорилось выше, без нужды лучше до таких значений не разгоняться.

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


    Реализация в Arduino

    В среде Ардуино общение с UART происходит с помощью класса Serial. Рассмотрим некоторые функции этого класса.

    Serial.begin(long);
    Запускает работу порта с заданной в параметре скоростью в бодах. У Меги 4 порта, запускаются командами эc номером, например, Serial1.begin(9600); и так далее. Все остальные команды к портам Меги тоже осуществляются с уточнением номера порта.

    Serial.end();
    Останавливает работу порта, если он был ранее запущен. На практике используется редко, но бывают случаи, когда необходимо освободить пины 0 и 1 хотя бы на время.

    = Serial.available();
    Возвращает в виде числа int количество принятых в буфер порта байт. Если возвращает 0, информации не поступало. Обычно используется как триггер для приема информации.

    = Serial.read();
    Возвращает байт из буфера приема. Следующий вызов возвращает следующий байт и так далее. Если буфер опустел, возвращает 0xFFFF.

    Serial.print(xxx);
    Предоставляет большое разнообразие вариантов передачи данных в порт, от байта до строки символов и числа с плавающей точкой. Очень удобная функция для отладки программ.

    Serial.println(xxx);
    Отличается от вышеупомянутой автоматической отправкой двух служебных символов переноса строки после информации из входящей в параметр информации. Следующее сообщение начнется с новой строки.

    Serial.write(xxx);
    Передает двоичные данные в порт. Возвращает число переданных байтов.

    = Serial.read();
    Возвращает принятые двоичные данные.

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


    Примеры использования

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

    Схему рисовать не будем, потому что ее нет. Достаточно просто подключить плату к USB компьютера и залить в нее такую программу:

    void setup() { Serial.begin(9600); // запускаем порт } void loop() { Serial.print("timer: "); // пишем слово timer: Serial.print(millis()); // выводим кол-во миллисекунд с начала запуска программы Serial.println("ms"); // подписываем их ms, переводим строку на новую delay(1000); // задержка 1 сек } 
    После чего запускаем встроенный в среду Ардуино монитор порта при помощи кнопки с лупой в верхнем правом углу окна:

    ugol.jpg

    И смотрим какие строки там побежали:

    stroki.jpg

    Две строки Serial.print() последовательно выводят на экран текст, значение таймера millis(), третья строка Serial.println() выводит последний кусочек текста и переводит строку. Получается бесконечная цепочка сообщений, которые мы можем читать с экрана.

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


    Заливаем программу:
    void setup() { pinMode(13, OUTPUT); Serial.begin(9600); } void loop() { if (Serial.available() > 0) { // если пришла команда char incom = Serial.read(); // считываем, опознаем, реагируем if (incom == '1') { digitalWrite(13, HIGH); } else if (incom == '0') { digitalWrite(13, LOW); } } } 

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

    Третий пример как раз про это. Для реализации нам потребуется две любых платы Ардуино, между которыми мы будем гонять данные. К каждой из них мы подключим две кнопки и два светодиода по одинаковой схеме, и соединим их RX-TX крест-накрест, как было описано выше.

    primer.jpg

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

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


    Заливаем в обе:
    #define LED_1 4 // светодиод 1 #define LED_2 5 // светодиод 2 #define BUT_1 2 // кнопка 1 #define BUT_2 3 // кнопка 2 byte but[2]; // переменные для отслеживания кнопок void setup() { // инициализируем пины, запускаем сирал порт pinMode(LED_1, OUTPUT); pinMode(LED_2, OUTPUT); pinMode(BUT_1, INPUT); pinMode(BUT_2, INPUT); Serial.begin(9600); } void loop() { if (get_but()) { // с кнопками что-то было Serial.write(but[1]); // отправляем в порт новое состояние кнопок } if (Serial.available() > 0) { // если пришли данные от соседних кнопок byte incom = Serial.read(); // считываем эти данные digitalWrite(LED_1, !(incom / 2)); // зажигаем или гасим светодиод 1 digitalWrite(LED_2, !(incom % 2)); // зажигаем или гасим светодиод 2 } } byte get_but() { static unsigned long timer; if (timer + 50 > millis()) return 0; // опрос каждые 50мс (антидребезг) timer = millis(); but[0] = but[1]; but[1] = digitalRead(BUT_1) + digitalRead(BUT_2) * 10; // данные с обеих кнопок в одну переменную (единицы и десятки) if (but[0] != but[1]) return 1; // если есть изменение, сигнализируем единицей return 0; // если нет, возвращаем 0 } 

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

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



    Вывод

    UART бесспорно и заслуженно самый известный и широко применяемый интерфейс передачи данных. С его помощью к Ардуино подключаются датчики, исполнительные устройства, индикаторы и дисплеи, GPS и GPRS-модули. Через него осуществляется заливка программы в Ардуино и ее отладка. С его помощью можно легко и быстро организовать обмен команд и информацией с другим контроллером. Однако, у него есть и недостатки, например ограничение по скорости, относительно невысокая помехозащищенность, требование к точности тактовой частоты у передающей и принимающей платы, что особенно критично для контроллеров, работающих от внутреннего RC-генератора. Тем не менее он остается очень важным инструментом с огромными возможностями. Знать этот интерфейс и уметь им пользоваться должен любой DIY-мастер без исключения.


    FAQ

    Можно ли соединить с помощью UART более двух устройств и/или контроллеров?
    Можно, однако придется слегка доработать шину передачи данных, чтобы все RX видели все TX. Для этого существуют адаптеры RS-485, позволяющие на физическом уровне объединить TX и RX всех устройств, входящих в сеть, в одно целое при помощи двух проводков. Но это тема отдельной статьи, а может, и не одной.

    На какое максимальное расстояние возможно передать данные с помощью UART без потерь?
    Расстояние сильно зависит от ряда параметров: толщины и материала провода, наличия экранирования, скорости. Однако даже в лучшем случае это не более пары десятков метров. Интерфейс не предназначен для дальних расстояний. Но, возвращаясь к предыдущему вопросу, стоит сказать, что преобразованный с помощью RS-485 сигнал может распространяться не только на несколько устройств, но и гораздо дальше, так как использует более высокое напряжение и противофазу сигналов.

    Нужно ли соблюдать строгую очередность в передаче и приеме информации?
    По умолчанию UART дуплексный, то есть может принимать и передавать данные одновременно. Однако важно в процессе передачи успевать забирать данные из буфера приема, иначе он переполнится и часть данных пропадет. По умолчанию размер буфера 64 байта, что довольно много и при правильном использовании более чем достаточно, но для особых случаев можно увеличить константу, например до 128 байт, при помощи команды препроцессору:

    #define SERIAL_RX_BUFFER_SIZE 128

    Что такое логические уровни, как и зачем их согласовывать?
    Не все устройства и контроллеры работают на питании и логике 5В, есть те, которым противопоказано напряжение выше 3.3В, они могут вывести принимающий порт из строя и, возможно, все устройство. Если для передачи в обратную сторону 5 <-- 3.3 можно ничего не менять, принимающая сторона все поймет и не повредится, то в направлении 5 --> 3.3 следует обязательно понизить напряжение. Вариантов несколько, самый простой - резистивный делитель, намного лучше применить стабилитрон на 3.3 В, отсекающий лишнее напряжение, или специальную микросхему, особенно если каналов несколько.

    Это интересно

    Драйвер шагового двигателя A4988
    Модули
    Драйвер шагового двигателя A4988
    1 января 2024
    RFID-модуль RC522
    Модули
    RFID-модуль RC522
    1 января 2024
    Реле электромеханическое 10А 5В
    Модули
    Реле электромеханическое 10А 5В
    1 января 2024
    Драйвер двигателя L9110S
    Модули
    Драйвер двигателя L9110S
    1 января 2024
    Nodemcu Lua Wi-Fi на Esp8266
    Модули
    Nodemcu Lua Wi-Fi на Esp8266
    1 января 2024
    Wi-Fi модуль ESP-01
    Модули
    Wi-Fi модуль ESP-01
    1 января 2024
    • Комментарии
    Загрузка комментариев...
    Назад к списку
    • Все публикации277
      • 3D принтеры59
      • 3D печать64
      • ЧПУ10
      • Датчики27
      • Модули38
      • 3D сканеры1
      • Arduino механика6
      • Arduino платы8
      • Дисплеи6
      • Кейсы1
      • Компоненты13
      • Мировые новости35
      • Проекты7
      • Сопутствующие2
    Связаться с нами
    8 (800) 500-45-93
    8 (800) 500-45-93отдел продаж Россия
    8 (495) 565-35-93отдел продаж Москва
    E-mail
    info@3d-diy.ru — отдел продаж

    print@3d-diy.ru — 3D печать на заказ

    support@3d-diy.ru — тех. поддержка

    buh@3d-diy.ru — Бухгалтерия
    Адрес
    Москва, Павелецкая набережная, 2с1
    Как до нас добраться, см. тут
    Режим работы
    пн - пт 09:00—18:00
    info@3d-diy.ru — отдел продаж

    print@3d-diy.ru — 3D печать на заказ

    support@3d-diy.ru — тех. поддержка

    buh@3d-diy.ru — Бухгалтерия
    Москва, Павелецкая набережная, 2с1
    Как до нас добраться, см. тут
    Магазин
    Бренды
    Акции
    Каталог
    Услуги
    Компания
    О компании
    Реквизиты
    Партнеры
    Клиенты
    Вакансии
    Информация
    Гарантия на товар
    Возврат товара
    Положение о персональных данных
    Политика конфиденциальности
    Согласие на получение рекламы
    Пользовательское соглашение
    Согласие на обработку персональных данных
    Использование cookie-файлов
    Договор-оферта
    Помощь
    Условия оплаты
    Условия доставки
    Товары под заказ
    Гос. закупки
    Как сделать заказ
    Вопрос-ответ
    2013 - 2026 © 3DiY (Тридиай) - интернет-магазин комплектующих для 3D принтеров, ЧПУ станков и робототехники
    Конфиденциальность
    Оферта
    ГлавнаяКаталог0Корзина0ИзбранныеКабинет0Сравнение
    d =
    Наш сайт использует куки. Продолжая им пользоваться, вы соглашаетесь на обработку персональных данных в соответствии с политикой конфиденциальности.
    Согласен