Программирование последовательной асинхронной передачи данных

Татьяна Кривченко, Максим Алексеев ООО «ЭФО»

Источник: http://atmel.efo.ru/Articles/Atmel12.htm


1. Описание встроенного универсального асинхронного приемопередатчика AVR-микроконтроллеров

Для приема и передачи данных в асинхронном последовательном формате (рисунок 1) AVR-микроконтроллеры содержат универсальный асинхронный приемопередатчик (Universal Asynchronous Receiver and Transmitter – UART). Также этот периферийный узел называют адаптером последовательного канала. Отличительными особенностями его работы являются:

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

  • Способность работы в дуплексном режиме (одновременная передача и прием данных);

  • Возможность передавать как 8-и, так и 9-битные данные;

  • Фильтрация помех на входе путем многократного опроса каждого бита;

  • Аппаратная фиксация ошибок переполнения и кадрирования (ложный стоп-бит) при приеме данных;

  • Формирование трех различных прерываний с индивидуальными адресами векторов прерывания: при завершении передачи (TX Complete), при завершении приема (RX Complete) и при освобождении регистра данных передатчика (TX Data Register Empty).


Рисунок 1 – Асинхронный последовательный формат передачи данных

Рисунок 1 – Асинхронный последовательный формат передачи данных

На рисунке 2 и 3 приведены программные модели передатчика и приемника UART. Управление приемопередатчиком осуществляется посредством двух регистров: регистра статуса USR и регистра управления UCR. Регистр статуса USR доступен только по чтению и обеспечивает информацию о состоянии UART. Регистр управления UCR предназначен для задания режимов работы UART и доступен как по чтению, так и по записи.

Установка бит управления TXEN = 1 (Transmitter Enable) и RXEN = 1 (Receiver Enable) в регистре управления UCR разрешает соответственно передачу и прием данных по последовательному каналу. При этом выход передатчика и вход приемника соединяются с внешними выводами TXD и RXD AVR-микроконтроллера и настраиваются соответственно на выход и на вход независимо от установки бит в регистре направления данных порта DDRx. При этом вход RXD, как и обычный цифровой вход AVR, может быть привязан к шине питания при помощи внутреннего резистора. Управление подключением/отключением этого резистора осуществляется обычным для выводов AVR способом – программированием соответствующих бит в регистре PORTx. При сбросе TXEN и RXEN выводы TXD и RXD могут использоваться как обычные цифровые входы/выходы.

Формат асинхронной передачи (рисунок 1) позволяет после 8 бит данных передавать один служебный бит, который, например, может быть битом четности или дополнительным стоп-битом. В AVR-микроконтроллерах такой режим 9-битного обмена задается одновременно и для передачи, и для приема данных установкой бита СНR9 = 1 в регистре управления UCR.

Передатчик и приемник UART содержат по одному буферному регистру данных UDR (UART Data Register) (рисунок 2 и 3). Регистр данных приемника UDR и регистр данных передатчика UDR – это два физически раздельных регистра, имеющих один адрес в адресном пространстве регистров ввода/вывода. Процессор определяет, к какому физическому регистру осуществлять обращение по типу выполняемой операции. При выводе (команда OUT UDR, Rx) данные записываются в регистр данных передатчика UDR, а при считывании (команда IN Rx, UDR) выборка осуществляется из регистра данных приемника.

Передача в последовательный канал инициируется записью байта в регистр данных передатчика UDR (рисунок 2). Все остальные операции по преобразованию данных из параллельной формы в последовательную и формированию кадра передачи байта берет на себя передатчик UART. Он переписывает данные из регистра UDR в регистр сдвига передатчика, где к ним автоматически добавляются старт-бит, стоп-бит и, если установлен режим 9-битной передачи, бит TXB8 из регистра UCR.

Если в момент записи UDR регистр сдвига уже освободился от передачи предыдущего байта, то данные переписываются из UDR в регистр сдвига немедленно. В противном случае перепись осуществляется лишь после того, как стоп-бит передаваемого в настоящий момент байта появится на выводе TXD.

Когда данные посылаются в регистр сдвига из UDR, устанавливается бит UDRE (UART Data Register Empty) в регистре статуса USR (UART Status Register), что означает, что UART готов получить от процессора новый байт. Когда процессор записывает очередной байт в регистр данных UDR, флаг UDRE автоматически сбрасывается. Если же новые данные не будут записаны в UDR к тому времени, как закончится передача текущего байта из регистра сдвига, то дополнительно к установленному флагу UDRE устанавливается флаг окончания передачи TXC (TX Complete Flag) в регистре USR.

Рисунок 2 - Программная модель передатчика UART

Рисунок 2 - Программная модель передатчика UART

Приемник UART выполняет операции по преобразованию входных данных из последовательной формы в параллельную. Он производит предварительную выборку сигнала на входе RXD с частотой, в 16 раз большей скорости обмена

Когда линия последовательной передачи свободна (данные не передаются), она находится в состоянии логической «1». Выборка приемником логического «0» после того, как линия была свободна, интерпретируется как срез старт-бита и инициирует последовательность определения старт-бита. Приемник, считая от первой нулевой выборки, анализирует 8-ю, 9-ю и 10-ю выборки. При обнаружении двух или более логических «1» в этих трех выборках старт-бит воспринимается как импульсная помеха, и приемник начинает следить за следующим перепадом «1/0».

Если старт-бит фиксируется, то затем осуществляется распознавание бит данных, причем для каждого бита также анализируются три значения входного сигнала в выборках 8, 9 и 10, считая от начала бита. За истинное значение бита принимается логическое значение, которое появилось хотя бы в двух выборках. Такие значения, полученные в результате голосования, последовательно посылаются в регистр сдвига приемника.

При поступлении стоп-бита результатом голосования трех выборок должна быть логическая «1». Если обнаружены хотя бы два логических «0», устанавливается флаг ошибки кадрирования FE (Framing Error) в регистре USR. Независимо от того, выявлен или нет стоп-бит в конце цикла приема байта, данные посылаются в регистр данных приемника UDR (рисунок 3) и устанавливается флаг завершения приема RXC (Receive Complete) в регистре USR.

Если установлен 9-битный режим обмена, 9-й бит регистра сдвига приемника загружается в бит RXB8 регистра UCR.

Если символ принят регистром сдвига, а предыдущая посылка еще не считана из регистра данных приемника UDR, то устанавливается флаг переполнения OR (OverRun) в регистре USR. Это означает, что последний байт данных, принятый регистром сдвига, не мог быть передан в регистр данных приемника UDR и был потерян. Для выявления ошибок переполнения, которые могут возникать при высоких частотах передачи или при большой загрузке процессора, бит OR следует опрашивать после считывания регистра UDR. При этом состояние бита OR = 0 будет говорить, что между последними двумя байтами, считанными из UDR, не было потерь информации. Напротив, состояние бита OR = 1 информирует процессор о том, что между последним и предпоследним байтами, считанными из UDR, были безвозвратно потеряны один или более байт. Обработкой такой ситуации может быть, например, запрос на повторную передачу утерянных данных. После того, как в регистр UDR успешно запишутся подряд два байта, бит OR снова сбросится.

Рисунок 3 - Программная модель приемника UART

Рисунок 3 - Программная модель приемника UART

Для тактирования приемопередатчика UART AVR-микроконтроллеры содержат специализированный программно управляемый тактовый генератор, который является делителем системной тактовой частоты и задает скорость обмена в соответствии со следующим уравнением:

BAUD=fck/(16(UBRR+1))

где: BAUD – скорость обмена, бод; fck – частота тактового генератора микроконтроллера, МГц; UBRR – содержимое 8-битного доступного для записи регистра UBRR (0 - 255).

Таким образом, для задания скорости передачи или приема необходимо записать в регистр UBRR определенное числовое значение.

2. Программирование UART

Организация передачи и приема байт при помощи опроса флагов

При программировании UART в простейшем случае решаются три задачи: инициализация UART (задание режимов работы), организация приема данных и организация передачи данных.

Примером инициализирующей подпрограммы может быть следующая последовательность команд:

.def tmp =r20
Init_uart: ldi tmp,0b00011101 ;Инициализация UART
out UCR,tmp ;TXEN=1,RXEN=1,СРH9=1,TXB8=1
ldi tmp,25 ;9600 бит/c при fclk=4МГц
out UBRR,tmp
ret

Если микропроцессор использует последовательный канал для коротких однобайтных сообщений, то передавать и принимать данные можно, просто опрашивая флаги готовности передатчика и приемника UART. При передаче байта в последовательный канал все, что должен сделать процессор – дождаться установки флага готовности передатчика UDRE и записать затем передаваемый символ в регистр данных передатчика:

trans: sbis USR, UDRE ;Если бит UDRE в USR установлен, то пропустить cледующую команду
rjmp trans ;Вернуться на метку trans
out UDR, r15 ;Вывести в регистр данных передатчика UART содержимое r15
ret

Во время приема данных, очевидно, регистр данных приемника UART необходимо считывать лишь тогда, когда установлен флаг готовности RXC. Например:

receive: sbis USR, RXC ;Если бит UDRE в USR установлен, то пропустить следующую команду
rjmp receive ;Вернуться на метку receive
in r15, UDR ;Cчитать регистр данных приемника в r15
ret

Или, например, так:

receive: sbis USR, RXC ;Если бит RXC в USR установлен, то пропустить следующую команду
in r15, UDR ;Cчитать регистр данных приемника UART в r15
ret

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