Работа с последовательными портами
PC может содержать до четырех последовательных портов, также называемых адаптерами RS-232C. В PS/2 (кроме моделей 25 и 30) может быть до восьми таких адаптеров. В MS-DOS последовательные порты называются COMX , где X - номер порта. Работать с последовательными портами можно как с использованием BIOS (Basic Input-Output System), так и непосредственно через использование аппаратных прерываний.
В BIOS для работы с последовательными портами выделено специальное прерывание int14 (Здесь и далее числа даны в 16-ричной системе счисления). С помощью этого прерывания можно установить параметры порта, проверить статус порта, принять или передать байт данных. Но при работе через BIOS программа должна обрабатывать данные со скоростью не меньшей чем скорость их поступления, т.к. в IBM PC не поддерживается аппаратная буферизация данных проходящих через последовательный порт. Работа с использованием int14 возможна при передаче данных со скоростями до 300 бод. При больших скоростях неизбежна потеря данных.
При работе на скоростях больше 300 бод приходится организовывать программную буферизацию принимаемых, а в отдельных случаях и передаваемых данных. Это можно сделать при использовании прерываний которые могут генерироваться последовательными портами.
В конце статьи приведена простейшая программа эмулятор терминала и в процессе ее разбора объясняются основные принципы программирования адаптера RS-232C.
Посмотрим на текст программы. В файле TERM.C содержится программа эмулятор терминала. Как видите, программа в начале анализирует аргументы командной строки. Анализ примитивный из за экономии места и Вы вправе написать его в своем стиле. В случае отсутствия ошибок вызывается функция portbase для определения базового адреса порта. Что это такое?
Дело в том, что к каждому из адаптеров относятся 8 специальных управляющих и контрольных регистров выполняющих одну или несколько функций в зависимости от режима работы RS-232C. Эти регистры располагаются один за другим начиная с базового адреса. Этот адрес содержится в специальной области данных базовой системы ввода-вывода (BIOS Data Area). Базовые адреса имеют формат слова и располагаются один за другим начиная с адреса 40:0. Если порт отсутствует,то в BIOS Data Area содержится 0.
Обычно COM1 имеет базовый адрес 3F8, COM2 - 2F8. Не спрашивайте меня почему COM1 имеет больший базовый адрес, я всего лишь программист. В дальнейшем, в пояснениях, мы будем использовать адресацию регистров соответствующую порту COM1, т.е. от 3F8 до 3FF.
Вернемся к головной функции. После определения базового адреса порта вызывается функция setparm, которая устанавливает параметры обмена: скорость, тип контроля по четности, число информационных битов и число стоповых битов. Как это делается?
Параметры линии, кроме скорости, устанавливаются в регистре, который называется регистром управления линией - LCR (Line Control Register). Этот регистр имеет адрес 3FB.
Скорость передачи устанавливается отдельно от остальных параметров. Для этого в регистре 3FB нужно установить бит 7 в 1 (В литературе по IBM PC принято нумеровать биты с права налево и самый правый бит имеет номер 0). Этот бит называется битом загрузки делителя (Divisor Latch Access Bit). DLAB управляет режимом регистров 3F8 и 3F9. Если в регистре 3FB бит 7 выставлен в 1 то эти регистры становятся регистрами в которые записывается или может считываться соответственно младший байт и старший байт делителя скорости обмена. Дело в том, что адаптер RS-232C имеет задающий генератор частоты 1.8432 МГц. Эта частота делится на 16 и на 16ти битовое число-делитель частоты, которое извлекается из регистров 3F8 и 3F9. Таким образом получается частота с которой передаются и принимаются данные. Делитель для любой требуемой скорости можно получить по формуле:
Как видно из формулы, скорость обмена не может превышать 115200 бод. Остальные параметры устанавливаются непосредственно в регистре 3FB. (Бит 6 этого регистра служит для посылки сигнала разрыва связи. При установлении этого бита в 1 порт начинает посылать в линию двоичные нули до тех пор пока этот бит не будет установлен в 0. Мы этот режим рассматривать не будем.) После установки параметров бит 7 нужно установить в 0, что переводит порт в рабочий режим. При этом регистр 3F8 становится буфером в который кладется байт для передачи или из которого берется принятый байт.
После установки параметров вызывается функция porton, которая подготавливает порт непосредственно к работе. В начале эта функция определяет уровень аппаратного прерывания IRQ (Interrupt ReQuest) которое будет вызывать порт. В IBM PC XT/AT,как правило,порты COM1 и COM3 вызывают прерывание IRQ 4, а COM2 и COM4 - IRQ 3. В PS/2 все порты с COM2 до COM8 вызывают прерывание IRQ 3. Аппаратные прерывания IRQ 4 обслуживаются обработчиком прерывания с вектором 0C, а IRQ 3 с вектором 0B. Существует способ определить программным путем номер прерывания вызываемого конкретным портом, но мы в целях экономии места его не приводим т.к. его применение имеет смысл при наличии в ПК более чем 2 портов, что в СССР редкость. Интересующихся отсылаем к исходным текстам известного пакета MS Kermit 2.32, файл MSXIBM.ASM.
После определения номера прерывания функция подменяет обработчик прерывания на свой - функция i_handler. Эта функция является обработчиком прерывания и вызывается непосредственно операционной системой, но не из других функций. Она получает управление при возникновении прерывания от последовательного порта, в нашем случае при приеме байта. Принятый байт помещается в буфер определенный в программе как массив символов buf.
Помимо буфера для хранения принятых данных, в программе определены два указателя: inptr и outptr. Первый из них указывает на первое свободное место в буфере, а второй - на первый считываемый байт. Буфер кольцевой, указатель inptr inptr inptr увеличивается на единицу если буфер не заполнен до конца или устанавливается в начало буфера в противном случае.
После выборки байта из порта и помещения его в программный буфер в регистр управления прерываниями контролера 8259A посылается сигнал об окончании обработки прерывания и обработка прерывания заканчивается. Контроллер 8259A и работа с ним описана чуть ниже. После замены обработчика прерывания выставляются сигналы: Запрос на
передачу - RTS (Request To Send), Терминал готов - DTR (Data Terminal Ready) и сигнал Выход 2 - OUT2. Эти сигналы выставляются установкой в 1 соответствующих битов в регистре управления модемом - MCR (Modem Control Register). Этот регистр имеет адрес 3FC.
Бит 3 этого регистра нужно выставить в 1 для того, чтобы разрешить прерывания от схем RS-232. Сигналы RTS и DTR используются как сигналы синхронизации связи. Остальные биты этого регистра мы рассматривать не будем.
Далее мы должны установить требуемый тип прерывания который должен вызываться портом. По условию нашей задачи требуется чтобы прерывания возникали по приходу каждого байта. Напомним, что регистр 3F9 может выполнять две функции. Если в регистре 3FB бит 7 выставлен в 0, то регистр 3F9 является регистром разрешения прерываний - IER (Interrupt Enable Register). Если бит 0 этого регистра установлен в 1 то порт будет инициировать прерывания по приходу каждого байта данных. Если бит 1 установлен в 1 то порт будет вызывать прерывания при готовности порта к передаче данных. Бит2 отвечает за генерацию прерываний при ошибках приема данных или при появлении сигнала разрыва связи (BREAK). Бит 3 управляет генерацией прерываний при изменении входного статуса порта. Остальные биты этого регистра всегда должны быть выставлены в 0.
Для того чтобы ПК мог воспринимать прерывания от последовательного порта мы должны также запрограммировать контроллер управления прерываниями 8259A. Этот контроллер имеет два регистра с адресами 20 и 21. В регистр с адресом 20, регистр управления прерываниями - ICR (Interrupt Control Register), посылается сигнал об окончании обработки прерывания. Для прерывания IRQ 3 таким сигналом является число 63, а для IRQ 4 - 64. Также можно использовать общий сигнал - число 20. В регистре 21, который называется регистром маскирования прерываний - IMR (Interrupt Mask Register) , каждый из 8 битов отвечает за соответствующее прерывание IRQ 0-7. Если соответствующий бит выставлен в 1 прерывание замаскировано, т.е. ПК на него не реагирует.
Этот контроллер управляет не только прерываниями от последовательных портов, но и прерываниями от других устройств включая клавиатуру, дисковые накопители и др. Поэтому при работе с ним нужно соблюдать осторожность. Для того, чтобы ПК воспринимал прерывания от порта COM1 нужно установить в 0 бит 4 регистра маскирования прерываний этого контроллера (см. рис. 4), а для порта COM2 - бит 3.
Вернемся к программе. После функции porton начинает выполняться основной цикл программы. С помощью функции portin выбираются данные из буфера по одному байту и отображаются на экране. Если пользователь ввел данные с клавиатуры. то они посылаются в линию связи с помощью функции portout. Если нажимается клавиша Esc цикл завершается.
Обратите внимание на то, что функция portin работает не с портом, а с нашим буфером в который данные помещаются автоматически обработчиком прерываний i_handler. Если буфер пустой функция возвращает -1.
Функция portout дожидается пока порт будет готов к передаче и затем передает байт. Готовность порта определяется по состоянию регистра с адресом 3FD который называется регистром статуса линии - LSR (Line Status Register).
Для нас важен бит 5 этого регистра. Если этот бит выставлен в 1, то это значит, что регистр 3F8 пуст и в него можно засылать байт который будет передан в линию. Обратите внимание на то, что этот регистр не показывает, что предыдущий передаваемый байт уже передан - это показывает бит 6. Готовность порта к передаче означает только то, что байт предназначенный для передачи уже выбран схемами порта из регистра 3F8 и побитно передается с заданной скоростью и др. параметрами.
В конце программы вызывается функция portoff которая производит действия обратные porton. Вызвать эту функцию необходимо для того, чтобы вернуть всю систему в изначальное состояние.
В заключение коротко поясним назначение регистров 3FA, 3FE и 3FF.
Регистр 3FA называется регистром идентификации прерываний - IIR (Interrupt Identification Register). В случае, когда в регистре 3F9 разрешены несколько типов прерываний, по состоянию регистра 3FA обработчик может определить конкретный тип прерывания.
Регистр 3FE называется регистром статуса модема - MSR (Modem Status Register). Этот регистр показывает наличие или изменение некоторых сигналов линии связи. По достоянию этого регистра можно можно определить например, включен или выключен модем.
Регистр 3FF не несет никакой функциональной нагрузки и может использоваться как буфер для хранения одного байта. Но нужно помнить, что в ранних реализациях RS-232C этот регистр может отсутствовать.
Оставить комментарий
Комментарии
[Ссылка]
О нас
http://www.incatalog.kz