![](https://habrastorage.org/getpro/habr/upload_files/b47/2c4/a1a/b472c4a1a0b7d676f2b3b3a1210bec1e.png)
Можно с уверенностью сказать, что с момента публикации первой версии стандарта RS‑232 в мае 1960 года и по настоящее время, было написано приблизительно 109 независимых реализаций UART на всём, чём угодно. Однако, подобно «Hello world» в мире прикладного ПО, а также мигания светодиодом — «Hello world» в мире цифровой электроники (сигнализирующий об успешной настройке оборудования и среды разработки) — процесс написания UART способен проиллюстрировать особенности языка или платформы, демонстрируя применение тех или иных синтаксических конструкций для решения практических, насущных и понятных проблем.
В данном цикле статей будет рассказано про написание модуля UART на SystemVerilog, про синтез данного модуля на различных платформах и про некоторые другие аспекты применения UART в ПЛИС. Но прежде, чем писать код, поговорим про сам протокол и про особенности аппаратной части вне контекста ПЛИС.
RS-232
Представим, что у нас есть необходимость передавать данные в одну сторону по одному проводу при помощи логических уровней напряжения. Мы можем просто пустить поток бит, договорившись об одинаковой скорости передачи и приёма данных. Но принимающее устройство не будет знать, где этот поток начался, где он закончится, идёт ли он вообще, как биты распределены по байтам и так далее.
Для начала, нам потребуется заранее оговоренное состояние, которое будет считаться отсутствием передачи данных, то есть паузами между отдельными байтами. Допустим, это будет логическая единица.
![](https://habrastorage.org/getpro/habr/upload_files/eaa/de1/b32/eaade1b3253fa28009f839b5ea9ec0aa.png)
Правда, без дополнительных условий будет невозможно отправить байт, состоящий из одних единиц, либо отличить последовательность 11010100 от 01010011.
Можно условиться, что к каждому передаваемому байту мы припишем дополнительный служебный бит (старт-бит), заведомо содержащий логический ноль. Тогда после паузы в передаче данных, приёмник при получении нисходящего фронта будет готов к приёму оговоренного количества бит, содержащих осмысленные данные.
![](https://habrastorage.org/getpro/habr/upload_files/b88/7ab/4d5/b887ab4d570d23a32cea6cc70b71e01c.png)
Остаётся проблема: что, если будет передаваться длинная последовательность бит, содержащих нулевые значения без пауз между отдельными байтами? Тогда, рано или поздно, накопленная рассинхронизация тактовых генераторов источника и приёмника превысит половину длительности одного бита. И приёмник либо дважды прочитает один и тот же передаваемый бит, либо наоборот, пропустит один из передаваемых битов.
![](https://habrastorage.org/getpro/habr/upload_files/4a2/070/b51/4a2070b51121ad1ae45ee67bf595f873.png)
Нисходящий фронт старт-бита мог бы позволить синхронизироваться источнику и приёмнику каждый раз при начале передачи очередного символа, обнуляя накопившееся рассогласование. Но это возможно, только если перед старт-битом линия каждый раз будет оказываться в состоянии логической единицы. То есть если между байтами имеются хоть небольшие, но паузы. Такие обязательные паузы называются стоп-биты.
Договорившись о наличии старт-бита, стоп-битов, количестве битов данных в рамках одной передачи («символа» в терминологии UART) от старт-бита до стоп-бита и частоте следования бит можно организовать устойчивую однонаправленную передачу данных по одному проводу.
Стандарт RS-232 задаёт значение выходного напряжения логической единицы от −5 до −15 В, а логического нуля — от +5 до +15 В (именно в таком порядке). Данные уровни напряжения не поддерживаются микросхемами ПЛИС напрямую и существует несколько вариантов соединения ПЛИС с компьютером через RS‑232.
![](https://habrastorage.org/getpro/habr/upload_files/81b/c8a/12e/81bc8a12ed198cb26048b2a8bbf443e9.png)
Если у компьютера предусмотрен com-порт, то соединение возможно при помощи пассивного кабеля и транслятора уровней. Зачастую трансляторы уровней для RS‑232 (к примеру, ADM3232E) изготавливают с встроенным умножителем (удвоителем) напряжения на основе переключаемых конденсаторов. Он преобразует +3,3 В в приблизительно ±6,6 В, которые используются в качестве уровней выходного сигнала на линии TX. А вход RX делают устойчивым к напряжениям вплоть до ±15 В.
![](https://habrastorage.org/getpro/habr/upload_files/dcf/499/a6c/dcf499a6cbcd6422c2f13e21bdc84744.png)
Если у компьютера отсутствует встроенный com-порт, то соединение возможно при помощи внешнего преобразователя USB-RS232 (к примеру, UPort1150).
В этом случае иногда происходит некоторая путаница с разъёмами. Если разъём DB-9 на материнской плате — всегда «папа» (штыри), то разъём на оборудовании почти всегда «папа». Исключение — прецизионные источники питания компании Keithley (которую купил Tektronix). У них разъём «мама» (гнёзда). Разъём же на преобразователях USB-RS232 почти всегда, как и на материнских платах — «папа». Соответственно, он может быть подключен к Keithley непосредственно. Но для большинства оборудования дополнительно потребуется кабель «мама-мама». Разъём DB-9 предусматривает наличие стягивающих винтов. И ввиду того, что их не расположить внутри корпуса оборудования, то ими оснащается именно кабель. А на разъёмах оборудования делают гайки, куда эти винты закручиваются.
![У преобразователя MOXA - гайки, у noname - винты. И у обоих в разъёме - штыри. У преобразователя MOXA - гайки, у noname - винты. И у обоих в разъёме - штыри.](https://habrastorage.org/getpro/habr/upload_files/cbd/3c5/99e/cbd3c599ec75496ee5f7aea1d8524633.png)
И, казалось бы, если на преобразователях USB-RS232 стоит разъём «папа» (для соединения с «мамой» кабеля, оснащённого винтами), то на нём должны быть гайки. Однако, данный элемент с вероятностью 50/50 будет также винтом! Зато к Keithley подходит идеально :) В общем, если вы решили соединять оборудование с компьютером и хотите чтобы всё собралось с первого раза, не полагайтесь на то, что «всё стандартизовано, тут не ошибёшься» и обратите внимание:
на разъём в оборудовании и преобразователе (штыри/гнёзда)
на крепления в оборудовании и преобразователе (винты/гайки)
![](https://habrastorage.org/getpro/habr/upload_files/4e7/fb7/a89/4e7fb7a898aa05417464e61dd306649b.png)
Электронная промышленность предоставляет широкую номенклатуру мостов USB-UART. Благодаря им, при создании устройства можно использовать все аппаратные плюсы интерфейса USB и при этом сохранить относительную простоту программного обеспечения, характерную для RS-232. В дальнейшем мы будем рассматривать именно этот вариант соединения, хотя с точки зрения кода для ПЛИС, разницы между предыдущими тремя примерами нет.
Есть, правда, весьма важный момент. Сам стандарт TIA/EIA-232-F (RS-232) содержит лишь электрические характеристики и размеры разъёмов. Типичные же скорости передачи данных, количество бит данных в символе, а также наличие/отсутствие дополнительного бита контрольной суммы (бита чётности) этим стандартом не оговаривается. Иногда можно встретить утверждение, что перечисленные выше аспекты оговорены в UART («Universal Asyncronous Receiver-Transmitter»), но это общее название некоторого свода обычаев передачи данных. Этому своду не соответствует какой-либо один-единственный написанный и утверждённый стандарт.
Неким подобием стандарта может считаться структура DCB, применяемая в функции SetCommState в Windows API и предназначенная для инициализации com-порта.
Так, в описании данной структуры говорится, что в символе UART может быть 1/1,5/2 стоп-бита. Однако, стандарт «ISO/IEC 7816-3», похожий на «обычный» UART и регламентирующий обмен данными со смарт-картами, предусматривает наличие 0,5 стоп-бита. И, к примеру, микроконтроллер STM32F103 способен через конфигурационные биты «STOP» ([13:12]) регистра «USART_CR2» задать режим работы модуля UART как с этим самым половинным стоп-битом, так и с более распространёнными количествами стоп-битов. А мост FT232R не только не способен поддерживать половинный стоп-бит, но также не способен поддерживать полуторный стоп-бит: только один или два стоп-бита.
Или в описании структуры DCB говорится, что значащих бит в одном символе UART может быть от 5 до 8 штук (в это количество не входит бит чётности). А уже упомянутый мост FT232R способен работать только с 7 или 8 битами. Однако, другой похожий на UART стандарт — MDB («Multi-Drop Bus») — содержит, по сути, 9 значащих бит (8 бит данных, плюс бит режима/направления). И микроконтроллер STM32F103 способен работать как с MDB, так и с 8-битным UART.
Теперь, если мы возьмём материнскую плату или преобразователь USB-RS232, вроде «UPort 1115», мы сможем сказать «где-то там есть RS-232». Однако, если мы возьмём микросхему-мост USB-UART с уровнями на линиях RX/TX равными +3,3/0 В, сложится парадоксальная ситуация: описываемые в TIA/EIA-232-F напряжения нигде не соблюдаются, а протокол, реализуемый этим мостом не описан в самом стандарте. То есть RS-232, упоминаемый в подобном контексте, приобретает некоторые постмодернистские черты симулякра — символа, у которого нет оригинала :)
![](https://habrastorage.org/getpro/habr/upload_files/869/b70/495/869b704954514f6dea673e4de2522d25.png)
Возможно также соединить линии USB напрямую к ПЛИС и наделить ПЛИС функционалом, позволяющим ей опознаваться компьютером как USB-устройство класса CDC («Communication Device Class») — то есть как com-порт. Однако, тратить (и в весьма большом количестве!) логические элементы ПЛИС на столь обыденную задачу, реализованную в готовых микросхемах USB-UART имеет смысл только в рамках учебных задач, связанных с изучением протокола USB.
Работа над ошибками
Рассматривая аспекты, связанные с ошибками, возникающими при передаче данных через UART, можно выделить три группы:
нестабильности электрических параметров сигнала
нестабильности временных параметров сигнала
нарушение в логике приёма/передачи
Обсудим ряд аспектов, связанных с каждой из этих групп.
Мажорирование
Когда речь заходит про аппаратное исправление нестабильности электрических параметров, регулярно произносится слово «мажорирование». То есть многократное (обычно — троекратное) снятие показаний в пределах одного принимаемого бита и последующий выбор в качестве истинного значения принимаемого бита того, которое чаще других встретилось в ходе этих замеров.
![](https://habrastorage.org/getpro/habr/upload_files/b90/828/7a9/b908287a9e9898772bf2b9b884398cba.png)
На первый взгляд, подобный механизм может показаться «серебряной пулей», сводящей вероятность ошибок практически к нулю. Попробуем, однако, оценить количественно степень влияния мажорирования на уровень ошибок.
Немного формул
Предположим, что ошибки в ходе замеров являются независимыми друг от друга и появляются с вероятностью «p». Выпишем в таблицу все 8 возможных комбинаций 3-битного числа. Но вместо единиц в ячейках таблицы запишем вероятность ошибки в конкретном замере («p»), а вместо нулей — вероятность верного считывания («1-p»). Вероятность появления каждой комбинации будет равна произведению содержимого ячеек соответствующего столбца. Поэтому отметим те комбинации, которые всё же приведут к ошибочному считыванию бита при мажорировании, определим вероятности появления этих комбинаций и сложим их всех.
![](https://habrastorage.org/getpro/habr/upload_files/e57/1aa/d12/e571aad1247447efb0a6f58b632598dd.png)
Как видно, вероятность ошибки при мажорировании будет равна:
Или, если раскрыть скобки и упростить выражение, то:
Пока что влияние мажорирования может просматриваться не слишком явно. Для более чёткой картины возьмём десятичный логарифм «pmaj»:
Преобразуем это выражение. Для начала вынесем за скобки логарифмируемого выражения квадрат «p»:
Затем заменим произведение логарифмируемого выражение на сумму логарифмов:
С уменьшением «p», второе слагаемое (второй логарифм) достаточно быстро будет стремиться к десятичному логарифму трёх, который равен 0,477 (так, при «p» равном 10-2 (одна ошибка на сто бит) это слагаемое уже будет равно 0,474).
Иными словами, если вероятность ошибки равна:
...то вероятность ошибки с использованием мажорирования по трём замерам приблизительно равна:
Здесь «x» по идее должен принимать значения от «0» до «-∞», но при приближении к нулю (то есть при приближении «p» к единице) начнут сказываться допущения. Однако уже при «x», равном «-1» (то есть одна ошибка на десять бит), приближённые значения будут отличаться от точных значений всего на 2%.
![](https://habrastorage.org/getpro/habr/upload_files/f04/2ee/218/f042ee218d0769d50570262c6340309f.png)
Представим, что происходит передача данных по UART с конфигурацией «старт‑бит/8 бит данных/стоп‑бит» на скорости 9600 бит/с и «p» равно 10-6. Это означает, что одна ошибка происходит в среднем один раз в две минуты (130 секунд, если точнее). Поиск причины ошибки, появление которой видится квази-случайным и происходит раз в несколько минут, является достаточно неприятным и трудозатратным занятием. Если же мы применим мажорирование, то ошибка, в теории, начнёт возникать с вероятностью 10-11,523. Или приблизительно один раз в 16,5 месяцев. Вроде бы отличный результат.
Однако, что если «p» равно 10-4 ? Что если ошибка происходит один раз в секунду (1,3 секунды, если точнее), но инженер принял решение не кропотливо настраивать различные условия захвата в цифровом осциллографе с целью выявления причин ошибки, а применить мажорирование, и оно сработало идеальным образом?
Тогда «pmaj» будет равно 10-7,523. Или приблизительно один раз в 72 минуты — как раз достаточно, чтобы в случае претензий сказать: «Ну и где? Где эта ошибка? Вот, всё же работает! А вы говорите!» и убыть в закат :)
Кроме того, предположение о том, что ошибки в различных замерах одного бита являются независимыми не совсем верно. Предположим, что ошибка при считывании очередного бита появляется из-за наводки, скачка в цепи питания, либо чего-то подобного. Если мажорирование не применяется, вероятность ошибки «p» тогда будет равна произведению вероятности возникновения помехи «pnoise» на отношение длительности помехи «tnoise» к длительности бита «T»:
Одинаковую вероятность ошибки может создать как длительная, но редкая помеха, так и короткая, но часто повторяющаяся помеха. Однако, часто повторяющуюся помеху («pnoise» которой много больше, чем собственно «p») будет легче обнаружить, проанализировать и выявить её источник. А редко повторяющаяся помеха, та, от поиска которой, по идее, и должно защитить мажорирование, будет длительной помехой, способной в ряде случаев «накрыть» сразу несколько замеров.
![](https://habrastorage.org/getpro/habr/upload_files/bde/761/fbb/bde761fbbdd60dfce6544f475a05b47e.png)
В общем, методы коррекции ошибок, применяемые бездумно, способны как решить проблему, так и в отдельных случаях оказаться заметанием мусора под ковёр или вообще не сработать.
Оверсемплинг
Представим, к примеру, ардуиновский микроконтроллер ATmega328P. В нём битрейт модуля USART задаётся при помощи делителя «UBRR» (он записывается в регистры «UBRRnL» и «UBRRnH») и равен:
Допустим, частота fOSC равна 10 МГц, а нам требуется получить стандартные 9600 бит/с. Тогда наиболее подходящим значением UBRR будет «64». Благодаря ему удастся задать битрейт, равный 9615,4 бит/с. Погрешность в 0,16% кажется незначительной, однако она накапливается с каждым битом. И для последнего фронта в символе составит 1,44%.
Точность внутреннего RC-генератора для того же микроконтроллера ATmega328P при фиксированной температуре в 25°C и напряжении 3,0 В заявлена ±2%. Во всём диапазоне рабочих температур и напряжений заявленная точность генератора падает до крайне грубых ±14%. Но ниже мы будем отталкиваться от первой цифры.
![](https://habrastorage.org/getpro/habr/upload_files/cac/123/552/cac1235527c03ebf42e0513ed113c098.png)
Нестабильность генератора создаёт дополнительную погрешность, которая хоть и не накапливается с каждым битом, но в конце символа способна сложиться с одним и тем же знаком с погрешностью от деления частоты. При этом, суммарная погрешность передатчика может удлинить передаваемые им биты, а суммарная погрешность приёмника — укоротить считываемые им биты. То есть, по сути, погрешности сложатся по модулю.
Если считывание производится непосредственно с частотой битрейта, то рано или поздно возникнет ситуация, когда принимающее устройство зафиксирует появление старт-бита не в середине бита, а в самом его начале (сразу после появления нисходящего фронта) или же в самом конце (перед первым битом данных). Причём сколь угодно близко к фронту. И к последнему биту символа приёмник гарантированно рассогласуется с передатчиком.
![](https://habrastorage.org/getpro/habr/upload_files/f9a/2b0/953/f9a2b0953d0b31e2d0836e128abf70b1.png)
Решением этой проблемы является многократное считывание логического состояния на линии RX — оверсемплинг. После первого считывания, результат которого может быть принят за старт-бит, приёмник ожидает половину битового периода и только начиная с этого момента приступает к считыванию бит через равные промежутки времени. При четырёхкратном чтении, ошибки передачи будут отсутствовать при общей временно́й погрешности, доходящей до 25%!
![](https://habrastorage.org/getpro/habr/upload_files/a67/89b/55b/a6789b55b8608006472e03a8f120591c.png)
На этом месте может возникнуть пара вопросов:
Какова временная погрешность приёмопередатчиков UART в реальных устройствах?
Если приёмник всё равно производит многократное чтение одного и того же бита, возможно ли получаемые данные эффективно использовать также для мажорирования?
Отвечая на первый вопрос, можно обратиться к документу «Determining Clock Accuracy Requirements for UART Communications», выпущенный компанией Maxim Integrated (на текущий момент она поглощена компанией Analog Devices), который говорит следующее:
It is difficult to quantitatively assess a worst-case acceptable sampling range across a bit's period. EIA/TIA-232-F does specify a 4% of bit-period maximum slew time for a transmission, but this is difficult to achieve for long runs at 192kbps. But for the purpose of this application note, let us define two data path scenarios. Consider a "nasty" scenario, which can only be sampled reliably within the middle 50% of the bit time. This could equate to a long capacitive RS-232 run. The "normal" scenario can be sampled within the middle 75% of the bit time.
То есть инженеры Maxim Integrated предполагают, что невозможность корректно считать значения на линии RX в течении 25% от длительности бита — это вполне нормальное явление.
Если же проводить тест по маске, к примеру, для платы производства WaveShare с микросхемой FT232RL (с внутренним тактовым генератором) при битрейте 9600 бит/с, то из допуска ±2% от длительности бита последний фронт символа (восходящий фронт стоп-бита) будет «вываливаться» с вероятностью 0,55%. А из допуска ±4% с вероятностью 0,5×10-5 %. Можно предположить, что допуск в 10–12% (±5…6%) будет достаточно широк для того, чтобы считать вероятность выхода из него несущественной величиной. Если происходит обмен данными между двумя устройствами с допуском в 10…12% у каждого, то имеет смысл говорить об общей погрешности как раз в 20…24%.
Для ответа на второй вопрос представим себе, что у нас есть 8-кратный оверсемплинг и 25% общей погрешности, связанной с временными характеристиками. Два семпла окажутся в зоне 25%. Ещё на один семпл попадает «игла», которую мы пытаемся устранить при помощи мажорирования (ведь исправлять помехи имеет смысл только когда они есть, а словосочетание «есть помеха» означает, что помехи попадают по семплам). Итого мы получим 5 годных для мажорирования семплов к которым добавлено 3 гарантированно ненадёжных семпла.
![](https://habrastorage.org/getpro/habr/upload_files/cc2/953/e30/cc2953e309677878dd37710875f5f4a0.png)
Подобная конструкция не представляется такой уж надёжной. Поэтому, к примеру, в STM32F103 коррекция ошибок (мажорирование по восьмому, девятому и десятому семплам бита), дополнена механизмом сигнализация об их наличии.
![](https://habrastorage.org/getpro/habr/upload_files/f7e/780/dab/f7e780dababdcdb2d2e93372883dd3f6.png)
![](https://habrastorage.org/getpro/habr/upload_files/184/b22/ae2/184b22ae2ffdcdd83749abf2447cf657.png)
То есть если три семпла, взятые посередине бита не равны все нулю или все единице, то такое значение, вообще говоря, не считается действительным.
Ошибки логики
Является ли ошибкой отсутствие стоп-бита? То есть если был передан старт-бит, затем оговоренные N бит данных, а после этого стоп-бит не появился (линия вместо стоп-бита оказалась в состоянии логического нуля)? Не всегда. Так, стандарт «ANSI E1.11», описывающий протокол обмена данными светотехнического оборудования DMX512, похожий на классический UART, использует при передаче данных аналогичное действие. При номинальной длительности бита DMX512 равной 4 мкс, переход в логический ноль и последующее удержание этого состояния в течение 92 мкс (то есть 23 нулевых бита подряд) или более, называется «break» и маркирует начало очередного пакета данных.
![](https://habrastorage.org/getpro/habr/upload_files/3ce/2e8/b8c/3ce2e8b8cca034039512f921fe417c7a.png)
![](https://habrastorage.org/getpro/habr/upload_files/66d/629/603/66d629603dfb8c37d919f4e87732a656.png)
Однако, в общем случае, если передаваемый символ состоял не только из нулей, отсутствие стоп-бита будет, пожалуй, именно ошибкой — «framing error».
Является ли ошибкой отсутствие второго стоп-бита, если на стороне компьютера был выбран режим с двумя стоп-битами, а коммуницирующее устройство было настроено на работу с одним стоп-битом?
Пожалуй, нет. Так, в документации на ардуиновский микроконтроллер ATmega328P написано:
The Receiver and Transmitter use the same setting. Note that changing the setting of any of these bits will corrupt all ongoing communication for both the Receiver and Transmitter. An FE (Frame Error) will only be detected in cases where the first stop bit is zero.
Ещё более подчёркнуто это написано в документации на упоминавшиеся микроконтроллеры STM32F103:
2 stop bits: Sampling for 2 stop bits is done on the 8th, 9th and 10th samples of the first stop bit. If a framing error is detected during the first stop bit the framing error flag will be set. The second stop bit is not checked for framing error.
Относительно современная микросхема Super-I/O NCT6776D, реализующая UART на материнских платах, косвенно ссылается в своей документации на ставшую де-факто стандартом, классическую микросхему PC16550D:
NSER (No Stop Bit Error). This bit is set to logical 1 to indicate that the received data have no stop bit. In 16550 mode, it indicates the same condition for the data on the top of the FIFO. When the CPU reads USR, it sets this bit to logical 0.
А в документации на микросхему PC16550D написано:
If bit 2 is a logic 0, one Stop bit is generated in the transmitted data. If bit 2 is a logic 1 when a 5-bit word length is selected via bits 0 and 1, one and a half Stop bits are generated. If bit 2 is a logic 1 when either a 6-, 7-, or 8-bit word length is selected, two Stop bits are generated. The Receiver checks the first Stop bit only, regardless of the number of Stop bits selected.
Заключение
Типичная схема применения UART — это старт-бит, 8 бит данных и один-единственный стоп-бит. Типичный битрейт — 9600 бит/с (то есть длительность любого бита будет равна 104,17 мкс). В типичном случае «break frame» (большое количество нулевых бит) не применяется и будет просто ошибкой передачи. Так что базово UART относительно прост.
А упомянутые в статье особые случаи являются исключениями. О существовании которых, однако, имеет смысл знать. Также имеет смысл знать о практике применения данного протокола в индустрии. К примеру, посмотреть, какие возможности предоставляют различные микросхемы мостов USB-UART. Их детальный обзор — в следующей статье.
Комментарии (22)
victor_1212
02.01.2023 18:45+3вполне качественная статья, единственное возможно стоит подчеркнуть что протокол full duplex, также было бы полезно четко указать разницу между синхронными и асинхронными протоколами (включая UART), типа преимущества и недостатки, это не сложно, для понимания полезно, исторически UART это интерефейс PDP-1, разработан Gordon Bell (DEC)
NickDoom
02.01.2023 18:57+1Кстати, о дуплексе. Когда я колхозил передачу максимума данных по тому же кабелю, я слегка проработал вариант «временного реверса линии»: устройство, гарантированно знающее, что некоторое время ему ничего не придётся передавать, передаёт по Tx специальную команду на реверс, после чего переключает его из Tx во второй Rx (то есть подключает по факту ко второму порту). И после этого может принять посылку фиксированной длительности, если второму устройству есть чего сказать в таких количествах, что по одной линии не пролезает за нужное время. После окончания такого реверса может делать всё как обычно — как правило, скинуть контрольную сумму всего принятого.
victor_1212
02.01.2023 20:44+1правильно делаете что разные возможности проверяете, хотя и сильно нестандарт
ps
заметим sampling - это то что реализовал Gordon Bell, до этого типа в ручную подстраивали
Sun-ami
02.01.2023 19:14+1Во многих микроконтроллерах есть режимы UART с 16 выборками на бит, и с 8 выборками на бит, причем второй рассматривается как компромисс на случай, если тактовая частота модуля UART не позволяет использовать режим x16. Почему считается, что х8 хуже? Ведь в случае длительной помехи система мажорирования трёх центральных выборок с большей вероятностью выдаст правильный результат как раз для х8. И если х8 хуже, чем х16, то насколько?
Зачем вообще нужны варианты длительности стоп-бита, отличные от 1?Flammmable Автор
02.01.2023 19:39Во многих микроконтроллерах есть режимы UART с 16 выборками на бит, и с 8 выборками на бит <...> Почему считается, что х8 хуже?
Количество 8...16 выборок - это количество выборок оверсемплинга. Оверсемплинг противостоит ошибкам, связанным с временными параметрами. Он позволяет выставить главное, так скажем, считывание как можно более близко к центру бита. Если он - 8, то сдвиг будет не более, чем на 1/8 периода. Если он - 16, то не более, чем на 1/16. В первом случае, если соседний фронт съедет на 37,5% от длительности бита, то будет ошибка, если меньше, то не будет. Во втором случае фронт для возникновения ошибки должен съехать на 43,75%. Выше поднимать оверсемплинг нет смысла, потому, что если фронт съехал на 50% и более - любой оверсемплинг не спасёт.
Ведь в случае длительной помехи система мажорирования трёх центральных выборок с большей вероятностью выдаст правильный результат.
Мажорирование - это попытка незаметно убрать ошибки. С некоторой вероятностью это приводит к, так скажем, заметанию ошибок под ковёр. Есть мнение, что не нужно ожидать, пока "мажорирование <...> с большей вероятностью выдаст правильный результат", а просто при наличие ошибок начать поиск их причин. Либо применять более надёжные методы коррекции ошибок на более высоких уровнях.
Зачем вообще нужны варианты длительности стоп-бита, отличные от 1?
Наличие 1,5 и 2 бит скорее исторически обусловлено. Большее количество стоп-бит даёт принимающему устройству больше времени на раскладывание бит принятого символа по своим внутренним регистрам. Сейчас, конечно, учитывая, что оверсемплинг (а значит и само принимающее устройство) работает на порядок быстрее базового битрейта, современные устройства должны всё успевать за 1 стоп-бит.
Sun-ami
02.01.2023 20:03В первом случае, если соседний фронт съедет на 37,5% от длительности бита, то будет ошибка, если меньше, то не будет. Во втором случае фронт для возникновения ошибки должен съехать на 43,75%.
Но и то, и другое — совершенно ненормальная ситуация, далеко выходящая даже за 25%. Это, конечно, некоторое преимущество, но на мой взгляд, не существенное.Есть мнение, что не нужно ожидать, пока «мажорирование <...> с большей вероятностью выдаст правильный результат», а просто при наличие ошибок начать поиск их причин.
Если ошибки обнаруживаются на этапе испытаний — конечно, нужно разобраться в причинах их возникновения. Это одна из причин, почему не стоит использовать устаревшие микроконтроллеры — в ATmega программа просто не может обнаружить шум, который был отфильтрован мажоритарной схемой UART — там UART не имеет флага noise. Но если ошибки не возникают на испытаниях — это еще не значит, что они не будут возникать в эксплуатации, потому что всегда возможны внешние воздействия, превышающие то, на что устройство было рассчитано, и если мажоритарная схема позволяет с ними справиться — значит её нужно использовать.Flammmable Автор
02.01.2023 20:22+1Но если ошибки не возникают на испытаниях — это еще не значит, что они не будут возникать в эксплуатации, потому что всегда возможны внешние воздействия, превышающие то, на что устройство было рассчитано
Есть мнение, что если внешние воздействия превышают то, на что устройство было рассчитано, то его не следует эксплуатировать в подобных внешних условиях :)
С другой стороны, требования бизнеса по срокам и стоимости могут быть различны. Где-то есть время и деньги, скажем, на изготовление специального кронштейна, а где-то синяя изолента будет признана лучшим решением по соотношению цена/качество.
На мой взгляд, с мажорированием - аналогичная ситуация.
checkpoint
02.01.2023 20:31+6К слову, не плохо было бы рассказать про автоматическое определение скорости. Небольшой appnote на эту тему от STmicro.
UPD: Заметка в Википедии на тему Automatic Baudrate Detection.
RV3EFE
03.01.2023 07:48+4Статья понравилась! Буду рекомендовать для обучения всем, кто не знаком с uart и 232'м
aumi13
03.01.2023 10:04+3Типичный битрейт — 9600 бит/с
лол. в усб-уарт нынче битрейт можно мегабитный задать, но если почитать форумы то со скоростью выше 115.4 возникают проблеммы. получается зоопарк переходников, систем и драйверов которые ведут себя по разному. а еще производители любят создавать "фирменные" переходники с нестандартными скоростями.
кстати, в промышленных компах ком порт бывает стандартов RS-485/RS-422
Flammmable Автор
03.01.2023 10:38+1лол. в усб-уарт нынче битрейт можно мегабитный задать, но если почитать форумы то со скоростью выше 115.4 возникают проблеммы
Это правда, видеопоток через UART пропустить хоть и, теоретически, возможно, но проблематично.
Где UART хорош, так это в управлении, в передаче команд. Выставить ток, напряжение и сказать "включись!" тому же Keithley - здесь и 9600 бит/с хватает (с потоком данных от Keithley чуть сложнее, но терпимо). И отлаживать такой поток куда проще, чем многие другие протоколы. В (самом) крайнем случае даже палец, водящий по осциллограмме сгодится :) С USB, к примеру, так не поводишь :)
Mirn
03.01.2023 10:49а классический стандарт на скорости свыше 115200 бод не распространяется да и даже далеко не все современные трансляторы уровней TTL-RS232 поддерживают скорости бод свыше 250к.
и в ОС обычно но не всегда, значение энума например BOD_9600 равно 9600 как инт32. Но иногда это например 7 (как седьмая по счёту константа) и размер параметра не int32 а int8 и другие скорости попросту не выбрать или выбрать надо спец параметрами через ioctl
И даже на уровне USB endpoint мостов уарт-усб реализованы аппаратно и поэтому они максимально мелкие, максимум под 115200. Это было например в самых старых первых аппаратных чипах и быстрее передавать попросту не могут без багов.
Тоесть, порой это и логически и физически невозможно.
Или возможно но с кучей ограничений (например нельзя непрерывно передавать на скоростях свыше 115.2кбод - обязательно делать паузы раз в миллисекунду чтоб усб успел отправить).
MaFrance351
03.01.2023 10:05+2В этом случае иногда происходит некоторая путаница с разъёмами. Если разъём DB-9 на материнской плате — всегда «папа» (штыри), то разъём на оборудовании почти всегда «папа». Исключение — прецизионные источники питания компании Keithley (которую купил Tektronix). У них разъём «мама» (гнёзда). Разъём же на преобразователях USB-RS232 почти всегда, как и на материнских платах — «папа». Соответственно, он может быть подключен к Keithley непосредственно.
Вроде бы традиционно считается, что разъём с гнёздами (как на модемах, некоторых бесперебойниках, упомянутых тут ЛБП) требует модемного кабеля (для прямого подключения к ПК), а разъём со штырьками (кассовые аппараты, телефоны, терминалы, всякое оборудование с таким интерфейсом, другие компьютеры) — нуль-модемного (перекрёстного, RX/TX, RTS/CTS). Но, сдаётся мне, и это где-то, да не соблюдается.
Ну и не стоит забывать, что производитель может по приколу (а на деле из желания заставить вас купить именно его кабель) может поменять местами контакты в разъёме, как, например, это сделали в ИБП компании APC. Если такой подрубить обычным модемным кабелем, он непрерывно пищит и не запускается.
victor_1212
03.01.2023 18:20+3возможно будет интересно про разъемы DB-9 и DB-25, здесь даже не история, а типа археология, для первых широко доступных модемов это был интерфейс DCE-DTE, между самим модемом и тем что им управляло, например компьютер или терминал, задействовано было 9 контактов из 25, Tx,Rx, остальные связаны с установлением телефонного соединения, например ringing, и управлением передачей двнных, ringing можно было использовать например как прерывание, DB-9 это в общем упрощенный вариант DB-25, те же сигналы но размещены иначе (буква D = форма разъема), как и RS-232 DB-25 появился в начале 60х в виде рекомендаций фактически на основе того что уже использовалось для модемов Bell 101 (1958, 110 bps) и Bell 103 (1962, 300 bps ) это были первые два модема доступные на рынке, в IBM PC разъемы вероятно попали потому, что хотели типа max переиспользовать, то что уже было на рынке для mini, так продлили жизнь этим разъемам еще на 20-30 лет, интересно что рабочие модемы на самом деле первые появились еще в начале 50х, но не в свободной продаже, а использовались для sage, выпускала их другая фирма не ATT (= Bell), скорость передачи данных тоже была выше, ATT участвовала в проекте sage обеспечивая каналы связи, поскольку телефонная сеть тогда ей полностью принадлежала, так получила опыт и доступ к технологии разработанной MIT, ниже на картинке Bell 103, 1962
ps
в то время Western Electric это производственное отделение AT&T, а Bell ее научное отделение
victor_1212
03.01.2023 20:40+2pps
9 линий интерфейса DTE-DCE (DB9/DB25) стали типа избыточными с началом использования в начале 80х Hayes AT команд стандартных сейчас для управления модемами, это конечно требует контроллера в составе модема, переключения в командный режим при помощи escape sequence и тд., но позволяет легко управлять модемом при помощи скриптов
chnav
04.01.2023 11:36На первом графике указано состояние "Пауза". Смысл её для асимметричной передачи мне прекрасно понятен, но всегда оставалось тайной - какова её длительность ?
Мой опыт показывает, что при надлежащих условиях скорость передачи данных достигает максимума, т.е. при стандартных настройках порта 8-N-1 (10 бит на символ) скорость передачи данных достигает Baudrate/10. Вроде всё просто, но если нет "паузы" - невозможно отличить последовательность "start bit -> stop bit" от бит данных. Тем не менее - работает !
Вполне возможно, что количество стоп бит 1.5 и 2 были придуманы именно для этого, причем 1.5 предпочтительнее т.к. его можно однозначно идентифицировать по нестандартной длительности.
При наличии линий CTS/RTS проблемы нет, но меня интересует именно случай трехпроводного соединения RX/TX/GND.
Flammmable Автор
04.01.2023 11:53Смысл её для асимметричной передачи мне прекрасно понятен, но всегда оставалось тайной - какова её длительность
Минимальная длительность паузы - это оговоренное количество стоп-битов. Если оговорен 1 стоп-бит, то минимальная пауза - это он и есть.
Вроде всё просто, но если нет "паузы" - невозможно отличить последовательность "start bit -> stop bit" от бит данных.
Возможно, вы имели ввиду "stop_bit -> start_bit", потому как переход "start_bit -> stop_bit" разделяют как раз биты данных.
Если так, то вообще говоря, определить окончание символа можно просто посчитав биты данных - стоп-бит для этого не нужен. Он нужен для того, чтобы у старт-бита был нисходящий фронт. По которому можно было бы обнулить накопленное рассогласование тактирующих систем передатчика и приёмника. В 50% случаев этот фронт и так бы был у старт бита (даже в случае гипотетического отсутствия стоп-бита). Но чтобы нисходящий фронт был с гарантией 100% и добавляют стоп-бит.
Если же представить плотный поток данных, к которому внезапно подключается USB-UART, то да, определить - где данные, а где служебные биты будет невозможно. Я бы сказал, пауза, достаточная для определения начала непрерывного потока данных формата 8N1 - 10 логических единиц подряд.
NickDoom
Да, с разъёмами просто беда. Жаль, не устаканился какой-нибудь мелкий коаксиал, мама TX и папа RX на расстоянии 2.5 радиуса от центра до центра. И никаких там «прямых» или «кросс» кабелей — мама всегда источник (розетка), папа всегда приёмник (вилка). И на кабеле, и на корпусе.
Ну и на случай питания можно какой-нибудь пин между ними предусмотреть. Если торчит — устройство нуждается в питании, если там отверстие — может дать +12В (это всё «например», просто как мысли вслух). И на питающем кабеле всегда с одной стороны пин, с другой отверстие. То есть если оба прибора нуждаются в питании, их не соединить, а если оба обеспечивают питание — получается отверстие напротив отверстия, без риска соединения линий питания и возникновения уравнивающих токов.
Почему коаксиал? А ваш покорный слуга любит побаловаться мегабодными компортами :-D
KbRadar
Так зарождался USB
NickDoom
Ваши слова бы Бо… машине времени в уши :) Если бы USB действительно так зарождался, скольких бы проблем со всякими OTG и асимметрией бы избежали… но нееет, стая бежит со скоростью самого медленного члена, а консорциум имеет интеллект самого глупого участника, поэтому в эпоху, когда даже в LPT осознали глубину ошибки и отказались от асимметрии, эти шедевральные, музейные умы родили асимметричный протокол с асимметричными кабелями. Я просто верещу от смеха, как хомяк (молодёжн. «ору в голосину»), когда вспоминаю, как на их глазах LPT переходил к симметричным режимам и каялся, как люди соединяли компы LPT LapLink-кабелями, но эти гении вредительской деятельности «презрительным окинули оком творенья Бога своего, и на челе их невысоком не отразилось ничего».
А зоопарк вольтажей можно было бы разрулить разными диаметрами питающих пинов, кстати.