На сегодняшний день последовательные интерфейсы полностью вытеснили параллельные, во всяком случае для бытового применения. Для персональных компьютеров общим стандартом для обмена данными с периферией стал USB интерфейс, практически полностью заменив собой RS-232 (рис.2). Связь через последовательный порт с использованием интерфейса RS-232 когда-то была популярным методом передачи данных. На задней панели некоторых компьютеров, особенно старых, среди разъёмов можно заметить D-образный штекер с 9 контактами, также известный как COM-порт (от слова communication).
Рис.2 – Внешний вид кабеля USB – COM-порт (RS-232)
COM-порт был неотъемлемой частью большинства компьютеров на протяжении последних 30 лет. Хотя многие новые системы полностью отказались от стандарта RS-232 в пользу USB интерфейса, он до сих пор используется в системах промышленной автоматики, различных исследовательских и измерительных приборах. COM-порты все еще используются в этих областях, поскольку они крайне просты, надёжны, поддерживаются любой операционной системой, а их функционал очень хорошо стандартизирован. Последовательный порт не требует дополнительных драйверов или специализированного программного обеспечения, и пользователи могут легко взаимодействовать с COM-портом при помощи распространённых программ, таких как Матлаб и Labview.
Все микроконтроллеры семейства Mega, на которых работают платы Arduino, имеют в своем составе аппаратный блок универсального последовательного интерфейса – UART. По структуре это обычный асинхронный последовательный протокол как и RS-232, только с другими логическими уровнями, т.е. передающая сторона по очереди выдает в линию нули и единицы, а принимающая отслеживает и запоминает их. Синхронизация в UART идет по времени – мы заранее задаем скорость передачи данных как на стороне передатчика информации, так и на стороне приемника (именно поэтому передача асинхронная – отдельная линия для передачи тактовых синхронизирующих импульсов отсутствует). Это весьма важное замечание, так как расхождение в скоростях передачи может привести к ошибкам в распознавании информации, при этом ошибки будут накапливаться с увеличением скорости передачи данных. Поэтому перед началом передачи данных мы обязаны сделать множество настроек, которые должны совпадать как на стороне нашего микроконтроллера, так и компьютера, иначе передача будет невозможна.
Помимо информационных бит, UART автоматически вставляет в поток синхронизирующие метки, так называемые стартовый и стоповый биты. При приёме эти лишние биты удаляются из потока. Также существует возможность автоматически контролировать целостность данных методом контроля битовой чётности, в нашем случае особой пользы от этой проверки нет. Все эти параметры задаются строго перед началом передачи данных и не могут быть изменены в процессе.
На физическом уровне интерфейс UART крайне прост. Для его аппаратной реализации достаточно всего двух проводов, не считая общего провода, подключаемого обычно к напряжению земли (рис. 3). Эти линии имеют разное назначение – линия RXD используется для приема сообщений (Receiver), а TXD – для передачи сообщений (Transmitter). UART является полнодуплексным интерфейсом. Это значит, что приемник и передатчик работают независимо друг от друга, позволяя одновременно как передавать, так и принимать данные (так называемая полнодуплексная передача данных).
Рис. 3. Аппаратное обеспечение UART
Протокол передачи данных
Самый распространенный формат передачи данных для микроконтроллеров – 8 бит данных, 1 стартовый бит, 1 стоповый бит, без проверки на четность. Передача и прием сообщений осуществляется фиксированными пакетами бит, такой пакет называют кадром (рис. 2). Кадр состоит из стартового бита (с него начинается каждый кадр), битов данных (их количество можно изменяться от 5 до 9), бита проверки четности (проверка правильности передачи данных) и одного или двух стоп-битов (обязательный сигнал окончания кадра).
Рис. 4. Пакеты данных
Вначале передатчик переводит линию в уровень логического нуля – это стартовый бит. Всё время в промежутках между пакетами данных линия передатчика находится в состоянии логической единицы, поэтому зафиксировав появление ноля (тот самый стартовый бит), приемник отсчитывает интервал Т1 и считывает первый бит данных, потом через интервалы Т2 считывает все оставшиеся биты. Последний бит (или два бита) является стоповым. Он сообщает принимающей стороне, что передача данных закончена.
В конце байта, перед стоповым битом, может находиться бит проверки четности. Стоповый бит – контрольный бит, служащий для проверки общей чётности двоичного числа (чётности количества единичных битов в числе). Он формируется при выполнении операции «Исключающее-ИЛИ» со всеми передаваемыми битами. Стоповых битовых может быть два, для повышения надежности передачи.
Рис. 5. Пакет данных для передачи по интерфейсу UART
В настоящее время физические интерфейсы на основе RS-232 практически исчезли из современных персональных компьютеров. Однако удобство пользования и обилие программного обеспечения, имеющего доступ к внешним устройствам через COM-порт, вынудило разработчиков создать драйвера виртуальных COM-портов. Виртуальный COM-порт является полной эмуляцией реального последовательного порта. На одном компьютере можно создать большое количество виртуальных COM-портов, единственным ограничением являются доступные ресурсы, такие как оперативная память и вычислительная мощность.
Виртуальные COM-порты работают так же, как и реальные, и любое приложение может работать с ними, как с реальными физическими портами на материнской плате компьютера. Виртуальные COM-порты эмулируют все функциональные возможности аппаратных, включая скорость передачи данных, проверку на чётность, количество стоп-бит и все остальные параметры.
Настройка и программирование интерфейса UART
Вначале рассмотрим регистры, имеющие отношение к нашему приёмопередатчику. У каждого микроконтроллера, поддерживающего UART, есть регистр UDRx – UART Data Register (в микроконтроллерах из серии Mega есть два блока UART, поэтому и регистров тоже два – UDR0 и UDR1). На физическом уровне UDR представляет собой два разных регистра, имеющих одинаковый адрес. При записи данных информация поступает в первый регистр (регистр передатчика), а при чтении берется из другого (регистр приемника). Таким образом, и при чтении, и при записи данных мы используем один регистр, что значительно облегчает процесс программирования.
О том, что байт полностью пришел в регистр UDR, нам указывает прерывание по завершении приема, которое вызывается сразу же после того, как приемник обработает все поступившие в него биты.
Поскольку передача идет довольно медленно, то бездумно посылать всё новые и новые данные в регистр UDR нельзя – необходимо дождаться окончания передачи предыдущего байта. О том, что UDR пуст и готов к приему нового байта сигнализирует бит UDRE, он же вызывает аппаратное прерывание по опустошению буфера (USART Data Register Empty Interrupt Enable).
Все настройки приемопередатчика хранятся в регистрах конфигурации, которые известны как UCSRA, UCSRB и UCSRC, скорость передачи данных задается регистровой парой UBBRH:UBBRL. Рассмотрим подробнее наиболее важные регистры.
Регистр UCSRxA (UART Control and Status Register). Здесь наибольший интерес вызывают биты RXCn (Receive Complete) и TXCn (Transmit Complete) – это флаги завершения приема и передачи данных, соответственно. RXC устанавливается в единицу, когда принимаемый байт запишется в регистр UDR для последующего чтения, а TXC – после прохождения последнего стоп-бита и отсутствия новых данных в регистре UDR, т. е. после окончания передачи всех битов. Также одновременно с этими флагами вызывается прерывание (если оно было разрешено). Сбрасываются эти флаги на аппаратном уровне – принимающий после чтения данных из регистра UDR, передающий при переходе на соответствующее прерывание, либо программным образом (чтобы сбросить флаг программно, в него надо записать логическую единицу).
Биты UDREn (USART Data Register Empty) сигнализирует о том, что регистр UDR приемника пуст, и в него можно записывать новый байт. Сбрасывается он аппаратно после записи новой порции данных в UDR, при этом генерируется соответствующее прерывание.
Бит U2Xn (Double the USART Transmission Speed) – бит удвоения скорости передачи данных при работе в асинхронном режиме. Его надо учитывать при расчете значения в регистровой паре UBBRH:UBBRL.
Регистр UCSRxB. В этом регистре основную роль играют биты RXEN (Receiver Enable) и TXEN (Transmitter Enable) – при записи в них логической единицы осуществляется разрешение приема и передачи, соответственно.
RXCIEn (RX Complete Interrupt Enable) – осуществляет разрешение прерывания по завершению приема данных.
TXCIE (TX Complete Interrupt Enable) – осуществляет разрешение прерывания по завершению передачи данных.
UDRIEn (UART Data Register Empty Interrupt Enable) – осуществляет разрешение прерывания по опустошению регистра передачи данных UDR.
Регистр UCSRxC. В этом регистре мы можем выбрать необходимый протокол передачи данных.
UMSELn (UART Mode Select) – здесь мы задаем формат передачи – синхронный либо асинхронный, в зависимости от значения бита, как показано в табл. 1.
Таблица 1. Выбор режима передачи данных по UART
UMSELn (значение бита) |
Режим передачи |
0 |
Асинхронный |
1 |
Синхронный |
UPMn1:0 (UART Parity Mode) – установка проверки на четность, в наших практических работах данная опция не используется, по умолчанию в оба бита записаны логические нули, передача данных ведется без проверки на четность.
USBSn (UART Stop Bit Select) – определяет количество стоповых битов, здесь возможно всего два варианта (табл. 2).
Таблица 2. Выбор количества стоп-бит
USBSn Stop Bit (значение бита) |
Количество стоп-бит |
0 |
1 стоповый бит |
1 |
2 стоповых бита |
UCSZn1:0 (UART Character Size) – определяет количество передаваемых битов данных – от 5 до 9, в соответствии с таблицей 3.
Таблица 3. Выбор количества передаваемых бит данных
UCSZn2 |
UCSZn1 |
UCSZn0 |
Количество бит |
0 |
0 |
0 |
5 бит |
0 |
0 |
1 |
6 бит |
0 |
1 |
0 |
7 бит |
0 |
1 |
1 |
8 бит |
1 |
1 |
0 |
Зарезервировано |
1 |
1 |
1 |
9 бит |
Скорость передачи данных
Здесь всё зависит от значения, записанного в регистровую пару UBBRH:UBBRL. Вычисляется требуемое значение по следующей формуле:
для U2X=0 (обычная скорость передачи);
для U2X=1 (удвоенная скорость передачи),
где XTAL – рабочая тактовая частота контроллера; baudrate – требуемая скорость. Чем выше скорость, тем больше ошибка рассинхронизации, поэтому на высоких скоростях целесообразно использовать специализированные кварцы (те самые, с неровным значением вроде 11.0592 МГц).
Теперь можно приступить к процедуре непосредственной инициализации, используется стандартный протокол передачи и единственный канал UART, доступный для нашего микроконтроллера.