Вот некоторая информация по программированию основных портов, которые можно использовать для ввода/вывода на устройствах общего назначения (TTL или CMOS).
Если вы хотите использовать эти или другие порты по их непосредственному назначению (напр. для управления принтером или модемом), лучше всего использовать существующие драйвера (которые обычно включены в ядро) вместо того, чтобы работать с портами так, как это описано в этом HOWTO. Этот раздел предназначен для людей, желающих подключить ЖК-индикатор, шаговый двигатель или другую электронику к стандартным портам компьютера.
Если вы хотите работать с таким распространенным устройством, как сканер, сначала поищите для него драйвер под Linux. Начать лучше всего с Hardware-HOWTO.
http://www.hut.fi/Misc/Electronics/
Основной адрес параллельного порта (далее "БАЗА") - 0x3bc для /dev/lp0, 0x378 для /dev/lp1 и 0x278 для /dev/lp2. Если вы хотите управлять чем-то вроде обычного принтера, см. Printing-HOWTO.
В дополнение к стандартному режиму только вывода, описываемому ниже, в большинстве параллельных портов существует `расширенный' двунаправленный режим. Для дополнительной информации по этому и более новому режиму ECP/EPP (и стандарт IEEE 1284 в общих чертах), см. http://www.fapo.com/ и http://www.senet.com.au/~cpeacock/parallel.htm. Только помните, что вы не можете в ваших программах использовать IRQ и DMA, и для использования ECP/EPP. Вам скорее всего придется написать свой драйвер ядра; хотя, я думаю, что кто-нибудь уже написал его.
Порт БАЗА+0 (Порт данных) соответственно управляет сигналами данных на параллельном порту (от D0 до D7 для битов от 0 до 7, соответствуют значения: 0 = 0В, 1 = 5В). Запись в этот порт устанавливает соответствующие уровни напряжения на контактах разъема принтера. При чтении возвращается последнее записанное значение в стандартном или расширенном режиме записи, или данные на разъеме от другого устройства в расширенном режиме чтения.
Порт БАЗА+1 (Порт состояния) предназначен только для чтения и возвращает следующие входные сигналы:
Биты 0 и 1 зарезервированы.
Бит 2 состояние IRQ (его нет на разъеме и я не знаю как он работает)
Бит 3 ERROR (1=ОШИБКА)
Бит 4 SLCT (1=ВЫБОР)
Бит 5 PE (1=ГОТОВ)
Бит 6 ACK (1=ПОДТВЕРЖДЕНИЕ)
Бит 7 -BUSY (0=ЗАНЯТ)
Порт БАЗА+2 (Порт управления) предназначен только для записи (чтение возвращает последнее записанное значение) и управляет следующими сигналами:
Bit 0 -STROBE (0=СТРОБ)
Бит 1 AUTO_FD_XT (1=АВТО_ПЕРЕВОД_СТРОКИ)
Бит 2 -INIT (0=СБРОС)
Бит 3 SLCT_IN (1=ВЫБРАН)
Бит 4 включает IRQ параллельно порта (которое возникает при изменении ACK с нуля на еденицу) (1=IRQ включено).
Бит 5 управляет направлением работы порта в расширенным режиме (0 = запись, 1 = чтение) и предназначен только для записи (чтение не возвращает ничего полезного).
Биты 6 и 7 зарезервированы.
Разводка (25-разъемный разъем (мама)) (i=ввод, o=вывод):
1io -STROBE, 2io D0, 3io D1, 4io D2, 5io D3, 6io D4, 7io D5, 8io D6, 9io D7, 10i ACK, 11i -BUSY, 12i PE, 13i SLCT, 14o AUTO_FD_XT, 15i ERROR, 16o -INIT, 17o SLCT_IN, 18-25 Ground |
Спецификация IBM говорит, что контакты 1, 14, 16 и 17 (управляющий вывод) подключены через открытый коллектор на 5В через резистор 4.7 КОм (рабочий ток 20 mA, холостой 0.55 mA, рабочее напряжение 5.0 В). Остальные контакты дают рабочий ток 24 mA, холостой 15 mA, и рабочее напряжение 2.4 В. В низком состоянии оба они дают максимум 0.5 В. Параллельный порты не-IBM могут отличаться от этого стандарта. Для дополнительной информации см. http://www.hut.fi/Misc/Electronics/circuits/lptpower.html.
И наконец, предупреждение: будьте осторожны с заземлением. Я сжег несколько параллельных портов, подключая принтеры к ним при включенном компьютере. Для таких случаев лучше всего использовать параллельный порты, не встроенные в материнскую плату. (Обычно вы можете установить второй параллельный порт при помощи дешевой `мультикарты'; просто отключите порты, которые вам не нужны, и установить адрес параллельного порта на карте на любой свободный адрес. Вам не нужно заботится о IRQ параллельного порта, если только он используется другим устройством)
Игровой порт находится по адресам 0x200-0x207. Для управления обычным джойстиком существует драйвер на уровне ядра. См. ftp://sunsite.unc.edu/pub/Linux/kernel/patches/ , имя файла joystick-*.
Разводка (15-контактный разъем (мама)):
1,8,9,15: +5В (питание)
4,5,12: Земля
2,7,10,14: Цифровые входы BA1, BA2, BB1 и BB2, соответственно
3,6,11,13: ``Аналоговые'' входы AX, AY, BX и BY, соответственно
Контакты +5В обычно подключены прямо к питанию материнской платы и не обеспечивают большую загрузку (в зависимости от материнской платы, блока питания и игрового порта).
Цифровые входы используются для определения состояния кнопок на двух джойстиках (джойстик A и джойстик B, по две кнопки на каждом), подключаемых к порту. Это должны быть обычные входы TTL, и вы можете считывать их состояние непосредственно из регистра состояния (см. ниже). Обычные джойстики устанавливают ноль (0В), при нажатой кнопке, и единицу (5В от питания через резистор 1КОм), в противном случае.
Так называемые аналоговые входы, на самом деле, измеряют сопротивление. Игровой порт имеет четыре одноимпульсных мультивибратора, подключенных к четырем входам. На каждом входе стоит резистор 2.2КОм между выходом мультивибратора и землей. Обычные джойстики имеют потенциометр по каждой оси (X и Y), связанный с +5В и соответствующим входным контактом (AX или AY для джойстика A, и BX или BY для джойстика B).
Во время включения, мультивибратор устанавливает напряжение +5В и ждет, когда напряжение на конденсаторе достигнет 3.3В, а затем сбрасывает напряжение. Таким образом, длительность импульса мультивибратора прямопропорциональна сопротивлению потенциометра на джойстике (т.е. положению джойстика по соответствующей оси): "R = (t - 24.2) / 0.011," где R - сопротивление (Ом) потенциометра, а t - длительность импульса (секунд).
Таким образом, чтобы считать состояние аналогового входа, сначала нужно включить мультивибратор (путем записи в порт; см. ниже), а затем считывать состояние всех четырех осей, пока они сбросятся с 1 на 0, измеряя длительность сигнала. Такое считывание требует много процессорного времени и на многозадачных операционных системах, таких как Linux (для пользовательских программ), результат будет не очень точен, т.к. вы не можете считывать из порта постоянно (если только не используете драйвер на уровне ядра и отключаете прерывания, что, впрочем, требует еще больше процессорного времени). Если вы знаете, что сигнал будет продолжаться достаточно долгое время (десятки миллисекунд), вы можете использовать usleep() перед считыванием, передав процессорное время другим процессам.
Вам нужно использовать только один порт - 0x201 (другие порты идентичны или вообще ничего не делают). Любая запись в этот порт (не важно, что вы записываете) включает мультивибратор. Чтение из порта возвращает состояние входных сигналов:
Бит 0: AX (состояние на выходе мультивибратора)
Бит 1: AY (состояние на выходе мультивибратора)
Бит 2: BX (состояние на выходе мультивибратора)
Бит 3: BY (состояние на выходе мультивибратора)
Бит 4: BA1 (цифровой вход)
Бит 5: BA2 (цифровой вход
Бит 6: BB1 (цифровой вход)
Бит 7: BB2 (цифровой вход)
Если устройство, с которым вы хотите общаться, поддерживает что-то похожее на RS-232, вы можете использовать последовательный порт. Драйвер Linux для последовательного порта должен быть достаточен для всех приложений (вам не нужно иметь непосредственный доступ к порту, или же для этого нужно написать драйвер ядра); он достаточно универсален, т.к. использует нестандартные скорости обмена и т.д., так что у вас не должно быть проблем.
Для дополнительной информации см. руководство termios(3), исходные тексты драйвера (linux/drivers/char/serial.c), и http://www.easysw.com/~mike/serial/index.html.