Uart что это arduino
UART – Последовательный интерфейс передачи данных
В сегодняшней статье мы с вами разберемся с последовательным интерфейсом UART, узнаем его плюсы и минусы, а также научимся отлаживать программу с помощью Arduino IDE без применения программаторов. Вас заинтересовало? Тогда читайте дальше!
Серьёзные среды разработки, типа IAR или ATMEL Studio, как правило, содержат в себе либо программный симулятор целевого микроконтроллера, либо имеют программные средства для работы с аппаратными отладчиками.
Среда Arduino IDE не имеет ни того, ни другого, что значительно усложняет поиск ошибок в программе. Компилятор выявляет только синтаксические ошибки, наряду с которыми существуют еще и логические (написано-то правильно, только не то делает), не говоря уж о подсчёте различных коэффициентов… Программы не пишутся без ошибок!
Существует множество методов отладки, но практически для всех необходимо физическое соединение с компьютером. Все платы Arduino (кроме Pro и Pro Mini) имеют «на борту» USB-разъём и специальную микросхему, которая преобразует интерфейс UART в USB. Так не будем же придумывать ничего лишнего и сделаем простейшую отладку с помощью интерфейса, который у нас уже есть!
Среда разработки Arduino IDE уже имеет в своём составе монитор последовательного порта, который позволяет просматривать данные, проходящие через порт, а также отправить свои данные. Таким образом, мы всегда можем передать данные из нашего устройства прямо в компьютер и вывести на экран.
Монитор порта – не единственное средство для работы с ним, в сети можно найти множество программ-мониторов, которые позволяют не только принимать данные, но и стоить графики на их основе, записывать данные в таблицу и многое другое! Это значительно упростит отладку программы.
Так как интерфейс UART выведен не только к преобразователю интерфейсов, его можно использовать и для связи между платами Arduino или, например, платой и датчиком, но это уже тема для другой статьи.
UART интерфейс — описание
UART в переводе с английского звучит как “Универсальный Асинхронный Приёмопередатчик”. Существует ещё его синхронная версия с дополнительной линией тактового сигнала, но она не интересна нам в рамках статьи.
Каждый бит каждого байта передаётся в равный отведённый промежуток времени (фактически, тайм-слот). Стандартным размером данных в посылке является 8 байт, но помимо данных каждый пакет несёт и служебную информацию, а именно:
Кратко параметры передаваемого сигнала записываются так:
[кол-во бит данных] [тип чётности] [кол-во стоп-битов], то есть запись 8N1 характеризует сигнал с 8 битами данных, без бита чётности (N – Not) с 1 стоп-битом.
Так как интерфейс асинхронный, то большую значимость имеет скорость передачи данных – и у приёмника, и у передатчика она должна быть одинаковой.
Скорость измеряется в битах в секунду, или коротко – в бодах. Стандарт RS232 подразумевает скорости от 1200 до 115200 бод, хотя по факту существуют скорости и ниже, и выше, причём до десятков мегабод!
Разумеется, точность везде относительна и скорость никогда не будет равняться 9600 бодам с точностью до единиц. Стандарт предусматривает возможную ошибку в скорости до 5% (не более 3% для уверенного приёма).
Далее сведены основные сведения о сигнале:
4800, 9600, 19200, 38400, 57600, 115200 бод.
Скорость передачи (бод) | Время передачи одного бита (мкс) | Время передачи байта (мкс) |
---|---|---|
4800 | 208 | 2083 |
9600 | 104 | 1042 |
19200 | 52 | 521 |
38400 | 26 | 260 |
57600 | 17 | 174 |
115200 | 8,7 | 87 |
UART может быть запущен как в полудуплексном (только приём или только передача) режиме, так и в полнодуплексном режиме, так как линии приёма и передачи разделены. Линия TXD отвечает за передачу, RXD – за приём, соответственно, линии от приёмника к передатчику перекрещиваются (TX-RX, RX-TX).
Реализация UART в Arduino
Все платы Arduino, построенные на основе оригинальных, имеют минимум один интерфейс UART, продвинутые же платы, типа Arduino Mega 2560 Или Arduino Due, имею сразу 4 аппаратных интерфейса! Они не загружают контроллер, так как они отделены от ядра; всё, что необходимо – это сконфигурировать порт и запихать данные в буфер, после чего операции передачи пойдут независимо от вас.
Конечно, существуют и программные реализации UART, но они нагружают процессор. В любом случае, лучше использовать сначала аппаратные интерфейсы, а потом уже начинать придумывать что-то программное.
Контроллеры Arduino используют логические уровни такие же, каким является питание, то есть для самой популярной платы Arduino UNO уровни будут равны – ноль = 0В, 1 = 5В.
Выводы подключены к преобразователю интерфейсов через резисторы с сопротивлением 1 КОм, а к гребёнкам по бокам платы – напрямую, поэтому сигналы с гребёнок будут иметь больший приоритет. Периодически это мешает прошивать платы с подключенным датчиком по UART, так как для прошивки тоже используется UART.
Микросхема преобразователя интерфейсов не делает из себя ещё один COM-интерфейс для компьютера, она лишь эмулирует его. Несмотря на это, все программы, которые работают с COM-портом посредством Windows API (Win32 API), не отличат порт от физического порта компьютера.
Класс Serial – RS232 в лучших традициях Arduino
Для удобной работы с последовательным портом разработчики Arduino написали целую библиотеку, которая значительно упрощает работу с портом, абстрагируя конечного пользователя от простой, «железной» работы с регистрами. Класс имеет множество функций, которые будут рассмотрены нами далее. Но сначала надо понять, как же компьютер примет и обработает, а точнее покажет то, что мы ему передали.
Всё дело в том, что каждый символ раскладки клавиатуры – это тоже байт. И если просто взять и отправить в порт число 65, он не выведет две цифры 6 и 5, а выведет заглавную латинскую букву А. Почему так? Потому что в таблице кодировки буква А имеет код 65. Класс позволяет выбрать между текстовым и бинарным методом передачи данных, то есть мы сможем отправить число 65 и как букву, и как число.
ОБОРУДОВАНИЕ
ТЕХНОЛОГИИ
РАЗРАБОТКИ
Блог технической поддержки моих разработок
Урок 12. Последовательный порт UART в Ардуино. Библиотека Serial. Отладка программ на Ардуино.
В уроке рассказывается о последовательном интерфейсе UART платы Ардуино, библиотеке для работы с ним и использовании порта UART для отладки программ.
Среда Arduino IDE не содержит отладчика, что создает определенные проблемы в поиске ошибок кода программы. Без ошибок программы сразу не пишутся. Формальные ошибки выявляются при компиляции, а с алгоритмическими и вычислительными ошибками намного сложнее.
В интернете описывается много способов отладки программ, которые используют дополнительные библиотеки, программы, аппаратные адаптеры. Но основная функция отладки это увидеть состояние программы, узнать значение переменных. Это можно сделать, передав нужную информацию на компьютер через последовательный интерфейс. Физическое подключение платы Ардуино к компьютеру через USB кабель существует всегда. Среда Arduino IDE имеет монитор последовательного порта, позволяющий получать и посылать данные обмена с платой. Можно передать на компьютер любую информацию о состоянии программы и вывести ее на дисплей. Меня такой способ отладки вполне устраивает. Только вместо монитора Arduino IDE я иногда использую свои программы, которые выводят данные в удобном мне виде.
Конечно, интерфейс UART в Ардуино может быть использован для связи с другими контроллерами или периферийными устройствами, но пока он нам интересен с точки зрения связи с компьютером.
Последовательный интерфейс UART.
UART в переводе это универсальный асинхронный приемопередатчик. Данные UART передаются последовательным кодом в следующем формате.
Каждый бит передается за равные промежутки времени. Время передачи одного бита определяется скоростью передачи. Скорость передачи указывается в бодах (бит в секунду). Кроме битов данных интерфейс UART вставляет в поток биты синхронизации: стартовый и стоповый. Таким образом, для передачи байта информации требуется 10 битов, а не 8. Погрешность временных интервалов передачи битов должна быть не более 5% (рекомендуется не более 1,5%).
Я описываю наиболее распространенный формат. Существуют варианты с разным количеством битов данных, битов синхронизации, может быть добавлен бит контроля четности и т.п. Но эти форматы используются редко. Главное запомнить:
Часто используются следующие стандартные скорости передачи интерфейса UART.
Скорость передачи, бод | Время передачи одного бита, мкс | Время передачи байта, мкс |
4800 | 208 | 2083 |
9600 | 104 | 1042 |
19200 | 52 | 521 |
38400 | 26 | 260 |
57600 | 17 | 174 |
115200 | 8,7 | 87 |
Обмен информацией через UART происходит в дуплексном режиме, т.е. передача данных может происходить одновременно с приемом. Для этого в интерфейсе UART есть два сигнала:
При соединении двух UART устройств выход TX одного устройства соединяется со входом RX другого. А сигнал TX второго UART подключается к входу RX первого.
Последовательный интерфейс UART в Ардуино.
Любая плата Ардуино имеет, как минимум, один аппаратный последовательный интерфейс UART. Платы Arduino Mega и Arduino Due имеют по три порта.
Когда я употребляю выражение аппаратный интерфейс, я подчеркиваю, что в контроллере существует электронный узел, в регистр которого программа только загружает байт для передачи, а формирование сигналов обмена и все остальные операции делает этот узел. Может быть реализована и программная передача данных по протоколу UART. В этом случае все сигналы формируются программой. Конечно, это занимает ресурсы процессора.
Плата Arduino UNO имеет один порт UART, сигналы которого подключены к выводам 0 (сигнал RX) и 1 (сигнал TX). Сигналы имеют логические уровни TTL (0…5 В). Через эти выводы (0 и 1) можно подключить к плате другое устройство имеющее интерфейс UART.
Фрагмент схемы платы Arduino UNO R3.
Таким образом, при свободных выводах 0 и 1 платы Ардуино сигналы с микросхемы ATmega16U2 поступают на контроллер ATmega328. А если к плате подключить внешнее UART устройство, то его сигналы будут иметь приоритет, т.к. ATmega16U2 подключена через резисторы.
Преобразователь интерфейса ATmega16U2 позволяет подключать плату Ардуино к компьютеру через USB порт. На компьютер устанавливается драйвер. Он создает на компьютере виртуальный COM порт. Через него и происходит обмен. Такая технология описана на примере другого преобразователя интерфейсов PL2303 USB-UART по этой ссылке. Там же есть информация о вариантах UART интерфейсах с разными уровнями сигналов.
Важно понимать, несмотря на то, что плата подключена к компьютеру через USB порт, все программы обмениваются данными через виртуальный COM порт, не подозревая, что порт виртуальный.
Библиотека Serial для работы с UART Ардуино.
Для работы с аппаратными UART контроллерами в Ардуино существует встроенный класс Serial. Он предназначен для управления обменом данными через UART. Перед тем, как рассказать о функциях класса Serial я хочу пояснить разницу в формате данных обмена.
Через последовательный интерфейс данные всегда передаются в двоичном коде. Вопрос как эти данные интерпретировать, как воспринимать. Например, передан двоичный код “01000001” (десятичный 65). Как его отобразить на экране? Может быть передано число 65 и на экране надо вывести ”65”. А может это код буквы ”A”, тогда на экране надо написать ”A”. Просто необходимо знать в каком формате передаются данные.
В классе Serial данные могут передаваться в двух форматах:
Например, монитор последовательного порта в программе Arduino IDE принимает данные как ASCII текст. Для того, чтобы он вывел на экран компьютера число “65” надо передать коды символов “6” и “5”. А код ”65” монитор отобразит как символ “A”.
Основные функции класса Serial.
void begin(long speed)
Разрешает работу порта UART и задает скорость обмена в бод (бит в сек). Для задания скорости передачи данных рекомендуется использовать стандартные значения (таблица в разделе “Последовательный интерфейс UART”).
Serial.begin(38400); // инициализация порта, скорость 38400 бод
void end(void)
Отключает порт UART, освобождает выводы RX и TX.
Serial.end(); // закрыть порт UART
int available(void)
Возвращает количество байт, принятых последовательным портом и записанных в буфер. Буфер последовательного порта может хранить до 64 байт. В случае пустого буфера возвращает 0.
int n;
n= Serial. available(); // в n число принятых байтов
int read(void)
Возвращает очередной байт из буфера последовательного порта. Если буфер пуст – возвращает число – 1 (0xffff).
receiveByte= Serial.read(); // чтение байта из буфера
void flush(void)
Ожидает окончания передачи данных из буфера последовательного порта.
Serial.flush(); // ждем окончания передачи
print()
Выводит данные через последовательный порт UART в виде ASCII символов. Функция имеет различные формы вызова для разных форматов и типов данных.
print(char d) | Если аргумент типа char выводит в порт код символа char d= 83; |
print(byte d) | Данные типа byte выводятся кодом числа byte d= 83; |
print(int d) | Если аргумент – целый тип, то выводит строку с десятичным представлением числа int d= 83; |
print(float) | Вещественные типы выводятся символами ASCII, два знака после запятой float d= 7.65432; |
print(* str) | Если аргумент указатель на массив или строка, то массив или строка побайтно передается в порт. int d= 83; |
print(int d, HEX) | Выводит строку ASCII – шестнадцатиричное представление числа int d= 83; |
print(int d, OCT) | Выводит строку ASCII – восьмеричное представление числа int d= 83; |
print(int d, BIN) | Выводит строку ASCII – двоичное представление числа int d= 83; |
print(int d, BYTE) | Выводит код младшего байта числа int d= 0x0283; |
print(float d, N) | Для вещественных чисел параметр N задает количество цифр после запятой. Serial.print(7.65432, 0); // выводит строку “7” |
println()
Выводит данные через последовательный порт UART в виде ASCII символов с добавлением символов переноса строки (\r, код 13) и (\n, код 10). Т.е. следующее сообщение будет отображаться с новой строки. В остальном аналогична функции print().
int d= 83;
Serial.print(d, DEC); // вывод строки “83”
Serial.println(d, DEC); // вывод строки “83 \r \n”
int write()
Выводит двоичные данные через последовательный порт UART. Возвращает количество переданных байтов.
int write(val) | Передает байт Serial.write(83); // передает байт 83 |
int write(str) | Передает строку, как последовательность байтов int bytesNumber; // число байтов |
int write(* buf, len) | Передает байты из массива, число байтов – len. char buf= “Строка”; |
int peek(void)
int readBytes(* buf, len)
Считывает байты, поступающие на последовательный порт, и записывает их в буфер. Прекращает работу после приема заданного количества байтов или в случае тайм-аута. Возвращает количество принятых байтов. Тайм-аут задается функцией setTimeout().
setTimeout(long time)
Задает время тайм-аута для функции readBytes(). Время time указывается в мс, по умолчанию оно равно 1000 мс.
void serialEvent()
Вызывается при поступлении данных в последовательный порт. По сути – прерывание по приему данных последовательным портом.
// код для обработки данных порта
Применение класса Serial.
Класс Serial встроенный. Для него не надо искать библиотеку и подключать ее. Чтобы использовать UART достаточно в setup() разрешить работу порта и задать скорость:
void setup() <
Serial.begin(9600); // инициализируем порт, скорость 9600
>
Теперь можно передавать данные с помощью функций print() или write().
Если через порт выводится несколько байтов, то класс Serial записывает их в программный буфер и последовательно по байту передает данные в контроллер UART по мере передачи.
Вот программа, которая каждую секунду выводит в монитор последовательного порта сообщение и номер прохода.
unsigned int i=0;
void setup() <
Serial.begin(9600); // инициализируем порт, скорость 9600
>
При поступлении данных на вход UART класс Serial записывает их в программный буфер. Для чтения данных из буфера необходимо сначала проверить, есть ли они там.
if( Serial.available() > 0 ) <
// есть данные
Вот программа, которая считывает байт из последовательного порта и отсылает его в порт. Т.е. все, что мы вводим в мониторе последовательного порта должно появляться в окне монитора для принятых данных.
unsigned int i=0;
void setup() <
Serial.begin(9600); // инициализируем порт, скорость 9600
>
Отладка программ с помощью последовательного порта на Ардуино.
Принцип отладки простой.
Например, мы проверяем работу кнопок и функций обработки сигналов кнопок. В блок программы, который выполняется по нажатию на кнопки, мы вставляем команду передачи сообщения на компьютер.
Для кнопок, подключенных по схеме предыдущего урока, скетч программы выглядит так.
// отладка кнопок с помощью порта UART
#define BUTTON_1_PIN 12 // кнопка 1 подключена к выводу 12
#define BUTTON_2_PIN 11 // кнопка 2 подключена к выводу 11
Button button1(BUTTON_1_PIN, 20); // создание объекта кнопка 1
Button button2(BUTTON_2_PIN, 20); // создание объекта кнопка 2
void setup() <
Serial.begin(9600); // инициализируем порт, скорость 9600
MsTimer2::set(2, timerInterupt); // задаем прерывания по таймеру с периодом 2 мс
MsTimer2::start(); // разрешаем прерывание
>
// проверка кнопки 1
if ( button1.flagClick == true ) <
button1.flagClick= false;
Serial.println(«Button 1 was pressed»); // сообщение для монитора
>
// проверка кнопки 2
if ( button2.flagClick == true ) <
button2.flagClick= false;
Serial.println(«Button 2 was pressed»); // сообщение для монитора
>
>
// обработка прерывания
void timerInterupt() <
button1.scanState(); // вызов метода обработки сигнала кнопки 1
button2.scanState(); // вызов метода обработки сигнала кнопки 2
>
Теперь на каждое нажатие кнопки 1 через последовательный порт платы Ардуино на компьютер будет передаваться сообщение “ Button 1 was pressed”, а по нажатию кнопки 2 – сообщение “Button 2 was pressed”. Приходится писать по английски. Монитор не воспринимает русские символы. В дальнейших уроках исправим.
Только необходимо, чтобы скорости обмена были одинаковы в программе и мониторе (у меня 9600 бод).
Также можно передавать значения переменных, результаты вычислений, режимы и т.п. В последующих уроках практически в каждой программе мы будем использовать последовательный порт для контроля состояния программы.
В следующем уроке научимся считывать значения сигналов на аналоговых входах платы Ардуино.
Работа с последовательным портом UART (serial) на Arduino
Последовательный интерфейс (serial) предназначен передачи данных через универсальный асинхронный порт UART. Порт UART очень часто используется для передачи данных с Ардуино на компьютер, и обратно, а также для связи нескольких плат ардуин между собой.
Для многопортовых DUE/MEGA см. здесь.
Основные функций для работы с последовательным портом (Serial)
Очевидно, когда задействован последовательный порт, выводы 0 (RX) и 1 (TX) не могут использоваться для других целей.
Разные варианты функции print:
(аналогично HEX, OCT, BIN).
Функция write:
Пример 1. Передача данных по Serial-порту с Arduino на компьютер
Инициализация порта со скоростью 9600 бот и передача данных (от Arduino на внешние устройства, например на компьютер):
Пример 2. Передача данных по Serial-порту с компьютера на Arduino
Возможные проблемы
1) auto-reboot DTR : возможна автоперезагрузка МК при передаче на него данных по serial-пору. Чтобы отключить это, надо поставить конденсатор 10мкФ между RES и GND. Я ставил электролитический кондер (естественно, + на RES).
Как соединить две ардуины по UART (serial) порту
Схема соединения двух ардуин:
Расстояние связи по RS232 максимум 15 метров.
Но всё зависит от скорости.
Работа Arduino MEGA/DUE с несколькими последовательными serial портами
Многопортовые ардуино.
Как вы уже заметили, на ардуиновских платах Mega и Due имеется по 4 последовательных порта, а именно:
Естественно, что на Due используется напряжение 3.3 В (на MEGA как обычно 5 В).
Как с ними работать?
Пример вывода на дисплей LCD1602 через последовательный порт UART Arduino из-под Linux средствами языка Python
Короче говоря, есть комп с линуксом, к которому подключена Arduino через USB, а к арудине подключен дисплей LCD1602, и мы хотим на него выводить инфу.
Сначала привожу полный код программы для Arduino UNO, к которой подключен дисплей LCD1602:
Я сделал здесь решетку ‘#’ в качестве символа завершения передачи пакета данных. Как только в потоке данных встречается символ #, данные выводятся на дисплей, и буфер обнуляется, при этом сам символ ‘#’ не выводится. Конечно, можно было бы использовать ‘\n’ или др.
Далее мы напишем скрипт на Python, который будет выводить инфу на дисплей. Я выбрал Python, потому что это прикладной язык и он лучше всего подходит для подобных задач. С такими языками как C++/C# и т.п. больше возни с библиотеками, а здесь всё просто, особенно если это дело происходит под линуксом.
Первым делом устанавливаем необходимые библиотеки (для 2-ой или 3-ей версии python)
$sudo apt-get install python-serial
$sudo apt-get install python3-serial
Далее в интерпретаторе python пишем: