Занимательная микроэлектроника — страница 83 из 117

уют трехпроводного соединения (включая «землю»), однако различаются по назначению линий.

В RS-232 передача каждого байта всегда сопровождается начальным (стартовым) битом, который служит для синхронизации. После него идут восемь (или девять — при проверке на четность) информационных битов, а затем стоповые биты, которых может быть один, два и более, но это уже не имеет принципиального значения (почему — мы сейчас увидим).

Общая диаграмма передачи таких последовательностей показана на рис. 16.1.



Рис. 16.1. Диаграмма передачи данных по последовательному интерфейсу RS-232 в формате 8n2


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

Подробности

Подавляющую часть времени линия находится в состоянии ожидания, т. е. имеет уровень логической единицы (отрицательный — этим фактом мы воспользуемся в главе 18 для создания простейшего преобразователя уровней.) Потому выбор уровней стартового и стопового бита не был полностью произвольным: такая комбинация уровней имеет большой смысл со схемотехнической точки зрения. Во-первых, в качестве преобразователя уровня удобно использовать транзистор, который инвертирует сигнал, и тогда специально об этом думать не приходится. Во-вторых, со стороны UART, где логика обратная, столовый бит должен иметь высокий уровень, что соответствует состоянию запертого транзистора «с открытым коллектором» (или «с открытым истоком»). Так как большую часть времени этот выходной транзистор оказывается выключен, то вывод не потребляет тока.

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

Обычный формат данных, по которому работает львиная доля всех устройств, обозначается 8n1, что читается так: 8 информационных бит, no parity, столовый бит. «No parity» означает, что проверка на четность не выполняется. На диаграмме рис. 16.1 показана передача некоего произвольного кода, а также передача байтов, состоящих из всех единиц и из всех нулей в формате (для наглядности) 8n2. А в каком случае это важно, два стоповых бита передается или один (ведь, по сути, в состоянии линии при этом ничего не меняется)?

Задание минимального числа стоповых битов производится для того, чтобы приемник «знал», сколько времени минимально ему нужно ожидать следующего стартового бита (как минимум, это может быть, естественно, один период частоты обмена, т. е. один столовый бит). Если по истечении этого времени стартовый бит не придет, приемник может регистрировать так называемый timeout, т. е. «перерыв», по-русски, и заняться своими делами. Мы никакими «тайм-аутами» себе голову заморачивать здесь не будем (передача одного байта с нашими скоростями будет занимать порядка миллисекунды, и за это время мы успеем перехватить данные даже без использования прерывания), и нам в принципе все равно, сколько стоповых битов будет. Но во избежание излишних сложностей следует их устанавливать у передатчика и у приемника всегда одинаково. Заметим, что если линия «зависнет» в состоянии логического нуля (высокого уровня напряжения), то это может восприниматься устройством, как состояние «обрыва» линии — не очень удобный механизм, и в микроконтроллерах он через UART не поддерживается.

Из описанного алгоритма работы понятно, что погрешность несовпадения скоростей обмена может быть такой, чтобы фронты не «разъезжались» за время передачи/приема всех десяти-двенадцати бит бóлее чем на полпериода, т. е. в принципе фактическая разница частот тактовых импульсов может достигать 4–5 %. На практике их стараются все же сделать как можно ближе к стандартным величинам, но это не всегда возможно.

Заметки на полях

А какова надежность при передаче таким способом? Приемник RS-232 дополнительно снабжают схемой, которая фиксирует уровень не один раз за период действия бита, а трижды, при этом за окончательный результат принимается уровень двух одинаковых из трех полученных состояний линии, таким образом удается избежать случайных помех. Дополнительная проверка целостности данных (контроль четности) и/или программные способы (вычисление контрольных сумм и т. п.) нам не потребуется, т. к. скорости обмена малы и ошибки маловероятны. Данные о разновидностях соединительных кабелей вы найдете в главе 18.

Для работы в обе стороны нужны две линии, которые у каждого приемопередатчика обозначаются RxD (приемная) и TxD (передающая). В каждый момент времени может работать только одна из линий, т. е. приемопередатчик либо передает, либо принимает данные, но не одновременно (это т. н. полудуплексный режим — так сделано потому, что у UART-микросхем традиционно один регистр и на прием, и на передачу).

Замечание

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

Кроме RxD и TxD, в разъемах RS-232 присутствуют также и другие линии,

о чем подробнее мы поговорим в главе 18. Отметим, что специально устанавливать состояния выводов порта (на вход или на выход), которые используются, как TxD и RxD, не требуется, как только вы «заведете» UART, они автоматически сконфигурируются, как надо. Только, в отличие от выводов программирования, их не рекомендуется задействовать еще для каких-то функций.

В AVR семейства Tuny (кроме модели 2313, которая все же, если позволительно так выразиться, «не совсем» Tuny) UART отсутствует, а в большинстве моделей семейства Mega этот порт реализован в виде более функционального USART («синхронно-асинхронного»), в некоторых моделях их даже несколько. USART полностью совместим с UART (кроме наименований некоторых регистров), и отличается от UART тем, что, во-первых, может самостоятельно обрабатывать девятибитовые посылки с контролем четности (не требуя программной реализации этого контроля), во-вторых, может иметь длину слова от 5 до 9 бит (UART только 8 или 9). Самое же главное его отличие (из-за которого он и получил свое название) в том, что его можно использовать в синхронном режиме, передавая по специальной дополнительной линии ХСК тактовые импульсы (в результате чего USART почти перестает отличаться от SPI, кроме того, что последний может работать значительно быстрее). Еще одна особенность USART — возможность работы в режиме мультипроцессорного обмена. Мы все эти режимы применять не будем, потому в дальнейшем будем вести речь только о UART, т. е. о работе в асинхронном режиме.


Прием и передача данных через UART

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

;для семейства Classic при частоте 4 МГц

    ldi temp,25  ;скорость передачи 9600 при 4 МГц

    out UBRR,temp  ;устанавливаем

   ldi temp, (1<

       out UCR,temp  ;разрешение приема/передачи 8 бит

Число BAUD для делителя частоты (в данном случае 25) можно определить из таблиц, которые имеются в каждом описании соответствующего контроллера (там же приводится и ошибка для выбранного значения частоты), или рассчитать по формуле: BAUD = fpeз/16(UBRR+1). Для семейства Mega процедура несколько усложняется, потому что регистров в USART больше:

;для семейства Меда при частоте 16 МГц

   ldi temp,103  ;9600 при 16 МГц

out UBRRL,temp

        ldi temp,(1<  ;разрешение приема/передачи

     out UCSRB,temp

        ldi temp,(1<  ;формат 8n1

  out UCSRC,temp

Чем выше тактовая частота МК /рез, тем точнее может быть установлена скорость. При частоте кварца 4 МГц мы с приемлемой точностью можем получить скорости обмена не более 28 800 бод. Правда, при выборе специального кварца (например, 3,6864 МГц) можно получить с нулевой ошибкой весь набор скоростей вплоть до 115 200, но зато для других целей такие частоты неудобны. Для получения скоростей передачи выше указанных (стандартно COM-порт позволяет установить скорости, как указано ранее до 256 кбод) придется увеличивать частоту. Так, при кварце 8 МГц и общем коэффициенте деления, равном единице, мы получим скорость 250 000, что отличается от стандартных 256 000 на приемлемые 2,4 %.

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

С UART связаны прерывания, причем в силу важности предмета тут их аж целых три: «передача завершена» (ТХ Complete), «регистр передатчика пуст» (ТХ UDR Empty) и «прием завершен» (RX Complete). Для их использования можно поступить следующим образом (примеры приведены для семейства Classic). Сначала вы инициализируете прерывание «прием закончен» (для чего надо установить бит