Введение

PC-ОС

БП

Дисплей

Координатор

Интерфейс rs232: общие соображения

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

Вообще-то, сначала я планировал, по старой памяти, использовать для связи компа и контроллера индикатора lpt-порт. Вроде как там все понятно - ТТЛ-уровни, битиком дернул - лапка прыгнула. Лапку дернул - битик прыгнул. Linux не поощряет использование прямого доступа к аппаратуре из пользовательских программ, но и не запрещает этого. Интересующиеся да вспомнят функцию iopl.

Но постепенно, по мере отладки, пришло понимание того, что либо нужно реализовывать протокол вроде i2c с двумя мастерами (инициировать обмен может любая сторона - контроллер при появлении кода с ИК-пульта, ПЭВМ при желании что либо вывести) либо иметь приличные задержки и хоть слабую, но привязку к реальному времени, что легко реализуется в контроллере, но не пользовательской программе под многозадачной ОС. Да и насчет задержек тоже возникли разные мысли - p166 легко декодирует музыку, но это пока его не тормозят наглыми пустыми циклами. В общем, прототип блока индикации с таким интерфейсом работал, но по мере отладки становилось понятно, что com-порт куда как перспективнее.

У него есть только две проблемы: физически канал использует не ТТЛ-уровни сигнала, а кроме того - я еще не пробовал им пользоваться :). Смешно сказать - но все оказалось очень просто и эффективно.

ТТЛ преобразовать в уровни +-12в можно двумя путями - правильным и неправильным. Правильный путь - это полная конверсия - реализуется либо специальной микросхемой либо дискретной схемой объемом около 4-6 транзисторов на бит. Требований много: недопустимо разрушение передатчика при коротком замыкании выходной шины, уровни должны фиксироваться на входе как определенные в диапазоне 3..12в любого знака (вне этого диапазона логическое значение бита не определено) и в аналогичном диапазоне удерживаться на выходе, входной ток не более, выходной - не менее и т.д.. Но те, кто работал с эти интерфейсом, знают, что скользкое место в диапазоне 0..+3в большинством приёмников, стоящих в ПЭВМ, определяется как '1'. А это значит, что достаточно просто проинвертировать выходной сигнал (т.е. пусть он будет 0в в случае '1' и > 3в случае '0') и также проинвертировать (но не допустив выгорания входного транзистра приёмника при уровнях +-12в !) входной сигнал - и получится, хоть и неправильная, но вполне работоспособная схема согласования - rs232 <-> ТТЛ:

Транзисторы в приведённой схеме - любые маломощные, кт315, например. Резисторы могут быть выбраны в весьма большом диапазоне. Например, в другом устройстве я использовал 4,7 кОм.

Существует более правильная, но требующая двойного питания (+12 и -12 в) схема (её использовали в ПЭВМ "Агат-7"):

Последний вариант существует также в интегральном исполнении и носит номер 75232. Есть легенда, что если к 75232 прицепить конденсаторный преобразователь напряжения +5в -> +-12в получится ещё один, реально существующий, интегральный преобразователь. Но его номер я не знаю. Может быть MAX232 ?

Еще одна проблема, с которой я столкнулся, была в том, что выводы аппаратного приёмо-передатчика контроллера были уже использованы (т.е. была собрана плата, где эти лапки были подключены к другим участкам схемы и переделывать "железо" уже не хотелось). Нужно было реализовать програмный com-порт. Это не сложно, но удобство аппаратного порта в том, что для его работы требуется меньший объём програмного кода и меньше процессорного времени (кроме того, часто аппаратный порт предусматривает цифровое подавление помех. Пользы в плейере вроде не много... но в других конструкциях это следует иметь ввиду). Однако и здесь выяснилась любопытная деталь: как известно, частота синхронизации последовательных передатчиков обычно (и в PC-компьютере и в AT89C2051) образуется путем деления некоей опорной частоты на постоянный коэффициент. Чем значение коэффициента выше, тем частота синхронизации ниже, скорость обмена тоже снижается, но вместе с тем возрастает и количество вариантов согласования двух устройств по скоростям. С другой стороны, на более низкой скорости при использовании программного порта без прерываний, существенно возрастает потребление процессорного времени на единицу переданной информации (задержки между битами - пустой цикл). Отсюда любопытный вывод: при низкой скорости обмена предпочтительнее аппаратный порт, а при высокой - программный - он позволяет более гибко подстраивать скорость обмена. Это не аксиома, но для используемого мной контроллера, кварцев и допустимых скоростей со стороны PC - очень похоже на правду.

Программный com-порт (со стороны контроллера)

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

InData = P3.3, OuData = P3.4, скорость обмена - 57600 бит/с.

;
; Обработчик прерываний внешней связи (получение байта по rs232)
; Эта процедура при вызове пытается получить байт по rs232, после
; чего сразу возвращает управление. Стоп-бит програмно не анализируется.
; В случае помех на линии будет считан неверный байт, но при отсутствии
; помех, благодаря фиксированной длительности приема байта, схема
; вновь синхронизуется.
;
.org	0x013
 jb	InData, INT1_2	; Если на входе "1" - это потерянное прерывание (т.е. фактически данных сейчас нет)
 push	PSW
 push	ACC

 mov	R6, #8		; Сейчас на линии должен быть 0 - он вызывает это прерывание
 acall	WaitHBit	; Первой принимается синхро "0"
 jb	InData, INT1_3	; Тут еще должен продолжаться "0"
 acall	WaitHBit	; Два полупериода

INT1_1:
 acall	WaitHBit	; Ожидаем один полупериод, чтобы начать считывание в середине
 mov	C, InData
 rrc	A
 acall	WaitHBit	; Еще полпериода, чтобы дождаться начало следующего бита
 djnz	R6, INT1_1

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

 mov	RecvByte, A
 setb	RecvFlag

INT1_3:
 pop	ACC
 pop	PSW
INT1_2:
 reti

; Пауза длительностью в полбита: 17/2 мкс = 12 тактов

WaitHBit:	; 2 [+2]
 nop		; 1x6
 nop
 nop
 nop
 nop
 nop
 ret		; 2
======================================================================
;
; Отсылает полученный по IR байт по rs232 наружу
; Берем скорость 57600. Бит передается 17 мкс
; Эта процедура работает в контексте процедур получения данных
; от IR, поэтому прерывания блокированы
;
SendByte:
 mov	R4, #8
 mov	A, IRByte

 clr	OuData		; Первой передается синхро "0"
 acall	WaitBit

SB_1:
 rrc	A
 mov	OuData, C	; Теперь передаем 8 бит
 acall	WaitBit
 djnz	R4, SB_1

 setb	OuData		; Две завершающих "1"
 acall	WaitBit

; Пауза 17 мкс = 25 тактов

WaitBit:	; 2 [+4 на цикл SB_1]
 mov	R3, #8	; 1
W_2:
 djnz	R3, W_2	; 2
 ret		; 2

Код расчитан на использование кварца 18 027 800 Гц = такт 0.7 мкс (1 502 316.(6) Гц).

com-порт со стороны PC

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

Команда инициализации:


stty -F /dev/ttyS0 57600 raw

Владимир