Программирование последовательного порта IBM-совместимого персонального компьютера /ПК/ возможно различными способами. Ниже рассмотрен наиболее простой способ с использованием программного прерывания BIOS.
Суть использования программного прерывания в данном случае заключается в том, что в состав базовой системы ввода-вывода /Base Input-Output System, сокращенно BIOS/ входит большое количество специализированных программ, предназначенных для работы с аппаратной частью ПК. Вызвать требуемую программу можно, если выполнить программное прерывание с заранее известным номером. Передать параметры вызываемой программе можно через регистры процессора. Какое прерывание надо вызвать для выполнения той или иной функции при работе с аппаратурой ПК, какие параметры надо этой функции передать и в какие регистры их поместить – все это стандартизованные сведения, описанные в руководствах и справочниках. Логически, оказалось удобно назначить одному номеру прерывания несколько функций, различая их по номерам. Так и говорят: «Первая функция четырнадцатого прерывания».
Для программирования последовательного порта, точнее, для программирования контроллера последовательного порта, используют прерывание 14h (Внимание! 14h –шестнадцатиричная величина, а не обычное десятичное число.). При использовании 14h прерывания доступны четыре функции, из которых мы будем использовать три. А именно:
0 – нулевая – инициализация последовательного порта
1 – передача байта через последовательный порт
2 – прием байта из последовательного порта
Инициализация последовательного порта заключается в том, что программист задает требуемый режим работы протокола последовательного порта, а именно:
Скорость передачи
Как обращаться с признаком четности
Количество стоповых бит в информационной посылке
Количество информационных бит в информационной посылке.
Инициализацию осуществляют, записывая в регистр AL процессора специальным образом сформированный байт, значения отдельных битов которого определяют различные параметры передачи. Пример байта инициализации приведен в таблице 1.
Таблица 1
Разряд, разряды |
За что отвечает |
Пример |
5,6,7 |
Скорость обмена данными |
111 – 9600 бод |
3,4 |
Как учитывать и учитывать-ли вообще признак четности |
00 – не учитывать |
2 |
Количество стоповых бит |
0 – один стоповый бит в информационной посылке |
0,1 |
Количество информационных бит |
11 – восемь информационных бит |
Таким образом, если нам необходимо установить режим работы последовательного порта такой: максимальная скорость передачи 9600 бод, без учета признака четности, с одним стоповым и восемью информационными битами в информационной посылке, константа инициализации, которую надо записать в регистр AL процессора будет равна 11100011 или E316. Следует понимать, что для правильного приема и преобразования информации, принятой по последовательному каналу, передающий и принимающий контроллеры должны быть настроены одинаковым образом. В случае соединения между собой ПК, как в предлагаемой лабораторной работе необходимо при инициализации записать одну и ту же константу в регистр AL на каждом ПК.
Какие еще регистры используют при инициализации контроллера последовательного порта? AH и DX.
В регистр AH записывают номер функции, в данном случае, для функции инициалиизации 0.
В регистр DX записывают номер порта. Как правило, на ПК имеется несколько последовательных портов, обозначаемых COM1, COM2 и т.п. Для того, чтобы указать, что мы инициализируем порт COM1, надо записать в регистр DX 0, для инициализации COM2 – 1. Надо отметить, что можно по-разному настроить разные порты одного и того же ПК.
После того, как все необходимые данные записаны в необходимые регистры, необходимо вызвать само прерывание. При этом процессор перейдет в режим обработки соответствующего прерывания, выполнит все необходимые действия и перейдет к выполнению следующей за командой вызова прерывания команды нашей программы.
Таким образом, инициализации последовательного порта COM2 с параметрами, указанными выше, будет выглядеть на псевдоассемблере так:
AH=0
AL= E316
DX=1
Int 14h
Как это написать на Pascal?
Pascal имеет предопределенную структуру данных типа регистров registers, описанную в модуле DOS, который надо подключить к нашей программе, иначе тип данных registers не будет идентифицирован. Следовательно, надо написать:
Uses DOS;
R:
registers;
Begin
R.AH:=0;
R.AL:=$E3;
R.DX:=1;
Intr($14,R);
…
Примечания:
Передача байта.
Передаче байта через последовательный порт соответствует функция 1.
Передаваемый байт должен быть записан в регистр AL.
Через какой именно порт COM1 или COM2, будет происходить передача байта, необходимо указать в регистре DX.
Это означает, что на псевдоассемблере эта передача байта 100 через COM2 будет выглядеть так:
AH=1
AL= 100
DX=1
Int 14h
Приему байта из последовательного порта соответствует функция 2.
Принятый байт будет сохранен в регистре AL.
Из какого именно порта COM1 или COM2 будет происходить прием байта, необходимо указать в регистре DX. Есть особенность при программировании приема байта из последовательного порта. Мы не знаем, передан ли уже байт с другого ПК к моменту нашего обращения к функции приема на данном ПК или нет. Ведь ПК работают асинхронно. Для этого предусмотрен анализ состояния контроллера последовательного порта после выполнения функции приема байта. А именно: если байт был успешно принят, то после выполнения прерывания в регистре AH будет записан 0. Если байт был принят с ошибками или совсем не принят, то в различных разрядах байта регистра AH будут установлены единицы, характеризующие, что именно было не так при приеме байта. В нашу задачу не входит детальный анализ кода состояния контроллера после приема байта, поэтому будем просто проверять 0 в регистре AH или не 0. Если после выполнения прерывания при приеме байта в регистре AH 0, то можно считать, что байт, который записан в регистр AL, принят правильно.
На псевдоассемблере прием байта из COM2 будет выглядеть так:
AH=2
DX=1
Int 14h
Если AH=0, использовать, например вывести на экран, байт AL
Иначе – повторить прием.