Uart framing error

Документация по внутреннему устройству последовательного порта ATmega2560, примеры практического использования.
     

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом — просто выделите ошибочное слово или фразу и нажмите Shift Enter.

ATmega2560: работа с UART Печать

Добавил(а) microsin

  

UART (USART) обычно нужен для организации взаимодействия с внешним миром — чтобы передать микроконтроллеру какие-то команды и забрать у него данные. Или как минимум для отладки — чтобы понять, что происходит с Вашей программой.

Примечание: аббревиатура USART переводится как Universal Synchronous and Asynchronous serial Receiver and Transmitter (USART), т. е. последовательный порт может работать как синхронный (по внешнему тактовому сигналу), так и асинхронный (аппаратно формировать посылки бит по интервалам времени).

Запуск USART обычно состоит из следующих простых действий:

1. Создать буферы приема и передачи (типа FIFO, обычно кольцевые).
2. Написать код инициализации USART.
3. Написать обработчик прерывания приема символа из USART.
4. Написать обработчик передачи USART.
5. Перенаправление вывода printf в USART.

Рассмотрим каждую из этих операций. Все, что написано далее, может относиться во многом не только к микроконтроллеру ATmega2560, но и к любому AVR, который имеет на борту аппаратуру USART (или UART).

[1. Буферы приема и передачи USART]

Буферы приема и передачи нужны для того, чтобы упорядочить потоки входных и выходных данных в программе. На приеме обработчик прерывания нужен потому, что символ (байт) может прийти из внешнего мира асинхронно, т. е. в любой момент времени. Аппаратный буфер USART у AVR очень мал — всего лишь 2 байта.

Примечание: в микроконтроллере ATmega2560 буфер приема читается через регистр UDRn, где буква n меняется на номер используемого порта 0, 1, 2 или 3 (у ATmega2560 целых 4 последовательных порта USART: USART0, USART1, USART2 и USART3).

Следовательно, чтобы не потерять пришедшие данные, нужно как можно быстрее считать из буфера и обработать принятый байт, иначе следующий поступивший байт может затереть только что пришедший байт, и этот предыдущий байт может быть потерян (так называемый RX overrun).

Для быстрого считывания поступившего байта обычно используется обработчик прерывания приема USART. Буфер считывается из регистра UDRn и помещается в буфер, откуда он потом может быть выбран основной программой. Возникает вопрос: так зачем все-таки нужен буфер, почему нельзя сразу в обработчике прерывания предпринять какие-то действия, и обойтись без дополнительного буфера? Ответ прост: да, можно так сделать, но только для самых простых случаев, когда обработка байта не займет много времени, и когда не нужно производить дополнительных действий. Например, не получится обойтись без программного буфера, если поток входных данных соответствует какому-то протоколу, нельзя обрабатывать каждый байт по отдельности, нужно отслеживать таймауты в потоке входных байт и т. п. Такие сложные действия иногда нельзя возложить на обработчик прерывания, потому что они займут слишком много времени, и это повлияет на работоспособность всей программы в целом. Таким образом, обработчик приема может просто поместить принятый в буфер байт и быстро завершить свою работу. Опустошать буфер приема может основная программа, которая может быть довольно сложной и медлительной. 

Буфер для передачи делают потому, что в одном действии программы обычно надо передать через USART не один байт, а сразу несколько. Например, нужно вывести приветствие printf(«Hello World!»), или какое-то диагностическое сообщение, состоящее из нескольких байт. Но USART может передавать только по одному байту, через аппаратный буфер регистра UDRn. Если аппаратный буфер не опустошился, т. е. если USART не успел еще передать только что записанный в UDRn байт, то нельзя в цикле без задержки писать все символы передаваемой строки в UDRn, иначе произойдет потеря данных при передаче (TX overrun). Чтобы не было непроизводительных потерь процессорного времени на циклы ожидания, делается программный буфер достаточного размера, куда программа может без задержки поместить все данные, которые надо передать. Опустошаться буфер передачи будет по одному байту — в основной программе и/или в обработчике прерывания опустошения буфера, по мере того, как аппаратура USART будет готова передать очередной байт. 

Вот пример организации буферов передачи и приема USART (подробнее про кольцевые буферы см. [1]):

#define BUFSIZERX 32 //размер буфера приема
#define BUFSIZETX 32 //размер буфера передачи
 
//Маски для обработки индексов кольцевых буферов:
#define BUFMASKRX (BUFSIZERX-1)
#define BUFMASKTX (BUFSIZETX-1)
 
//Буфер приема и его индексы:
char bufRX [BUFSIZERX];
unsigned char rxIn, rxOut;
 
//Буфер передачи и его индексы:
char bufTX [BUFSIZETX];
unsigned char txIn, txOut;

В этом примере размеры буферов приема и передачи выбраны одинаковыми, но это совершенно не обязательно. К размеру буферов передачи и приема есть два простых требования, которые зависят от того, как работает Ваша программа. Во-первых, размер буфера должен быть достаточно велик, чтобы он никогда не переполнялся. Это означает, что на приеме Вы всегда успеваете забрать и обработать поступающие данные до того, как буфер переполнится (т. е. данные поступают всегда медленнее, чем Вы их читаете и обрабатываете). Аналогично на передаче Вы не должны писать в буфер передачи слишком часто, буфер передачи должен успевать опустошаться кодом поддержки аппаратуры передачи USART. Во-вторых, есть требование, которое вытекает из примененного принципа обработки кольцевого буфера [1]: размер буфера должен быть равен степени 2, т. е. 2, 4, 8, 16, 32, 64 и т. д. Это требование не обязательное, если Вы согласны усложнить обработку индексов буфера, но имейте в виду, что усложнение кода обработки индексов замедлит обработку приема и передачи, и иногда такое замедление может оказаться недопустимым. 

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

[2. Код инициализации USART

В этом примере будем настраивать USART0, который используется в плате Arduino Mega 2560 [2] в качестве стандартного канала обмена с компьютером через USB. Параметры для настройки 115200 bps, 8 бит данных, без четности, 1 стоп-бит.

После сброса (перезагрузки) все регистры AVR, в том числе и регистры, которые устанавливаются в исходное состояние. Чтобы USART заработал как нужно, необходимо настроить биты его регистров (подробное описание регистров см. во врезке «Справочная информация по USART ATmega2560»):

UCSR0A.U2Xn бит двойной скорости передачи.
UCSR0A.MPCMn бит включения функции мультипроцессорного обмена.

Обе эти функции не нужны, поэтому в UCSR0A нужно записать 0.

Примечание: можно было бы этого и не делать, потому что после сброса регистр UCSR0A сам автоматически обнуляется. Однако сброс регистра UCSR0A в программе не помешает, он будет явно показывать, какая настройка порта USART используется.

UCSR0B.RXCIE0 разрешение прерывания приема. Мы будем использовать обработчик прерывания по наличию в буфере приема данных, поэтому этот бит нужно установить в 1.
UCSR0B.RXEN0 разрешение работы приемника, сюда нужно записать 1.
UCSR0B.TXEN0 разрешение работы передатчика, сюда нужно записать 1.
UCSR0B.UCSZ02 это один из 3 бит, который настраивает количество бит данных во фрейме. У нас размер данных фрейма 8 бит, по таблице 22-7 значение этого бита должно быть равно 0.

Остальные биты не нужны, поэтому они будут сброшены.

UCSR0B = (1 << RXCIE0)|(1 << RXEN0)|(1 << TXEN0);

UCSR0C.UMSEL01 и UMSEL00 эти биты определяют режим работы USART. Нас интересует асинхронный режим, по таблице 22-4 значение этих бит должно быть нулевое.
UCSR0C.UPM01 и UPM00 эти биты определяют контроль четности. Нам он не нужен, поэтому по таблице 22-5 значение этих бит будет нулевое.
UCSR0C.USBS0 бит количества стоп-битов фрейма. У нас 1 стоп-бит, поэтому согласно таблице 22-6 значение этого бита нулевое.
UCSR0C.UCSZ00 и UCSZ01 эти биты совместно с битом UCSR0B.UCSZ02 определяют количество бит данных во фрейме. По таблице 22-7 значение бит UCSZ01 и UCSZ00 должно быть 11.
UCSR0C.UCPOL0 этот бит работает только в синхронном режиме, поэтому должен быть сброшен в 0.

Следовательно, в регистре UCSR0C нужно установить только биты UCSZ01 и UCSZ00:

UCSR0C = (1 << UCSZ01)|(1 << UCSZ00); 

UBRR0H, UBRR0L. Для этих регистров нужно по формуле рассчитать настройки для скорости (это 12-битный регистр UBRR0, доступ к которому дает пара регистров UBRR0H:UBRR0L). Поскольку у нас асинхронный режим, нет включенной двойной скорости, то наша формула будет следующей (см. таблицу 22-1):

                 16000000
UBRR0 = —————- — 1
               16 * 115200

Получается, что значение для UBRR0 должно быть 7.68. Это дробное число, и его конечно же записать в регистры, поэтому число нужно округлить до ближайшего целого, получится 8.

Примечание: можно было бы воспользоваться таблицей 22-12, где есть готовое вычисленное значение UBRR для скорости 115.2K. Как следует из таблицы, для режима двойной скорости настройка получится точнее, в этом случае нужно записать в UBRR0 значение 16, и бит U2X0 в регистре UCSR0A нужно установить в 1:

UCSR0A = (1 << U2X0);
UBRR0H = 0;
UBRR0L = 16;

Несмотря на то, что на двойной скорости настройка получается точнее, все равно не факт, что это будет работать лучше, потому что оцифровка бит RXD будет осуществляться не по 16 выборкам, а по 8 (см. подробное описание работы приемника во врезке «Справочная информация по USART ATmega2560»).

void SetupUSART0 (void)
{
   //Режим двойной скорости выключен:
   UCSR0A = 0;
   //Разрешены прерывание приема, работа приемника и передатчика:
   UCSR0B = (1 << RXCIE0)|(1 << RXEN0)|(1 << TXEN0);
   //Настройка размера фрейма данных 8 бит, без четности, 1 стоп-бит:
   UCSR0C = (1 << UCSZ01)|(1 << UCSZ00);
   //Настройка скорости 115200 bps:
   UBRR0H = 0;
   UBRR0L = 8;
}

Примечание: после того, как будет разрешен приемник и передатчик установкой бит RXEN0 и TXEN0 соответственно, функционирование портов ввода/вывода PE0 и PE1 будет автоматически переназначено. Теперь они будут работать как вход приемника и выход передатчика USART.

[3. Обработчик прерывания приема USART]

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

ISR(USART0_RX_vect)
{
   bufRX [rxIn++] = UDR0;
   rxIn &= BUFMASKRX;
}

Примечание: константу USART0_RX_vect можно подсмотреть в файле avrincludeavriomxx0_1.h тулчейна (это может быть WinAVR или тулчейн AVR-GCC, который устанавливается в составе Atmel Studio).

[4. Обработка передачи USART]

Обработка передачи будет простейшая: в главный цикл main будет вставлена процедура handlerTXUSART, проверяющая наличие данных в буфере передачи. Если данные в буфере передачи есть, и передатчик свободен, то из буфера передачи будет выбран байт и записан в регистр UDR0.

static void handlerTXUSART (void)
{
   if((txIn != txOut) && (UCSR0A & (1 << UDRE0)))
   {
      UDR0 = bufTX[txOut++];
      txOut &= BUFMASKTX;
   }
}
 
int main(void)
{
   ...
   SetupUSART0();
   sei();
   while(1)
   {
      ...
      handlerTXUSART();
   }
}

Минимальная настройка завершена. Все, что будет попадать в буфер передачи bufTX, будет выведено через USART0. Все, что поступит из внешнего мира, попадет в буфер приема bufRX. Само собой основной код должен использовать эту возможность, чтобы осуществлять обмен данными через USART, т. е. при необходимости нужно читать буфер приема и писать данные в буфер передачи. Все остальное будет происходить автоматически.

Что можно улучшить: если написать обработчик прерывания опустошения буфера передатчика, то можно ускорить передачу. В этом обработчике можно делать то же самое, что осуществляется в подпрограмме handlerTXUSART, за исключением того, что не нужно проверять флаг UDRE0, достаточно проверить только наличие данных в кольцевом буфере bufTX.

[5. Настройка printf на вывод через USART]

Перенаправление printf в USART нужно в основном чисто для удобства: чтобы проще выводить нужные отладочные (или какие-то другие) текстовые сообщения в какое-то устройство, где их можно отобразить и прочитать. Если для перенаправления используется USART (можно кстати использовать и другие устройства вывода текста, например экран LCD), то выводимые текстовые сообщения можно увидеть на компьютере в окне программы-терминала (например, putty, TerraTerm, HyperTerminal, Serial Monitor у Arduino IDE), подключенной к COM-порту, куда поступают данные от микроконтроллера (обычно это виртуальный COM-порт через соединение USB, как например это сделано у плат Arduino). Короче говоря, задача состоит в том, чтобы текст, который выводится оператором printf, сразу попадал в консоль программы терминала.

Описание решения этой задачи подробно описано в [4], здесь я просто кратко покажу что нужно сделать. Вывод в USART через printf с использованием библиотек avr-libc настраивается за 3 простых шага (последний шаг необязательный):

1. Подключить заголовочный файл stdio.h.

2. Определить функцию, которая будет выводить символ в UART (в этом примере функция uart_putchar).

3. (Необязательно) опциями линкера выбрать вариант обработки преобразований формата printf.

Простой пример:

#include < stdio.h >
 
static int uart_putchar(char c, FILE *stream);
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
 
static int uart_putchar(char c, FILE *stream)
{
   if (c == 'n')
      uart_putchar('r', stream);
   loop_until_bit_is_set(UCSRA, UDRE);
   UDR = c;
   return 0;
}
 
int main(void)
{
   init_uart();
   stdout = &mystdout;
   printf("Hello, world!n");
   return 0;
}

Здесь настраивается поток mystdout, который привязывается к функции вывода символа и стандартному потоку вывода stdout.

Если пропустить шаг 3, то оператор printf будет работать с ограничениями при обработке формата для чисел с плавающей запятой (подробнее про это и про опции настройки линкера см. [4]).

Как уже упоминалось, у ATmega2560 имеется 4 последовательных порта USART: USART0, USART1, USART2 и USART3, которые фиксировано привязаны к определенным ножкам корпуса микроконтроллера. Т. е. определенный вывод микроконтроллера может работать либо просто как порт ввода/вывода, либо как аппаратный вход или выход интерфейса USART. Все зависит от программной настройки — данных, которые Вы запишете в управляющие регистры микроконтроллера. В таблице и на картинке показана привязка аппаратуры USART к выводам микроконтроллера. 

Имя Прерывания Регистры Порты RXD, TXD, XCK
USART0 UDRE0, TXC0, RXC0 UDR0, UCSR0A, UCSR0B, UCSR0C, UBRR0L, UBRR0H PE0, PE1, PE2
USART1 UDRE1, TXC1, RXC1 UDR1, UCSR1A, UCSR1B, UCSR1C, UBRR1L, UBRR1H PD2, PD3, PD5
USART2 UDRE2, TXC2, RXC2 UDR2, UCSR2A, UCSR2B, UCSR2C, UBRR2L, UBRR2H PH0, PH1, PH2
USART3 UDRE3, TXC3, RXC3 UDR3, UCSR3A, UCSR3B, UCSR3C, UBRR3L, UBRR3H PJ0, PJ1, PJ2

ATmega2560 USART pins

Порты USART обладают следующими основными возможностями: 

• Поддерживают полный дуплекс (имеют независимые аппаратные буферы приема и передачи).
• Могут работать асинхронно и синхронно.
• В синхронном режиме могут либо вырабатывать такты, либо использовать внешнее тактирование (Master or Slave Clocked Synchronous Operation).
• Генератор скорости передачи, настраиваемый с высокой точностью (High Resolution Baud Rate Generator).
• Поддерживает размеры фрейма передачи из 5, 6, 7, 8 или 9 бит данных и 1 или 2 стоповых бита.
• Аппаратная поддержка генерации и проверки на нечетность или четность (Odd or Even Parity).
• Детектирование потери данных на приеме (Data OverRun Detection).
• Детектирование ошибок фрейма (Framing Error Detection).
• Фильтрация помех (Noise Filtering) с помощью цифрового ФНЧ, включающая детектирования ошибочного стартового бита.
• 3 отдельных прерывания по событиям TX Complete, TX Data Register Empty и RX Complete.
• Режим обмена с несколькими процессорами (Multi-processor Communication Mode).
• Асинхронный режим с двойной скоростью (Double Speed Asynchronous Communication Mode). 

Для уменьшения общего энергопотребления кристалла ненужные USARTn могут быть полностью выключены с помощью битов управления регистров PRR0 и PRR1. 

Порт USART0 используется в платах Arduino Mega 2560 [2] под аппаратный мост USB-UART, чтобы обеспечить работу загрузчика кода и поддержку отладочного вывода через Serial Monitor. 

ATmega2560 USART block diagram fig22 1

Рис. 22-1. Блок-диаграмма внутреннего устройства USART. 

На диаграмме пунктирными линиями выделены 3 отдельных блока USART (перечисленные далее сверху вниз): Clock Generator (тактовый генератор), Transmitter (передатчик) и Receiver (приемник). Регистры управления общие для всех этих блоков. Логика Clock Generation состоит из логики синхронизации для внешних тактов (SYNC LOGIC, используется в подчиненном режиме для синхронизации передачи бит), и генератора скорости передачи (BAUD RATE GENERATOR). Вывод XCKn (такты передачи) используется только для синхронного режима работы (synchronous transfer mode). Передатчик состоит из одиночного буфера записи (UDR), последовательного регистра сдвига (TRANSMIT SHIFT REGISTER), генератора четности (PARITY GENERATOR) и логики управления (TX CONTROL) для поддержки разных форматов фрейма. Наличие аппаратного буфера фрейма позволяет вести непрерывные передачи без задержек между отдельными фреймами. Приемник наиболее сложный узел USART, потому что он имеет узлы восстановления тактов (CLOCK RECOVERY) и данных (DATA RECOVERY), которые используются для асинхронного приема данных. В дополнение к узлам восстановления приемник содержит блок проверки на четность (PARITY CHECKER), логику управления (RX CONTROL), регистр сдвига и двухуровневый буфер приема (UDR). Приемник поддерживает одинаковый формат фрейма, который использует передатчик, и может детектировать ошибку фрейма (Frame Error), событие потери данных на приеме (Data OverRun) и ошибку четности (Parity Error). Модуль PIN CONTROL управляет поведением порта микроконтроллера — или этот вывод работает как обычный порт ввода/вывода GPIO, или он подключен к аппаратуре USART и выполняет специальную функцию.

[Генерация тактов]

Логика генерации тактов синтезирует базовую частоту синхронизации для передатчика и приемника. The USARTn поддерживает 4 режима тактирования: нормальный асинхронный (Normal asynchronous), асинхронный двойной скорости (Double Speed asynchronous), синхронный главный (Master synchronous) и синхронный подчиненный (Slave synchronous). Бит UMSELn в USART Control and Status Register C (UCSRnC) выбирает между асинхронным и синхронным режимами. Двойная скорость (применимо только к асинхронному режиму) управляется битом U2Xn, находящемся в регистре UCSRnA. Когда используется синхронный режим (UMSELn = 1), регистр направления данных (Data Direction Register, DDR) для вывода XCKn определяет, каким будет тактирование для синхронного режима: внутренним (Master mode) или внешним (Slave mode). Вывод XCKn активен только в при использовании синхронного режима, в асинхронном режиме он работает как простой порт GPIO.

ATmega2560 USART Clock Generation Logic fig22 2

Рис. 22-2. Блок-диаграмма логики генерации тактов USART.

Описание сигналов:

txclk такты передатчика (внутренний сигнал).
rxclk базовые такты передатчика (внутренний сигнал).
xcki ввод от вывода XCK (внутренний сигнал). Используется для работы в синхронном подчиненном режиме (synchronous slave operation).
xcko выходной сигнал тактов для подачи на вывод XCK (внутренний сигнал). Используется для работы в синхронном подчиненном режиме (synchronous master operation).
fOSC частота вывода XTAL (System Clock, системная частота).
DDR_XCK разряд регистра DDRX, управляющий направлением работы ножки порта (вход или выход).

Baud Rate Generator, внутренняя генерация тактов. Генерация тактов внутри чипа используется для асинхронного и синхронного режимов работы. USART Baud Rate Register (UBRRn) и считающий вниз счетчик (Prescaling Down-Counter) подключены к программируемому прескалеру, или другими словами к генератору скорости передачи (Baud Rate Generator). Обратно-считающий счетчик (down-counter), работающей на системной частоте (fOSC), каждый раз загружается значением из UBRRn, когда счетчик достигает нуля, или когда записан регистр UBRRLn. В этот момент генерируется тактовый импульс для USART, появляющийся на выходе Baud Rate Generator (= fOSC/(UBRRn+1)). Передатчик делит выходную тактовую частоты Baud Rate Generator на 2, 8 или 16 в зависимости от режима. Выход Baud Rate Generator напрямую используется для тактирования приемника и узлов восстановления данных. Однако узлы восстановления используют машину состояний из 2, 8 или 16 состояний в зависимости от режима, установленного битами UMSELn, U2Xn и DDR_XCKn. 

Таблица 22-1 содержит выражения для вычисления скорости baud rate (в битах на секунду) и для вычисления значения UBRRn для каждого режима работы, когда используется генерируемый внутри источник тактов. 

Табл. 22-1. Формулы для расчета скорости и настроек в зависимости от режима.

Режим Скорость(1) UBRR
Асинхронный нормальный (U2XN = 0)                        fOSC
BAUD = ————————
               16 * (UBRRn+1)
                     fOSC
UBRRn = —————- — 1
                16 * BAUD
Асинхронный двойной скорости (U2XN = 1)                        fOSC
BAUD = ————————
               8 * (UBRRn+1)
                    fOSC
UBRRn = ————— — 1
                8 * BAUD
Синхронный главный                        fOSC
BAUD = ————————
               2 * (UBRRn+1)
                    fOSC
UBRRn = ————— — 1
                2 * BAUD

Примечание (1). Скорость передачи определена как скорость следования бит в секунду (baud rate, bit per second, bps).

BAUD Baud rate (в битах/сек, bps).
fOSC системная тактовая частота (System Oscillator clock frequency).
UBRRn содержимое регистров UBRRHn и UBRRLn (0-4095). 

Некоторые примеры значений UBRRn для разных тактовых частот микроконтроллера можно найти в таблице 22-9. 

Double Speed Operation (U2Xn). Скорость передачи может быть удвоена (это пошло еще от микроконтроллеров серии MCS51) путем установки бита U2Xn в регистре UCSRnA. Установка этого бита дает эффект только для асинхронной работы USART, сбросьте этот бит в 0 для синхронного функционирования. 

Установка бита U2Xn уменьшит коэффициент деления синтезатора скорости с 16 до 8, что соответствует удвоению скорости передачи и приема для асинхронного режима. Имейте в виду, что приемник в этом случае будет делать в 2 раза меньше выборок при восстановлении данных и тактов (количество выборок также уменьшиться с 16 до 8), так что для удвоения скорости с сохранением точной установки скорости понадобится более точно выдерживать системную частоту. Это важно для приемника, а для передатчика нет никаких проблем. 

Внешнее тактирование. Используются в подчиненном синхронном режиме работы. Внешние такты поступают от вывода XCKn (см. рис. 22-2), и их значения выбираются регистром синхронизации, чтобы уменьшить шансы нестабильности. Выход регистра синхронизации затем должен поступить сначала на детектор перепада, перед тем как сигнал тактов можно было использовать в передатчике и приемнике. Этот процесс занимает два цикла системной тактовой частоты CPU, так что эта задержка ограничивает максимально возможную тактовую частоту XCKn: 

            fOSC
fXCK < ——
              4

Имейте в виду, что fOSC зависит от стабильности частоты источника системных тактов. Так что рекомендуется добавить некоторый запас, чтобы избежать возможных потерь данных из-за неточной установки системной частоты. 

Синхронный режим работы. Когда используется синхронный режим (UMSELn = 1), вывод XCKn будет аппаратно использоваться либо как вход тактов (подчиненное устройство), либо как выход тактов (главное устройство). Зависимость между перепадами тактов и выборкой данных остается той же самой. Базовый принцип состоит в том, что вход данных (on RxDn) оцифровывается по противоположному перепаду XCKn, когда меняется сигнал на выходе данных (TxDn). 

ATmega2560 USART Synchronous Mode XCKn Timing fig22 3

Рис. 22-3. Временные диаграммы XCKn синхронного режима. 

Бит UCRSC регистра UCPOLn выберет, какой из перепадов XCKn будет использоваться для выборки данных, а какой для изменения выходных данных. Как видно из рис. 22-3, когда UCPOLn == 0 данные изменяются по нарастанию XCKn и выборка делается по спаду XCKn. И наоборот, если UCPOLn == 1, то данные изменяются по спаду XCKn, и их выборка делается по фронту XCKn. 

Форматы фрейма. Под фреймом подразумевается элементарная, неделимая посылка из нескольких бит. Во фрейм входят последовательно передаваемый код символа определенной разрядности, биты синхронизации (биты start и stop), и опционально бит четности для проверки на ошибку. USART позволяет настроить все 30 комбинаций следующих допустимых форматов фрейма: 

• 1 start-бит
• 5, 6, 7, 8 или 9 бит данных
• no, even или odd parity bit (бит четности отсутствует, есть бит четности или есть бит нечетности)
• 1 или 2 stop-бита 

Фрейм начинается start-битом, за которым идет наименее значащий бит данных (least significant bit, LSB). Далее идут биты данных (всего бит данных может быть от 5 до 9), завершающий бит самый старший (most significant bit, MSB). Если контроль четности разрешен, то за битами данных, перед stop-битами вставляется бит четности. Когда весь фрейм передан, то за ним может без задержки следовать следующий фрейм, или обмен может перейти в состояние ожидания idle, когда на линии данных уровень лог. 1. На рис. 22-4 показаны возможные комбинации форматов фрейма. Биты внутри квадратных скобок опциональны. 

ATmega2560 USART frame formats fig22 4

Рис. 22-4. Форматы фрейма. 

St start-бит, всегда лог. 0.
(n) биты данных (от 0 до 8).
P Parity bit, бит четности. Может быть битом нечетности, или битом четности (odd или even, в зависимости от настройки).
Sp stop-бит, всегда лог. 1.
IDLE нет активности на линии передачи (RxDn или TxDn). В состоянии IDLE на линии всегда должен быть уровень лог. 1. 

Используемый формат фрейма USART устанавливается битами UCSZn2:0, UPMn1:0 и USBSn в регистрах UCSRnB и UCSRnC. Приемник и передатчик использует одну и ту же настройку. Имейте в виду, что изменение настроек этих бит во время осуществления активного обмена повредит данные передатчика и приемника. 

Биты размера символа USART (UCSZn2:0) выбирают количество бит данных во фрейме. Биты режима четности USART Parity mode (UPMn1:0) разрешают и устанавливают тип контроля четности. Выбор между одним или двумя stop-битами устанавливается битом USART Stop Bit Select (USBSn). Приемник игнорирует второй stop-бит. Таким образом FE (Frame Error, ошибка фрейма) будет детектироваться в тех случаях, когда первый stop-бит равен 0. 

Вычисление Parity Bit. Бит четности (parity bit) вычисляется функцией исключающее ИЛИ от всех бит данных. Если используется контроль по нечетности (odd parity), то берется результат инвертированного исключающего ИЛИ. Бит четности размещается между последним битом данных и первым (или единственным) stop-битом фрейма. Зависимость между битом четности и битами данных следующая: 

ATmega2560 USART Parity Bit Calculation

Peven бит четности, когда для контроля используется четность (even).
Podd бит четности, когда для контроля используется нечетность (odd).
dn биты данных (в количестве n) передаваемого символа. 

[Инициализация USART]

Чтобы можно было начать какой-либо обмен через USART, его надо инициализировать. Процесс инициализации обычно состоит из настройки скорости baud rate, установки формата фрейма и разрешения передатчика и/или приемника в зависимости от использования. Для работы с USART через систему прерываний (самый эффективный способ работы с USART) перед настройкой должен быть сброшен глобальный флаг разрешения прерываний (Global Interrupt Flag, I-флаг в регистре SREG), что означает запрет всех прерываний. 

Перед тем, как делать повторную инициализацию с целью поменять baud rate или формат фрейма нужно убедиться, что сейчас активной передачи в момент изменения регистров. Для проверки, что передача завершена может использоваться флаг TXCn, и флаг RXCn может использоваться для того, чтобы узнать, есть ли не прочитанные данные в буфере приема. Имейте в виду, что флаг TXCn должен быть очищен перед каждой передачей (перед тем, как записывается регистр UDRn), если он используется с такой целью. 

В следующем простом примере кода инициализации USART показан один и тот же функционал на языке ассемблера и в функции на языке C. Примеры подразумевают асинхронный режим работы с использованием опроса (без разрешенных прерываний) и фиксированного формата фрейма. Скорость (baud rate) предоставляется в виде параметра функции. Для кода на ассемблере подразумевается, что параметр baud rate сохранен в регистровую пару r17:r16. 

USART_Init:
; установка baud rate
   sts UBRRnH, r17
   sts UBRRnL, r16
   ldi r16, (1 << U2Xn)
   sts UCRnA, r16
; разрешить приемник и передатчик
   ldi r16, (1 << RXENn)|(1 << TXENn)
   sts UCSRnB,r16
; установка формата фрейма: 8data, 1stop bit
   ldi r16, (2 << UMSELn)|(3 << UCSZn0)
   sts UCSRnC,r16
   ret
#define FOSC 1843200  // тактовая частота системы
#define BAUD 9600
#define (MYUBRR FOSC/16/BAUD-1)
 
void main( void )
{
   ...
   USART_Init ( MYUBRR );
   ...
}
 
void USART_Init( unsigned int ubrr)
{
   /* Установка baud rate */
   UBRRH = (unsigned char)(ubrr >> 8);
   UBRRL = (unsigned char)ubrr;
   /* Разрешить приемник и передатчик */
   UCSRB = (1 << RXEN)|(1 << TXEN);
   /* Установка формата фрейма: 8data, 2stop bit */
   UCSRC = (1 << USBS)|(3 << UCSZ0);
}

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

[Передача данных – USART Transmitter]

Передатчик USART разрешается путем установки бита Transmit Enable (TXEN) в регистре UCSRnB. Когда передатчик разрешен, нормальное функционирование порта GPIO для вывода TxDn переназначается на аппаратную функцию последовательного выхода данных USART. Параметры baud rate, режим работы и формат фрейма должны быть настроены перед осуществлением любых передач. Если используется синхронный режим работы, то такты вывода XCKn принудительно будут использоваться для тактирования передачи. 

Передача фреймов размером от 5 до 8 бит данных. Передача начинается с загрузки буфера передачи данными, которые должны быть переданы. CPU может загрузить данные в буфер передачи путем записи регистра UDRn по его адресу размещения в пространстве I/O. Данные, находящиеся в буфере передачи, переместятся в регистр сдвига, и будут готовы к отправке в новом фрейме. Регистр сдвига загружается новыми данными если USART находится в состоянии ожидания idle (нет активной передачи) или сразу после завершения последнего stop-бита предыдущего переданного фрейма. Когда регистр сдвига загружен новыми данными, они будут передаваться в полном фрейме со скоростью, заданной регистром Baud Register и битом U2Xn, или в зависимости от режима работы скорость будет определятся тактами на XCKn. 

Следующие примеры кода показывают простую функцию передачи USART, основанную на опросе флага Data Register Empty (UDREn). Когда используются фреймы меньше 8 бит, самый старший бит, записанный в UDRn, будет игнорироваться. USART должен быть инициализирован перед тем, как можно будет использовать функцию передачи. Для кода на ассемблере подразумевается, что передаваемые данных сохранены в регистре R16. 

USART_Transmit:
; Ожидание опустошения буфера передачи
   lds r17, UCSRnA
   sbrs r17, UDREn
   rjmp USART_Transmit
; Поместить данные (r16) в буфер, отправка данных
   sts UDRn,r16
   ret
void USART_Transmit( unsigned char data )
{
   /* Ожидание опустошения буфера передачи */
   while ( !( UCSRnA & (1 << UDREn)) )
   {
   }
   /* Поместить данные в буфер, отправка данных */
   UDRn = data;
}

Функция просто ждет, пока буфер передачи не опустошится, путем постоянного опроса флага UDREn, перед тем как загрузить новые данные для передачи. Если бы было задействовано прерывание по опустошению буфера Data Register Empty, то обработчик этого прерывания записал бы данные в буфер передачи (и было бы сэкономлено время процессора, затраченное на пустые циклы ожидания опустошения буфера). 

Передача фреймов размером 9 бит данных. Если используются 9-разрядные символы (UCSZn = 7), то старший девятый бит должен быть записан в бит TXB8 регистра UCSRnB перед тем, как младшие 8 бит символа должны быть записаны в регистр UDRn. Следующие примеры кода показывают функцию передачи, которая поддерживает передачу символов из 9-бит. Для кода ассемблера подразумевается, что данные для отправки сохранены в регистровой паре R17:R16.

USART_Transmit:
; Ожидание опустошения буфера передачи
   sbis UCSRnA,UDREn
   rjmp USART_Transmit
; Копирование 9-го бита из r17 в TXB8
   cbi UCSRnB,TXB8
   sbrc r17,0
   sbi UCSRnB,TXB8
; Поместить LSB данные (r16) в буфер, отправка данных
   sts UDRn,r16
   ret
void USART_Transmit( unsigned int data )
{
   /* Ожидание опустошения буфера */
   while ( !( UCSRnA & (1 << UDREn))) )
   {
   }
   /* Копирование 9-го бита в TXB8 */
   UCSRnB &= ~(1 << TXB8);
   if ( data & 0x0100 )
   UCSRnB |= (1 << TXB8);
   /* Поместить данные в буфер, отправка данных */
   UDRn = data;
}

Примечание: эти функции передачи написаны только для примера. Они могут быть оптимизированы, если содержимое UCSRnB статическое. Например, после инициализации в регистре UCSRnB используется только бит TXB8.

9-й бит может использоваться для того, чтобы показать адрес фрейма в режиме обмена с несколькими процессорами (multi processor communication mode) или для другого протокола, например для синхронизации.

Флаги передатчика и прерывания. У передатчика USART есть 2 флага, которые показывают его состояние: USART Data Register Empty (UDREn) и Transmit Complete (TXCn). Оба флага можно использовать для генерации прерываний.

Флаг Data Register Empty (UDREn) показывает, готов или нет буфер передачи к записи туда новых данных. Этот бит устанавливается, когда буфер передачи опустошается, и очищается, когда буфер передачи содержит данные для отправки, которые еще пока не перемещены в регистр сдвига. Для совместимости с микроконтроллерами, которые возможно появятся в будущем, всегда записывайте этот бит в 0, когда записываете регистр UCSRnA.

Когда в бит Data Register Empty Interrupt Enable (UDRIEn) регистра UCSRnB записана 1, будет возможен запуск прерывания USART Data Register Empty, если установлен бит UDREn (подразумевается, что глобально прерывания разрешены).

UDREn очищается путем записи UDRn. Когда используется передача данных с управлением по прерываниям, подпрограмма прерывания Data Register Empty должна либо записать новые данные в UDRn, чтобы очистить UDREn, либо запретить прерывание Data Register Empty, иначе новое прерывание запустится после завершения обработчика прерывания.

Бит флага Transmit Complete (TXCn) устанавливается в 1, когда весь фрейм в регистре сдвига передачи будет выдвинут наружу, и в буфере передачи нет новых данных. Бит флага TXCn Flag автоматически очищается, когда запускается прерывание transmit complete, или этот флаг может быть очищен записью в него лог. 1. Флаг TXCn полезен при полудуплексном обмене (наподобие стандарта RS-485), где передающее приложение должно войти в режим приема и немедленно освободить шину обмена после завершения передачи.

Если бит Transmit Compete Interrupt Enable (TXCIEn) в регистре UCSRnB установлен, запустится прерывание USART Transmit Complete, когда установится флаг TXCn (подразумевается, что глобально прерывания разрешены). Когда используется прерывание transmit complete, обработчику прерывания не нужно очищать флаг TXCn, это автоматически произойдет, когда сработает прерывание. 

Parity Generator. Генератор четности (Parity Generator) вычисляет бит четности для последовательного фрейма данных. Когда разрешен бит четности (UPMn1 = 1), логика управления передатчиком вставляет бит четности между последним битом данных и первым stop-битом отправляемого фрейма. 

Запрет передатчика. Запрет передатчика (сброс TXEN в 0) не вступит в силу, пока происходит активная передача, т. е. пока регистр сдвига и регистр буфера передачи еще содержат данные для передачи. После того, как передатчик запрещен, но больше не будет переназначать вывод порта TxDn. 

[Прием данных – USART Receiver

Приемник USART разрешатся путем записи бита Receive Enable (RXENn) регистра UCSRnB в 1. Когда приемник разрешен, нормальная работа порта RxDn переназначается аппаратурой USART, и этот порт становится входом приемника для последовательных данных. Параметры baud rate, режима работы и формат фрейма должны быть установлены до того, как можно будет осуществлять любой прием. Если используется синхронный режим, то вывод XCKn будет использоваться как такты приема. 

Прием фреймов длиной от 5 до 8 бит данных. Приемник начнет прием данных, когда детектирует допустимый start-бит. Каждый бит, который следует за стартовым, будет оцифровывается на скорости baud rate, или  с тактами XCKn, и вдвигаться регистр сдвига, пока не будет принят первый stop-бит фрейма. Второй stop-бит будет приемником игнорироваться. Когда будет принят первый stop-бит, т. е. когда полный фрейм присутствует в регистре сдвига, то содержимое регистра сдвига будет перемещено в буфер приема. Буфер приема может быть прочитан через UDRn. 

Следующий пример кода показывает простую функцию приема USART на базе опроса флага Receive Complete (RXCn). Когда используются фреймы размером меньше 8 бит, самый старший бит байта данных, прочитанного из UDRn, будет маскирован нулем. USART должен быть инициализирован перед использованием этой функции.

USART_Receive:
; Ожидание поступления данных
   lds r17, UCSRnA
   sbrs r17, RXCn
   rjmp USART_Receive
; Получить и возвратить данные из буфера
   lds r16, UDRn
   ret
unsigned char USART_Receive( void )
{
   /* Ожидание поступления данных */
   while ( !(UCSRnA & (1 << RXCn)) )
   {
   }
   /* Получить и возвратить данные из буфера */
   return UDRn;
}

Функция просто ждет появления данных в буфере приема путем проверки флага RXCn перед чтением буфера и возврата значения. Это означает, что она полностью блокирует программу, если на вход USART не поступают данные. 

Прием фреймов длиной 9 бит данных. Если используются 9-битные символы (UCSZn=7), то 9-й бит должен быть прочитан из бита RXB8n регистра UCSRnB до чтения младших 8 бит из UDRn. То же самое правило действует и для флагов состояния FEn, DORn и UPEn. Сначала прочитайте состояние из UCSRnA, затем данные из UDRn. Чтение UDRn по его адресу I/O поменяет состояние приемного буфера FIFO и следовательно поменяется состояние битов TXB8n, FEn, DORn и UPEn, которые все сохраняются в FIFO. 

Следующий пример кода покажет простую функцию приема USART, которая обрабатывает как 9-й бит, так и биты статуса. 

USART_Receive:
; Ожидание поступления данных
   lds r17, UCSRnA
   sbrs r17, RXCn
   rjmp USART_Receive
; Получить состояние и 9-й бит, и затем данные из буфера
   lds r18, UCSRnA
   lds r17, UCSRnB
   lds r16, UDRn
; Если ошибка, вернуть -1
   andi r18,(1 << FEn)|(1 << DORn)|(1 << UPEn)
   breq USART_ReceiveNoError
   ldi r17, HIGH(-1)
   ldi r16, LOW(-1)USART_ReceiveNoError:
; фильтр 9-го бита, вернуть символ
   lsr r17
   andi r17, 0x01
   ret
unsigned int USART_Receive( void )
{
   unsigned char status, resh, resl;
   /* Ожидание поступления данных */
   while ( !(UCSRnA & (1 << RXCn)) )
   {
   }
   /* Получить состояние и 9-й бит, затем данные из буфера */
   status = UCSRnA;
   resh = UCSRnB;
   resl = UDRn;
   /* Если ошибка, вернуть -1 */
   if ( status & (1 << FEn)|(1 << DORn)|(1 << UPEn) )
      return -1;
   /* Фильтр 9-го бита, и возврат символа */
   resh = (resh >> 1) & 0x01;
   return ((resh << 8) | resl);
}

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

Флаг и прерывание Receive Compete. У приемника USART есть 1 флаг, который показывает состояние приемника. Флаг Receive Complete (RXCn) показывает, что в буфере приема есть не прочитанные данные. Этот флаг равен 1, когда не прочитанные данные есть в буфере приема, и 0, когда буфер приема пуст (т. е. в нем не содержится никаких не прочитанных данных). Если приемник запрещен (RXENn = 0), буфер приема сбрасывается, и следовательно флаг RXCn обнуляется. 

Когда установлен бит Receive Complete Interrupt Enable (RXCIEn) в регистре UCSRnB, выполнится прерывание USART Receive Complete, когда флаг RXCn установится (подразумевается, что глобально прерывания разрешены). Когда работает прием данных по прерываниям, то подпрограмма обработчика прерывания Receive Complete должна прочитать принятые данные UDRn, чтобы очистить флаг RXCn, иначе после завершения работы обработчика прерывания снова запуститься тот же обработчик прерывания. 

Флаги ошибок приемника. У приемника USART есть 3 флага ошибки: Frame Error (FEn), Data OverRun (DORn) и Parity Error (UPEn). Все биты ошибок доступны через чтение UCSRnA. Общим для флагов ошибок является то, тчо они размещены в буфере приема вместе с данными фрейма, для которого флаги ошибок показывают состояние (т. е. буферизация данных фрейма привязана к буферизации флагов ошибки). По этой причине сначала нужно прочитать UCSRnA, и только потом буфер данных приема (UDRn), поскольку чтение UDRn по его месту размещения I/O освободит буфер под новые данные. Еще флаги ошибок объединяет то, что их нельзя сбросить программно записью. Однако для обеспечения совместимости с изменениями в USART, которые возможно появятся в будущем, все флаги должны быть сброшены в 0, когда осуществляется запись UCSRnA. Флаги ошибки не могут генерировать прерывание. 

Флаг Frame Error (FEn) показывает состояние первого stop-бита принятого фрейма, находящегося в буфере приема. Флаг FEn равен 0, если stop-бит был прочитан правильно (как 1), и флаг FEn будет в 1, когда stop-бит ошибочен (равен 0). Этот флаг может использоваться для детектирования событий выхода из синхронизации, событий остановки потока (break conditions) и поддержки обработки протокола. На флаг FEn не влияет настройка бита USBSn в регистре UCSRnC, поскольку приемник игнорирует все stop-биты, кроме первого. Для обеспечения совместимости с микроконтроллерами, который возможно появятся в будущем, всегда сбрасывайте этот бит в 0, когда записываете UCSRnA. 

Флаг Data OverRun (DORn) показывает потерю данных, из-за того, что у буфере приемника были не прочитанные данные. Data OverRun произойдет, когда буфер приема заполнен (в нем находится 2 символа), ожидается прием следующего символа, и детектирован новый start-бит. Если флаг DORn установлен, то была потеря одного или большего количества фреймов между последним чтением и следующим чтением фрейма из UDRn. Для обеспечения совместимости с микроконтроллерами, который возможно появятся в будущем, всегда записывайте этот бит в 0, когда записываете UCSRnA. Флаг DORn очищается, когда принятый фрейм успешно перемещен из регистра сдвига в буфер приема. 

Флаг ошибки четности Parity Error (UPEn) показывает, что следующий фрейм, находящийся в буфере приема, имеет ошибку четности на приеме. Если контроль четности не разрешен, то бит UPEn будет всегда читаться как 0. Для обеспечения совместимости с микроконтроллерами, который возможно появятся в будущем, всегда сбрасывайте этот бит в 0, когда пишете в UCSRnA. 

Узел проверки бита четности (Parity Checker) активен, когда установлен в 1 бит USART Parity mode (UPMn1). Тип выполняемой проверки на четность (нечетность odd или четность even) выбирается битом UPMn0. Когда проверка четности разрешена, Parity Checker вычисляет четность от бит данных приходящих фреймов, и сравнивает результат с битом четности из последовательного фрейма. Результат проверки сохраняется в буфере приема вместе с принятыми данными и stop-битами. Флаг Parity Error (UPEn) может быть прочитан программно, чтобы проверить, была ли во фрейме ошибка четности. 

Бит UPEn установится, если в следующем символе, который можно прочитать из буфера приема, была ошибка четности на приеме, и проверка четности в этот момент была разрешена (UPMn1 = 1). Этот бит действителен, пока не произойдет чтение буфера приема (регистра UDRn).

Запрет приемника. В отличие от передатчика, запрет приемника срабатывает немедленно. Таким образом, принимаемый в настоящий момент фрейм данных (и конечно последующие после запрета) будут потеряны. Когда приемник запрещен (т. е. RXENn сброшен в 0), то он больше не переназначает нормальную работу порта RxDn как ножки GPIO. При запрете приемника буфер FIFO приемника будет сброшен, все оставшиеся в нем непрочитанные данные будут потеряны.

Сброс буфера приема. Буфер FIFO приемника будет сброшен, когда приемник запрещен, т. е. запомненные в буфере данные уничтожаются, непрочитанные данные будут потеряны. Если нужно сбросить буфер во время нормальной работы, например по причине события ошибки, просто делайте чтение UDRn, пока флаг RXCn не очистится. В следующем примере кода показана очистка буфера приема.

USART_Flush:
   sbis UCSRnA, RXCn
   ret
   in r16, UDRn
   rjmp USART_Flush
void USART_Flush( void )
{
   unsigned char dummy;
   while ( UCSRnA & (1 << RXCn) )
      dummy = UDRn;
}

[Асинхронный прием данных]

В состав USART включены блоки восстановления тактов (Asynchronous Clock Recovery) и данных (Asynchronous Data Recovery), чтобы поддержать асинхронный прием данных. Логика восстановления используется для синхронизации генерируемых внутри тактов скорости (baud rate) для входящих асинхронных последовательных фреймов на выводе RxDn. Логика восстановления данных оцифровывает и пропускает через ФНЧ каждый бит приходящих данных, чтобы улучшить стойкость приемника к помехам. Диапазон работоспособности асинхронного приема зависит от точности внутренних тактов скорости, скорости входящих фреймов, размера фрейма в количестве бит.

Asynchronous Clock Recovery. Логика восстановления тактов синхронизирует внутренние такты по входящим последовательным фреймам. На рис. 22-5 показан процесс оцифровки стартового бита входящего фрейма. Частота оцифровки в 16 раз больше частоты бит (baud rate) для нормального режима (Normal mode), и в 8 раз больше частоты бит для режима двойной скорости (Double Speed mode). Горизонтальные стрелки показывают интервалы подстройки синхронизации в процессе оцифровки. Обратите внимание на увеличенные интервалы для режима двойной скорости (Double Speed mode, U2Xn = 1). Выборки, помеченные нулями, означают выборки, когда сигнал RxDn в состоянии ожидания idle (т. е. нет активной передачи). 

ATmega2560 USART Start bit Sampling fig22 5

Рис. 22-5. Выборка (оцифровка) start-бита. 

Когда логика восстановления тактов детектировала переход от лог. 1 (idle) к лог. 0 (start) на линии RxDn, инициируется последовательность детектирования start-бита. Выборка 1 на рисунке показывает первую нулевую выборку. Затем логика восстановления тактов использует выборки 8, 9 и 10 для нормального режима, и выборки 4, 5 и 6 для режима двойной скорости (эти цифры выделены прямоугольной рамкой на рисунке), чтобы определить, что действительно принят допустимый start-бит. Если 2 или большее количество этих выборок имеют лог. 1 (принцип большинства), то start-бит отбрасывается как шумовая помеха, и приемник снова начинает детектирование следующего перехода от 1 к 0. Однако если детектирован допустимый start-бит («большинство» указывает на 0), то в логика восстановления тактов синхронизируется, и может начаться процесс восстановления данных. Процесс синхронизации повторяется для каждого start-бита. 

Asynchronous Data Recovery. Когда произошла синхронизация тактов приемника по start-биту, может начать работу восстановление данных. Блок восстановления данных использует машину из 16 состояний для каждого бита в нормальном режиме и машину 8 состояний для режима двойной скорости. На рис. 22-6 показана оцифровка битов данных и бита четности (BITn). Каждая выборка помечена цифрой, которая равна состоянию блока восстановления. 

ATmega2560 USART Sampling Data and Parity bit fig22 6

Рис. 22-6. Выборка данных и бита четности. 

Принятие решения о лог. уровне принятого бита выполняется по тому же самому «принципу большинства» на 3 выборках посередине принимаемого бита. Номера этих выборок помечены на рисунке рамочками. Если 2 или большее количество из этих 3 выборок прочитаны как 1, то принятый бит регистрируется как лог. 1. И аналогично если 2 или большее количество из этих 3 выборок прочитаны как 0, то принятый бит регистрируется как лог. 0. Этот принцип работает как простейший цифровой ФНЧ для входящего сигнала на выводе RxDn. Процесс восстановления данных повторяется для каждого бита, пока не завершится прием всего фрейма, включая первый stop-бит. Имейте в виду, что приемник использует только первый stop-бит фрейма. 

На рис. 22-7 показана оцифровка stop-бита как можно раньше относительно начала start-бита следующего фрейма. 

ATmega2560 USART Sampling Stop bit and Next Start bit fig22 7

Рис. 22-7. Выборка стоп-бита и следующего стартового бита. 

Для оцифровки (получения значения) stop-бита применяется тот же самый мажоритарный принцип голосования, как и для других бит фрейма. Если определено, что stop-бит равен лог. 0, то регистрируется ошибка фрейма, и будет установлен флаг Frame Error (FEn). 

Новый переход 1 -> 0 покажет начало start-бита нового фрейма, и он может появиться сразу после последнего бита, в котором использовалось детектирование уровня по мажоритарному принципу. Для режима Normal Speed, первая выборка с низким уровнем может быть в точке, промаркированной как (A) на рис. 22-7. Для Double Speed mode первый низкий уровень должен быть задержан до (B). (C) помечает stop-бит полной длины. Раннее детектирование start-бита влияет на рабочий диапазон приемника (Asynchronous Operational Range). 

Asynchronous Operational Range. Рабочий диапазон приемника зависит от несоответствия скорости принимаемых бит и генерируемой внутри скорости. И передатчик, и приемник должны быть настроены на одну и ту же скорость, но из-за погрешности частоты системного тактового генератора реальные частоты могут отличаться. Если передатчик посылает фреймы со слишком большой частотой бит или слишком малой частотой бит, или если генерируемая частота бит приемника имеет отличающуюся базовую частоту (см. таблицу 22-2), то приемник не сможет синхронизировать фреймы по start-биту. 

Следующие формулы можно использовать для вычисления соотношения между скоростью принимаемых данных и внутренней скоростью приемника. 

                  (D + 1) * S
Rslow = ———————-
              S — 1 + D*S + SF
                     (D + 2) * S
Rfast = ———————-
             (D + 1) * S + SM

D сумма числа бит символа и бита четности (D = 5 .. 10 бит).
S количество выборок на бит, S = 16 для Normal Speed mode и S = 8 для Double Speed mode.
SF номер первой выборки, используемой для детектирования уровня по мажоритарному принципу. SF = 8 для Normal Speed mode и SF = 4 для Double Speed mode.
SM номер средней выборки, используемой для детектирования уровня по мажоритарному принципу. SM = 9 для Normal Speed mode и SM = 5 для Double Speed mode.
Rslow соотношение между самой низкой входной скоростью и собственной скоростью приемника, при котором приемник все еще может принимать данные.
Rfast соотношение между самой высокой входной скоростью и собственной скоростью приемника, при котором приемник все еще может принимать данные. 

Таблицы 22-2 и 22-3 дают список максимально допустимой ошибки baud rate приемника. Обратите внимание, что для Normal Speed mode допуск больше. 

Табл. 22-2. Рекомендуемые максимальные скорости передачи и погрешность приемника для нормального режима скорости (U2Xn = 0). 

D (Data + Parity Bit) Rslow (%) Rfast (%) MAX общая ошибка, % Рекомендуемая MAX ошибка приемника, %
5 93.20 106.67 +6.67 / -6.8 ±3.0
6 94.12 105.79 +5.79 / -5.88 ±2.5
7 94.81 105.11 +5.11 / -5.19 ±2.0
8 95.36 104.58 +4.58 / -4.54 ±2.0
9 95.81 104.14 +4.14 / -4.19 ±1.5
10 96.17 103.78 +3.78 / -3.83 ±1.5

Табл. 22-3. Рекомендуемые максимальные скорости передачи и погрешность приемника для двойной скорости (U2Xn = 1). 

D (Data + Parity Bit) Rslow (%) Rfast (%) MAX общая ошибка, % Рекомендуемая MAX ошибка приемника, %
5 94.12 105.66 +5.66 / -5.88 ±2.5
6 94.92 104.92 +4.92 / -5.08 ±2.0
7 95.52 104.35 +4.35 / -4.48 ±1.5
8 96.00 103.90 +3.90 / -4.00 ±1.5
9 96.39 103.53 +3.53 / -3.61 ±1.5
10 96.70 103.23 +3.23 / -3.30 ±1.0

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

Есть 2 возможных источника ошибок baud rate приемника. Системная тактовая частота приемника (XTAL) всегда будет незначительно зависеть от напряжения питания и температуры окружающей среды. Когда для генерации системной частоты используется кварц, то в этом случае проблем чаще всего не будет. Однако если применить некачественный резонатор с допуском более 2%, то это может послужить причиной ошибок. Второй источник ошибки более управляемый. Генератор baud rate не всегда делает точное деление системной частоты, чтобы получить желаемое значение baud rate. В этом случае желательно использовать то значение для UBRR, которое дает ошибку как можно меньше. 

[Multi-processor Communication Mode

Установка бита Multi-processor Communication mode (MPCMn) в регистре UCSRnA разрешает функцию фильтрации входящих фреймов, полученных приемником USART. Фреймы, которые не содержат информацию адреса, будут игнорироваться и не попадут в буфер приема. Это эффективно уменьшит количество входящих фреймов, которые должны быть программно обработаны CPU в системе, где несколько процессоров (MCU) обмениваются данными по одной и той же последовательной шине данных. На передатчик не влияет установка бита MPCMn, но передатчик должен использоваться по-другому, когда он работает как часть системы, использующей Multi-processor Communication mode. 

Если приемник настроен для приема фреймов, содержащих от 5 до 8 бит данных, то первый stop-бит показывает, есть ли во фрейме информация адреса. Если приемник настроен на фреймы с 9 битами данных, то 9-й бит (RXB8n) используется для идентификации фреймов адреса и данных. Когда бит типа фрейма (это первый stop-бит или 9-й бит) равен 1, то фрейм содержит адрес. Когда бит типа фрейма равен 0, то это будет фрейм данных. 

Multi-processor Communication mode разрешает нескольким подчиненным MCU принимать данные от главного MCU. Это осуществляется путем декодирования фрейма адреса, чтобы определить, какой именно MCU адресован на шине. Если адресован конкретный подчиненный MCU, то он примет следующие фреймы данных как обычно, в то время другие подчиненные MCUs будут игнорировать принятые фреймы, пока не будет принят другой адресный фрейм. 

Использование MPCMn. Для MCU, который работает как главный на общей шине, можно использовать 9-битный формат фрейма (UCSZn = 7). Девятый бит (TXB8n) должен быть установлен, когда передается фрейм адреса (TXB8n = 1), или очищен, когда передается фрейм данных (TXB = 0). Подчиненные MCU в этом случае должны быть настроены для использования 9-битного формата фрейма. 

Для обмена данными в Multi-processor Communication mode должна использоваться следующая процедура: 

1. Все подчиненные MCU настроены в Multi-processor Communication mode (установлен бит MPCMn в регистре UCSRnA).

2. Главный MCU посылает фрейм адреса, и все подчиненные устройства принимают и читают этот фрейм. В подчиненных MCU флаг RXCn в регистре UCSRnA будет установлен как обычно.

3. Каждый подчиненный MCU читает регистр UDRn, чтобы определить, что для приема выбран именно он (проверяет совпадение адреса). Если так, то он очищает бит MPCMn в регистре UCSRnA, в противном случае просто ждет следующего адресного фрейма, сохраняя установленным бит MPCMn.

4. Адресованный MCU будет принимать все фреймы данных, пока не поступит новый фрейм адреса. Другие подчиненные MCUs, у которых установлен бит MPCMn, будут (аппаратно) игнорировать фреймы данных.

5. Когда адресованный MCU примет последний фрейм данных, то он устанавливает бит MPCMn и ждет новый фрейм адреса от главного MCU. Затем процедура повторяется начиная с шага 2. 

Можно использовать любой формат фрейма от 5 до 8 бит, но это непрактично, потому что приемник нужно перепрограммировать между использованием n и n+1 форматом бит фрейма. Это делает полнодуплексный обмен сложным, потому что передатчик и приемник используют настройку для одного и того же размера символа. Если используется формат символа от 5 до 8 бит, то передатчик должен быть установлен на использование двух stop-битов (USBSn = 1), поскольку первый stop-бит используется для указания типа фрейма (адрес или данные). 

Не используйте инструкции ассемблера Read-Modify-Write (SBI и CBI) для установки или очистки бита MPCMn. Бит MPCMn использует то же самое место в пространстве I/O, как и флаг TXCn, и это может случайно очистить его при использовании инструкций SBI или CBI.

USART ATmega2560 может также работать в режиме SPI, но здесь этот вариант настройки USART не рассматривается.

UDRn – USART I/O Data Register n

№ разрядов 7 6 5 4 3 2 1 0
Регистры
RXB[7:0] (UDRn при чтении)
TXB[7:0] (UDRn при записи)
Чтение/запись rw rw rw rw rw rw rw rw
Нач. значение 0 0 0 0 0 0 0 0

Регистры USART Transmit Data Buffer (TXB) и Receive Data Buffer (RXB) разделяют одну и ту же ячейку пространства адресов I/O, которая носит мнемоническое название USART Data Register, или UDRn. TXB будет точкой назначения для записываемых в UDRn данных. Чтение UDRn вернет данные из RXB.

Для 5, 6 или 7-разрядных символов верхние неиспользуемые биты будут игнорироваться при передаче и автоматически обнуляться при приеме.

Буфер передачи можно записать только тогда, когда установлен флаг UDREn в регистре UCSRnA. Данные, записанные в UDRn, когда флаг UDREn не установлен, будут игнорироваться передатчиком USART. Если данные записаны в буфер передачи, и передатчик разрешен, то передатчик загрузит данные в регистр сдвига передачи, когда регистр сдвига пуст. Тогда данные будут последовательно передаваться через вывод TxDn.

Буфер приема состоит из 2-уровневого FIFO. FIFO поменяет свое состояние независимо от того, был ли к нему доступ, или нет. Из-за этого поведения буфера приема не используйте для него инструкции ассемблера Read-Modify-Write (SBI и CBI). Будьте осторожны, когда используете инструкции проверки бит (SBIC и SBIS), поскольку они также изменят состояние FIFO.

UCSRnA – USART Control and Status Register A

№ разрядов 7 6 5 4 3 2 1 0
Имена бит RXCn TXCn UDREn FEn DORn UPEn U2Xn MPCMn
Чтение/запись r rw r r r r rw rw
Нач. значение 0 0 1 0 0 0 0 0

• 7 – RXCn: USART Receive Complete

Этот флаг установится, когда в буфере приема есть непрочитанные данные, и очищается, когда буфер приема пуст (т. е. в нем не содержатся какие-либо непрочитанные данные). Если приемник запрещен, то буфер приема сбрасывается, следовательно бит RXCn становится нулем. Флаг RXCn может использоваться для генерации прерывания Receive Complete (см. описание бита RXCIEn).

• 6 – TXCn: USART Transmit Complete

Этот бит установится, когда весь фрейм в регистре сдвига передачи выдвинут на выход, так что в настоящий момент нет новых данных в буфере передачи (UDRn). Флаг TXCn автоматически очищается, когда запускается прерывание Transmit Complete, или этот бит может быть очищен программно записью туда 1. Флаг TXCn может генерировать прерывание Transmit Complete (см. описание бита TXCIEn).

• 5 – UDREn: USART Data Register Empty

Флаг UDREn показывает, что буфер передачи (UDRn) пуст и готов к записи туда новых данных. Если бит UDREn в состоянии 1, то буфер пуст, и туда можно записать новый символ для передачи. Флаг UDREn может генерировать прерывание Data Register Empty (см. описание бита UDRIEn).

UDREn устанавливается после сброса, показывая этим, что передатчик готов к работе.

• 4 – FEn: Frame Error

Этот бит установится, если следующий символ в буфере приема получил ошибку фрейма, т. е. когда первый stop-бит оказался нулевым. Этот бит действителен, пока не будет прочитан буфер приема (UDRn), т. е. этот флаг привязан с принятому символу. FEn равен 0, когда stop-бит принятого фрейма равен 1 (нормальная ситуация, ошибки нет). Всегда сбрасывайте этот бит, когда записываете регистр UCSRnA.

• 3 – DORn: Data OverRun

Этот бит установится, если детектировано событие Data OverRun. Оно произойдет, когда буфер приема заполнен (в нем находится 2 принятых символа), ожидается прием нового символа, и был детектирован новый start-бит. Этот бит действителен, пока не будет прочитан буфер приема (UDRn), т. е. этот флаг привязан с принятому символу. Всегда сбрасывайте этот бит, когда записываете регистр UCSRnA.

• 2 – UPEn: USART Parity Error

Этот бит установится, если следующий символ в буфере приема имеет ошибку четности на приеме, и в момент его приема была разрешена проверка четности (UPMn1 = 1). Этот бит действителен, пока не будет прочитан буфер приема (UDRn), т. е. этот флаг привязан с принятому символу. Всегда сбрасывайте этот бит, когда записываете регистр UCSRnA.

• 1 – U2Xn: Double the USART Transmission Speed

Этот бит работает только для асинхронного режима. Запишите этот бит в 0, когда используете синхронный режим.

Запись в этот бит лог. 1 уменьшит в 2 раза коэффициент деления генератора скорости (с 16 до 8), так что в асинхронном режиме скорость увеличится в 2 раза.

• 0 – MPCMn: Multi-processor Communication Mode

Этот бит разрешит работу Multi-processor Communication mode. Когда этот бит в 1, все входящие фреймы, принятые приемником USART, не содержащие информации адреса, будут игнорированы. Этот бит не влияет на передатчик. Подробнее см. описание «Multi-processor Communication Mode».

UCSRnB – USART Control and Status Register B

№ разрядов 7 6 5 4 3 2 1 0
Имена бит RXCIEn TXCIEn UDRIEn FERXENn n TXENn UCSZn2 RXB8n TXB8n
Чтение/запись rw rw rw rw rw rw r rw
Нач. значение 0 0 0 0 0 0 0 0

• 7 – RXCIEn: RX Complete Interrupt Enable n

Запись в этот бит 1 разрешает работу прерывания по флагу RXCn. Прерывание USART Receive Complete будет сгенерировано, если бит RXCIEn записан в 1, разрешены глобально прерывания (установлен в 1 Global Interrupt Flag в SREG), и установился в 1 бит RXCn регистра UCSRnA.

• 6 – TXCIEn: TX Complete Interrupt Enable n

Запись этого бита в 1 разрешает работу прерывания по флагу TXCn. Прерывание USART Transmit Complete будет сгенерировано, если бит RXCIEn записан в 1, разрешены глобально прерывания (установлен в 1 Global Interrupt Flag в SREG), и установился в 1 бит TXCn в регистре UCSRnA.

• 5 – UDRIEn: USART Data Register Empty Interrupt Enable n

Запись в этот бит 1 разрешает работу прерывания по флагу UDREn. Прерывание Data Register Empty будет сгенерировано, если бит RXCIEn записан в 1, разрешены глобально прерывания (установлен в 1 Global Interrupt Flag в SREG), и установился в 1 бит UDREn в регистре UCSRnA.

• 4 – RXENn: Receiver Enable n

Запись этого бита в 1 разрешает работу приемника USART. Приемник переназначит нормальную работу ножки порта как GPIO, и она станет входом приемника RxDn. Запрет приемника очистит буфер приема и сделает недействительными флаги FEn, DORn и UPEn.

• 3 – TXENn: Transmitter Enable n

Запись этого бита в 1 разрешает работу передатчика USART. Передатчик переназначит нормальную работу ножки порта как GPIO, и она станет выходом передатчика TxDn. Запрет передатчика (запись в TXENn нуля) не вступит в силу, пока не завершится текущие передачи, т. е. пока не опустошаться регистр сдвига передачи и буфер передачи. Когда передатчик запрещен, то он не занимает порт TxDn под выход передатчика (порт может работать как обычный GPIO).

• 2 – UCSZn2: Character Size n

Бит UCSZn2 комбинируется с битами UCSZn1:0 регистра UCSRnC, и вместе с ними задает количество бит данных (Character SiZe) в фрейме передатчика и приемника.

• 1 – RXB8n: Receive Data Bit 8 n

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

• 0 – TXB8n: Transmit Data Bit 8 n

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

UCSRnC – USART Control and Status Register C

№ разрядов 7 6 5 4 3 2 1 0
Имена бит  UMSELn1 UMSELn0 UPMn1 UPMn0 USBSn UCSZn1 UCSZn0 UCPOLn
Чтение/запись rw rw rw rw rw rw rw rw
Нач. значение 0 0 0 0 0 1 1 0

• 7:6 – UMSELn1:0 USART Mode Select

Эти биты выбирают режим работы USARTn, как это показано в таблице 22-4.

Табл. 22-4. Настройки бит UMSELn.

UMSELn1 UMSELn1 Режим
0 0 Асинхронный USART
0 1 Синхронный USART
1 0 зарезервировано
1 1 Master SPI (MSPIM)(1)

Примечание (1): см. в даташите раздел «USART in SPI Mode».

• 5:4 – UPMn1:0: Parity Mode

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

UPMn1 UPMn0 Режим проверки четности
0 0 Отключено
0 1 зарезервировано
1 0 Разрешено, проверка по четности (Even Parity)
1 1 Разрешено, проверка по нечетности (Odd Parity)

• 3 – USBSn: Stop Bit Select

Этот бит выбирает количество stop-битов, которые вставляет передатчик. Приемник эту настройку игнорирует.

USBSn Количество стоп-битов
0 1
1 2

• 2:1 – UCSZn1:0: Character Size

Биты UCSZn1:0 в комбинации с битом UCSZn2 регистра UCSRnB устанавливают количество бит данных (Character SiZe) в фрейме передатчика и приемника.

UCSZn2 UCSZn1 UCSZn0 Размер символа, бит
0 0 0 5
0 0 1 6
0 1 0 7
0 1 1 8
1 0 0 зарезервировано
1 0 1
1 1 0
1 1 1 9

• Bit 0 – UCPOLn: Clock Polarity

Этот бит используется только в синхронном режиме. Запишите в этот бит 0, когда используется асинхронный режим работы. Бит UCPOLn устанавливает взаимосвязь между изменениями данных на выходе, выборкой данных на входе и тактами синхронизации (XCKn).

UCPOLn Когда изменяются передаваемые данные (на выводе TxDn) Когда считываются данные на входе (на выводе RxDn)
0 По нарастанию уровня на XCKn По спаду уровня на XCKn
1 По спаду уровня на XCKn По нарастанию уровня на XCKn

UBRRnL и UBRRnH – регистры USART Baud Rate

№ разрядов 15 14 13 12 11 10 9 8
UBRRHn UBRR[11:8]
UBRRLn UBRR[7:0]
№ разрядов 7 6 5 4 3 2 1 0
Чтение/запись r r r r rw rw rw rw
rw rw rw rw rw rw rw rw
Нач. значение 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

• 15:12 – резерв

Эти биты зарезервированы для возможного использования в будущем. Для совместимости в эти биты следует записывать 0, когда Вы записываете UBRRH.

• 11:0 – UBRR11:0: USART Baud Rate Register

Это 12-разрядный регистр, который содержит настройку скорости для USART (baud rate). UBRRH содержит 4 старших бита, UBRRL 8 младших USART baud rate. Текущая активная передача передатчика или активный прием приемника будут испорчены, если на лету была изменена скорость. Запись UBRRL приведет к немедленному обновлению прескалера в генераторе baud rate.

Для стандартных частот кварцев и резонаторов наиболее часто используемые скорости для асинхронного режима работы могут быть сгенерированы настройкой UBRR по таблицам от 22-9 до 22-12. Рекомендуется использовать настройки с погрешностью скорости 0.5% от целевой или менее. Более высокие погрешности допустимы, но в этом случае приемник будет меньше защищен от шумов, и вероятность возникновения ошибки будет больше, особенно на фреймах большого размера (см. раздел «Asynchronous Operational Range»). Значение ошибки установки скорости вычисляется по следующей формуле:

                   BaudRateближайшая
Error[%] = (———————— — 1) * 100%
                          BaudRate

Табл. 22-9. Примеры настройки UBRRn для наиболее часто используемых частот системного генератора.

Baud
Rate
[bps]
fosc = 1.0000 МГц
fosc = 1.8432 МГц fosc = 2.0000 МГц
U2Xn = 0 U2Xn = 1 U2Xn = 0 U2Xn = 1 U2Xn = 0 U2Xn = 1
UBRR Error UBRR Error UBRR Error UBRR Error UBRR Error UBRR Error
2400 25 0.2% 51 0.2% 47 0 95 0 51 0.2% 103 0.2%
4800 12 0.2% 25 0.2% 23 0 47 0 25 0.2% 51 0.2%
9600 6 -7.0% 12 0.2% 11 0 23 0 12 0.2% 25 0.2%
14.4K 3 8.5% 8 -3.5% 7 0 15 0 8 -3.5% 16 2.1%
19.2K 2 8.5% 6 -7.0% 5 0 11 0 6 -7.0% 12 0.2%
28.8K 1 8.5% 3 8.5% 3 0 7 0 3 8.5% 8 -3.5%
38.4K 1 -18.6% 2 8.5% 2 0 5 0 2 8.5% 6 -7.0%
57.6K 0 8.5% 1 8.5% 1 0 3 0 1 8.5% 3 8.5%
78.8K 1 -18.6% 1 -25.0% 2 0 1 -18.6% 2 8.5%
115.2K 0 8.5% 0 0 1 0 0 8.5% 1 8.5%
230.4 0 0
250K 0 0
MAX(1) 62.5K 125K 115.2K 230.4K 125K 250K

Примечание (1): UBRR = 0, Error = 0%.

Табл. 22-10. Примеры настройки UBRRn для наиболее часто используемых частот системного генератора.

Baud
Rate
[bps]
fosc = 3.6864 МГц fosc = 4.0000 МГц fosc = 7.3728 МГц
U2Xn = 0 U2Xn = 1 U2Xn = 0 U2Xn = 1 U2Xn = 0 U2Xn = 1
UBRR Error UBRR Error UBRR Error UBRR Error UBRR Error UBRR Error
2400 95 0 191 0 103 0.2% 207 0.2% 191 0 383 0
4800 47 0 95 0 51 0.2% 103 0.2% 95 0 191 0
9600 23 0 47 0 25 0.2% 51 0.2% 47 0 95 0
14.4K 15 0 31 0 16 2.1% 34 -0.8% 31 0 63 0
19.2K 11 0 23 0 12 0.2% 25 0.2% 23 0 47 0
28.8K 7 0 15 0 8 -3.5% 16 2.1% 15 0 31 0
38.4K 5 0 11 0 6 -7.0% 12 0.2% 11 0 23 0
57.6K 3 0 7 0 3 8.5% 8 -3.5% 7 0 15 0
78.8K 2 0 5 0 2 8.5% 6 -7.0% 5 0 11 0
115.2K 1 0 3 0 1 8.5% 3 8.5% 3 0 7 0
230.4 0 0 1 0 0 8.5% 1 8.5% 1 0 3 0
250K 0 -7.8% 1 -7.8% 0 0 1 0 1 -7.8% 3 -7.8%
0.5M 0 -7.8% 0 0 0 -7.8% 1 -7.8%
1M 0 -7.8%
MAX(1) 230.4K 480.8K 250K 0.5M 460.8K 921.6K

Примечание (1): UBRR = 0, Error = 0%.

Табл. 22-11. Примеры настройки UBRRn для наиболее часто используемых частот системного генератора.

Baud
Rate
[bps]
fosc = 8.0000 МГц fosc = 11.0592 МГц fosc = 14.7456 МГц
U2Xn = 0 U2Xn = 1 U2Xn = 0 U2Xn = 1 U2Xn = 0 U2Xn = 1
UBRR Error UBRR Error UBRR Error UBRR Error UBRR Error UBRR Error
2400 207 0.2% 416 -0.1% 287 0 575 0 383 0 767 0
4800 103 0.2% 207 0.2% 143 0 287 0 191 0 383 0
9600 51 0.2% 103 0.2% 71 0 143 0 95 0 191 0
14.4K 34 -0.8% 68 0.6% 47 0 95 0 63 0 127 0
19.2K 25 0.2% 51 0.2% 35 0 71 0 47 0 95 0
28.8K 16 2.1% 34 -0.8% 23 0 47 0 31 0 63 0
38.4K 12 0.2% 25 0.2% 17 0 35 0 23 0 47 0
57.6K 8 -3.5% 16 2.1% 11 0 23 0 15 0 31 0
78.8K 6 -7.0% 12 0.2% 8 0 17 0 11 0 23 0
115.2K 3 8.5% 8 -3.5% 5 0 11 0 7 0 15 0
230.4 1 8.5% 3 8.5% 2 0 5 0 3 0 7 0
250K 1 0 3 0 2 -7.8% 5 -7.8% 3 -7.8% 6 5.3%
0.5M 0 0 1 0 2 -7.8% 1 -7.8% 3 -7.8%
1M 0 0 0 -7.8% 1 -7.8%
MAX(1) 0.5M 1M 691.2K 1.3824M 921.6K 1.8432M

Примечание (1): UBRR = 0, Error = 0%.

Табл. 22-12. Примеры настройки UBRRn для наиболее часто используемых частот системного генератора.

Baud
Rate
[bps]
fosc = 16.0000 МГц fosc = 18.4320 МГц fosc = 20.0000 МГц
U2Xn = 0 U2Xn = 1 U2Xn = 0 U2Xn = 1 U2Xn = 0 U2Xn = 1
UBRR Error UBRR Error UBRR Error UBRR Error UBRR Error UBRR Error
2400 416 -0.1% 832 0 479 0 959 0 520 0 1041 0
4800 207 0.2% 416 -0.1% 239 0 479 0 259 0.2% 520 0
9600(2) 103 0.2% 207 0.2% 119 0 239 0 129 0.2% 259 0.2%
14.4K 68 0.6% 138 -0.1% 79 0 159 0 86 -0.2% 173 -0.2%
19.2K 51 0.2% 103 0.2% 59 0 119 0 64 0.2% 129 0.2%
28.8K 34 -0.8% 68 0.6% 39 0 79 0 42 0.9% 86 -0.2%
38.4K 25 0.2% 51 0.2% 29 0 59 0 32 -1.4% 64 0.2%
57.6K 16 2.1% 34 -0.8% 19 0 39 0 21 -1.4% 42 0.9%
78.8K 12 0.2% 25 0.2% 14 0 29 0 15 1.7% 32 -1.4%
115.2K(3) 8 -3.5% 16 2.1% 9 0 19 0 10 -1.4% 21 -1.4%
230.4 3 8.5% 8 -3.5% 4 0 9 0 4 8.5% 10 -1.4%
250K 3 0 7 0 4 -7.8% 8 2.4% 4 0 9 0
0.5M 1 0 3 0 4 -7.8% 4 0
1M 0 0 1 0
MAX(1) 1M 2M 1.152M 2.304M 1.25M 2.5M

Примечания:
(1): UBRR = 0, Error = 0%.
(2) скорость по умолчанию, которая используется в консоли Serial Monitor и скетчах Arduino.
(3) на этой скорости работает UART-загрузчик платы Arduino Mega 2560 [2].

[Ссылки]

1. Работа с кольцевым буфером.
2. Arduino MEGA 2560.
3. AVR: отладочный вывод через UART (RS232 debug).
4. stdio.h: стандартные возможности ввода/вывода.

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

V. Hunter Adams (vha3@cornell.edu)¶

Video discussion of the content on this page¶

Hardware Hookup¶

A UART channel has two data lines. On each device there is an RX pin and a TX pin (RX for receive and TX for transmit). The RX pin of each device is connected to the TX pin of the other. Note that there is no shared clock line! This is the «asynchronous» aspect of Universal Asynchronous Receiver Transmitter.

missing

Timing Diagram¶

In an idle state, the Tx line from the sending device is held high. This is a legacy of old telegraph machines, for which the line is held high to make it obvious that it is not damaged. To send a packet, the transmitter first sends a start bit, which pulls the line low.

“UART” stands for Universal Asynchronous Receiver-Transmitter. The word “Asynchronous” in the name means that there is no shared clock between the transmitter and receiver. Instead, this start bit acts like a synchronization pulse between the transmitter and receiver. Each has their own clock, and they synchronize those clocks using the falling edge of this start bit.

That suggests that those two clocks need to running at the same speed. And indeed they do. These need to by synchronized to within ~2 percent or communication won’t work.

After this start bit 8 (or 9, depending on the configuration) bits are sent in least significant bit first format. At the end of the packet, there is a stop bit. The stop bit is one more down time followed by a rising edge. When the receiver sees the rising edge of that stop bit, it knows that there is now a valid character in its receive buffer and it will send some sort of internal signal to indicate as such. It may throw an interrupt, for example. It needs some sort of signal because this is asynchronous — a valid character could arrive at any time.

The number of clock pulses per bit can be configured to be 4 or 16. With only 4 pulses per bit, you can transmit faster, but you also only use a single sample per bit to determine whether a high or low level is present. With 16x the baud rate, majority detect circuitry is implemented to determine the value on the RX pin. The fastest that you can transmit is 1/4 the clock rate. So, at 40 MHz, you can in principle send data at up to 10Mbps, but don’t expect to be able to do that over very far distances.

missing

Some things to notice about this protocol:

  • It takes 10 bit-times to transmit 8-bits.
  • It takes 1/(baud rate) seconds to transmit each bit
  • The number of clock pulses per bit is configurable (4 or 16)
  • You could transmit at up to 1/4 the clock rate, but not for very far distances
  • Clock synchronization to within about 2 percent is required for successful communication

Error states¶

Framing errors¶

The UART status and control registers will indicate various status conditions, including error states associated with a transmission. Understanding this protocol makes understanding the error states a bit easier. They include framing errors, which occur when the receiver does not see a stop bit at the expected bit time. If the data line is not in the expected high state when the stop bit is expected (according to the number of data and parity bits for which the UART is set), the UART will signal a framing error.

Parity error¶

A parity error only gets thrown if the UART is in parity mode. In parity mode, an extra bit is sent which holds the parity (even or odd) of all of the transmitted data bits. If there is an error in a data bit (1 for 0 or 0 for 1), this parity bit will be wrong and an error will be thrown specifying an error.

Overrun error¶

An overrun error occurs when the receiver has not processed (removed characters from the input buffer) before the next character arrives.

Break condition¶

A break condition is not an error, necessarily. It occurs when the receiver input is at a logic level low state for longer than some duration of time, typically for more than a character time. It looks to the receiver like a character of all zero bits with a framing error. This is hacked for the software reset circuitry. In the python code, you can see that a reset is triggered by sending a break. This pulls the data line low for long enough that MCLR is pulled low and the board resets.

9-bit networking¶

missing

There is a configuration that allows you to setup a network that uses UART as the communication protocol. Doing so requires that all the lines of all the devices are wired together. There’s a diode going into each Tx line, and the whole thing is gently pulled up by a pull-up resistor.

This configuration means that a transmit pin can pull down the line, and the resistor will pull it back up. You then need a scheme for addressing a particular device from a particular device. A way to do this is to configure the UART to 9-bit mode (which means, as the name suggests, that 9 data bits are transmitted instead of 8). That 9th bit is then used to indicate whether the information that was just sent was an address or data.

If it was an address, then all secondary devices look for a match of their own hardcoded addresses. If they receive a match, they can be configured to automatically setup their receive/transmit functions. This address stays the bus address until a new address is sent. In other words, it’s persistent.

A universal asynchronous receiver-transmitter (UART ) is a computer hardware device for asynchronous serial communication in which the data format and transmission speeds are configurable. It sends data bits one by one, from the least significant to the most significant, framed by start and stop bits so that precise timing is handled by the communication channel. The electric signaling levels are handled by a driver circuit external to the UART. Two common signal levels are RS-232, a 12-volt system, and RS-485, a 5-volt system. Early teletypewriters used current loops.

It was one of the earliest computer communication devices, used to attach teletypewriters for an operator console. It was also an early hardware system for the Internet.

A UART is usually an individual (or part of an) integrated circuit (IC) used for serial communications over a computer or peripheral device serial port. One or more UART peripherals are commonly integrated in microcontroller chips. Specialised UARTs are used for automobiles, smart cards and SIMs.

A related device, the universal synchronous and asynchronous receiver-transmitter (USART) also supports synchronous operation.

Transmitting and receiving serial data[edit]

The universal asynchronous receiver-transmitter (UART) takes bytes of data and transmits the individual bits in a sequential fashion.[1] At the destination, a second UART re-assembles the bits into complete bytes. Each UART contains a shift register, which is the fundamental method of conversion between serial and parallel forms. Serial transmission of digital information (bits) through a single wire or other medium is less costly than parallel transmission through multiple wires.

The UART usually does not directly generate or receive the external signals used between different items of equipment. Separate interface devices are used to convert the logic level signals of the UART to and from the external signalling levels, which may be standardized voltage levels, current levels, or other signals.

Communication may be 3 modes:

  • simplex (in one direction only, with no provision for the receiving device to send information back to the transmitting device)
  • full duplex (both devices send and receive at the same time)
  • half duplex (devices take turns transmitting and receiving)

Data framing[edit]

UART frame, field length in Bits

1 5-9 0-1 1-2
Start Bit Data Frame Parity Bits Stop Bits

For UART to work the following settings need to be the same on both the transmitting and receiving side:

  • Baud Rate
  • Parity bit
  • Data bits size
  • Stop bits size
  • Flow Control

In the most common settings of 8 data bits, no parity and 1 stop bit (aka 8N1), the protocol efficiency is 80%. Ethernet by comparison is up to 97%.

Example of a UART frame. In this diagram, one byte is sent, consisting of a start bit, followed by eight data bits (D0-7), and two stop bit, for a 11-bit UART frame. The number of data and formatting bits, the presence or absence of a parity bit, the form of parity (even or odd) and the transmission speed must be pre-agreed by the communicating parties. The «stop bit» is actually a «stop period»; the stop period of the transmitter may be arbitrarily long. It cannot be shorter than a specified amount, usually 1 to 2 bit times. The receiver requires a shorter stop period than the transmitter. At the end of each data frame, the receiver stops briefly to wait for the next start bit. It is this difference which keeps the transmitter and receiver synchronized. BCLK = Base Clock

A UART frame consists of 5 elements:

  • Idle (logic high (1))
  • Start bit (logic low (0))
  • Data bits
  • Parity bit
  • Stop (logic high (1))

The idle, no data state is high-voltage, or powered. This is a historic legacy from telegraphy, in which the line is held high to show that the line and transmitter are not damaged.

Each character is framed as a logic low start bit, data bits, possibly a parity bit and one or more stop bits. In most applications the least significant data bit (the one on the left in this diagram) is transmitted first, but there are exceptions (such as the IBM 2741 printing terminal).

Start bit[edit]

The start bit signals the receiver that a new character is coming.

Data bit[edit]

The next five to nine bits, depending on the code set employed, represent the character.

Parity bit[edit]

If a parity bit is used, it would be placed after all of the data bits.

It describes the odd or eveness of the number.

Stop bit[edit]

The next one or two bits are always in the mark (logic high, i.e., ‘1’) condition and called the stop bit(s). They signal to the receiver that the character is complete. Since the start bit is logic low (0) and the stop bit is logic high (1) there are always at least two guaranteed signal changes between characters.

If the line is held in the logic low condition for longer than a character time, this is a break condition that can be detected by the UART.

Receiver[edit]

All operations of the UART hardware are controlled by an internal clock signal which runs at a multiple of the data rate, typically 8 or 16 times the bit rate. The receiver tests the state of the incoming signal on each clock pulse, looking for the beginning of the start bit. If the apparent start bit lasts at least one-half of the bit time, it is valid and signals the start of a new character. If not, it is considered a spurious pulse and is ignored. After waiting a further bit time, the state of the line is again sampled and the resulting level clocked into a shift register. After the required number of bit periods for the character length (5 to 8 bits, typically) have elapsed, the contents of the shift register are made available (in parallel fashion) to the receiving system. The UART will set a flag indicating new data is available, and may also generate a processor interrupt to request that the host processor transfers the received data.

Communicating UARTs have no shared timing system apart from the communication signal. Typically, UARTs resynchronize their internal clocks on each change of the data line that is not considered a spurious pulse. Obtaining timing information in this manner, they reliably receive when the transmitter is sending at a slightly different speed than it should. Simplistic UARTs do not do this; instead they resynchronize on the falling edge of the start bit only, and then read the center of each expected data bit, and this system works if the broadcast data rate is accurate enough to allow the stop bits to be sampled reliably.[2][3]

It is a standard feature for a UART to store the most recent character while receiving the next. This «double buffering» gives a receiving computer an entire character transmission time to fetch a received character. Many UARTs have a small first-in, first-out (FIFO) buffer memory between the receiver shift register and the host system interface. This allows the host processor even more time to handle an interrupt from the UART and prevents loss of received data at high rates.

Transmitter[edit]

Transmission operation is simpler as the timing does not have to be determined from the line state, nor is it bound to any fixed timing intervals. As soon as the sending system deposits a character in the shift register (after completion of the previous character), the UART generates a start bit, shifts the required number of data bits out to the line, generates and sends the parity bit (if used), and sends the stop bits. Since full-duplex operation requires characters to be sent and received at the same time, UARTs use two different shift registers for transmitted and received characters. High performance UARTs could contain a transmit FIFO (first in first out) buffer to allow a CPU or DMA controller to deposit multiple characters in a burst into the FIFO rather than have to deposit one character at a time into the shift register. Since transmission of a single or multiple characters may take a long time relative to CPU speeds, a UART maintains a flag showing busy status so that the host system knows if there is at least one character in the transmit buffer or shift register; «ready for next character(s)» may also be signaled with an interrupt.

Application[edit]

Transmitting and receiving UARTs must be set for the same bit speed, character length, parity, and stop bits for proper operation. The receiving UART may detect some mismatched settings and set a «framing error» flag bit for the host system; in exceptional cases, the receiving UART will produce an erratic stream of mutilated characters and transfer them to the host system.

Typical serial ports used with personal computers connected to modems use eight data bits, no parity, and one stop bit; for this configuration, the number of ASCII characters per second equals the bit rate divided by 10.

Some very low-cost home computers or embedded systems dispense with a UART and use the CPU to sample the state of an input port or directly manipulate an output port for data transmission. While very CPU-intensive (since the CPU timing is critical), the UART chip can thus be omitted, saving money and space. The technique is known as bit-banging.

History[edit]

Some early telegraph schemes used variable-length pulses (as in Morse code) and rotating clockwork mechanisms to transmit alphabetic characters. The first serial communication devices (with fixed-length pulses) were rotating mechanical switches (commutators). Various character codes using 5, 6, 7, or 8 data bits became common in teleprinters and later as computer peripherals. The teletypewriter made an excellent general-purpose I/O device for a small computer.

Gordon Bell of DEC designed the first UART, occupying an entire circuit board called a line unit, for the PDP series of computers beginning with the PDP-1.[4][5]
According to Bell, the main innovation of the UART was its use of sampling to convert the signal into the digital domain, allowing more reliable timing than previous circuits that used analog timing devices with manually adjusted potentiometers.[6] To reduce the cost of wiring, backplane and other components, these computers also pioneered flow control using XON and XOFF characters rather than hardware wires.

DEC condensed the line unit design into an early single-chip UART for their own use.[4] Western Digital developed this into the first widely available single-chip UART, the WD1402A, around 1971. This was an early example of a medium-scale integrated circuit. Another popular chip was the SCN2651 from the Signetics 2650 family.

An example of an early 1980s UART was the National Semiconductor 8250 used in the original IBM PC’s Asynchronous Communications Adapter card.[7] In the 1990s, newer UARTs were developed with on-chip buffers. This allowed higher transmission speed without data loss and without requiring such frequent attention from the computer. For example, the popular National Semiconductor 16550 has a 16-byte FIFO, and spawned many variants, including the 16C550, 16C650, 16C750, and 16C850.

Depending on the manufacturer, different terms are used to identify devices that perform the UART functions. Intel called their 8251 device a «Programmable Communication Interface». MOS Technology 6551 was known under the name «Asynchronous Communications Interface Adapter» (ACIA). The term «Serial Communications Interface» (SCI) was first used at Motorola around 1975 to refer to their start-stop asynchronous serial interface device, which others were calling a UART. Zilog manufactured a number of Serial Communication Controllers or SCCs.

Starting in the 2000s, most IBM PC compatible computers removed their external RS-232 COM ports and used USB ports that can send data faster. For users who still need RS-232 serial ports, external USB-to-UART bridges are now commonly used. They combine the hardware cables and a chip to do the USB and UART conversion. Cypress Semiconductor and FTDI are two of the significant commercial suppliers of these chips.[8] Although RS-232 ports are no longer available to users on the outside of most computers, many internal processors and microprocessors have UARTs built into their chips to give hardware designers the ability to interface with other chips or devices that use RS-232 or RS-485 for communication.

Structure[edit]

A UART usually contains the following components:

  • a clock generator, usually a multiple of the bit rate to allow sampling in the middle of a bit period
  • input and output shift registers
  • transmit/receive control
  • read/write control logic
  • autobaud measurement (optional)
  • transmit/receive buffers (optional)
  • system data bus buffer (optional)
  • first-in, first-out (FIFO) buffer memory (optional)
  • signals needed by a third party DMA controller (optional)
  • integrated bus mastering DMA controller (optional)

Special transceiver conditions[edit]

Overrun error[edit]

An overrun error occurs when the receiver cannot process the character that just came in before the next one arrives. Various devices have different amounts of buffer space to hold received characters. The CPU or DMA controller must service the UART in order to remove characters from the input buffer. If the CPU or DMA controller does not service the UART quickly enough and the buffer becomes full, an overrun error will occur, and incoming characters will be lost.

Underrun error[edit]

An underrun error occurs when the UART transmitter has completed sending a character and the transmit buffer is empty. In asynchronous modes this is treated as an indication that no data remains to be transmitted, rather than an error, since additional stop bits can be appended. This error indication is commonly found in USARTs, since an underrun is more serious in synchronous systems.

Framing error[edit]

A UART will detect a framing error when it does not see a «stop» bit at the expected «stop» bit time. As the «start» bit is used to identify the beginning of an incoming character, its timing is a reference for the remaining bits. If the data line is not in the expected state (high) when the «stop» bit is expected (according to the number of data and parity bits for which the UART is set), the UART will signal a framing error. A «break» condition on the line is also signaled as a framing error.

Parity error[edit]

A parity error occurs when the parity of the number of one-bits disagrees with that specified by the parity bit. Parity checking is often used for the detection of transmission errors. Use of a parity bit is optional, so this error will only occur if parity-checking has been enabled.

Break condition[edit]

A break condition occurs when the receiver input is at the «space» (logic low, i.e., ‘0’) level for longer than some duration of time, typically, for more than a character time. This is not necessarily an error, but appears to the receiver as a character of all zero-bits with a framing error.

The term «break» derives from current loop signaling, which was the traditional signaling used for teletypewriters. The «spacing» condition of a current loop line is indicated by no current flowing, and a very long period of no current flowing is often caused by a break or other fault in the line. Some equipment will deliberately transmit the «space» level for longer than a character as an attention signal. When signaling rates are mismatched, no meaningful characters can be sent, but a long «break» signal can be a useful way to get the attention of a mismatched receiver to do something (such as resetting itself). Computer systems can use the long «break» level as a request to change the signaling rate, to support dial-in access at multiple signaling rates. The DMX512 protocol uses the break condition to signal the start of a new packet.

UART models[edit]

A dual UART, or DUART, combines two UARTs into a single chip. Similarly, a quadruple UART or QUART, combines four UARTs into one package, such as the NXP 28L194. An octal UART or OCTART combines eight UARTs into one package, such as the Exar XR16L788 or the NXP SCC2698.

Model Description
WD1402A The first single-chip UART on general sale. Introduced about 1971. Compatible chips included the Fairchild TR1402A and the General Instruments AY-5-1013.[9]
Exar XR21V1410
Intersil 6402
CDP 1854 (RCA, now Intersil)
Zilog Z8440 Universal synchronous and asynchronous receiver-transmitter. 2000 kbit/s. Async, Bisync, SDLC, HDLC, X.25. CRC. 4-byte RX buffer. 2-byte TX buffer. Provides signals needed by a third party DMA controller to perform DMA transfers.[10]
Z8530/Z85C30 This universal synchronous and asynchronous receiver-transmitter has a 3-byte receive buffer and a 1-byte transmit buffer. It has hardware to accelerate the processing of HDLC and SDLC. The CMOS version (Z85C30) provides signals to allow a third party DMA controller to perform DMA transfers. It can do asynchronous, byte level synchronous, and bit level synchronous communications.[11]
8250 Obsolete with 1-byte buffers. These UARTs’ maximum standard serial port speed is 9600 bits per second if the operating system has a 1 millisecond interrupt latency. 8250 UARTs were used in the IBM PC 5150 and IBM PC/XT, while the 16450 UART were used in IBM PC/AT-series computers.
8251
Motorola 6850
6551
Rockwell 65C52
16450
82510 This UART allows asynchronous operation up to 288 kbit/s, with two independent four-byte FIFOs. It was produced by Intel at least from 1993 to 1996, and Innovastic Semiconductor has a 2011 Data Sheet for IA82510.
16550 This UART’s FIFO is broken, so it cannot safely run any faster than the 16450 UART. The 16550A and later versions fix this bug.
16550A This UART has 16-byte FIFO buffers. Its receive interrupt trigger levels can be set to 1, 4, 8, or 14 characters. Its maximum standard serial port speed if the operating system has a 1 millisecond interrupt latency is 128 kbit/s. Systems with lower interrupt latencies or with DMA controllers could handle higher baud rates. This chip can provide signals that are needed to allow a DMA controller to perform DMA transfers to and from the UART if the DMA mode this UART introduces is enabled.[12] It was introduced by National Semiconductor, which has been sold to Texas Instruments. National Semiconductor claimed that this UART could run at up to 1.5 Mbit/s.
16C552
16650 This UART was introduced by Startech Semiconductor which is now owned by Exar Corporation and is not related to Startech.com. Early versions have a broken FIFO buffer and therefore cannot safely run any faster than the 16450 UART.[13] Versions of this UART that were not broken have 32-character FIFO buffers and could function at standard serial port speeds up to 230.4 kbit/s if the operating system has a 1 millisecond interrupt latency. Current versions of this UART by Exar claim to be able to handle up to 1.5 Mbit/s. This UART introduces the Auto-RTS and Auto-CTS features in which the RTS# signal is controlled by the UART to signal the external device to stop transmitting when the UART’s buffer is full to or beyond a user-set trigger point and to stop transmitting to the device when the device drives the CTS# signal high (logic 0).
16750 64-byte buffers. This UART can handle a maximum standard serial port speed of 460.8 kbit/s if the maximum interrupt latency is 1 millisecond. This UART was introduced by Texas Instruments. TI claims that early models can run up to 1 Mbit/s, and later models in this series can run up to 3 Mbit/s.
16850 128-byte buffers. This UART can handle a maximum standard serial port speed of 921.6 kbit/s if the maximum interrupt latency is 1 millisecond. This UART was introduced by Exar Corporation. Exar claims that early versions can run up to 2 Mbit/s, and later versions can run up to 2.25 Mbit/s depending on the date of manufacture.
16C850
16950 128-byte buffers. This UART can handle a maximum standard serial port speed of 921.6 kbit/s if the maximum interrupt latency is 1 millisecond. This UART supports 9-bit characters in addition to the 5- to 8-bit characters that other UARTs support. This was introduced by Oxford Semiconductor, which is now owned by PLX Technology. Oxford/PLX claims that this UART can run up to 15 Mbit/s. PCI Express variants by Oxford/PLX are integrated with a first party bus mastering PCIe DMA controller. This DMA controller uses the UART’s DMA mode signals that were defined for the 16550. The DMA controller requires the CPU to set up each transaction and poll a status register after the transaction is started to determine if the transaction is done. Each DMA transaction can transfer between 1 and 128 bytes between a memory buffer and the UART. PCI Express variants can also allow the CPU to transfer data between itself and the UART with 8-, 16-, or 32-bit transfers when using programmed I/O.
16C950
16954 Quad-port version of the 16950/16C950. 128-byte buffers. This UART can handle a maximum standard serial port speed of 921.6 kbit/s if the maximum interrupt latency is 1 millisecond. This UART supports 9-bit characters in addition to the 5–8 bit characters that other UARTs support. This was introduced by Oxford Semiconductor, which is now owned by PLX Technology. Oxford/PLX claims that this UART can run up to 15 Mbit/s. PCI Express variants by Oxford/PLX are integrated with a first party bus mastering PCIe DMA controller. This DMA controller is controlled by the UART’s DMA mode signals that were defined for the 16550. The DMA controller requires the CPU to set up each transaction and poll a status register after the transaction is started to determine if the transaction is done. Each DMA transaction can transfer between 1 and 128 bytes between a memory buffer and the UART. PCI Express variants can also allow the CPU to transfer data between itself and the UART with 8-, 16-, or 32-bit transfers when using programmed I/O.
16C954
16C1550/16C1551 UART with 16-byte FIFO buffers. Up to 1.5 Mbit/s. The ST16C155X is not compatible with the industry standard 16550 and will not work with the standard serial port driver in Microsoft Windows.
16C2450 Dual UART with 1-byte FIFO buffers.
16C2550 Dual UART with 16-byte FIFO buffers. Pin-to-pin and functional compatible to 16C2450. Software compatible with INS8250 and NS16C550.
SCC2691 Currently produced by NXP, the 2691[3] is a single channel UART that also includes a programmable counter/timer. The 2691 has a single-byte transmitter holding register and a 4-byte receive FIFO. Maximum standard speed of the 2692 is 115.2 kbit/s.

The 28L91 is an upwardly compatible version of the 2691, featuring selectable 8- or 16-byte transmitter and receiver FIFOs, improved support for extended data rates, and faster bus timing characteristics, making the device more suitable for use with high performance microprocessors.

Both the 2691 and 28L91 may also be operated in TIA-422 and TIA-485 modes, and may also be programmed to support non-standard data rates. The devices are produced in PDIP-40, PLCC-44 and 44 pin QFP packages, and are readily adaptable to both Motorola and Intel buses. They have also been successfully adapted to the 65C02 and 65C816 buses. The 28L91 will operate on 3.3 or 5 volts.

SCC28L91
SCC2692 Currently produced by NXP, these devices are dual UARTs (DUART), consisting of two communications channels, associated control registers and one counter/timer. Each communication channel is independently programmable and supports independent transmit and receive data rates.

The 2692 has a single-byte transmitter holding register and a 4-byte receiver FIFO for each channel. Maximum standard speed of both of the 2692’s channels is 115.2 kbit/s.

The 26C92 is an upwardly compatible version of the 2692, with 8-byte transmitter and receiver FIFOs for improved performance during continuous bi-directional asynchronous transmission (CBAT) on both channels at the maximum standard speed of 230.4 kbit/s. The letter C in the 26C92 part number has nothing to do with the fabrication process; all NXP UARTs are CMOS devices.

The 28L92 is an upwardly compatible version of the 26C92, featuring selectable 8- or 16-byte transmitter and receiver FIFOs, improved support for extended data rates, and faster bus timing characteristics, making the device more suitable for use with high performance microprocessors.

The 2692, 26C92 and 28L92 may be operated in TIA-422 and TIA-485 modes, and may also be programmed to support non-standard data rates. The devices are produced in PDIP-40, PLCC-44 and 44 pin QFP packages, and are readily adaptable to both Motorola and Intel buses. They have also been successfully adapted to the 65C02 and 65C816 buses. The 28L92 will operate on 3.3 or 5 volts.

SC26C92
SC28L92
SCC28C94 Currently produced by NXP, the 28C94 quadruple UART (QUART) is functionally similar to a pair of SCC26C92 DUARTs mounted in a common package, with the addition of an arbitrated interrupt system for efficient processing during periods of intense channel activity. Some additional signals are present to support the interrupt management features and the auxiliary input/output pins are arranged differently than those of the 26C92. Otherwise, the programming model for the 28C94 is similar to that of the 26C92, requiring only minor code changes to fully utilize all features. The 28C94 supports a maximum standard speed of 230.4 kbit/s, is available in a PLCC-52 package, and is readily adaptable to both Motorola and Intel buses. It has also been successfully adapted to the 65C816 bus.
SCC2698B Currently produced by NXP, the 2698 octal UART (OCTART) is essentially four SCC2692 DUARTs in a single package. Specifications are the same as the SCC2692 (not the SCC26C92). Due to the lack of transmitter FIFOs and the small size of the receiver FIFOs, the 2698 can cause an interrupt «storm» if all channels are simultaneously engaged in continuous bi-directional communication. The device is produced in PDIP-64 and PLCC-84 packages, and is readily adaptable to both Motorola and Intel buses. The 2698 has also been successfully adapted to the 65C02 and 65C816 buses.
SCC28L198 Currently produced by NXP, the 28L198 OCTART is essentially an upscaled enhancement of the SCC28C94 QUART described above, with eight independent communications channels, as well as an arbitrated interrupt system for efficient processing during periods of intense channel activity. The 28L198 supports a maximum standard speed of 460.8 kbit/s, is available in PLCC-84 and LQFP-100 packages, and is readily adaptable to both Motorola and Intel buses. The 28L198 will operate on 3.3 or 5 volts.
Z85230 Synchronous/Asynchronous modes, 2 ports. Provides signals needed by a third party DMA controller needed to perform DMA transfers. 4-byte buffer to send, 8-byte buffer to receive per channel. SDLC/HDLC modes. 5 Mbit/s in synchronous mode.
Hayes ESP 1 KB buffers, 921.6 kbit/s, 8-ports.[14]
Exar XR17V352, XR17V354 and XR17V358 Dual, Quad and Octal PCI Express UARTs with 16550 compatible register Set, 256-byte TX and RX FIFOs, Programmable TX and RX Trigger Levels, TX/RX FIFO Level Counters, Fractional baud rate generator, Automatic RTS/CTS or DTR/DSR hardware flow control with programmable hysteresis, Automatic Xon/Xoff software flow control, RS-485 half duplex direction control output with programmable turn-around delay, Multi-drop with Auto Address Detection, Infrared (IrDA 1.1) data encoder/decoder. They are specified up to 25 Mbit/s. DataSheets are dated from 2012.
Exar XR17D152, XR17D154 and XR17D158 Dual, Quad and Octal PCI bus UARTs with 16C550 Compatible 5G Register Set, 64-byte Transmit and Receive FIFOs, Transmit and Receive FIFO Level Counters, Programmable TX and RX FIFO Trigger Level, Automatic RTS/CTS or DTR/DSR Flow Control, Automatic Xon/Xoff Software Flow Control, RS485 HDX Control Output with Selectable Turn-around Delay, Infrared (IrDA 1.0) Data Encoder/Decoder, Programmable Data Rate with Prescaler, Up to 6.25 Mbit/s Serial Data Rate. DataSheets are dated from 2004 and 2005.
Exar XR17C152, XR17C154 and XR17C158 Dual, Quad and Octal 5 V PCI bus UARTs with 16C550 Compatible Registers, 64-byte Transmit and Receive FIFOs, Transmit and Receive FIFO Level Counters, Automatic RTS/CTS or DTR/DSR Flow Control, Automatic Xon/Xoff Software Flow Control, RS485 Half-duplex Control with Selectable Delay, Infrared (IrDA 1.0) Data Encoder/Decoder, Programmable Data Rate with Prescaler, Up to 6.25 Mbit/s Serial Data Rate. DataSheets are dated from 2004 and 2005.
Exar XR17V252, XR17V254 and XR17V258 Dual, Quad and Octal 66 MHz PCI bus UARTs with Power Management Support, 16C550 compatible register set, 64-byte TX and RX FIFOs with level counters and programmable trigger levels, Fractional baud rate generator, Automatic RTS/CTS or DTR/DSR hardware flow control with programmable hysteresis, Automatic Xon/Xoff software flow control, RS-485 half duplex direction control output with selectable turn-around delay, Infrared (IrDA 1.0) data encoder/decoder, Programmable data rate with prescaler. DataSheets are dated from 2008 and 2010.

UART in modems[edit]

Modems for personal computers that plug into a motherboard slot must also include the UART function on the card. The original 8250 UART chip shipped with the IBM personal computer had a one character buffer for the receiver and the transmitter each, which meant that communications software performed poorly at speeds above 9600 bit/s, especially if operating under a multitasking system or if handling interrupts from disk controllers. High-speed modems used UARTs that were compatible with the original chip but which included additional FIFO buffers, giving software additional time to respond to incoming data.

A look at the performance requirements at high bit rates shows why the 16-, 32-, 64- or 128-byte FIFO is a necessity. The Microsoft specification for a DOS system requires that interrupts not be disabled for more than 1 millisecond at a time. Some hard disk drives and video controllers violate this specification. 9600 bit/s will deliver a character approximately every millisecond, so a 1-byte FIFO should be sufficient at this rate on a DOS system which meets the maximum interrupt disable timing. Rates above this may receive a new character before the old one has been fetched, and thus the old character will be lost. This is referred to as an overrun error and results in one or more lost characters.

A 16-byte FIFO allows up to 16 characters to be received before the computer has to service the interrupt. This increases the maximum bit rate the computer can process reliably from 9600 to 153,000 bit/s if it has a 1 millisecond interrupt dead time. A 32-byte FIFO increases the maximum rate to over 300,000 bit/s. A second benefit to having a FIFO is that the computer only has to service about 8 to 12% as many interrupts, allowing more CPU time for updating the screen, or doing other chores. Thus the computer’s responses will improve as well.

See also[edit]

  • Automatic baud rate detection
  • Baud
  • Bit rate
  • Comparison of synchronous and asynchronous signalling
  • Crystal oscillator frequencies
  • MIDI
  • Synchronous serial communication

References[edit]

  1. ^ Adam Osborne, An Introduction to Microcomputers Volume 1: Basic Concepts, Osborne-McGraw Hill Berkeley California USA, 1980 ISBN 0-931988-34-9 pp. 116–126
  2. ^ «Determining Clock Accuracy Requirements for UART Communications» (PDF). an2141. Maxim Integrated. 2003-08-07. Retrieved 1 November 2021.
  3. ^ a b «Universal asynchronous receiver/transmitter (UART)» (PDF). SCC2691. Philips NXP. 2006-08-04. p. 14. Retrieved 1 November 2021.{{cite web}}: CS1 maint: url-status (link)
  4. ^ a b C. Gordon Bell, J. Craig Mudge, John E. McNamara, Computer Engineering: A DEC View of Hardware Systems Design, Digital Press, 12 May 2014, ISBN 1483221105, p. 73
  5. ^ Allison, David. «Curator, Division of Information Technology and Society, National Museum of American History, Smithsonian Institution». Smithsonian Institution Oral and Video Histories. Retrieved 14 June 2015.
  6. ^ Oral History of Gordon Bell, 2005, accessed 2015-08-19
  7. ^ Technical Reference 6025008 (PDF). Personal Computer Hardware Reference Library. IBM. August 1981. pp. 2–123.
  8. ^ «FTDI Products». www.ftdichip.com. Retrieved 22 March 2018.
  9. ^ Interfacing with a PDP-11/05: the UART, blinkenbone.com, accessed 2015-08-19
  10. ^ «Zilog Product specification Z8440/1/2/4, Z84C40/1/2/3/4. Serial input/output controller» (PDF). 090529 zilog.com
  11. ^ «Zilog Document Download» (PDF). www.zilog.com. Retrieved 22 March 2018.
  12. ^ «FAQ: The 16550A UART & TurboCom drivers 1994». Retrieved January 16, 2016.
  13. ^ T’so, Theodore Y. (January 23, 1999). «Re: Serial communication with the 16650». The Mail Archive. Retrieved June 2, 2013.
  14. ^ bill.herrin.us — Hayes ESP 8-port Enhanced Serial Port Manual, 2004-03-02

Further reading[edit]

  • Serial Port Complete: COM Ports, USB Virtual COM Ports, and Ports for Embedded Systems; 2nd Edition; Jan Axelson; Lakeview Research; 380 pages; 2007; ISBN 978-1-931-44806-2.
  • Serial Port Complete: Programming and Circuits for RS-232 and RS-485 Links and Networks; 1st Edition; Jan Axelson; Lakeview Research; 306 pages; 1998; ISBN 978-0-965-08192-4.
  • Serial port and Microcontrollers: Principles, Circuits, and Source Codes; 1st Edition; Grzegorz Niemirowski; CreateSpace; 414 pages; 2013; ISBN 978-1-481-90897-9.
  • Serial Programming (Wikibook).

External links[edit]

  • FreeBSD Serial and UART Tutorial, includes standard signal definitions, history of UART ICs, and pinout for commonly used DB25 connector.
  • UART Tutorial for Robotics, contains many practical examples.

JanJansen

Super Member

  • Total Posts : 530
  • Reward points : 0
  • Joined: 2012/08/25 03:26:34
  • Location: 0
  • Status: offline

Hi, i am getting framing errors with serial communication ( for MIDI ).
Why do i get a frame error ?, because of a unexpected stop bit says the manual.

 It all works good, only i keep repeated framing errors.
Someone told me that my interrupt takes to long, that might cause the framing error,
can anyone explain to me why ?

 thanks in advance

jtemples

عُضْوٌ جَدِيد

  • Total Posts : 12049
  • Reward points : 0
  • Joined: 2004/02/13 12:31:19
  • Location: Southern California
  • Status: offline

Re: Understanding why framing error (EUSART)


2015/03/07 11:15:48

(permalink)

Framing errors are usually caused by a baud rate mismatch between the UART and the received data.

Someone told me that my interrupt takes to long, that might cause the framing error

 That is not correct.  If you fail to read the UART quickly enough, that can cause an overrun error, but not a framing error.

ric

Super Member

  • Total Posts : 35935
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online

Re: Understanding why framing error (EUSART)


2015/03/07 15:17:16

(permalink)

I agree with everything jtemples just said.

JanJansen
Why do i get a frame error ?, because of a unexpected stop bit says the manual.

That is precisely the reason. A «framing error» means that the USART saw a low when it was expecting a high (in the middle of the STOP bit pulse).
This means one of:
[1] Your baud rate at sender and receiver are very different, so the receiver (i.e. the PIC) is sampling each bit earlier and earlier, so it sometimes sees the end of the 8th bit instead of the middle of the stop bit.
[2] Your sender is sending 9 bits of data, not 8. This could be if it is set to send 8 data bits + a parity bit.
[3] You have a lot of noise on the signal.

I also post at: PicForum
To get a useful answer, always state which PIC you are using!

JanJansen

Super Member

  • Total Posts : 530
  • Reward points : 0
  • Joined: 2012/08/25 03:26:34
  • Location: 0
  • Status: offline

Re: Understanding why framing error (EUSART)


2015/03/08 07:50:30

(permalink)

Thanks,
only i dont understand why :
1 start bit is correct, 3 x 8 bit data is correct,
why would a stop bit be incorrect ?

DarioG

Allmächtig.

  • Total Posts : 54081
  • Reward points : 0
  • Joined: 2006/02/25 08:58:22
  • Location: Oesterreich
  • Status: offline

Re: Understanding why framing error (EUSART)


2015/03/08 09:29:57

(permalink)

What are «3×8 bit data»? No start/stop in between??

JanJansen

Super Member

  • Total Posts : 530
  • Reward points : 0
  • Joined: 2012/08/25 03:26:34
  • Location: 0
  • Status: offline

Re: Understanding why framing error (EUSART)


2015/03/08 09:34:54

(permalink)

1and0

Access is Denied

  • Total Posts : 15919
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry’s Gray Matter
  • Status: offline

Re: Understanding why framing error (EUSART)


2015/03/08 09:59:42

(permalink)

JanJansen
only i dont understand why :
1 start bit is correct, 3 x 8 bit data is correct,
why would a stop bit be incorrect ?

Each UART frame consists of 1 start bit, 8 or 9 data bits, and 1 stop bit.

Можно с уверенностью сказать, что с момента публикации первой версии стандарта RS‑232 в мае 1960 года и по настоящее время, было написано приблизительно 109 независимых реализаций UART на всём, чём угодно. Однако, подобно «Hello world» в мире прикладного ПО, а также мигания светодиодом — «Hello world» в мире цифровой электроники (сигнализирующий об успешной настройке оборудования и среды разработки) — процесс написания UART способен проиллюстрировать особенности языка или платформы, демонстрируя применение тех или иных синтаксических конструкций для решения практических, насущных и понятных проблем.

В данном цикле статей будет рассказано про написание модуля UART на SystemVerilog, про синтез данного модуля на различных платформах и про некоторые другие аспекты применения UART в ПЛИС. Но прежде, чем писать код, поговорим про сам протокол и про особенности аппаратной части вне контекста ПЛИС.

RS-232

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

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

Правда, без дополнительных условий будет невозможно отправить байт, состоящий из одних единиц, либо отличить последовательность 11010100 от 01010011.

Можно условиться, что к каждому передаваемому байту мы припишем дополнительный служебный бит (старт-бит), заведомо содержащий логический ноль. Тогда после паузы в передаче данных, приёмник при получении нисходящего фронта будет готов к приёму оговоренного количества бит, содержащих осмысленные данные.

Остаётся проблема: что, если будет передаваться длинная последовательность бит, содержащих нулевые значения без пауз между отдельными байтами? Тогда, рано или поздно, накопленная рассинхронизация тактовых генераторов источника и приёмника превысит половину длительности одного бита. И приёмник либо дважды прочитает один и тот же передаваемый бит, либо наоборот, пропустит один из передаваемых битов.

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

Договорившись о наличии старт-бита, стоп-битов, количестве битов данных в рамках одной передачи («символа» в терминологии UART) от старт-бита до стоп-бита и частоте следования бит можно организовать устойчивую однонаправленную передачу данных по одному проводу.

Стандарт RS-232 задаёт значение выходного напряжения логической единицы от −5 до −15 В, а логического нуля — от +5 до +15 В (именно в таком порядке). Данные уровни напряжения не поддерживаются микросхемами ПЛИС напрямую и существует несколько вариантов соединения ПЛИС с компьютером через RS‑232.

Если у компьютера предусмотрен com-порт, то соединение возможно при помощи пассивного кабеля и транслятора уровней. Зачастую трансляторы уровней для RS‑232 (к примеру, ADM3232E) изготавливают с встроенным умножителем (удвоителем) напряжения на основе переключаемых конденсаторов. Он преобразует +3,3 В в приблизительно ±6,6 В, которые используются в качестве уровней выходного сигнала на линии TX. А вход RX делают устойчивым к напряжениям вплоть до ±15 В.

Если у компьютера отсутствует встроенный com-порт, то соединение возможно при помощи внешнего преобразователя USB-RS232 (к примеру, UPort1150).

В этом случае иногда происходит некоторая путаница с разъёмами. Если разъём DB-9 на материнской плате — всегда «папа» (штыри), то разъём на оборудовании почти всегда «папа». Исключение — прецизионные источники питания компании Keithley (которую купил Tektronix). У них разъём «мама» (гнёзда). Разъём же на преобразователях USB-RS232 почти всегда, как и на материнских платах — «папа». Соответственно, он может быть подключен к Keithley непосредственно. Но для большинства оборудования дополнительно потребуется кабель «мама-мама». Разъём DB-9 предусматривает наличие стягивающих винтов. И ввиду того, что их не расположить внутри корпуса оборудования, то ими оснащается именно кабель. А на разъёмах оборудования делают гайки, куда эти винты закручиваются.

У преобразователя MOXA - гайки, у noname - винты. И у обоих в разъёме - штыри.

У преобразователя MOXA — гайки, у noname — винты. И у обоих в разъёме — штыри.

И, казалось бы, если на преобразователях USB-RS232 стоит разъём «папа» (для соединения с «мамой» кабеля, оснащённого винтами), то на нём должны быть гайки. Однако, данный элемент с вероятностью 50/50 будет также винтом! Зато к Keithley подходит идеально :) В общем, если вы решили соединять оборудование с компьютером и хотите чтобы всё собралось с первого раза, не полагайтесь на то, что «всё стандартизовано, тут не ошибёшься» и обратите внимание:

  • на разъём в оборудовании и преобразователе (штыри/гнёзда)

  • на крепления в оборудовании и преобразователе (винты/гайки)

Электронная промышленность предоставляет широкую номенклатуру мостов 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, упоминаемый в подобном контексте, приобретает некоторые постмодернистские черты симулякра — символа, у которого нет оригинала :)

Возможно также соединить линии USB напрямую к ПЛИС и наделить ПЛИС функционалом, позволяющим ей опознаваться компьютером как USB-устройство класса CDC («Communication Device Class») — то есть как com-порт. Однако, тратить (и в весьма большом количестве!) логические элементы ПЛИС на столь обыденную задачу, реализованную в готовых микросхемах USB-UART имеет смысл только в рамках учебных задач, связанных с изучением протокола USB.

Работа над ошибками

Рассматривая аспекты, связанные с ошибками, возникающими при передаче данных через UART, можно выделить три группы:

  • нестабильности электрических параметров сигнала

  • нестабильности временных параметров сигнала

  • нарушение в логике приёма/передачи

Обсудим ряд аспектов, связанных с каждой из этих групп.

Мажорирование

Когда речь заходит про аппаратное исправление нестабильности электрических параметров, регулярно произносится слово «мажорирование». То есть многократное (обычно — троекратное) снятие показаний в пределах одного принимаемого бита и последующий выбор в качестве истинного значения принимаемого бита того, которое чаще других встретилось в ходе этих замеров.

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

Немного формул

Предположим, что ошибки в ходе замеров являются независимыми друг от друга и появляются с вероятностью «p». Выпишем в таблицу все 8 возможных комбинаций 3-битного числа. Но вместо единиц в ячейках таблицы запишем вероятность ошибки в конкретном замере («p»), а вместо нулей — вероятность верного считывания («1-p»). Вероятность появления каждой комбинации будет равна произведению содержимого ячеек соответствующего столбца. Поэтому отметим те комбинации, которые всё же приведут к ошибочному считыванию бита при мажорировании, определим вероятности появления этих комбинаций и сложим их всех.

Как видно, вероятность ошибки при мажорировании будет равна:

p_{maj}=p^3+3(p^2(1-p))

Или, если раскрыть скобки и упростить выражение, то:

p_{maj}=3p^2-2p^2

Пока что влияние мажорирования может просматриваться не слишком явно. Для более чёткой картины возьмём десятичный логарифм «pmaj»:

log_{10}(3p^2-2p^3)

Преобразуем это выражение. Для начала вынесем за скобки логарифмируемого выражения квадрат «p»:

log_{10}{(p^2(3-2p))}

Затем заменим произведение логарифмируемого выражение на сумму логарифмов:

log_{10}(p^2)+log_{10}(3-2p)

С уменьшением «p», второе слагаемое (второй логарифм) достаточно быстро будет стремиться к десятичному логарифму трёх, который равен 0,477 (так, при «p» равном 10-2 (одна ошибка на сто бит) это слагаемое уже будет равно 0,474).

Иными словами, если вероятность ошибки равна:

p=10^x

…то вероятность ошибки с использованием мажорирования по трём замерам приблизительно равна:

p_{maj}≈10^{2x+0,477}

Здесь «x» по идее должен принимать значения от «0» до «-∞», но при приближении к нулю (то есть при приближении «p» к единице) начнут сказываться допущения. Однако уже при «x», равном «-1» (то есть одна ошибка на десять бит), приближённые значения будут отличаться от точных значений всего на 2%.

Представим, что происходит передача данных по 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»:

p=p_{noise}frac{t_{noise}}{T}

Одинаковую вероятность ошибки может создать как длительная, но редкая помеха, так и короткая, но часто повторяющаяся помеха. Однако, часто повторяющуюся помеху («pnoise» которой много больше, чем собственно «p») будет легче обнаружить, проанализировать и выявить её источник. А редко повторяющаяся помеха, та, от поиска которой, по идее, и должно защитить мажорирование, будет длительной помехой, способной в ряде случаев «накрыть» сразу несколько замеров.

В общем, методы коррекции ошибок, применяемые бездумно, способны как решить проблему, так и в отдельных случаях оказаться заметанием мусора под ковёр или вообще не сработать.

Оверсемплинг

Представим, к примеру, ардуиновский микроконтроллер ATmega328P. В нём битрейт модуля USART задаётся при помощи делителя «UBRR» (он записывается в регистры «UBRRnL» и «UBRRnH») и равен:

BAUD=frac{f_{osc}}{16(UBRR-1)}

Допустим, частота fOSC равна 10 МГц, а нам требуется получить стандартные 9600 бит/с. Тогда наиболее подходящим значением UBRR будет «64». Благодаря ему удастся задать битрейт, равный 9615,4 бит/с. Погрешность в 0,16% кажется незначительной, однако она накапливается с каждым битом. И для последнего фронта в символе составит 1,44%.

Точность внутреннего RC-генератора для того же микроконтроллера ATmega328P при фиксированной температуре в 25°C и напряжении 3,0 В заявлена ±2%. Во всём диапазоне рабочих температур и напряжений заявленная точность генератора падает до крайне грубых ±14%. Но ниже мы будем отталкиваться от первой цифры.

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

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

Решением этой проблемы является многократное считывание логического состояния на линии RX — оверсемплинг. После первого считывания, результат которого может быть принят за старт-бит, приёмник ожидает половину битового периода и только начиная с этого момента приступает к считыванию бит через равные промежутки времени. При четырёхкратном чтении, ошибки передачи будут отсутствовать при общей временно́й погрешности, доходящей до 25%!

На этом месте может возникнуть пара вопросов:

  • Какова временная погрешность приёмопередатчиков 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 гарантированно ненадёжных семпла.

Подобная конструкция не представляется такой уж надёжной. Поэтому, к примеру, в STM32F103 коррекция ошибок (мажорирование по восьмому, девятому и десятому семплам бита), дополнена механизмом сигнализация об их наличии.

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

Ошибки логики

Является ли ошибкой отсутствие стоп-бита? То есть если был передан старт-бит, затем оговоренные N бит данных, а после этого стоп-бит не появился (линия вместо стоп-бита оказалась в состоянии логического нуля)? Не всегда. Так, стандарт «ANSI E1.11», описывающий протокол обмена данными светотехнического оборудования DMX512, похожий на классический UART, использует при передаче данных аналогичное действие. При номинальной длительности бита DMX512 равной 4 мкс, переход в логический ноль и последующее удержание этого состояния в течение 92 мкс (то есть 23 нулевых бита подряд) или более, называется «break» и маркирует начало очередного пакета данных.

Однако, в общем случае, если передаваемый символ состоял не только из нулей, отсутствие стоп-бита будет, пожалуй, именно ошибкой — «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. Их детальный обзор — в следующей статье.

Понравилась статья? Поделить с друзьями:
  • U9n ошибка старлайн
  • U9n ошибка сигнализации starline
  • U3fff ошибка ssangyong kyron
  • U3fff ошибка mitsubishi outlander
  • U3fff ошибка mitsubishi colt