Искусство схемотехники. Том 2 [Изд.4-е]

Хоровиц Пауль

Хилл Уинфилд

Глава 10

МИКРОЭВМ

 

 

Мини-ЭВМ, микроЭВМ и микропроцессоры

Доступность недорогих малых ЭВМ, стоимостью порядка 1 К долл., сделала их привлекательными для использования при управлении экспериментом и технологическими процессами, для накопления данных и выполнения оперативных вычислений. Малые ЭВМ широко используются в лабораторных исследованиях и промышленности, поэтому информация об их потенциальных возможностях, языках программирования и способах сопряжения с внешними устройствами составляет существенную часть электронного «ноу-хау».

МикроЭВМ эволюционировали от ранней мини-ЭВМ — малой электронно-вычислительной машины, центральный процессор (ЦП) которой был собран на микросхемах малой и средней степени интеграции, как правило расположенных на одной или нескольких больших печатных платах. По мере совершенствования микросхем БИС стало возможно реализовать рабочие характеристики центрального процессора мини-ЭВМ на одном кристалле высокой степени интеграции; таким образом, микроЭВМ — это электронно-вычислительная машина, центральный процессор которой собран на нескольких, а зачастую на одной микросхеме БИС, а тип микросхемы ЦП или соответствующий микропроцессорный комплект определяет тип микроЭВМ. Например, на смену популярным мини-ЭВМ фирмы DEC PDP-11, ЦП которых занимал несколько печатных плат, пришло семейство ЭВМ под таким же названием, ЦП которых был собран на нескольких микросхемах БИС, заменивших большое количество микросхем малой и средней степени интеграции; приблизительно в то же время фирма Motorola представила высокопроизводительный микропроцессор МП (серии 68000), несомненно испытавший влияние PDP-11, рабочие характеристики которого во многом были сходны с характеристиками ЦП этой ЭВМ.

В основе большинства современных малых ЭВМ, являющихся на самом деле микроЭВМ, лежат впечатляющие характеристики современного поколения микропроцессоров. Не так давно возникло идиоматическое выражение «супермини-ЭВМ», по-видимому, для того, чтобы выделить класс ЭВМ, имеющих более высокие технические характеристики и подчас конкурирующих с большими и дорогостоящими ЭВМ, построенными в соответствии с традиционными техническими решениями. В некоторых случаях различия между ними относятся скорее к габаритным размерам или количеству внешних устройств, чем к степени интеграции ЦП.

Более существенно различие между микроЭВМ и микроконтроллерами. Термин микроконтроллер использован для обозначения устройства, в котором микропроцессор вместе с небольшим по объему ЗУ и другими необходимыми элементами используют для специализированного управления процессом или аппаратом. В такой ситуации микропроцессор да несколько подходящих микросхем плюс ПЗУ могут с успехом заменить сложную комбинационную схему, состоящую из логических элементов, триггеров, аналого-цифровых и цифро-аналоговых преобразователей; это надо иметь ввиду, как только вы включаетесь в крупный технический проект.

Для такого рода приложений разработаны специализированные МП, характеризующиеся тем, что такие узлы, как тактовые генераторы, схемы ввода-вывода и некоторые другие, обычно собираемые с использованием дополнительных микросхем, реализованы на том же кристалле, что и собственно микропроцессор за счет вычислительной мощности и большого адресного пространства, которые характеризуют МП, предназначенные для построения микроЭВМ, ориентированных на вычислительные задачи.

В этой главе мы опишем архитектуру и программирование микроЭВМ, а также их сопряжение с внешними устройствами на примерах полезных и простых способов подключения внешних устройств к IBM PC/XT. Здесь мы ссылаемся на стандартную PC-магистраль и ее модификации, такие как магистраль PC/AT и совместимых с ней ЭВМ, а также младших моделей линии PS/2. Большинство изложенных в настоящей главе идей будет перенесено в следующую главу, где мы углубимся в обстоятельное обсуждение по поводу проектирования и конструирования схем и целых систем на основе МП, а для примеров будем использовать МП «Motorola 68008» из серии 68000, которая совместно с серией Intel 8086 господствует в малых ЭВМ. Говоря о микроЭВМ в целом, надо отметить, что проектирование собственно ЭВМ, включая ОЗУ, внешние запоминающие устройства, устройства ввода-вывода, а также системное программирование и разработка сервисных программ являются предметом заботы изготовителя, а также его коллег, производящих комплектующие аппаратные и программные средства. Пользователю надо только позаботиться о специализированных интерфейсах и программировании своих прикладных задач. Напротив, в специализированных МП-системах выбор типа ЗУ, схемных и программных решений, вообще говоря, должен быть сделан проектировщиком. Изготовители микроЭВМ, как правило, принимают на себя вопросы разработки системного и сервисного программного обеспечения, как части вычислительной системы в целом (часто-совместно с внешними устройствами), тогда как изготовители МП-комплектов и интегральных микросхем сосредоточены на вопросах проектирования и сбыта как собственно МП, так и вспомогательных микросхем. В настоящей главе мы рассмотрим архитектуру и программирование микроЭВМ и сосредоточимся на подробностях внутренних связей и сопряжений с внешними устройствами.

10.01. Архитектура микроЭВМ

Рисунок 10.1 представляет типовую обобщенную схему большинства микроЭВМ. Рассмотрим эту схему.

Рис. 10.1. Блок-схема компьютера.

Центральный процессор. Центральный процессор — это сердце ЭВМ. Компьютеры выполняют вычисления в центральном процессоре над порциями данных, организованных как машинные слова. Размер слова может составлять от 4 до 32 бит и более, наиболее популярные современные микроЭВМ имеют 16-битовое слово. Восемь бит составляют байт, а половину байта-четыре бита-иногда называют «нибл». Часть ЦП, называемая дешифратором команд, интерпретирует последовательные команды, выбираемые из памяти, выясняя тем самым, что надлежит делать процессору в каждом случае. В состав ЦП входит арифметическое устройство, которое может выполнять такие операции, как сложение, нахождение дополнения, сдвиг, пересылку и некоторые другие над числами, находящимися в регистрах, а в некоторых случаях и в памяти. Программный счетчик постоянно отслеживает ход выполнения программы. Обычно значение программного счетчика инкрементируется после выполнения очередной команды, но оно может получить другое значение в результате выполнения команд безусловного перехода или ветвления — условного перехода. Управляющие линии магистрали обеспечивают сопряжение с памятью и устройствами ввода-вывода. Большинство компьютеров (и чем дальше - тем больше) имеют также регистр указателя стека и несколько флажков (переноса, нуля, знака), проверяемых при выполнении условных переходов. В состав многих высокопроизводительных процессов входит также сверхоперативная память (кэш-память), которая для ускорения доступа содержит величины, незадолго до этого извлеченные из памяти.

Значительная активность наблюдается в области экспериментов с параллельными процессами, где вы соединяете между собой много ЦП с целью достижения потрясающей вычислительной мощности. Со временем в области высокопроизводительной обработки такая тенденция может стать определяющей. В наше же время, однако, стандарт архитектуры микро-ЭВМ представлен однопроцессорными ЭВМ, которые выполняют команды последовательно.

Память. Все компьютеры имеют некоторый объем быстрой памяти с произвольным доступом, такую память, бывало, называли «сердцем» компьютера, поскольку запоминали и сохраняли данные малюсенькие магнитные сердечники - по одному на каждый запоминаемый бит. В большой микроЭВМ объем ОЗУ может достигать 10 Мбайт и более, хотя типичным значением является 1 Мбайт, а в микроконтроллерах объем ОЗУ может составлять всего 16 Кбайт. (Когда память измеряют в единицах К, это означает не 1000 байт, а 1024 или 210 байт; таким образом, 16 Кбайт на самом деле составляют 16 384 байт. Для обозначения 1000 мы употребляем строчную букву к.) Для того чтобы записать в такую память какой-либо код или считать его, обычно требуется около 100 не. Память с произвольным доступом почти всегда «разрушаема», это означает, что, когда электропитание отключается, информация улетучится (возможно, эту характеристику следовало бы назвать «забывчивостью»). Поэтому все компьютеры в своем составе имеют и неразрушаемую память, обычно доступную только для чтения (ПЗУ) и предназначенную для того, чтобы «завести» машину, находящуюся до включения питания в состоянии полной амнезии.

В дополнительное ПЗУ часто записывают системные и графические процедуры, а также другие программы, которые должны быть доступны в любой момент.

Для того чтобы считать из памяти или сохранить в памяти ту или иную информацию, ЦП «адресует» то слово (памяти), какое пожелает. Большинство компьютеров адресует память побайтно, начиная с нулевого байта и последовательно перебирая байты вплоть до последнего в памяти. Поскольку машинное слово большинства компьютеров составляет несколько байт, обычно за один раз вы заносите в память или извлекаете из нее группу байт; обычно необременительно иметь шину данных с разрядностью в несколько байт. Например, микроЭВМ, которые построены на МП 80386 или 68020, имеют 32-разрядную шину данных (что равно 4 байт), так что 32-разрядное слово может быть записано в память или считано из нее за один цикл выборки. Для того чтобы указать длину последовательности передаваемых байт, используют управляющие сигналы, причем даже для «солидных» шин вам на это потребуется всего 1–2 байт.

В компьютере с большим количеством сегментов памяти для указания произвольного адреса памяти необходимо 3–4 байт. Поскольку большинство адресов памяти в реальной программе обычно близко, все компьютеры поддерживают упрощенные модели адресации: «относительная» адресация определяет адрес по удалению его от текущей команды в памяти; «косвенная» адресация использует содержимое регистра ЦП для указания ячейки в памяти; «страничная» адресация использует укороченные адреса для указания на заданную ячейку памяти в пределах малого диапазона (страницы); «прямая» или «абсолютная» адресация использует несколько следующих за командой байт для указания адреса. Современные ЦП венчают этот краткий список «индексной», «автоинкрементной» и другими полезными способами адресации, которых мы коснемся в следующей главе.

Во время выполнения программы в памяти находятся как собственно программа, так и данные. Центральный процессор извлекает команды из памяти, выясняет, что они означают и поступает соответственно, при этом часто требуется сохранить данные где-нибудь в памяти. Обычно неспециализированные универсальные компьютеры хранят программы и данные в одной и той же памяти, причем компьютер на самом деле не отличает одних от других. Если программа пойдет не туда и начнет «исполнять» данные, могут начаться забавные вещи!

Поскольку компьютерные программы большую часть своей жизни проводят в циклах, состоящих из сравнительно коротких последовательностей команд, вы можете увеличить производительность машины, используя малую по объему, но быструю кэш-память, в которую вы просто заносите копии ближайших используемых ячеек памяти. Центральный процессор с кэш-памятью сначала обращается именно к ней, перед тем, как осуществить выборку из более медленной основной памяти, когда циклы «крутятся» по одним и тем же адресам; часто можно достичь рекордной эффективности использования кэш-памяти до 95 % и выше, разительно увеличивая быстродействие.

Массовая память. Компьютеры, предназначенные для разработки программ или вычислений, в противоположность специализированным управляющим процессорам, обычно имеют одно или более запоминающее устройство достаточной емкости, называемое устройством массовой памяти. Жесткие диски (именуемые также «винчестерскими») и гибкие диски (флоппи-диски или дискеты) — вот типичные представители устройств массовой памяти, емкость которых изменяется от нескольких сотен килобайт до нескольких мегабайт для гибких дисков, и от нескольких десятков до нескольких сотен мегабайт для жестких дисков. Наиболее полно экипированные компьютеры имеют в своем составе дополнительно одно или два устройства ввода-вывода на магнитную ленту, конструкция которых может быть различна-от простого кассетного «стриммера» до магнитофона, рассчитанного на большие катушки 9-дорожечной полудюймовой стандартной ленты, те самые, которые всегда вращаются на заднем плане в научно-фантастических кинофильмах. Более современная технология, используя 8-мм видеокассеты, те же самые, что обитают в легких переносных видеокамерах, позволяет записать на одну такую кассету 1 Гбайт. Последним достижением в разработке массовой памяти являются компакт-диски, предназначенные только для чтения и использующие ту же технологию производства оптических дисков, что и при изготовлении аудио компакт-дисков; их емкость составляет 600 Мбайт на сторону 5-дюймового пластикового диска, обладающего к тому же гораздо меньшим временем доступа, чем любая магнитная лента.

В отличии от аудио компакт-дисков существуют такие устройства массовой памяти на компакт-дисках, которые позволяют как считывать, так и записывать информацию путем образования на пустом ровном компакт-диске ямок за счет лазерного нагрева; такие устройства называют WORM от английской аббревиатуры «записать однажды - читать многократно». Более того, сейчас доступны также устройства внешней памяти на магнитооптических дисках, поддерживающие операции чтения-записи и позволяющие полностью обновлять содержимое таких дисков.

По сравнению с ОЗУ произвольного доступа устройства массовой памяти, вообще говоря, обладают меньшим быстродействием, причем самыми медленными являются устройства на магнитных лентах (их время доступа достигает многих секунд), а самыми быстрыми (и дорогими) — жесткие диски (среднее время доступа порядка десятков миллисекунд). Скорость обмена данными для всех устройств массовой памяти высока и составляет от 10 Кбайт до 100 Кбайт в секунду и более, без учета задержки доступа к устройству. Как правило, вы храните программы, файлы данных, в том числе файлы графической информации, на некотором устройстве массовой памяти и загружаете их в ОЗУ только на время вычислений. С одним диском одновременно могут работать несколько пользователей; средних размеров оптический диск может хранить несколько копий Британской энциклопедии.

Если ваш компьютер имеет ОЗУ достаточно большого объема, элегантный способ поднять быстродействие компьютера, в том случае, если он часто обращается к диску, заключается в том, чтобы организовать псевдодиск путем загрузки всех необходимых дисковых файлов в ОЗУ в начале работы. Таким образом, вы можете загрузить в ОЗУ текстовый редактор, компилятор, редактор связей, загрузчик, после чего можно обращаться к такому диску для чтения или записи без потерь времени на ожидание. Тем не менее будьте бдительны: если компьютер отключится, ничто из результатов вашей работы не будет сохранено на внешнем носителе и вы потеряете всю наработку.

Алфавитно-цифровой и графический ввод-вывод. Замечательно иметь мощный компьютер, способный выполнять миллионы интеллектуальных вычислений в секунду, но если он все результаты держит в себе, вам от этого мало проку. Такие внешние устройства, как клавиатура с экраном, составляющие вместе терминал, «мышь», печатающее устройство и другие обеспечивают общение человека с машиной и существенны для любой «дружественной» по отношению к пользователю вычислительной системы. Эти устройства ориентированы в основном на программирование, редактирование текстов, работу с электронными таблицами и на графику; вы используете их, когда пишете, отслеживаете и распечатываете программу, вводите и печатаете документы, манипулируете числами или изображениями, играете в компьютерные игры. Такие внешние устройства вкупе с соответствующей интерфейсной частью легко найти у многих поставщиков, включая фирмы-изготовители собственно компьютеров.

Ввод-вывод в реальном времени. В лабораторных исследованиях, управлении технологическими процессами, при сборе данных или для таких экзотических приложений, как синтез речи или музыки, вам необходимы аналого-цифровые и цифро-аналоговые устройства, которые могут общаться с компьютером в реальном масштабе времени, т. е. в то же самое время, когда продолжается процесс, контролируемый этими устройствами. Возможности здесь практически безграничны; если взять хотя бы набор мультиплексируемых АЦП общего назначения, немного быстрых ЦАПов и несколько цифровых «портов» (последовательных или параллельных) для обмена данными, это уже обеспечит массу интересных приложений. Для наиболее популярных стандартов внутренней магистрали компьютеров подобная периферия общего назначения коммерчески доступна. Если же вы хотите от этих устройств чего-нибудь более причудливого, например, улучшенных характеристик (повышенного быстродействия, увеличенного числа каналов) или специализированных функций (генерации звуков, частотного синтеза, генерации временных интервалов и т. п.), вам придется сделать такие устройства самостоятельно. Вот здесь-то сведения об организации магистрали компьютера и технике программирования существенны, хотя подобные сведения полезны всегда.

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

Другим путем расширения сферы действия вашего компьютера является использование локальной вычислительной сети (ЛВС) для совместного объединения группы ЭВМ. Примером такой сети является ЛВС (Ethernet), которая обеспечивает передачу данных между машинами сети со скоростью до 10 Мбит/с по одному коаксиальному кабелю. Локальная вычислительная сеть позволяет вам обмениваться файлами с любой ЭВМ, включенной в эту сеть; на самом деле, работая в хорошо организованной сети, вы скорее всего приумножите ресурсы своего компьютера, совместно с другими ЭВМ используя быстрый диск большой емкости, дорогостоящие графопостроители и печатающие устройства и т. д. В этом случае каждая рабочая станция ЛВС может иметь внешнюю память весьма ограниченной емкости, зато обладать значительными вычислительными возможностями. Такая идеология организации ЛВС является идеальной, например, для издательств, где в процессе подготовки рукописи к публикации с ней работают разные люди. Для большинства компьютеров разработаны интерфейсы их подключения к Ethernet или другим ЛВС.

Магистраль данных. Для обмена данными между ЦП и ОЗУ или адаптерами внешних устройств все компьютеры используют магистраль — набор обобщенных «линий» (проводников), по которым осуществляется обмен двоичными словами. (Многие магистрали допускают также обмен данными непосредственно между адаптерами внешних устройств, хотя такие возможности используются менее часто.) Использование магистрали с обобщенными линиями значительно упрощает межсоединения, поскольку в противном случае вам потребовались бы многожильные кабели, соединяющие каждую пару взаимодействующих друг с другом устройств. Немного внимания как при проектировании самой магистрали, так и при подключении к ней — и все работает отлично. Магистраль состоит из набора линий данных (их обычно столько же, сколько разрядов (бит) составляет слово данных-8 для микроконтроллера и ПЭВМ с невысокими рабочими характеристиками, 16 или 32-для более сложных микрокомпьютеров), нескольких линий адреса для определения того, какое устройство будет «вещать», а какое - «слушать», подключившись к соответствующим линиям, а также набора управляющих линий, которые определяют, какое действие выполняется (передача данных от или к ЦП, обработка прерываний, прямой доступ к ОЗУ и т. п.). Все линии данных, равно как и ряд других линий, являются двунаправленными - они либо подключены к выходу элементов с тремя состояниями, либо в некоторых случаях к открытому коллекторному выходу логических элементов с нагрузочными резисторами (эти резисторы обычно устанавливают на конце магистрали, при этом они дополнительно выполняют функцию согласования для уменьшения отражений сигналов в линиях магистрали, см. также разд. 13.09); нагрузочные резисторы могут оказаться необходимыми и в случае применения устройств с тремя состояниями в том случае, когда магистраль имеет большую физическую длину.

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

Среди разных типов внутренних магистралей компьютеров существует одно интересное различие. Они могут быть либо синхронными, либо асинхронными, в популярных микрокомпьютерах можно найти примеры каждого типа. Что это значит, вы увидите, когда мы будем детально рассматривать взаимодействие отдельных узлов компьютера через магистраль.

Мы вернемся к подробному рассмотрению магистрали с примерами соответствующих интерфейсов, рассматривая популярное семейство IBM PC/XT. Однако сначала нам необходимо познакомиться с набором команд ЦП.

 

Набор команд компьютера 

10.02. Язык ассемблера и язык машинных кодов

Для того чтобы понять сигналы магистрали и функционирование компьютера, необходимо выяснить, что делает ЦП во время выполнения различных команд. Соответственно нам хотелось бы познакомить читателя с набором команд семейства IBM PC/XT. К сожалению, набор команд большинства реально существующих микропроцессоров имеет тенденцию к расширению, сопровождающуюся усложнением, наряду с добавлением дополнительных возможностей, и МП Intel 8086 не исключение. Однако поскольку нашей целью является только иллюстрация сигналов магистрали и функционирования компьютера (а не изощренное программирование), рассмотрим сокращенный набор команд — подмножество набора команд МП 8086. Исключив «лишние» команды, мы тем самым решаем проблему выбора ограниченного содержательного подмножества понятных команд, достаточных для программирования любой задачи. Далее мы используем этот набор команд для того, чтобы продемонстрировать несколько примеров функционирования аппаратной части и программирования. Эти примеры помогут выразить идею программирования на уровне машинных команд, что решительно отличается от программирования на таких языках высокого уровня, как

Фортран или Си . Несколько слов по поводу языка машинных кодов и языка ассемблера. Как уже упоминалось выше, ЦП компьютера предназначен для интерпретации определенных машинных слов в качестве команд и выполнения соответствующих программных процедур. Такой машинный язык состоит из набора двоичных команд, каждая из которых занимает один или несколько байт. Например, команда инкрементирования (увеличения на единицу) содержимого регистра ЦП будет однобайтовой, в то время как загрузка в регистр содержимого памяти обычно требует как минимум двух байт, причем это число может быть увеличено до пяти (при этом первый будет определять собственно команду и регистр, а четыре будут необходимы для указания произвольной ячейки памяти для большой машины). Печальной реальностью нашей действительности является то, что разные компьютеры имеют отличающиеся машинные языки и здесь нет совершенно никакой стандартизации.

Программирование непосредственно в машинных кодах является исключительно тоскливым занятием, так как приходится иметь дело с колонками двоичных чисел, каждый бит которых существенен. Поэтому вы неизбежно должны использовать программу, называемую ассемблером; она позволяет писать программы, используя легко запоминаемые мнемонические обозначения команд и символьные имена, которые вы можете придумывать сами для ячеек ОЗУ и переменных. Программа на языке ассемблера на самом деле не более, чем набор похожих на шифр строк, содержащих буквы и числа; ее следует передать «в руки» программы, называемой ассемблер, для того чтобы получить в результате законченную программу в машинном объектном коде, которую компьютер может выполнить. Каждая строка ассемблерного кода превращается в несколько байт машинного кода (1–6 байт для МП Intel 8086). Непосредственно выполнять команды на языке ассемблера компьютер не в состоянии.

Для того чтобы конкретизировать высказанные соображения, рассмотрим наше подмножество команд языка ассемблера МП Intel 8086/8 и выполним несколько примеров.

10.03. Упрощенный набор команд процессора Intel 8086/8

Intel 8086 — это 16-разрядный процессор с богатым и несколько своеобразным набором команд, сложность которого отчасти обусловлена стремлением разработчиков сохранить совместимость с 8-разрядным МП Intel 8080 ранней модели. Более поздние разработки, такие как МП Intel 80286 и 80386, все еще поддерживают полный набор команд МП Intel 8086. Вооружившись подходящим мачете, выберемся из джунглей полного набора команд, сохранив лишь нужные нам сейчас 10 арифметических команд и 11 прочих. Вот они:

Краткий обзор. Некоторые пояснения: первые шесть арифметических команд работают с парами чисел (2-х операндные команды), которые мы обозначим как Ь, а и которые могут представлять собой любую из пяти пар, указанных в примечании; при этом m означает содержимое ячейки памяти, r означает содержимое регистра ЦП (их 8), a imm — непосредственный аргумент, который представляет собой число, располагаемое в следующих за командой от 1 до 4 байт памяти. Таким образом, например, команды:

MOV count,CX

ADD small,02H

AND AX,007FH

имеют аргументы типов m, r, m, imm, r, imm соответственно. Первая копирует содержимое регистра СХ в ячейку памяти, именуемую count; вторая прибавляет 2 к содержимому другой ячейки памяти, именуемой small; третья обнуляет 9 старших разрядов 16-разрядного регистра АХ, сохраняя при этом 7 младших разрядов неизменными (так называемая операция маскирования). Отметим принятое фирмой Intel соглашение о порядке аргументов: первый аргумент замещается вторым или модифицируется на основе значения второго аргумента. (В следующей главе мы увидим, что Motorola предписывает другой порядок действий).

Последние четыре арифметические операции имеют только один операнд, который может быть содержимым либо регистра, либо ячейки памяти. Вот два примера:

INC count

NEG AL

Первая команда прибавляет 1 к ячейке памяти, именуемой count, а вторая изменяет знак содержимого регистра AL.

Лирическое отступление: адресация. Прежде, чем продолжить, несколько слов по поводу адресации регистров и памяти. Процессор Intel 8086 предлагает использовать 8 его регистров общего назначения, однако после изучения рис. 10.2 вы придете к заключению о том, что большинство этих регистров используются специфически.

Рис. 10.2. Регистры общего назначения МП 8086 .

Четыре из них (A-D) могут быть использованы как в виде единых 16-разрядных регистров (АХ, где X означает extended — расширенный), так и в виде пар байтовых регистров [АН, AL, соответственно Η означает старший (high) байт регистра АХ, a AL- младший (low) байт]. Регистры ВХ и ВР, так же как и SI, DI, могут содержать адреса и предназначены для использования при адресации (см. ниже). Специальные циклические команды (которые мы исключили из нашего краткого перечня) используют регистр С, а команды умножения/деления и ввода-вывода используют регистры А и D.

Данные, используемые в командах, могут представлять собой константу, величину, содержащуюся в регистре или величину, содержащуюся в памяти. Константы вы указываете, просто записывая их, а регистры - по именам, так, как было показано выше. Для адресации памяти МП Intel 8086 обеспечивает 6 режимов адресации, три из которых пояснены схемами на рис. 10.3.

Рис. 10.3. Некоторые способы адресации.

Вы можете прямо указать имя переменной, в этом случае ее адрес при ассемблировании будет определяться парой байтов, следующих сразу же за командой; вы можете занести адрес переменной в один из регистров, используемых для адресации (ВХ, ВР, SI или DI), а затем выполнить команду, в которой предусмотрена косвенная адресация через соответствующий регистр; можно модифицировать последний режим адресации и получать адрес переменной, прибавляя константу смещения к содержимому регистра, используемого для адресации. Косвенный режим быстрее (в предположении, что адрес уже загружен в соответствующий регистр) и является гораздо более приемлемым, если вы хотите выполнять некоторые операции над множеством чисел (строкой или массивом).

Вот несколько примеров адресации:

MOV count,100Н (прямая, непосредственная)

MOV [ВХ],100Н (косвенная, непосредственная)

MOV [ВХ + 1000Н], (адресация по базе, регистр)

АХ

В двух последних командах предполагается, что мы уже загрузили адрес в ВХ. Последняя команда копирует содержимое АХ в ячейку памяти, смещенную на 4 К (1000-ричное) выше от ячейки, на которую указывает ВХ; ниже мы вкратце рассмотрим пример, иллюстрирующий, как можно использовать эту команду для копирования массива.

При адресации памяти для МП 8086 существует сложность другого рода, которую мы было «замели под ковер»: адрес, формируемый в любом из вышеуказанных режимов адресации, не является окончательным, действительным адресом, поскольку получаемый таким образом адрес имеет только 16 разрядов (и может адресовать только 64 Кбайт памяти). На самом деле то, что вычисляется по указанным выше правилам, называется смещением. Для того чтобы получить действительный, физический адрес, вы должны прибавить к смещению 20-разрядную базовую величину, получаемую сдвигом на 4 разряда влево содержимого 16-разрядного сегментного регистра (таких регистров имеется 4). Другими словами, МП 8086 позволяет вам обращаться к областям памяти по 64 Кбайт; положение этих «сегментов» внутри полного адресного пространства 1 Мбайт, что в свою очередь определяется содержимым сегментных регистров. Использование 16-разрядной адресации в МП 8086 по большому счету было большой ошибкой, унаследованной от ранних поколений.

Более современные МП (начиная с 80386, а также серии 68000) сделаны как надо во всех отношениях, с 32-разрядной адресацией. Для того чтобы не усложнять наши примеры, мы просто игнорируем сегменты вообще; на практике вы, конечно, должны будете о них побеспокоиться.

Обзор набора команд (продолжение). Рассмотрим теперь команды управления стеком PUSH и POP. Стек — это часть памяти, организованная специальным образом: когда вы заносите некоторое значение в стек (выполняя операцию push), это значение заносится в очередную доступную ячейку (вершину стека); а когда вы извлекаете значение из стека (выполняя операцию POP), оно выбирается из вершины стека, т. е. выбирается то, что было занесено в стек последним. Таким образом, стек — это последовательный набор данных, организованный по принципу: последним пришел-первым вышел. Вам, может быть, будет легче освоить это понятие, если вы представите себе монетную кассу водителя автобуса или стопку подносов в столовой.

Рис. 10.4 показывает, как работает стек. Стек располагается в обычном ОЗУ, а указатель стека (регистр SP) ЦП обеспечивает возможность доступа к той ячейке памяти, которая является «вершиной» в данный момент времени. Для МП 8086 стек состоит из 16-разрядных слов и по мере занесения в него данных «растет» вниз в ОЗУ. Содержимое регистра SP автоматически декрементируется на 2 перед каждой операцией PUSH и инкрементируется на 2 после каждой операции POP. Таким образом, например, 16-разрядное содержимое регистра АХ копируется в вершину стека командой PUSH АХ; SP указывает на последний занесенный байт. Команда POP выполняется в обратном порядке, как показано на рис. 10.4.

Рис. 10.4. Операции со стеком.

Мы увидим, что при реализации вызовов подпрограмм и прерываний стек играет ведущую роль. Команда JMP заставляет ЦП отклониться от обычной процедуры последовательного выполнения команд, переходя к выполнению той команды, на которую совершается переход. Команда условного перехода (возможно 8 различных вариантов, обозначаемых обычно Jcc ) проверяет регистр флагов, который располагается в ЦП (биты разрядов этого регистра устанавливаются в соответствии с результатом выполнения самой последней арифметической операции), а затем либо выполняет переход (если условие истинно), либо выполняет следующую за командой условного перехода команду (если условие не истинно). Программа 10.1 показывает пример условного перехода.

Она копирует 100 слов из массива, начинающегося с адреса 1000Н, в новый массив, начинающийся на 1 Кбайт (400Н), выше. Отметим явную загрузку указателя (в регистр ВХ, используемый для адресации) и счетчика цикла (в CL). Собственно массив слов должен быть пропущен через регистр (мы выбрали АХ), поскольку МП 8086 не поддерживает команды типа память-память (см. примечание к набору команд). В конце 100-го цикла CL = 0 и команда «перейти, если не нуль» (JNZ) более не выполняется. Этот пример будет работать, однако на практике вам, возможно, следует использовать более быстрые команды МП 8086-пересылки строк. Хорошим тоном в практическом программировании считается использование символьных имен для обозначения массивов и их размеров вместо соответствующих констант, таких как 400Н и 1000Н.

Оператор CALL является вызовом подпрограммы; он подобен каманде перехода, за исключением того, что адрес возврата (адрес команды, следующей за командой CALL) заносится в стек. В конце подпрограммы вы выполняете оператор RET, который извлекает из стека его содержимое так, чтобы программа могла найти «обратную дорогу» (рис. 10.5).

Рис. 10.5. Работа команды CALL .

Три оператора STI, CLI и IRET имеют отношения к прерываниям, их работу мы проиллюстрируем вместе с примерами соответствующих электрических схем и ниже в этой главе. Наконец, команды ввода-вывода IN и OUT пересылают слово или байт между регистром А и соответствующим образом адресованным портом; подробнее об этом чуть позже.

10.04. Программный пример

Примеры, приведенные выше, наводят на мысль о тяге языка ассемблера к многословию; требуется множество маленьких шажков для того, чтобы сделать в общем-то простую вещь. Вот пример другого рода: допустим, вам необходимо инкрементировать число N, если оно равно другому числу — Μ. Таким будет типичный крошечный фрагмент большой программы, и на языках высокого уровня такое действие будет выполняться единственной командой:

IF (n = = n) + + n; (Си)

IF (N. EQ. M) N = N + 1; (Фортран)

IF  n = m then n: = n + 1; (Паскаль) и т. п.

На ассемблере МП 8086 эти действия будут выглядеть, как показано в программе 10.2.

Программа-ассемблер превратит этот набор мнемонических выражений в машинные коды, как правило, транслируя каждую строку исходного ассемблерного текста в несколько байтов машинных команд, и полученные коды машинных команд прежде чем быть исполненными, будут загружены в последовательно расположенные ячейки памяти.

Отметим, что ассемблеру надо указать на необходимость выделения некоторого объема памяти под переменные. Это делается с помощью ассемблерного псевдооператора DW (Define Word-определить слово) (этот оператор является псевдооператором, так как ему не соответствует никакой исполняемый код). Для того чтобы помечать команды, могут быть использованы уникальные символьные метки (например, NEXT). Команды обычно помечаются лишь в тех случаях, когда на них осуществляется переход (JNZ NEXT). Присваивая переменным понятные вам самому имена и вводя комментарии (отделенные точкой с запятой), вы облегчаете себе процесс программирования; эти рекомендации означают также, что у вас будет шанс несколькими неделями позже понять, что вы написали. Программирование на языке ассемблера может по-прежнему оставаться неприятным делом, однако часто на этом языке бывает необходимо написать короткую процедуру управления вводом-выводом, вызываемую из программы, написанной на языке высокого уровня. Программы на языке ассемблера работают быстрее, чем скомпилированные с языка высокого уровня, так что их часто используют там, где показатель скорости работы является решающим (например, во многократно выполняемых внутренних циклах численных вычислений большого объема).

Разработка языка программирования Си, обладающего большими возможностями, минимизировала количество тех случаев, когда вы должны использовать ассемблерные программы, тем самым расширив сферу применимости Си. В любом случае вам трудно будет понять, как отдельные узлы компьютера работают совместно, без уяснения существа ассемблерных команд ввод-вывода. Соответствие между мнемоникой языка ассемблера и исполняемыми машинными командами будет изучено ниже в разд. 11.03, где будет проиллюстрировано примерами программирования МП 68000.

 

Сигналы магистрали и ее функционирование 

Типовая магистраль данных микроЭВМ имеет около 50-100 сигнальных линий, предназначенных для передачи данных, адресов и управляющих сигналов. IBM PC/XT — типичный микрокомпьютер, внутренняя магистраль которого состоит из 53 сигнальных линий и 8 линий, предназначенных для подачи питания и заземления. Для того чтобы не обрушивать на вас все эти сигналы сразу, мы будем приближаться к осмыслению полного набора сигналов, «надстраивая» магистраль, начав с такого количества сигнальных линий, какое необходимо для простейшего режима обмена данными (программируемого ввода-вывода) и добавляя по мере необходимости дополнительные сигнальные линии. Далее мы приведем несколько полезных примеров организации сопряжения тех или иных узлов с магистралью для того, чтобы всесторонне обсудить эту тему, не теряя интереса читателя.

10.05. Основные сигналы магистрали: данные, адрес, синхронизация

Для того чтобы переслать данные на магистраль с разделяемыми ресурсами (мультиплексируемую), вы должны уметь описать сами данные, приемник, а также момент, когда данные являются достоверными. Таким образом, по минимуму магистраль должна иметь шину данных (для передачи данных), адресную шину (для того чтобы идентифицировать устройство ввод-вывода или адрес в памяти) и несколько линий синхронизации, или стробирования (которые сообщают, когда передаются данные). Обычно в шине данных предусматривается столько же проводников, сколько разрядов в компьютерном слове, чтобы можно было сразу передать все слово. Однако в PC есть только 8 проводников шины данных (D0-D7); за один цикл передачи вы можете переслать байт, но для того, чтобы переслать 16-разрядное слово, необходимо выполнить два цикла передачи. Количество разрядов шины адреса определяет количество адресуемых устройств: если магистраль используется для обращения как к устройствам ввода-вывода, так и к памяти (стандартная ситуация), она должна иметь от 16 до 32 проводников адресной шины, что соответствует адресному пространству от 64 Кбайт до 4 Гбайт; магистраль, используемая только для ввода-вывода, может иметь от 8 до 16 разрядов адреса (от 256 до 64 К устройств ввода-вывода). [IBM PC общается по своей магистрали как с памятью, так и с устройствами ввода-вывода и имеет 20 адресных проводников (А0-А19), что соответствует 1 Мбайт адресного пространства.] И наконец, передаваемые данные синхронизуются стробирующими импульсами, передаваемыми по дополнительным проводникам магистрали. Для того чтобы реализовать описанную схему, существуют два пути: предусмотреть отдельные линии «чтение» и «запись» (с названиями, например, READ и WRITE) и возбуждать на той или другой из этих линий сигналы, синхронизирующие передачу данных; иметь одну линию стробирующих сигналов (STROBE) и одну линию READ/WRITE', причем импульс на линии STROBE синхронизирует передачу данных в направлении, которое определяется уровнем сигнала на линии READ/WRITE'. IBM PC использует схему (действующий уровень сигнала-низкий) с линиями «чтение/запись», названными IOR', IOW', MEMR' и MEMW'. Поскольку PC различает память и устройства ввода-вывода, то и линий этих четыре, по два строба (чтения и записи) на тот и другой тип ввода-вывода.

Сигналы данных, адреса и четыре строб-сигнала — это обычно все, что требуется для организации простейшего режима передачи данных. Однако для PC необходим еще один сигнал, названный выбор адреса (AEN — Adress ENable) для того, чтобы различать обычную передачу данных в устройстве ввода-вывода от режима передачи, называемого прямой доступ к памяти (ПДП) (DMA — Direct Memory Access). Режим ПДП мы рассмотрим в разд. 10.12, а сейчас вам достаточно знать, что AEN имеет низкий уровень для обычного ввода-вывода и высокий-для режима ПДП. Таким образом, сейчас у нас есть 33 сигнала магистрали: D0-D7, А0-А19, IOR', IOW', MEMR', MEMW' и AEN. Давайте посмотрим, как они работают.

10.06. Программируемый вывод данных ввод-вывод:

Простейший метод обмена данными по магистрали компьютера известен как программируемый ввод-вывод, это обозначает, что данные передаются с помощью операторов программы IN или OUT (направления передачи для IN и OUT входят в состав тех немногих правил, которых придерживаются все изготовители компьютеров: IN всегда означает направление к ЦП, a OUT всегда означает направление из ЦП). В целом процесс вывода данных (и записи в ОЗУ) предельно прост и логичен (рис. 10.6).

Рис. 10.6. Цикл ввода-вывода при записи (все измерения в нc).

Адрес приемника и данные, которые необходимо передать, выставляются на соответствующие линии магистрали центральным процессором. Строб-сигнал записи (IOW' или MEMW') устанавливается в низкое состояние цетральным процессором для того, чтобы сигнализировать приемнику о том, что данные установлены и их можно считывать. На магистрали PC адрес гарантированно установлен, начиная с момента времени приблизительно за 100 нс до IOW', а данные гарантированно установлены по крайней мере за 500 нс до окончания IOW' (и в течение следующих 185 нс после окончания этого сигнала).

Для того чтобы принимать участие в подобных играх, периферийное устройство (пусть в нашем случае это — графический дисплей) наблюдает за шинами адреса и данных. Когда устройство обнаруживает свой собственный адрес, оно считывает информацию с шины данных по спаду сигнала IOW'. Вот и все.

Рассмотрим пример, приведенный на рис. 10.7.

Рис. 10.7. Растровый дисплей.

Здесь мы спроектировали растровый графический дисплей; вы последовательно передаете ему пары чисел X, Υ и на его экране отображается каждая точка в декартовой прямоугольной системе координат, причем первое число соответствует абсциссе, а второе — ординате отображаемой точки. Сначала мы должны выбрать адрес устройства ввода-вывода. На рис. 10.8 приведены зарезервированные и доступные адреса устройства ввода-вывода для IBM PC; мы выбираем 3C0H для Х-регистра и ЗС1Н для Y-peгистра.

Рис. 10.8. Адреса ввода-вывода IBM PC.

Микросхема `688-8-разрядный компаратор со стробированием; состоянию равенства сравниваемых кодов которого соответствует низкий уровень на выходе, вырабатывает низкий выходной сигнал в том случае, когда 8 бит разрядов А2-А9 совпадают с заданными значениями, в нашем случае - когда адрес на магистрали лежит в диапазоне 3C0H-3С3Н (вы можете использовать комбинационную схему, но компаратор адреса компактнее). Мы также потребуем в соответствии с ранее приведенными разъяснениями, чтобы AEN был низкого уровня. Трехвходовые логические схемы И-НЕ завершают дешифрацию адреса, используя адресные линии А0, А1 для того, чтобы установить низкий уровень на своих выходах отдельно для адресов 3C0H и ЗС1Н (другой способ будет вкратце описан ниже). В конце концов указанные выходы логически перемножаются с IOW' для того, чтобы получить синхросигнал для Х- и Y-регистров, которые представляют собой 8-разрядные регистры на D-триггерах (микросхемы `574). Эти регистры фиксируют байты с шины данных в тех случаях, когда а) выбран требуемый адрес, б) сигнал AEN — в низком состоянии, в) был выработан сигнал IOW'. Восьмиразрядные цифро-аналоговые преобразователи (ЦАП) преобразуют считываемые байты в аналоговое напряжение, подаваемое на Х- и Y-входы устройства управления выводом на электронно-лучевую трубку (ЭЛТ) дисплея. Спустя несколько микросекунд после считывания Y-координаты, два одновибратора вырабатывают 5-микросекундный импульс подсветки, увеличивающий интенсивность свечения изображаемой на экране точки (все устройства управления выводом на ЭЛТ имеют для этого вход Z). Для того чтобы изобразить график или набор символов на экране, необходимо последовательно выводить Х- и Y-координаты, повторяя их в одном и том же порядке (сначала X, а затем Y) достаточно быстро, чтобы глаз не видел мерцания.

Микрокомпьютеры достаточно быстры для того, чтобы успевать в цикле отображать на дисплее несколько тысяч точек без раздражающего мерцания. Учитывая, что растровый дисплей — это стандартное устройство микрокомпьютера для вывода изображений, приведенный пример более полезен в качестве модели фотографического графопостроителя сверхвысокого разрешения, использующего 14-разрядный ЦАП и дисплей с микроскопическим размером точек (см. следующее упражнение).

Несколько полезных замечаний:

а) Отметим, что мы подобрали полярность сигналов таким образом, что D-триггеры переключаются по спаду сигналов IOW'; это существенно, так как в момент времени, соответствующий фронту этого импульса, данные могут еще не установиться. Для большей надежности следует удостовериться, что временные соотношения сигналов удовлетворяют временам упреждения и удержания схем `574; фактически, однако, для такой медленной, как у IBM PC магистрали трудно заставить схему, подобную описываемой, работать правильно, поскольку с момента установки данных до спада IOW' проходит более 500 нc.

б) Вы можете сэкономить несколько логических элементов, использовав в цепи дешифрации адреса стробируемый дешифратор так, как показано на рисунке. Дешифраторы типа,138 (3 разряда на 8 направлений) и типа `139 (сдвоенный, 2 разряда на 4 направления) имеют один или более стробирующих входов и удобны для построения схем такого рода.

в) Отметим также, что мы могли бы объединить 3-входовые и 2-входовые элементы И-НЕ в 4-входовые И-НЕ, здесь этого не сделано для того, чтобы четче выделить отдельно факт дешифрации адреса и затем — совпадения результата дешифрации со строб-сигналом IOW'.

г) На самом деле мы можем полностью игнорировать разряд А1 и схема будет работать по-прежнему! Однако тогда она начнет откликаться также на адреса 3С2 и 3С3 (как X и Y, соответственно) и произойдет потеря двух адресов ввода-вывода. На практике, однако, часто идут этим путем и, не полностью дешифруя адрес, экономят микросхемы (ведь адресное пространство остается достаточно обширным, даже если вы и потеряете таким образом некоторое количество адресов). В рассматриваемом примере мы можем подключить IOW' вместо А1 и полностью отказаться от 2-входовой схемы И-НЕ.

д) Сопряжение с магистралью, подобное обсуждаемому, будет более гибким, если адрес устанавливать DIP-переключателями (или DIP-перемычками); тогда вы сможете выбрать адрес верно, чтобы не было конфликта с адресом другого устройства, подключенного к той же магистрали. Внести соответствующие изменения в схему несложно-достаточно восемь входов компаратора подсоединить через ключи к общему проводнику («земле»), а через резисторы — к цепи +5 В.

е) Для пояснения существа дела в этом примере мы использовали отдельные микросхемы 8-разрядных регистров и ЦАПов. На практике у вас есть возможность применить ЦАП со встроенной схемой выборки адреса (например, «микропроцессорно-совместимый» ЦАП типа AD 7528-сдвоенный ЦАП с входной схемой выборки адреса); такая схема выпускается даже в счетверенном варианте (AD7226), а также в варианте с двойной буферизацией, двухкаскадной выборкой адреса для каждого ЦАП (счетверенный ЦАП AD 7225).

Упражнение 10.1. Нарисуйте функциональную схему адресного компаратора с настройкой адреса.

Упражнение 10.2. Нарисуйте схему сопряжения растрового дисплея с магистралью, используя 16-разрядные ЦАП для преобразования как Х-, так и Υ-κοординат. Вам потребуется 4 последовательно расположенные адреса. Используйте первые 2 для регистрации Х-регистра, а два последних-для Y-регистра; конечно, надо предусмотреть возможность настройки базового адреса ввода-вывода с использованием переключателей в DIP-исполнении. Как для Х-, так и для Y-координат четным адресам соответствует младший, а нечетным — старший байт соответствующего кода; это удобно (поскольку МП 8086 оперирует 16-разрядными словами, можно пользоваться командами ввода-вывода слов для передачи данных этому устройству).

Программирование графического дисплея. Программирование такого устройства не представляет сложностей. Как это делается показывает программа 10.3, которой надо указать адреса ячеек, где хранятся Х- и Y-координаты первой точки и количество точек, которое надо отобразить. Программа обслуживания дисплея возможно, будет оформлена как подпрограмма с этими параметрами, передаваемыми при ее вызове. Программа заносит адреса массивов Х- и Y-координат (т. е. адрес первой пары Х-, Y-координат) в индексные регистры SI и DI, а байт количества точек в регистр СХ. Этот регистр потом используется в цикле, в котором пары Х-, Y-координат последовательно передаются в порты ввода-вывода по адресам 3C0 и ЗС1. В каждом цикле перемещаются указатели массивов X и Υ; а содержимое счетчика декрементируется и сравнивается с нулем, который характеризует отображение последней точки; затем указатели и счетчик устанавливаются в исходное состояние и процесс вывода начинается снова.

Пара важных моментов: однажды запустившись, программа постоянно отображает массив точек. В действительности программа должна проверять состояние клавиатуры, чтобы заметить, если оператор захочет прекратить вывод на дисплей. Можно также прекратить вывод спустя заданное время или с помощью прерывания, о чем речь будет идти ниже.

Обычно при регенерации изображения на дисплее, организованной подобным образом, для дополнительных продолжительных вычислений во время вывода изображения времени нет. Гораздо лучшим методом является обновление изображения на экране из собственной памяти дисплея, что разгружает компьютер. Как бы то ни было, если ваша цель — построить изображение с высоким разрешением для получения фотографической копии, эта программа и схема сопряжения, спроектированная по условиям упражнения 10.2, будет работать замечательно.

10.07. Программируемый ввод-вывод: ввод данных

Передача данных в другом направлении при программируемом вводе-выводе осуществляется столь же просто. Схема сопряжения следит за шиной адреса так же, как и ранее. Если эта схема обнаруживает свой собственный адрес (и сигнал AEN находится в низком состоянии), она выставляет данные на шину данных, обеспечивая их совпадение во времени с сигналом IOR' (рис. 10.9).

Рис. 10.9. Цикл ввода-вывода при чтении.

Пример такой схемы приведен на рис. 10.10.

Рис. 10.10. Параллельный входной порт.

Схема позволяет компьютеру считать байт, хранящийся в регистре на D-триггерах типа `574. Поскольку и тактовый вход, и входы данных регистра доступны внешнему устройству, в регистр может быть занесена цифровая информация практически любого характера (выход цифрового прибора, АЦП и т. п.). Для разнообразия мы использовали вместо всех логических элементов 2-разрядный дешифратор адреса типа `679. Эта «умная микросхема» имеет 12 адресных входов, вход выборки и 4 «программируемых» входа. Если вы хотите дешифровать некоторый определенный адрес, это делается хитро: функционально такая микросхема представляет собой 12-входовую схему И-НЕ, программируемое число этих входов может быть дополнительно инвертировано; инвертируются всегда входы с меньшими номерами, а их количество вы можете задавать с помощью 4-х отдельных программируемых входов.

Пусть мы хотим «добраться» до резервного порта ввода-вывода с адресом 200Н (рис. 10.8). Нам необходимо распознать состояние А9 — высокий уровень, А0-А8 — низкий. Ко всему прочему мы можем использовать микросхему `679 для стробирования дешифрованного адреса низкими уровнями сигналов AEN и IOR'.

Итак, окончательно нам требуется схема И-НЕ с 11-ю инвертирующими входами и одним неинвертирующим входом, что обеспечивается подачей кода 1011, осуществляемой аппаратным образом на программируемые входы. Затем подключим адресную шину и синхросигналы так, как показано на рис. 10.10. Как только команда

IN AL,200H

выполнится, ЦП выставляет адрес 200Н на линиях А0-А9 и затем устанавливает IOR' на время 630 нc. Центральный процессор считывает то, что он обнаруживает на шине данных (D0-D7) в момент времени, соответствующий спаду сигнала IOR', затем сбрасывает А0-А9.

Реакция периферийного устройства должна заключаться в том, чтобы выдать данные на соответствующие разряды D0-D7 по крайней мере за 50 нc до конца IOR'; выполнить это условие не составляет никакого труда, так как устройству известно, что от него требуются данные, уже по меньшей мере 600 не. Для типовой задержки срабатывания используемых здесь микросхем 10 нc, 600 нс выглядят вечностью.

Начиная с этого примера, мы прекратим пристально рассматривать весь клубок линий магистрали, а просто будем называть отдельные линии по именам.

Сигналы магистрали: двунаправленность и однонаправленность. Из двух примеров, которые мы рассмотрели до сих пор, вы могли увидеть, что некоторые линии магистрали являются двунаправленными, например линии шины данных: во время записи на них выставляется выходной код ЦП, а во время чтения — выходной код периферийного устройства. Как ЦП, так и периферийное устройство для подключения к таким линиям используют элементы с третьим состоянием на выходе.

Другие сигналы, такие как IOW' и IOR', всегда вырабатываются ЦП с помощью стандартных драйверов. Типичным для компьютерных магистралей является существование обоих типов линий, двунаправленных линий для данных, передаваемых как в одном, так и в другом направлении, и однонаправленных линий для сигналов, которые всегда вырабатываются ЦП (или, более точно, соответствующими логическими схемами управления магистралью). Процессор всегда использует какой-то простой протокол, вроде наших правил установки/чтения в соответствии с сигналами IOW', IOR' и адресными, который предотвращает конфликтные ситуации на совместно используемых линиях магистрали.

Среди перечисленных до сих пор только шина данных является двунаправленной; адрес, сигнал AEN и синхросигналы распространяются только в одном направлении — от ЦП. (Чтобы не создавать неправильного впечатления, надо уточнить, что более сложные компьютерные системы позволяют другим адресатам магистрали становиться ее «хозяевами»; очевидно, в таких системах почти все сигналы магистрали являются мультиплексируемыми и двунаправленными. IBM PC в этом отношении необычайно проста.)

10.08. Программируемый ввод-вывод: регистры состояний

В нашем последнем примере компьютер мог считать байт из схемы сопряжения в любое время, когда захочет. Это замечательно, но как узнать, когда можно считать что-нибудь стоящее? В некоторых случаях вы можете потребовать, чтобы компьютер считывал данные через равные интервалы времени, отсчитываемые его таймером реального времени. Пусть например, компьютер «заставляет» АЦП начинать преобразование через равные промежутки времени (командой OUT) и затем считывает результат несколькими микросекундами позже (командой IN). В измерительных системах этого может быть вполне достаточно. Однако часто встречаются такие случаи, когда внешнее устройство имеет свой собственный «интеллект», и было бы хорошо, если бы оно могло без промедления сообщить компьютеру, что что-то произошло.

Классическим примером является алфавитно-цифровой ввод при нажатии каких-либо клавиш клавиатуры дисплея. Если вы не хотите терять символы, компьютер должен ввести каждый из них и без большой задержки. Еще более серьезная ситуация с быстрым накопительным устройством, таким как диск или ленточный магнитофон; данные необходимо передавать со скоростью до 100000 байт в секунду без задержки. Для того чтобы решить эту проблему, существуют три реальные возможности: использовать регистры состояний, прерывания и прямой доступ в память (ПДП). Давайте начнем с простейшего метода-регистров состояния — проиллюстрированного схемой сопряжения клавиатуры на рис. 10.11.

Рис. 10.11. Интерфейс клавиатуры с битом состояния.

В этом примере ASCII-код записывается в 8-разрядный регистр на D-триггерах типа `574 строб-сигналом, вырабатываемым клавиатурой при нажатии на очередную клавишу. Мы соорудили типовое программируемое устройство ввода данных так, как показано на рис. 10.11, используя трехстабильные выходы микросхемы `574 для непосредственной связи с шиной данных. Входной сигнал, обозначенный как KBDATA SEL', поступает от схемы дешифратора адреса того же в точности типа, который приведен в предыдущем примере, и устанавливается в низкое состояние, когда код адреса, предварительно присвоенного данному устройству, появляется на шинах адреса магистрали (вместе с низким уровнем сигнала AEN).

Что в этом примере нового, так это — триггер, который устанавливается в единичное состояние, когда клавиша некоторого символа нажата и сбрасывается, когда символ считывается компьютером. Фактически это — одноразрядный регистр состояния, высокий уровень выходного сигнала которого означает возможность считать очередной символ, низкий уровень — отсутствие таковой. Компьютер может опросить бит состояния, выполнив команду ввода данных IN с другого адреса рассматриваемого устройства, дешифрованного как KBFLAG SEL' (с помощью логических вентилей, дешифраторов или каких-либо других элементов).

Для того чтобы описать состояние этого устройства, требуется только один бит, поэтому схема сопряжения управлялась только битом старшего разряда, в данном случае с помощью буфера с тремя выходными состояниями типа `125. (Никогда не подключайте двунаправленные линии к выходам устройств, специально для этого не предназначенным!) Линия, подходящая на рисунке к изображению буфера снизу, управляет трехстабильным выходным сигналом, разрешая его своим низким уровнем, что обозначено кружком.

Клавиатура терминала: пример программы. Итак, теперь у компьютера имеется возможность узнать, когда готовы очередные данные. Программа 10.4 показывает как.

Эта программа предназначена для того, чтобы считывать символы с клавиатуры терминала, адрес порта данных которого — KBDATA (хорошим стилем программирования является определение действительного кода адреса порта, который соответствует адресу, определяемому аппаратным образом, как KBDATA SEL и т. п. — несколькими операторами, располагаемыми в начале программы, как показано); каждый символ отображается (режим «эхо») на экране дисплея компьютера (адрес порта = OUTBYTE). Когда набирается целая строка, программа передает управление блоку обработки строки, функционирование которого определяется символьным содержанием строки. Когда программа готова к обработке другой строки, она печатает звездочку. Если у вас есть какой-то опыт в работе на компьютере, программа покажется вам достаточно очевидной.

Программа начинается с инициализации указателя буфера символов, осуществляемой пересылкой адреса буфера в адресный регистр ВР. Отметим, что мы не можем записать

MOV BP,charbuf

так как такая команда загрузит содержимое, а не адрес; в языке ассемблера процессора 8086 для обозначения адреса ячейки памяти используют слово offset перед идентификатором этой ячейки. После этого программа с помощью команды IN считывает бит состояния клавиатуры, логически умножает его на 80Н, чтобы оставить только бит состояния (это называется «маскированием») и результат сравнивает с нулем. Нуль означает, что бит не равен единице и программа выполняет цикл. Когда обнаружен ненулевой бит состояния, программа считывает данные из порта данных клавиатуры (при этом обнуляется бит состояния триггера) и последовательно запоминает их в буфере строки, инкрементируя указатель (ВР) и вызывая подпрограмму, которая отображает символ на экран. Наконец, программа проверяет, не оканчивается ли строка символом возврата каретки: если этого нет, то управление передается циклу повторной проверки бита состояния клавиатуры; если последний символ является символом перевода строки (CR), программа передает управление обработчику строки, после чего печатает звездочку и начинает все заново.

Даже простая подпрограмма, используемая для вывода символа на дисплей, требует нескольких операций проверки флага (бита) состояния и маскирования. Сначала подпрограмма запоминает байт в регистре АН, затем считывает и маскирует флаг занятости экрана дисплея. Ненулевой флаг означает, что дисплей занят и надо продолжить проверку этого флага; в противном случае подпрограмма заносит символ в регистр AL, пересылает этот символ в порт данных дисплея и завершается.

Несколько замечаний по программе: а) поскольку бит старшего разряда (который мы аппаратным образом определили как бит флага) является знаковым, стадию маскирования флага клавиатуры можно опустить; при этом можно использовать команду JPL KFCHK. Эта уловка, однако, срабатывает только при проверке старшего разряда и поэтому весьма специфична; б) продолжая практику хорошего стиля программирования, символ возврата каретки (0DH) и звездочки можно было бы определить как константы, подобно KBMASK; в) блок обработки строки может быть оформлен в качестве подпрограммы; г) в том случае, если процедура обработки строки слишком длинна, могут быть потеряны символы; это соображение приводит к использованию более изящного механизма прерывания, который мы вскоре рассмотрим; д) программы обслуживания клавиатуры и дисплея используются настолько часто, что PC имеет встроенные программы такого рода, вызываемые посредством программных прерываний (рассмотрим их позже); таким образом, наша программа вообще не нужна!

Обобщение битов состояний. Пример с клавиатурой иллюстрирует протокол обработки бита состояния; однако протокол настолько прост, что у вас может создаться неправильное представление об этом предмете. На самом деле интерфейс внешнего устройства несколько сложнее, как правило он предусматривает несколько флагов для фиксации различных условий. Например, в интерфейсе ленточного магнитофона вам, как правило, надо иметь следующие биты состояний: начало ленты, конец катушки, ошибка четности, движение ленты и т. д. Традиционная процедура заключается в том, чтобы свести все биты состояний в один байт или слово так, чтобы сразу считать все биты из регистра состояний с помощью команды ввода данных IN. Обычно надо назначить бит, показывающий наличие любой из ошибочных ситуаций, старшему разряду слова состояний с тем, чтобы простая проверка знака сигнализировала бы о наличии какой-нибудь ошибки; если это обнаруживается, можно проверять отдельные разряды слова (накладывая маску с помощью логической функции «И») для выявления конкретной ошибки. Более того, в сложных интерфейсах, возможно, не требуется, чтобы биты состояния сбрасывались «автоматически», как это происходило с единственным битом в нашем примере; вместо этого можно воспользоваться командой вывода данных, каждый бит которых сбрасывает соответствующий флаг.

Упражнение 10.3. У нашего интерфейса клавиатуры нет средства, позволяющего компьютеру определить, был ли пропущен символ. Измените схему так, чтобы она использовала два бита состояний: «готовность символа» (это у нас уже есть) и «потеря данных». Флаг «потеря данных» должен устанавливаться на линии D6 того же порта состояний, что и «готовность символа»; флаг «потеря данных» должен становиться равным единице, если клавиша была нажата до того, как предыдущий символ был считан компьютером, в остальных случаях он должен быть равен нулю.

Упражнение 10.4. Дополните программу 10.4 блоком проверки потерянных данных. Это должно осуществляться вызовом подпрограммы с именем LOST в тех случаях, когда флаг «потеря данных» установлен равным единице; в остальных случаях программа должна работать как и раньше.

10.09. Прерывания

Только что проиллюстрированное использование флагов состояний является одним из трех способов, используемых внешним устройством для того, чтобы «намекнуть» компьютеру на необходимость выполнения каких-то действий. Хотя во многих простых случаях этого вполне достаточно, имеется серьезный недостаток в том, что внешнее устройство не может само объявить о необходимости выполнения каких-то действий — оно должно ждать до тех пор, пока ЦП не опросит его посредством считывания содержимого регистра состояния командой IN. Устройствам, которым требуется быстродействие (такие, как диски или другие, чья работа предусматривает ввод-вывод в реальном масштабе времени), необходим частый опрос флагов состояний, и в компьютерной системе с несколькими подобными устройствами ЦП вскоре обнаружит себя проводящим основное время за проверкой флагов состояний, как в последнем примере.

Более того, даже при постоянно выполняемой проверке флагов состояний у вас еще остается повод для беспокойства. В частности, в последнем примере ЦП будет успевать вводить символы, набираемые на клавиатуре, если он находится в главном цикле проверки флагов. Но что, если ЦП затратит 1/10 секунды в той части алгоритма, которая обеспечивает обработку строки? Или дисплей медленный и заставляет программу ждать, пока сбросится флаг занятости? Все, что в таких случаях необходимо, это — механизм, позволяющий внешнему устройству прервать обычный порядок работы ЦП в тех случаях, когда надо что-нибудь сделать. Затем ЦП может проверить регистр состояния для того, чтобы определить, чем вызвано беспокойство, аккуратно сделать то, что положено и вернуться к нормальной работе.

Для того чтобы дополнительно использовать потенциальные возможности прерываний в компьютере, необходимо добавить несколько новых сигналов на магистрали: по крайней мере, одна обобщенная линия для передачи прерываний от внешних устройств и (обычно) пара линий, с помощью которых ЦП может определить, какое устройство выдало сигнал прерывания. К сожалению, пример с IBM PC не очень удачен, так как эта машина не использует всех возможностей прерываний. Однако недостаток гибкости более чем компенсируется простотой; реализация аппаратных прерываний в периферийных устройствах PC проще пареной репы.

Теперь о том, как это все работает: магистраль PC имеет набор из 6-ти линий для передачи сигналов запросов прерываний, именуемых IRQ2-IRQ7. Эти линии используют положительную логику и подключены к схемам обрамления ЦП (в частности, к контроллеру прерываний типа 8259). Для того чтобы возбудить прерывание, вы просто устанавливаете на одной из линий высокий уровень сигнала. Если прерывания разрешены (в том числе и то конкретное IRQ, которое вы выбрали), ЦП после завершения очередной команды прерывает выполнение программы, а затем (после сохранения в стеке флагов и текущего указателя команд) переходит к программе обработчика прерывании, расположенной где-то в памяти.

В обработчике вы предусматриваете любые требуемые действия (например, чтение данных с клавиатуры), и поместить его вы можете где угодно по своему усмотрению; ЦП выясняет, по какому адресу надо совершить переход, анализируя 4-байтовый адрес обработчика, расположенный в выделенной области в начале памяти. Адрес этой области зависит от выбранного IRQ; для МП 8086 16-ричное значение этого адреса вычисляется по формуле 20 + 4n, где n-уровень прерывания. Например, ЦП будет реагировать на прерывание IRQ2 посредством перехода по 4-байтовому адресу, который хранится в ячейках памяти с адреса 28Н по 2ВН (это похоже на косвенную адресацию, с той лишь разницей, что адрес располагается в памяти, а не в регистре); конечно, начальные адреса ваших обработчиков прерываний следует заранее поместить в память. В конце обработчика надо выполнить команду IRET, которая обеспечит восстановление предварительно сохраненного содержимого регистра флагов и передачу управления обратно в точку вызова.

Проиллюстрируем это, добавив в схему интерфейса клавиатуры прерывания (рис. 10.12).

Рис. 10.12. Интерфейс клавиатуры с прерываниями.

Мы оставили флаг «символ готов» и схему программируемого ввода-вывода практически без изменений, за исключением того, что сигнал сброса флага включен по схеме «ИЛИ» с новым сигналом магистрали RESET DRV, который является выходным для ЦП, он на короткое время устанавливается в высокое состояние при включении компьютера. Обычно этот сигнал используется для установки триггеров и других элементов последовательной логики в определенное состояние при включении питания. Очевидно, этот сигнал должен сбросить флаг готовности байта к приему его в программу (в нашем новом интерфейсе установленный флаг готовности даже вызвал бы прерывание). Еще одно внесенное нами изменение — использование сокращенных обозначений для описания разрядности шины данных для того, чтобы сделать схему более удобочитаемой.

Новая схема обработки прерываний включает драйвер для установки IRQ2 в случае готовности символа. Вот и все схемные новшества, которые вам необходимы. Мы добавили, хотя в этом нет обязательной необходимости, возможность отключения устройства выработки сигнала прерывания (которое представляет собой трехстабильный буферный элемент) путем передачи байта, младший разряд которого установлен в низкое состояние, по адресу порта KBFLAG. Это можно будет использовать в том случае, если вам захочется подключить к тому же уровню IRQ другое устройство, вырабатывающее прерывания, причем так, чтобы в каждый момент только одно устройство могло инициировать прерывание (ниже мы дополнительно поясним этот щекотливый момент).

10.10. Обработка прерываний

Компьютеры семейства IBM PC/XT реализуют обработку прерываний просто (хотя и ограничивая при этом гибкость), используя интегральную микросхему контроллера прерываний типа 8259, установленную на базовой плате. Эта микросхема выполняет основной объем работы, которая включает в себя определение приоритетов, маскирование и выбор векторов прерываний (мы опишем это после примера, приведенного ниже). Со своей стороны ЦП определяет, что наступило прерывание и реагирует на это сохранением указателя команд и регистра флагов, а также запрещением дальнейших прерываний, а затем-совершая переход по соответствующему адресу, записанному в области векторов прерываний в начальных ячейках памяти. Ваша программа обработки прерываний делает остальное, а именно: а) сохраняет с помощью команды push все регистры, которые вы собираетесь использовать (напомним, что прерываемая программа не может заранее подготовиться к прерыванию, поскольку оно может произойти в любой момент во время выполнения программы как гром среди ясного неба); б) выясняет, при необходимости, с помощью чтения одного или нескольких регистров состояний, что именно требуется выполнить; в) выполняет это; г) восстанавливает ранее сохраненные регистры из стека; д) сообщает микросхеме 8259, что все сделано (передавая байт признака завершения прерывания 20Н и, наконец, е) выполняет возврат из прерывания — команду IRET, что заставляет ЦП восстановить содержимое прежнего регистра флагов, сохраненное предварительно в стеке и передать управление (использовав прежнее, также предварительно сохраненное в стеке значение указателя команд) обратно в ту программу, выполнение которой было прервано. Где-то в программе вы должны ж) загрузить адрес программы-обработчика прерываний по адресу вектора прерываний, соответствующего уровню IRQ, используемого аппаратной частью компьютера, и сообщить контроллеру прерываний 8259 о том, что необходимо разрешить прерывание указанного уровня.

Программа 10.5 демонстрирует программирование клавиатуры с использованием прерываний. Вот общая схема: главная процедура выполняет необходимые предустановки, а затем в цикле прерывает значение флага (программного, не аппаратного), который устанавливает обработчик прерываний, обнаружив код «возврата каретки»; когда главная процедура замечает, что флаг установлен, она переходит к заданным действиям над строкой, а затем происходит возврат к циклу проверки флага. Обработчик прерываний, в который передается управление при каждом прерывании, заносит символ в буфер строки, устанавливает флаг, если символ оказался «возвратом каретки» и возвращает управление.

Давайте более пристально посмотрим на программу. После задания адреса порта и адреса вектора прерываний IRQ2 она выделяет 100 байт под буфер строки (первоначально буфер заполняется нулями). Собственно выполнение программы начинается с занесения адреса буфера в адресный регистр SI, обнуление флага конца строки, и помещения адреса обработчика прерываний (который начинается с ΚΒΙΝΤ) в ячейку 28Н. Для того чтобы разрешить контроллеру прерываний 8259 прерывания 2-го уровня, обнулим бит 2 маски (команды IN, AND, OUT); затем разрешим прерывания ЦП и передадим единицу в KBFLAG, что приводит к разрешению трехстабильного драйвера.

Теперь можно работать. После этого программа выполняет цикл, а прямо под «носом» главной процедуры скрыто обрабатывается прерывание до тех пор, пока не будет обнаружено, что "buflg" загадочным образом установился. Флаг и указатель буфера немедленно устанавливаются в исходное состояние (на тот случай, если придет следующее прерывание), затем строка «проглатывается». Хорошим советом было бы пожелать либо быстрее выполнять программу, либо скопировать строку в другой буфер, поскольку через несколько миллисекунд может произойти другое прерывание (сопровождаемое занесением нового байта в буфер), однако за это время можно выполнить несколько тысяч команд, что более чем достаточно для копирования строки.

Обработчик прерываний является отдельной программой, которая не входит в главную процедуру. Он активизируется с помощью прерывания 2-го уровня через свой адрес, который, в свою очередь, заранее был загружен по адресу 28Н. Обработчик в точности знает, что должно быть сделано, и делает это безропотно: он сохраняет содержимое регистра АХ (поскольку планирует разнести последнее вдребезги), считывает символ из порта данных клавиатуры, заносит этот символ в буфер, инкрементирует указатель, дополнительно отображает символ на экран (в эхо-режиме), устанавливает флажок (если был введен символ возврата каретки), посылает сигнал об окончании прерывания контроллеру 8259, восстанавливает содержимое регистра АХ и возвращает управление.

Если вы еще раз взглянете на приведенный выше перечень действий, выполняемых обработчиком, то можно заметить, что мы не упомянули только один этап, а именно, считывание флажков состояний, которые позволяют выяснить, какие из нескольких действий должны быть выполнены. В данном случае, поскольку существует единственная причина, вызывающая прерывание, а именно, запрос на ввод очередного символа с клавиатуры, чтение флажков не требуется. (Программист должен отчетливо понимать, при каких условиях происходит аппаратное прерывание и что требуется для его обработки.)

Несколько замечаний по поводу этой программы: во-первых, даже хотя мы и использовали прерывания, программа выглядит столь же тупой, что и раньше — она постоянно выполняет цикл, проверяя состояние признака конца строки. Однако при необходимости можно организовать цикл и по-другому, если необходимо выполнять еще какие-то действия. Это и происходит на самом деле в нашей программе, в той ее части, которая начинается с метки LINE и выполняет вывод символа «звездочка»; в течение этого времени прерывания обеспечивают занесение новых символов в буфер, в то время как в нашем предыдущем примере без прерываний эти символы были бы потеряны.

Второе замечание можно сформулировать следующим образом: даже в том случае, когда мы используем прерывания, остается беспокойство, не выполняет ли программа какие-либо операции с предыдущей строкой в то время, когда следующая строка уже полностью введена. Конечно, в среднем, программа просто обязана не отставать от ввода с клавиатуры; тем не менее может возникнуть ситуация, при которой обработчик строки случайно затратит много времени, и вам потребуется временный буфер более чем на одну строку. Одно решение этой проблемы — скопировать информацию во второй буфер или поочередно обращаться к каждому из двух буферов. Изящной альтернативой является организация входного потока в виде очереди, устроенной как кольцевой буфер, в котором два указателя обеспечивают извлечение очередного входного символа, а предыдущий символ удаляется. Обработчик прерываний продвигает вперед входной указатель, а обработчик строки продвигает выходной указатель. Подобный кольцевой буфер как правило имеет емкость 256 байт, что позволяет поддерживать обработку нескольких строк.

Третье замечание относится к обработчику прерываний самому по себе. Обычно чем он короче и проще, тем лучше, например, в нем возможна установка флажков для указания на необходимость выполнения в главной процедуре более сложных операций. Если обработчик прерываний будет долго переводить дух после каждого прерывания, вы рискуете потерять данные, источником которых являются другие устройства, вырабатывающие прерывания, поскольку в то время, когда ЦП обрабатывает прерывание, другие прерывания запрещены. В такой ситуации выход заключается в том, чтобы вновь разрешить обработку прерываний в вашем собственном обработчике командой STI после того, как будут выполнены критические отрезки программы, которые должны выполняться в первую очередь. Затем, если возникло прерывание, ваш обработчик прерываний будет сам прерван. Поскольку флажки и адреса возврата сохраняются в стеке, программа сумеет найти обратную дорогу, сначала в ваш обработчик, а затем в главную программу.

10.11. Прерывания в целом

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

Другим примером устройств, использующих прерывания, являются часы реального времени, в которых периодически (часто 10 раз в секунду, но в ПЭВМ типа IBM PC 18,2 раза в секунду) вырабатываемое прерывание «подталкивает» подпрограмму определения текущего времени; еще одним примером является параллельный интерфейс печатающего устройства, который вырабатывает прерывания всякий раз, когда готов новый символ. Используя прерывания, такие периферийные устройства позволяют компьютеру одновременно выполнять другие задания; вот почему вы можете работать с текстовым редактором, пока ваша ПЭВМ печатает файл (и при этом еще и отсчитывает текущее время).

IBM PC, однако, не иллюстрирует всех возможностей прерываний. Как мы видели, имеются 6 линий IRQ на магистрали, каждая из которых может быть задействована только одним устройством, использующим прерывания. Линии IRQ пронумерованы в соответствии с приоритетом; в том случае, когда вырабатываются несколько прерываний, первым отрабатывается то, номер которого меньше. Четыре из IRQ-линий предопределены для таких устройств, как последовательный порт (IRQ4), жесткий диск (IRQ5), гибкий диск (IRQ6) и порт печатающего устройства (IRQ7), оставляя неиспользуемыми только IRQ2 и IRQ3 [линии, соответствующие двум другим, используемым в IBM PC уровням IRQ, даже не выведены на магистраль, а используются на системной плате для обеспечения работы таймера с частотой пересчета 18,2 Гц (IRQ0) и клавиатуры (IRQ1)]. В том случае, если вы хотите дополнительно подключить стример или локальную сеть, придется использовать IRQ2 и IRQ3. Более того, прерывания отрабатываются по фронту сигнала, что делает тщетным какие бы то ни было разумные попытки использовать проводное «ИЛИ» для того, чтобы подключить несколько периферийных устройств к одной IRQ-линии.

Общие линии прерываний. Обычный протокол обработки прерываний, применяемый во многих компьютерах, обходит подобные ограничения. Посмотрите на рис. 10.13.

Рис. 10.13. Линии прерываний, совместно используемые несколькими устройствами.

Имеется несколько приоритетных линий IRQ-типа; здесь на входах ЦП (или других узлов, непосредственно с ними связанных) используется отрицательная логика. Для того чтобы сформировать сигнал прерывания, вы должны задать низкий уровень потенциала на одной из IRQ'-линий, используя, как показано, микросхему с открытым коллекторным выходом (или с тремя выходными состояниями). (Отметим хитрость, которая заключается в использовании элемента с трехстабильным выходом в качестве имитатора элемента с открытым коллектором.) Линии IRQ', каждая из которых подключена к нагрузочному резистору, используются несколькими периферийными устройствами совместно, так что к каждой IRQ'-линии можно подключить столько устройств, сколько захочется; в нашем примере два порта совместно используют IRQL Вообще говоря, более «нетерпеливое» устройство следует подключать к IRQ'-линии с более высоким приоритетом.

Поскольку линии IRQ' используются совместно, всегда может возникнуть прерывание, вызванное еще одним устройством в то же время и на той же линии (где уже выставлено прерывание). Центральный процессор должен знать, чем инициировано прерывание для того, чтобы передать управление соответствующему обработчику. Для этого существуют два пути - простой и сложный. Простой путь называется автовекторизованным опросом и используется практически повсеместно (хотя и не в IBM PC). Это делается следующим образом.

Автовекторизованный опрос. На одной плате с ЦП расположены некоторые электронные схемы (для примера мы возьмем электронные узлы, описываемые в гл. 11), которые инструктируют микропроцессор, что ему надо делать для поддержания режима автовекторизации, которая организована подобно тому, что сделано в IBM PC-каждый уровень прерывания вызывает передачу управления, адресуемую с помощью вектора, соответствующим образом расположенного в младших адресах памяти. Например, для МП серии 68000, с которой мы встретимся в гл. 11, существует 7 уровней приоритетных прерываний, которые адресуются 4-байтовыми указателями, располагаемыми в 28-ми (7x4) ячейках памяти с 64Н по 7FH. Адрес вызова обработчика прерываний вы записываете в эти ячейки как в вышеприведенном примере. Например, 4-байтовый адрес для обработчика, соответствующего 3-му уровню прерывания, вы должны записать в ячейки памяти с адресами (в 16-ричной форме) с 6С по 6F.

Перейдя в обработчик, вы знаете, какой уровень прерываний вы обслуживаете; вам только неизвестно, какое конкретно устройство инициировало прерывание. Для того чтобы выяснить, вы просто должны проверить регистры состояний каждого из устройств, подключенных к линии, соответствующей этому уровню прерываний (устройство никогда не должно выставлять запрос на прерывание без дополнительной установки одного или более битов состояний, которые можно считать). Если бит установлен, показывая, что надо бы что-то сделать, вы делаете то, что надо, и еще заботитесь о сбросе сигнала IRQ'. Некоторые устройства (такие, как клавиатура) сами сбрасывают в исходное состояние сигнал прерывания, когда осуществляется чтение данных, тогда как другие могут потребовать передачи специального байта по некоторому адресу порта ввода-вывода.

Если устройство, которое вы обслуживаете, было единственным источником прерываний данного уровня, то теперь, после передачи управления обратно в прерванную программу и продолжения ее выполнения, сигнал IRQ' будет установлен в высокое состояние. Однако если существовало второе устройство, выработавшее прерывание того же уровня, то сигнал на IRQ'-линии будет по-прежнему оставаться в низком состоянии (с помощью приводного «ИЛИ») и после возврата управления из обработчика прерываний ЦП немедленно адресуется к тому же самому вектору и соответственно обработчику. При этом путем опроса будет обнаружено другое устройство, инициировавшее прерывание, выполнено то, что надо и управление будет вновь передано прерванной программе. Отметим, что порядок, в котором вы опрашиваете регистры состояний, эффективно устанавливает программный приоритет, дополнительно к аппаратному приоритету нескольких IRQ'-уровней.

Подтверждение прерывания. Мы не можем проститься с прерываниями без того, чтобы не упомянуть о более сложной процедуре идентификации источника прерывания — подтверждении прерывания. При этом ЦП не должен опрашивать регистры состояний возможных кандидатов, поскольку устройство, инициирующее прерывание, сообщает по запросу ЦП свое имя. Устройство осуществляет это, устанавливая «вектор прерывания» (обычно-уникальный 8-разрядный код) на шине данных, в ответ на сигнал подтверждения прерывания, вырабатываемый ЦП в процессе реализации прерывания. Необходимые сигналы вырабатывает почти каждый МП. Последовательность событий такова: а) ЦП замечает ожидающее прерывание; б) ЦП завершает выполнение текущей команды, затем вырабатывает (1) сигналы магистрали, говорящие о прерывании, (2) определяет уровень прерывания (по младшим разрядам шины адреса), а также (3) вырабатывает подобные сигналам чтения строб-сигналы, которые приглашают устройство, инициировавшее прерывание, идентифицировать себя; в) устройство отвечает на такой набор сигналов магистрали, выставляя свой идентификатор (вектор прерывания) на шину данных; г) ЦП считывает вектор и передает управление обработчику прерываний, соответствующему прерывающему устройству; д) программная часть обработчика прерываний, как в нашем последнем примере, считывает флажки, получает и передает данные и т. д. В число прочих обязанностей обработчика прерываний входит наблюдения за тем, чтобы устройство, затребовавшее прерывание, не «забыло» потом его отменить; е) в конце концов обработчик прерываний возвращает управление той программе, выполнение которой было прервано.

Возможно, проницательные читатели заметили слабое место в изложенной процедуре. В частности, она рассчитана на то, что только одно устройство выставляет свой вектор, тогда как одному IRQ-уровню могут соответствовать несколько устройств, которые вырабатывают запросы на прерывание одновременно. Традиционный метод обработки прерываний в такой ситуации заключается в том, что на магистрали формируется дополнительный сигнал (называемый INTP, приоритет прерывания), необычность которого состоит в том, что линия магистрали, соответствующая этому сигналу, не является общей для устройств, подключенных к магистрали, а, наоборот — проходит через схемную часть интерфейса каждого устройства, пронизывая все интерфейсы, начиная с ближайшего к ЦП устройства с наивысшим уровнем приоритета. На цветистом языке электроники такая конструкция называется daisy chain (дейзи-цепочка, или шлейфовое соединение). Правило, в соответствии с которым аппаратная логика обрабатывает сигнал INTP, следующее: в том случае, если вы не запрашивали прерывание на том уровне, требующем подтверждения, пропустите сигнал INTP к следующему устройству без изменения; если вы хотите подтвердить прерывание на данном уровне, поддерживайте низкий уровень сигнала INTP, выходящего из вашего устройства.

Правило, в соответствии с которым надо теперь выставить вектор, выглядит следующим образом. Как только будет выработан вопрос от ЦП, установите код вашего вектора на шине данных только в том случае, если а) прерывание ожидает на том уровне, который требует подтверждение и б) на входе вашего устройства сигнал INTP имеет высокий уровень. Это гарантирует, что только одно устройство выставит свой вектор; таким образом, также устанавливается цепочка последовательных приоритетов для каждого IRQ-уровня, при этом устройство, электрически ближайшее к ЦП, будет обслуживаться в первую очередь. В таких компьютерах, где применяется подобная схема, для того, чтобы пропустить сигнал INTP через неиспользуемые разъемы магистрали, применяются малогабаритные разъемные замыкатели. Не забудьте их удалить, когда будете устанавливать дополнительную интерфейсную плату (а затем не забудьте их вернуть на место, когда будете отключать соответствующую плату!).

У метода подтверждения прерывания, реализуемого с помощью последовательной дейзи-цепочки, имеется изящная альтернатива: вместо того, чтобы пропускать сигнал через каждый возможный источник прерываний, вы соединяете каждое подобное устройство отдельной линией с приоритетным шифратором (см. разд. 8.14), который, в свою очередь, подтверждает прерывание, идентифицируя наиболее приоритетное из устройств прерывания. Такая схема исключает суету с перетыканием замыкателей. Детально мы это обсудим в разд. 11.4 (рис. 11.8).

В большинстве микрокомпьютерных систем описанная только что организация подтверждения запроса прерывания не используется в полной мере. В конце концов при 8-ми уровневой автовекторизации можно обслужить 8 устройств — источников прерываний без опроса и в несколько раз большее их количество с опросом. Только в больших компьютерных системах, где требуется быстрая реакция при наличии десятков устройств, которые вырабатывают прерывания, возможно, вы поддадитесь искушению усложнить протокол подтверждения прерывания, либо используя аппаратно реализованную последовательную дейзи-цепочку приоритетов, либо — параллельное приоритетное кодирование.

Однако важно понимать, что даже простые компьютеры могут использовать внутреннее векторизованное подтверждение прерывания. Например, простая 6-ти уровневая автовекторизованная схема прерываний IBM PC, как она представляется пользователям магистрали, на самом деле поддерживается микросхемой программируемого контроллера прерываний типа 8259, которая размещается вблизи ЦП и генерирует надлежащую последовательность подтверждений прерывания, описанную ниже. Это необходимо, так как МП 8086 (и его «наследники») не могут сами по себе использовать автовекторизацию. С другой стороны, МП популярной серии 68000 могут использовать автовекторизацию всего лишь с использованием одной дополнительной микросхемы (см. гл. 11).

Маскирование прерываний. В нашем простом примере с клавиатурой мы включили триггер таким образом, что прерывания клавиатуры могут быть заблокированы, даже несмотря на то, что контроллер типа 8259 позволяет выключать («маскировать») каждый уровень прерывания в отдельности. Мы поступили таким образом, чтобы какое-нибудь другое устройство могло затем использовать IRQ2. Для магистрали с совместно используемыми IRQ'-линиями (чувствительными к уровню) особенно важно сделать каждый источник прерываний маскируемым с помощью бита выходного порта ввода-вывода. Например, порт печатающего устройства обычно вырабатывает прерывание всякий раз, когда его выходной буфер пуст («дайте еще данных»); но после завершения печати этот запрос уже не нужен. Очевидное решение заключается в том, чтобы выключить прерывания печатающего устройства. Поскольку могут быть другие устройства, «захватившие» тот же уровень прерываний, надо не маскировать целиком весь уровень, а передать бит в порт печатающего устройства для того, чтобы блокировать его прерывание.

Как IBM PC это делает. Используемый в IBM PC МП 8086/8 в самом деле использует полный протокол подтверждения векторизованных прерываний. Однако для простоты проектировщики IBM PC использовали микросхему контроллера прерываний 8259 на системной плате. Эта микросхема используется следующим образом. К ней подключены линии IRQ от устройств ввода-вывода, расположенных на вставных печатных платах (где вырабатываются соответствующие запросы на прерывания), сам же контроллер соединен с линиями данных и управления собственно МП. Когда контроллер получает от внешнего устройства запрос на прерывание по линии IRQ, он выясняет его приоритет и осуществляет весь комплекс действий, связанных с формированием соответствующего вектора на шине данных. Он имеет регистр маски (доступный через порт ввода-вывода 21Н) так, что вы можете запретить произвольный набор прерываний.

Контроллер типа 8259 позволяет выбирать (программным образом) способ формирования прерывания либо по уровню, либо по фронту соответствующего сигнала на входных линиях IRQ; выбор осуществляется с помощью записи байта в управляющий регистр (порт ввода-вывода 20Н). К сожалению, конструкторы PC решили использовать формирование по фронту, возможно из-за того, что это несколько упрощает формирование прерываний (например, можно непосредственно подать выходной прямоугольный сигнал таймера реального времени на линию IRQ0). Если же вы вместо этого выбрали способ формирования прерываний по уровню сигнала, вы можете «повесить» на каждую IRQ'-линию множество устройств, вырабатывающих прерывания и программно опрашивать их так, как это было описано выше. К несчастью, базовая система ввода-вывода PC (ROM BIOS) и операционная система (за исключением аппаратной части) предполагают формирование по фронту, так что выбор окончателен. (Почти все остальные компьютеры, включая даже «потомков» PC и PC/AT, используют формирование прерываний по уровню.)

Существует частичное решение этой проблемы. Постольку, поскольку IRQ- линия доступна, вы можете объединить на одной плате PC несколько устройств, вырабатывающих прерывания, и логическую схему, которая формирует прерывания для соответствующей IRQ-линии по фронту; для этого можно даже воспользоваться дополнительным контроллером типа 8259 (порты ввода-вывода которого должны быть доступны ЦП). Но поскольку устройство, вырабатывающее прерывание, должно знать о каждом из остальных устройств, такую схему нельзя использовать при независимом подключении внешних устройств. Более того, вы по-прежнему вынуждены использовать по одной IRQ-линии на плату внешних устройств, и сложную систему так построить трудно: в IBM PC имеются только два незадействованных IRQ-уровня.

Программные прерывания. Микропроцессоры серии Intel 8086 имеют команду (INT n, где n = 0… 255), которая позволяет вам осуществить векторизованную передачу управления того же рода, что и настоящее аппаратное прерывание. В самом деле, среди 256 возможных векторов переходов имеются и соответствующие 8 уровням IRQ-запросов аппаратных прерываний (с ΙΝΤ 8 по ΙΝΤ 15, чтобы быть точным). Таким образом, вы можете организовать программное прерывание из некоторой программы. IBM PC использует такие программные прерывания для того, чтобы разрешить вам взаимодействовать с операционной системой и различными программами, «зашитыми» в ПЗУ. Например, INT 5 пересылает копию экрана на печатающее устройство. Особенно важно применение INT 21Н, поскольку это прерывание обеспечивает вызов системных функций: вы сообщаете системе, какую из системных функций хотите использовать, записывая соответствующее число в регистр АН прежде, чем выполнить INT 21Н.

Не следует путать такие программные прерывания с аппаратными прерываниями, вырабатываемыми внешними устройствами, о чем мы говорили выше. Выполнение программных прерываний — это искусный прием использования векторизованной передачи управления из программы пользователя системному программному обеспечению. Но такие прерывания не являются настоящими прерываниями в смысле аппаратно вырабатываемых запросов внешних автономных устройств. Напротив, вы можете встроить эти прерывания в свою программу, вы знаете, когда они произойдут (вот почему вы можете передавать аргументы через регистры ЦП) и они являются всего навсего реакцией (почти такой же, какая следует в случае «истинного» прерывания) ЦП на свою собственную команду. Можете считать программные прерывания мудрым способом расширения набора команд ЦП.

10.12. Прямой доступ в память

Встречаются ситуации, когда данные должны быть переданы от устройства или в устройство очень быстро. Классическим примером является быстрое устройство массовой памяти, например диск или магнитная лента, а также такие приложения, связанные со сбором данных в реальном времени, как многоканальный амплитудный анализ. Программная передача каждого отсчета, инициируемая по прерыванию, в таком случае будет неудобной и, возможно, слишком медленной. Например, данные считываются с гибкого диска с высокой плотностью записи со скоростью около 500 Кбит/с или 1 байт каждые 16 мкс. Если соблюдать все описанные этапы обработки запроса на прерывание, данные почти наверняка будут пропущены, даже если гибкий диск будет единственным источником прерываний в компьютере; с несколькими подобными устройствами ситуация становится безнадежной. Еще хуже дело обстоит с жестким диском, для которого типичное время, затрачиваемое на передачу байта, составляет 2 мкс, что полностью исчерпывает возможности программируемого ввода-вывода. Такие устройства, как диски и магнитные ленты (не говоря уж об упомянутых сигналах и данных в реальном масштабе времени), не могут остановиться на полпути так, что требуется метод, обеспечивающий возможно более быструю реакцию и высокую общую скорость передачи данных. Даже для внешних устройств с низкой средней скоростью передачи данных может требоваться малое время реакции, т. е. время от начального запроса до собственно передачи данных.

Решением этих проблем является прямой доступ в память (ПДП), метод непосредственной связи внешнего устройства с памятью. В некоторых микрокомпьютерах (в том числе и IBM PC) такая связь фактически поддерживается аппаратным устройством (архитектурой ЦП), но не это главное. Важным моментом является то, что при передаче данных отсутствует программирование; байты передаются между памятью и внешним устройством по магистрали, без участия программы. Единственным влиянием на программу является некоторое замедление ее работы, поскольку режим ПДП «захватывает» такты магистрали, которые в противном случае могли бы быть использованы для доступа к памяти при выполнении программы. Аппаратная реализация интерфейса, поддерживающего режим ПДП, сложна, не следует без необходимости использовать этот режим. Однако полезно знать потенциальные возможности, поэтому мы вкратце опишем, что необходимо для построения интерфейса, поддерживающего режим ПДП. Как и в случае с прерываниями, конструкторы IBM PC упростили протокол ПДП; основную работу выполняет контролллер ПДП, расположенный на системной плате, что делает протокол ПДП сравнительно простым. Однако интерфейсы, поддерживающие режим ПДП, обычно оказываются машинно-зависимыми и сложными. Сначала мы поясним функционирование более употребительного метода ПДП с управлением сигнала магистрали, а затем — упрощенный протокол ПДП для PC.

Типовой протокол ПДП. При пересылках данных в режиме ПДП внешние устройства получают доступ к магистрали с помощью специализированных линий «запроса магистрали» (которые также, как IRQ-линии, имеют приоритеты), являющихся составной частью магистрали. Центральный процессор разрешает и ПДП и отдает управление адресами, данными и строб-сигналами. Затем внешнее устройство выставляет адреса памяти на магистраль и либо передает, либо принимает данные побайтно, синхронизуясь с устанавливаемыми им же строб-сигналами; другими словами, внешнее устройство «захватывает» магистраль и работает как ЦП, непосредственно пересылая данные. Устройство, которое в режиме ПДП управляет магистралью, отвечает за вычисление адресов (как правило, непрерывную область адресов, вырабатываемых с помощью двоичного счетчика) и подсчет количества переданных байтов. Обычно для этого достаточно иметь счетчик байтов и адресный счетчик в составе интерфейса.

Эти счетчики первоначально загружаются на ЦП, посредством программируемого ввода-вывода, для того, чтобы предустановить требуемые параметры передачи данных в режиме ПДП. По команде ЦП (посредством записи управляющего бита с помощью программируемого ввода-вывода) интерфейс формирует требование ПДП и начинает пересылать данные. Интерфейс может освобождать магистраль в промежутки времени между передачей байтов (позволяя тем самым ЦП «урвать» время и выполнить несколько команд), или он может вести себя более эгоистично, захватывая магистраль на все время передачи блока данных. После того, как все данные переданы, интерфейс освобождает магистраль до следующего раза и сообщает программе о том, что все закончено, устанавливая бит состояния и вырабатывая прерывание, после чего ЦП может решить, что делать дальше.

Загрузка данных или программ с диска-наиболее общий пример передачи данных в режиме ПДП. Выполняемая программа запрашивает какие-нибудь файлы по именам; операционная система (подробнее - чуть позже) преобразует эти имена в команды программируемого вывода данных для управляющего (или командного) регистра интерфейса диска, регистра счетчика байтов и адресного регистра (описывая с какого места на диске, и сколько байтов надо считать, и в какую область памяти их поместить). Затем интерфейс диска отыщет необходимую область на диске, сформирует запрос ПДП и начинает передавать блоки данных в заданную область памяти. Когда это будет выполнено, интерфейс установит определенные биты в регистре состояния для того, чтобы обозначить завершение работы и затем инициирует прерывание. Центральный процессор, который тем временем выполняет другие команды (или, возможно, как раз ожидает данных с диска), «откликается» на прерывание, по содержимому регистра состояния интерфейса диска определяет, что данные находятся в памяти и затем переходит к выполнению следующих команд. Таким образом, программируемый ввод-вывод (простейший вариант ввода-вывода) был использован для инициализации режима ПДП, собственно ПДП (перехватывающий у ЦП циклы магистрали) был использован для быстрой передачи данных, а прерывание было использовано для того, чтобы дать знать компьютеру о том, что передача выполнена. Такого рода иерархия ввода-вывода — исключительно частый прием, особенно для устройств массовой памяти; максимальная скорость передачи данных по типовой микрокомпьютерной магистрали в режиме ПДП может составлять от 1 до 10 млн. слов в секунду.

ПДП в IBM PC. Компьютер IBM PC, который в общем-то прост, поддерживает упрощенный протокол ПДП. На системной плате установлен контроллер ПДП (Intel 8237) со встроенными адресным и байтовым счетчиками, а также дополнительными логическими схемами для блокировки ЦП и перехвата управления магистралью. Таким образом, внешнее устройство, которое хочет выполнить ПДП, не должно вырабатывать адреса и управлять магистралью. Вместо этого он сигнализирует контроллеру с помощью одной из трех DRQ1-DRQ3 линий запроса ПДП; контроллер откликается по соответствующей линии DACK0-3' (подтверждение ПДП). Затем контроллер управляет передачей данных, формируя адрес и соответствующие строб-сигналы, синхронно с формированием внешним устройством данных для передачи в память (или синхронно с приемом данных из памяти). Во всем этом процессе память не замечает ничего необычного, поскольку генерация адресов и строб-сигналов управления памятью (MEMW' или MEMR'), которая обычно поддерживается ЦП, в данном случае поддерживается контроллером 8237 и, если ПДП сопровождает передачу данных в память, данные формируются внешним устройством. С другой стороны внешние устройства «знают» все особенности того, как надо формировать запрос ПДП (и что делать при получении подтверждения посредством сигнала DACK'); таким образом, когда контроллер ПДП выставляет сигнал IOR' (или IOW'), внешнее устройство вырабатывает (или принимает) соответствующие байты. Вы можете удивиться, как это такой простодушный, сторонний наблюдатель, как внешнее устройство, не запутается во время ПДП, когда выставлены и строб- сигналы ввода-вывода, и адреса, причем эти адреса являются адресами в памяти, установление которых сопровождается строб-сигналами управления памятью MEMW' или MEMR', генерируемыми контроллером; эти адреса не имеют никакого отношения к портам ввода-вывода.

Секрет здесь заключается в нашем старом знакомом-сигнале AEN, который добавлен к магистрали специально только для решения подобных проблем. Уровень сигнала AEN во время передачи данных в режиме ПДП устанавливается высоким, и функции разрешения адресации всех портов ввода-вывода должны вычисляться как логическое произведение с низким уровнем сигнала AEN для того, чтобы предотвратить ложную реакцию при адресации памяти в режиме ПДП.

Даже при использовании отдельной микросхемы контроллера вам все еще надо задать начальный адрес, количество байтов и направление передачи данных для грядущего режима ПДП. Эти параметры заносятся в контроллер 8237, который обязан иметь набор регистров, куда из ЦП (с помощью программируемого ввода-вывода) можно записать соответствующие значения. Настройка ПДП осуществляется весьма просто (см. книгу Эггбрехта для более детального ознакомления), если не считать того, что, как и у большинства микросхем БИС, здесь также имеется ошеломляющее разнообразие выбора различных режимов работы (посимвольная передача, поблочная передача и т. п.). К счастью IBM PC достаточно примитивна и позволяет вам использовать только режим посимвольной передачи, при котором каждый запрос DRQ сопровождается передачей лишь одного байта. Если вы настаиваете на передаче целого блока данных, поддерживая сигнал DRQ в высоком состоянии, контроллер 8237 освобождает магистраль на один цикл ЦП между циклами ПДП; это позволяет компьютеру сохранять работоспособность даже в том случае, когда у вас такое «прожорливое» внешнее устройство, что оно старается «заграбастать» магистраль полностью.

Стандартная PC обладает довольно скромными возможностями режима ПДП-около 2 мкс на передаваемый байт. По сравнению с количеством прерываний количество каналов ПДП в IBM PC меньше. Для шины ввода-вывода доступны три канала DRQ1-DRQ3 (DRQ0 уже задействован на внутренние нужды — для регенерации динамической памяти): DRQ1 используется жестким диском, а DRQ2 — гибким. На все остальное остается DRQ3.

10.13. Сводный перечень сигналов магистрали IBM PC

На рассмотренных нами примерах-программируемого ввода-вывода, прерываний, ПДП-мы познакомились с большинством сигналов магистрали, поступающими на плату внешнего устройства IBM PC В табл. 10.1 (и на рис. 10.14) приведен полный перечень сигналов магистрали с цоколевкой разъема. Для полноты изложения ниже описан каждый из этих сигналов, начиная с тех, с которыми мы уже встретились.

Рис. 10.14. Магистраль IBM PC.

А0-А19. Шина адреса. Два состояния, работает только на запись, действующий уровень сигнала-высокий. Все 20 разрядов используются для адресации памяти (совместно с сигналами MEMR' и MEMW', которые играют роль строб-сигналов, по аналогии с сигналами IOR' и IOW'), но только 16 младших разрядов используются при адресации ввода-вывода, (64 К адресов портов); устройства ввода-вывода должны осуществлять выборку адреса только при низком уровне сигнала AEN.

Важное замечание: ввод-вывод в пределах системной платы предусматривает адресацию только десятью младшими разрядами, используя при этом лишь адреса 000H-1FFH, поэтому адреса устройств ввода-вывода должны иметь в своих младших разрядах коды в диапазоне 200H-3FFH. Вы можете поступить умнее, используя наряду со свободными 10-разрядными адресами еще и 6 старших бит, расширив таким образом адресное пространство портов ввода-вывода до 64К.

D0-D7. Шина данных. Три состояния, двунаправленная, действующий уровень сигнала-высокий. Данные выставляются ЦП при записи в память или в порт ввода-вывода: выставляются памятью при чтении из памяти, в том числе и при ПДП; выставляются портом ввода-вывода при чтении из порта, в том числе и в память при ПДП.

IOR ' , IOW ' , MEMR ' , MEMW ' . Строб-сигналы данных. Два состояния являются выходными (по отношению к ЦП), действующий уровень сигнала — низкий. Формируются ЦП при чтении или записи. При записи данные должны быть зафиксированы по спаду (положительному) и при надлежащем адресе; при чтении должны быть выставлены одновременно со строб-сигналом при заданном адресе.

AEN. Разрешение адреса. Два состояния, является выходным (по отношению к ЦП), действующий уровень сигнала — высокий. Вырабатывается ЦП во время циклов ПДП. Порты ввода-вывода не должны дешифровать адрес при наличии сигналов IOR', IOW', за исключением тех случаев, когда порты ввода-вывода принимают сигнал DACK и используют сигналы IOR' и IOW' для стробирования байтов данных ПДПН.

IRQ2-IRQ7. Запрос прерывания. Два состояния, является входным (по отношению к ЦП), действующим является нарастающий фронт. Вырабатывается устройством, запрашивающим прерывания. Приоритеты установлены таким образом, что IRQ2 имеет наивысший, a IRQ7 — наинизший приоритет. Контроллер прерываний 8259 допускает их маскирование, устанавливаемое ЦП посредством записи в порт по адресу 21Н. Каждый уровень IRQ может быть использован одновременно только одним устройством.

RESET DRV. Предустановка драйвера. Два состояния, является выходным (по отношению к ЦП), действующий уровень — высокий. Вырабатывается ЦП при включении электропитания. Используется для предустановки устройства ввода-вывода в заданное начальное состояние.

DRQ1-DRQ3. Запрос ПДП. Два состояния, является входным (по отношению к ЦП), действующий уровень — высокий. Вырабатывается устройством ввода-вывода, которое запрашивает канал ПДП. Приоритеты установлены таким образом, что DRQ1 имеет наивысший, a DRQ3 — наинизший приоритеты. Подтверждается сигналами DACK1'-DACK3'.

DACK0 ' -DACK3 ' . Подтверждение ПДП. Два состояния, является выходным (по отношению к ЦП), действующий уровень — низкий. Вырабатывается ЦП (или контроллером ПДП) для того, чтобы обозначить подтверждение соответствующего запроса ПДП.

ALE. Разрешение фиксации адреса. Два состояния, является выходным (по отношению к ЦП), действующий уровень — высокий. Микропроцессор Intel 8088 использует мультиплексируемую шину данные/адрес, и этот сигнал соответствует строб-сигналу МП, используемому регистрами-фиксаторами на системной плате для фиксации адреса. Может быть использован в качестве сигнала начала цикла ЦП; обычно при проектировании ввода-вывода игнорируется.

CLK. Тактовый сигнал. Два состояния, является выходным (по отношению к ЦП). Это-тактовый сигнал ЦП; он асимметричен, 1/3 периода поддерживается высокий уровень, а 2/3 — низкий. Исходные PC работали на частоте 4,77 МГц, сейчас используются более высокие частоты. Сигнал CLK применяется для синхронизации состояний ожидания при запросах (с использованием сигнала I/O CHRDY) для того, чтобы удлинить цикл ввода-вывода для медленных устройств.

OSC. Тактовый сигнал. Два состояния, является выходным (по отношению к ЦП). Этот сигнал представляет собой меандр с частотой 14,31818 МГц, который может использоваться (будучи поделенным на 4) для синхронизации работы цветного дисплея.

Т/С. Завершение передачи. Два состояния, является выходным (по отношению к ЦП), действующим является высокий уровень. Этот сигнал сообщает порту ввода-вывода, что передача блока данных в режиме ПДП завершена. Устройство, выполняющее ПДП, должно обрабатывать этот сигнал по совпадению с сигналом DACK' для используемого канала, поскольку сигнал Т/С вырабатывается независимо от того, по какому из каналов ПДП завершилась передача блока.

I/O СН СК ' . Проверка канала ввода-вывода. Открытый коллекторный выход, является входным (по отношению к ЦП), действующий уровень-низкий. Инициирует прерывание с наивысшим приоритетом (немаскируемое прерывание); используется для того, чтобы сигнализировать о состоянии ошибки в каком-то из внешних устройств. Центральный процессор определяет «возмутителя спокойствия» опросом внешних устройств (см. разд. 10.11); следовательно, каждое устройство, которое вырабатывает сигнал I/O СН СК', должно иметь бит состояния, который может быть прочитан ЦП.

I/O СН RDY. Готовность канала ввода-вывода. Открытый коллекторный выход, является входным (по отношению к ЦП), действующий уровень — высокий. Формирует состояние ожидания, если перед вторым фронтом сигнала CLK цикла процессора (в цикле обычно 4 такта сигнала CLK) уровень сигнала I/O СН RDY установлен низким. Используется для удлинения цикла магистрали для медленных устройств ввода-вывода или при обращении к памяти.

GND,+5VDC, —5VDC, +12VDC, -12VDC. «Земля» и уровни постоянных напряжений питания. Регулируемые уровни постоянного напряжения, передаваемые по магистрали для питания внешних устройств, размещенных на вставных платах. Изучите описание вашего компьютера для того, чтобы выяснить ограничения на суммарную потребляемую электрическую мощность, которая зависит от модификации компьютера. Вообще говоря, мощности должно хватить для питания всего того, что вы подключите с помощью разъемов расширения магистрали.

10.14. Синхронный и асинхронный протоколы магистрали

Протокол ввода-вывода, описанный нами ранее, является примером синхронного обмена данными; данные выставляются на шину или принимаются с нее синхронно со стробирующими сигналами, которые генерируются ЦП (или контроллером ПДП). Этот метод отличается простотой, однако он чреват неприятностями в случае использования протяженных длинных шин, поскольку большое время распространения сигнала может привести к тому, что данные в операции ввода будут устанавливаться недостаточно быстро, чтобы обеспечить надежную передачу. Собственно говоря, при синхронном протоколе устройство, посылающее данные, так никогда и не узнает, получены ли эти данные! Это может показаться серьезным недостатком, но в действительности компьютерные системы с синхронными магистралями превосходно работают.

Альтернативой является асинхронная магистраль, на которой операция, например, ввода осуществляется следующим образом. ЦП устанавливает адрес порта, а на стробирующей линии (назовем ее, как и раньше, IOR') уровень (не импульс), который показывает адресному устройству, что идет операция ввода. Адресуемое устройство устанавливает данные на линиях DATA, а также уровень, сигнализирующий о наличии достоверных данных (назовем его DTACK', data transfer acknowledged, подтверждение передачи данных). ЦП, обнаружив DTACK', фиксирует («защелкивает») данные и затем снимает уровень IOR'. Как только интерфейс замечает, что линия IOR' переходит в высокое состояние, он снимает сигналы с линий DTACK' и DATA. Другими словами, ЦП заявляет: «Дай мне данные». Периферийное устройство отвечает: «Вот они, бери». Тогда ЦП говорит: «Готово, взял». И, наконец, периферийное устройство завершает диалог: «Отлично! Пойду снова спать». Описанную процедуру иногда называют «рукопожатием», или квитированием. Асинхронный протокол допускает использование длинных шин и позволяет взаимодействующим устройствам убедиться, что данные действительно передаются. Если удаленное устройство будет выключено, ЦП узнает об этом. Собственно говоря, эта информация доступна (через регистры состояния) на магистралях любого вида, и основное достоинство асинхронного протокола заключается в возможности использовать линии связи любой длины за счет незначительного усложнения аппаратуры.

Иногда вам может понадобиться подключить к магистрали относительно медленные интерфейсные ИС; примером может служить ПЗУ с большим временем доступа или даже ОЗУ. Все магистрали предоставляют какие-то средства удлинения цикла магистрали, однако при асинхронном протоколе это происходит само по себе, поскольку цикл магистрали продолжается до тех пор, пока не будет снят сигнал DTACK'. Синхронные магистрали всегда содержат какую-то линию типа HOLD' (в компьютерах PC она называется I/O СН RDY) для организации состояний ожидания и задержки во времени конца цикла. Результирующая длительность цикла всегда увеличивается на целое число тактов генератора ЦП, т. е. на число включенных в цикл «состояний ожидания». Например, стандартная IBM PC имеет тактовую частоту 4,77 МГц (период 210 нc), а длительность обычного цикла магистрали при обращении к памяти составляет 4 тактовых периода (840 нc). Если сигнал I/O СН RDY переводится в низкое состояние при обращении к памяти перед вторым фронтом сигнала CLK и снова переходит в высокое состояние перед третьим, генерируется одно состояние ожидания с удлинением цикла магистрали (а также и сигналов MEMW' или MEMR') до 5 тактов (1050 нc). Удерживая сигнал I/O СН RDY в низком состоянии на протяжении большего числа тактов, вы создаете дополнительные состояния ожидания, вплоть до 10 периодов тактового генератора.

Теперь мы можем открыть тщательно скрываемый секрет про синхронные и асинхронные магистрали: практически все микрокомпьютеры с одним процессором (или, точнее, с одним ведущим на магистрали) являются синхронными, потому что вся синхронизация привязана к единственному генератору ЦП (вроде 4,77 МГц тактового генератора исходных IBM PC). В результате если периферийное устройство задерживает свое подтверждение на «асинхронной» магистрали, цикл всегда удлиняется на целое число тактов ЦП. Разница между синхронными и асинхронными магистралями в действительности заключается в следующем. На «асинхронной» магистрали состояния ожидания включаются в цикл по умолчанию, если только не установлен в низкое состояние сигнал DTACK' (поступающий через проводное ИЛИ), в то время как на «синхронной» магистрали состояния ожидания по умолчанию не возникают; они генерируются лишь если линия проводного ИЛИ (HOLD') устанавливается в низкое состояние. Однако различие не носит лишь семантический характер — «синхронный» протокол не позволяет работать с длинными шинами, потому что в этом случае сигнал HOLD' поступает в ЦП слишком поздно, чтобы удлинить цикл, в то время как на «асинхронной» магистрали ЦП не завершит цикл обмена без вашего разрешения (сигнал DTACK'). Со свойственной нам скромностью мы предлагаем, во избежание недоразумений, пользоваться следующей многообещающей терминологией: если состояния ожидания генерируются на магистрали по умолчанию («асинхронная» магистраль), будем называть ее «с ожиданием по умолчанию» (default-wait); если состояния ожидания возникают только при их запросе («синхронная» магистраль), будем называть ее «с ожиданием по запросу» (request-wait). Магистраль IBM PC характеризуется ожиданием по запросу, а магистраль VME (см. ниже) — по умолчанию.

Процессы на магистрали еще более усложняются в многопроцессорных системах, где управление магистралью переходит из рук в руки. На синхронной магистрали с несколькими ведущими все ведущие должны использовать единый тактовый генератор, в то время как асинхронная магистраль допускает различные тактовые частоты. К счастью для вас, обсуждение многопроцессорных систем выходит за рамки этой книги! Следует отметить обстоятельство, могущее привести к недоразумениям. Вы не добавляете состояния ожидания при работе с медленными периферийными устройствами (например принтером); это следует делать лишь при наличии медленных ИС (скажем, ПЗУ с временем доступа 250 нc или медленной периферийной БИС). Медленная периферия обычно безнадежно медленна (миллисекунды, а не наносекунды); с такими устройствами следует посылать (или принимать) байт на полной скорости магистрали, фиксируя его в регистре байтовой ширины, после чего ожидать прерывания (или, возможно, установки флага состояния), чтобы инициировать следующую передачу на, полной скорости.

10.15. Магистрали других микрокомпьютеров

Для иллюстрации архитектуры микрокомпьютерной магистрали-сигналов на магистрали, разновидностей ввода-вывода, прерываний, прямого доступа к памяти, мы выбрали магистраль IBM PC. Для книги по электронике это оправданный выбор, так как компьютеры типа PC выпускаются повсеместно и широко применяются в технике вообще и в системах сбора данных и управления в частности. К тому же, магистраль PC исключительно проста в объяснении и использовании.

Однако за простоту приходится платить. Магистрали исходных IBM PC свойственны серьезные ограничения, уже упоминавшиеся ранее (например, малое число уровней прерываний и каналов ПДП). Кроме того, магистраль IBM PC имеет по нынешним меркам слишком маленькое адресное пространство (20 бит, и доступны только 640 К), слишком узкую шину данных (8 бит), недостаточную скорость передачи данных (максимально 1,2 Мбайт/с) и невозможность работы с несколькими ведущими шины. Для последующих поколений машин PC фирма IBM разработала улучшенные магистрали, сначала магистраль PC/AT (совместимое усовершенствование исходных PC), а затем новую (и несовместимую!) «микроканальную» магистраль для серии машин PS/2. Вне мира IBM можно найти конкурирующие магистрали конкретных разработчиков (например, Q-bus и VAXBI фирмы DEC), а также типовые магистрали (Multibus, NuBus, VME). Давайте пройдемся по компьютерным магистралям, перечисленным в табл. 10.2.

PC/AT и Micro Channel. Компьютеры IBM PC/AT (сокращение от Advanced Technology, улучшенная технология) появились в 1984 г., а в 1987 г., на вершине популярности, их производство было приостановлено, чтобы уступить место серии машин IBM PS/2, использовавших улучшенную магистраль Micro Channel и призванных одним махом прихлопнуть производителей АТ-аналогов. (Однако машины PC/AT продолжали процветать, поскольку производители их аналогов, как и многие покупатели, сначала игнорировали новинку IBM, улучшенные качества которой требовали несуществующего программного обеспечения.) В PC/AT используется микропроцессор 80286 и расширенная (но совместимая) магистраль исходных PC: дополнительный (и необязательный) разъем для добавочных 8 бит данных, 4 бит адресов и 5 линий IRQ (со срабатыванием, как и прежде, по фронту). В результате 16-разрядная шина данных и более высокая тактовая частота подняли пропускную способность магистрали до 5,3 Мбайт/с, что в сочетании с расширением адресного пространства и увеличением числа уровней прерываний сделали PC/AT весьма серьезным микрокомпьютером. Магистраль PC/AT (иногда называемая Industry Standard Architecture, или ISA - стандартная промышленная архитектура) даже допускает нескольких ведущих на магистрали, хотя ее возможности в этом отношении ограничены. Платы, предназначенные для исходных PC, будут работать и на PC/AT (если они обладают необходимым быстродействием), так как усовершенствования, собранные на дополнительном разъеме, можно игнорировать; в этом случае, конечно, вы возвращаетесь к 8-разрядной шине данных и 20-разрядному адресному пространству. АТ-совместимые компьютеры обычно эксплуатируют свою магистраль ввода-вывода на высоких скоростях, и при использовании старых вставных плат могут возникнуть дополнительные трудности синхронизации.

Магистраль Micro Channel была впервые применена в серии персональных компьютеров второго поколения IBM PS/2, появившихся в 1987 г. Магистраль характеризуется большой шириной шин адресов и данных (до 32 разрядов у моделей с микропроцессором 80386), 11 уровнями разделяемых прерываний (чувствительных к уровню), возможностью работы нескольких ведущих шины и асинхронным протоколом. Платы, подключаемые к магистрали Micro Channel, не содержат запаянных адресов портов ввода-вывода; адреса (вместе с другими конфигурационными характеристиками) назначаются ЦП в процессе загрузки на основе информации, прочитанной в ПЗУ на плате. Это приятное качество избавляет вас от необходимости настраивать каждую плату с помощью микропереключателей или беспокоиться о возможности наложения адресных пространств разных плат. Платы Micro Channel характеризуются очень небольшими геометрическими допусками, что связано с использованием разъемов с расстоянием между контактами всего 1,27 мм.

EISA. Расширенная стандартная промышленная архитектура (Extended Industry Standard Architecture, EISA) явилась ответом производителей АТ-аналогов на наступление магистрали Micro Channel. Магистраль EISA была предложена в 1988 г. девятью фирмами, выпускающими АТ-совместимые компьютеры. Добавив к АТ-магистрали дополнительный разъем, разработчики EISA реализовали многие привлекательные черты магистрали Micro Channel, сохранив совместимость с существующими вставными платами AT. Таким образом, вы можете вставить стандартную плату AT в магистраль EISA и получить обычную машину AT. Однако при использовании с магистралью EISA специально разработанных для нее плат, магистраль поддерживает 32-бит передачу данных (с максимальной скоростью передачи 33 Мбайт/с), 32-бит адресацию памяти, несколько ведущих магистрали, программируемые прерывания по уровню или по перепаду, а также автоматическое конфигурирование платы.

Multibus I и II. Форматы магистрали Multibus, первоначально предложенные фирмой Intel, нашли применение во многих компьютерах. Исходная магистраль Multibus I имеет большие возможности, в том числе 16-разрядную шину данных, 24-разрядное адресное пространство и несколько ведущих на магистрали. Miltibus II предназначена для высокопроизводительных микропроцессорных систем и отличается 32-разрядными шинами адресов и данных, контролем четности, распределенным арбитражем, протоколами передачи сообщений. Магистраль использует 10 МГц тактовый генератор в синхронном режиме и может передавать до 40 Мбайт/с по последовательным адресам в режиме «блочной передачи». Так же, как и некоторые другие сложные магистрали, в Multibus II экономятся контакты путем мультиплексирования данных и адресов на подшине из 32 линий. В Multibus II используются также 96-контактные соединители DIN, укрепленные на платах, вместо торцевых плоских позолоченных соединителей; хорошо разработанный «составной» соединитель на плате обеспечивает большую надежность, и система соединения оказывается нечувствительной к искривлению плат и грубому обращению.

Хотя Multibus II отличается многими преимуществами, гибкость этой магистрали усложняет ее использование. Например, на магистрали отсутствуют обычные прерывания; вы «прерываете» путем запроса на захват магистрали и посылки затем сообщения в процессор о вашем желании прервать его работу! Для простых систем удобнее использовать более простую магистраль Multibus 1 (или какую-то другую того же класса).

NuBus. Это еще одна высокопроизводительная синхронная многопроцессорная магистраль с 32-разрядными мультиплексированными данными и адресами, соединителями DIN и высокой скоростью передачи данных (до 40 Мбайт/с в режиме блочной передачи). Как и в случае Multibus II, прерывания реализуются путем запроса на захват магистрали. Магистраль NuBus используется в старших моделях компьютеров Macintosh, где, к счастью, фирма Apple добавила к каждому разъему линию прерываний. Таким образом, каждый разъем для установки вставной платы имеет назначенный ему вектор; соответствующий обработчик прерываний определяет плату-источник прерывания без процедуры опроса, которая требуется лишь в тех случаях, когда плата содержит несколько прерывающих устройств.

Магистраль VME. Эта магистраль, как и NuBus или Multibus II, предназначена для многопроцессорных 32-разрядных систем. Однако в ней не используются мультиплексированные линии данных/адресов. Нет в ней и главного тактового генератора для синхронной передачи, поскольку для магистрали принят асинхронный протокол; это дает возможность без труда объединять процессоры, работающие с разными скоростями. Магистраль VME включает обычную многоуровневую систему прерываний IRQ-типа, с полным подтверждением прерывания (и линией INTR, образующей последовательную цепочку). Магистраль VME часто рассматривают, как альтернативную по отношению к Multibus; например, исходные компьютеры Sun фирмы Sun Microsystems использовали Multibus, в то время как в более поздних моделях Sun2 и Sun3 применена магистраль VME. Магистрали VME и Multibus II под одобрение фирм Motorola и Intel постоянно выясняют свои отношения в технической прессе с обличительными заявлениями и бранью.

Fastbus и Futurebus. Это весьма высокопроизводительные магистрали, работающие с ошеломляющей скоростью. Магистраль Fastbus использует платы большого размера (14x16 дюйм), ECL — драйверы и протоколы арбитража для работы с несколькими ведущими на магистрали. Сильной стороной этих магистралей является система магистральных взаимодействий с возможностью изощренной «географической» адресации за пределы собственно крейта плат.

Q-bus иVAXBI. Это патентованные магистрали компьютеров фирмы DEC. Магистраль Q-bus, использовавшаяся в машинах LSI-11 и ранних компьютерах Micro VAX, произошла от магистрали Unibus исходных машин PDP-11 фирмы DEC. Q-bus поддерживает 16-разрядные данные и 22-разрядную адресацию, асинхронный протокол с несколькими ведущими и многоуровневые прерывания IRQ-типа. VAXBI является высокопроизводительной магистралью с мультиплексированной 32-разрядной шиной данных/адресов, предназначенной для более совершенных машин VAX серии 8600.

10.16. Подключение к компьютеру периферийных устройств

Интерфейсы обычно изготавливаются в виде печатных плат, либо плат с накруткой (см. гл. 12), предназначенных для вставления в плоские разъемы («слоты») микрокомпьютера. Обычно в микрокомпьютере предусматривается некоторое количество свободных разъемов именно для этой цели (либо занятые разъемы допускают «расширение» и вставление новых плат), причем по всем разъемам разводятся сигналы магистрали и питающие напряжения. Некоторые машины используют «патентованные» магистрали (например IBM PC), другие базируются на стандартных микрокомпьютерных магистралях (например рабочая станция Sun3 с магистралью VME), наконец, в некоторых вообще не предусматривается дополнительных разъемов (например исходные машины Macintosh). Каждая магистраль рассчитана на платы некоторого стандартного размера (или размеров), от крошечных плат IBM PS/2 размером 3,2x11,5 дюйм до гигантских 14,4x15,9 дюйм плат Fastbus. Каждая плата, в зависимости от магистрали, для которой она предназначена, имеет вдоль одного края от 50 до 300 соединений либо в форме позолоченных печатных ламелей, либо в виде многоштырьковых соединителей, припаянных к плате; последние известны под именем «составных» (two-part) соединителей и, как правило, более надежны, чем печатные плоские разъемы. Имеющиеся на рынке интерфейсы для решения стандартных задач (диски, графика, связь, аналоговый ввод-вывод) обычно монтируются на платах, которые вставляются в свободные разъемы машины. Если интерфейс управляет периферийным устройством, они связываются кабелями; в тех случаях, когда у интерфейса очень много входов и выходов (как, например, у цифрового логического анализатора), он может соединяться кабелем с внешней частью в виде панели или коробки, где больше места для разъемов (и дополнительных схем). В любом случае обычно используется гибкий ленточный кабель, причем предусматриваются меры для снижения уровня перекрестных помех на сигнальных и стробирующих линиях.

Один из способов заключается в заземлении каждой второй линии в кабеле; другой предполагает использование гибкого кабеля, скрепленного с гибкой же металлической заземленной подложкой, которая уменьшает индуктивность и помехи и в то же время обеспечивает почти постоянный импеданс кабеля. Для обоих конструкций в продаже имеются многоконтактные «оконечные заземлители», которые подключаются к кабелю путем обжатия; смотрите каталоги AMP, Berg, Т&В Ansley, ЗМ и т. д. Альтернативой ленточному кабелю служит кабель, сделанный из многих скрученных пар, каждая из которых содержит одну сигнальную и одну заземленную линию. Кабель из скрученных пар выпускается во многих модификациях, включая щеголеватый плоский кабель, напоминающий ленточный (кабель Twist-'n-flat — «кручено-плоский» фирмы Allied/Spectra). В кабель через каждые полметра включается плоский нескрученный участок, на который можно надеть обычный обжимающий соединитель для ленточного кабеля. Поскольку для передачи данных между интерфейсной платой и устройством обычно используется протокол со стробированием, защищать все сигнальные линии от наводок нет необходимости. Защита требуется лишь для синхронизирующих импульсов и, других линий стробов и разрешений. Если линии имеют значительную длину, следует использовать согласованные нагрузки и комбинации приемников и драйверов, как это описано в разд. 9.14.

Нестандартные интерфейсы лучше всего выполнять таким же образом, либо путем разработки для них печатной платы, либо используя одну из универсальных интерфейсных плат, выпускаемых такими компаниями, как Douglas, Electronic Solutions и Vector. Эти пустые платы имеют места для подключения микросхем и других компонентов (включая оконечные заземлители для внешних кабелей) как припаиванием, так и накруткой (подробнее об этом см. в гл. 12). Некоторые платы содержат встроенные схемы для взаимодействия с магистралью, включая обслуживание прерываний и даже ПДП.

В некоторых случаях наилучшим решением является разработка интерфейса, частично располагаемого в компьютере, а частично-снаружи, как это показано на рис. 10.15.

Рис. 10.15. Структура разделенного интерфейса.

Тогда «компьютерная» часть интерфейса может включать, например, лишь простой параллельный порт ввода-вывода, либо в виде покупной платы, либо собственной разработки. Кабель, соединяющий две части интерфейса, оказывается простым; если требуется скоростная передача при большой протяженности кабеля, можно использовать высокопроизводительные комбинации драйверов/приемников, обсуждавшиеся в разд. 9.14 (например RS-232 или симметричные микросхемы 75S110, или даже волоконную оптику). Такой подход к конструированию интерфейсов может быть особенно полезен при работе со слабыми аналоговыми сигналами, поскольку в этом случае чувствительные к помехам линейные цепи можно удалить от рева наводок цифровых схем компьютера (и приблизить к источнику аналоговых сигналов); это также позволяет с особым вниманием отнестись к поддержанию «в чистоте» заземленных линий аналогового сигнала.

SCSI, IEEE-488 и другие интерфейсы. В продаже имеются буквально сотни вставных плат для распространенных магистралей вроде IBM PC, Multibus, VME и Q-bus, выполняющих необозримое множество функций. Эти платы недороги и просты в использовании, так что перед разработкой собственной платы вы должны сначала выяснить (а) нет ли такой же платы в продаже и (б) нельзя ли использовать в качестве «резидентной в компьютере» части вашего интерфейса простую плату параллельного порта, как это описывалось в предыдущем разделе. Есть и другая возможность-подключить ваше устройство к компьютеру через стандартный встроенный параллельный порт Centronics либо через последовательный порт RS-232 (см. разд. 10.19 и 10.20). Поскольку эти порты одинаковы на всех микрокомпьютерах, такое решение сделает ваше устройство переносимым, даже на микрокомпьютер с другой магистралью (или вообще без магистрали!). Если ваше устройство подключается к последовательному порту, оно, скорее всего, будет включать собственный микропроцессор, что даст вам право думать о нем скорее как о компьютере, чем о периферийном устройстве. Однако как мы покажем в следующей главе, разработка небольшого прибора, управляемого микропроцессором — дело забавное, простое и недорогое; собственно, нет никаких причин выделять микропроцессор среди других БИС, а их-то вы не колеблясь используете в своем приборе!

Развивая дальше предложенную идею, следует сказать, что имеется целый ряд стандартов на «кабельные интерфейсы», ставшие последнее время весьма популярными. Они называются SCSI (Small Computer System Interface-интерфейс малых компьютерных систем), IPI (Intelligent Peripherals Interface-интерфейс интеллектуальной периферии), ESDI (Enhanced Small-Disk Interface — улучшенный интерфейс малого диска) и IEEE-488 (известный также под именами HPIB и GPIB, General-Pur-Кабель — Внешняя часть интерфейса pose Interface Bus-интерфейсная магистраль общего назначения). Интерфейс SCSI (произносится «скази»), в особенности благодаря обилию дисков и другой периферии, подключаемой непосредственно к порту SCSI, стал стандартным элементом многих микрокомпьютеров. При этом для компьютеров, не имеющих встроенного порта SCSI, выпускаются вставляемые интерфейсные платы с этим портом.

SCSI является потомком SASI (Shugart Assosiates System Interface-простой параллельной магистрали, которую фирма Shugart придумала для своих дисководов жестких дисков) и в простейшем виде представляет собой байтовый двунаправленный параллельный протокол с квитированием. Интерфейс обеспечивает несколько режимов, включая синхронную и асинхронную передачу с симметричными или несимметричными драйверами; хотя первоначально он использовался для связи единственного ЦП с единственным диском, однако с его помощью можно несколько ЦП подключить к нескольким дискам. Типичные скорости передачи составляют 1,5 Мбайт/с для асинхронного режима и 4 Мбайт/с для синхронного; асинхронный протокол медленнее, так как в процессе каждой пересылки туда и сюда передаются сигналы квитирования. С несимметричными драйверами SCSI обеспечивает передачу на 6 м, а с симметричными на 24 м.

Магистраль IEEE-488 (первоначально — интерфейс HPIB фирмы Hewlett-Packard) была разработана для подключения лабораторных приборов к компьютеру. Интерфейс включает полный протокол связи по магистрали нескольких приборов и использует терминологию локальных сетей. IEEE-488 занимает прочные позиции в инструментальной технике; фирмы Hewlett-Packard, Keithley, Philips/Fluke, Tektronix и Wavetek комплектуют этим интерфейсом большую часть выпускаемых ими приборов. Платы с интерфейсом IEEE-488 выпускаются почти для всех микрокомпьютеров. В разд. 10.20 мы еще вернемся к обсуждению интерфейсов SCSI и IEEE-488.

 

Системные концепции программного обеспечения 

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

Рассмотрев программное обеспечение и системы программирования, мы закончим главу разделом о принципах передачи данных, остановившись на стандартизованном последовательном протоколе ASCII RS-232, параллельном порте Centronics, других возможностях параллельной передачи данных (SCSI, IPI, GPIB) и, наконец, на локальных сетях.

10.17. Программирование

Язык ассемблера. Как уже упоминалось выше, ЦП компьютера распознает определенные комбинации бит, как команды, и действует в соответствии с их значением. Однако этим двоичным машинным языком пользуются крайне редко. Обычно вы составляете программы на мнемоническом языке ассемблера (как это было сделано в приводившихся ранее примерах программирования интерфейсов), а специальная программа, называемая ассемблером, преобразует их в выполнимые машинные коды. Язык ассемблера очень близок к машинному языку; каждая команда языка преобразуется непосредственно в одну или несколько строк машинного кода (из которых первая обычно представляет код операции, а последующие описывают адресацию переменных или содержат константы). Программирование на языке ассемблера позволяет получить максимально эффективную программу и дает возможность обращения к флагам и регистрам, что недоступно из языков высокого уровня. Однако такое программирование утомительно, как это показывают приведенные примеры, и для решения большинства задач (особенно требующих значительного объема вычислений) более целесообразно использовать компилятор или интерпретатор с языка высокого уровня, такого как Си или Фортран, а к процедурам на языке ассемблера обращаться лишь в случае необходимости.

Компиляторы и интерпретаторы. Си, Фортран, Паскаль и Бейсик — примеры популярных языков высокого уровня. При составлении программы вы можете использовать алгебраические выражения вроде

χ = (—Ь + sqrt (b*b — 4*а*с))/(2*а)

и управляющие структуры типа if…elseif… else, for…, while… и do…. Вам не приходится гонять туда и обратно крошечные порции информации объемом 1 байт или заботиться об адресации, сохранении регистров и прочем; вы просто объявляете переменные и массивы с указанием типов и размеров, а затем используете их в арифметических и логических выражениях. Не жизнь, а малина.

Выше шла речь об исходном тексте, который можно преобразовать в выполнимую программу двумя способами. Исходные программы на языках Си или Фортран компилируются, т. е. преобразуются специальной программой (компилятором языка) в строки на языке ассемблера; затем программа ассемблера переводит этот промежуточный язык ассемблера в машинный язык. Программы же на языках Бейсик и АПЛ обычно интерпретируются; вместо преобразования исходной программы в программу на языке ассемблера интерпретатор анализирует предложения программы и выполняет соответствующие машинные команды.

В целом интерпретация занимает гораздо больше времени, чем компиляция. Поскольку, однако, в случае интерпретации отсутствуют процессы компиляции, ассемблирования или компоновки (о компоновке см. ниже), программу можно запустить немедленно после ее ввода в машину. Интерпретирующие программы часто включают простые редакторы, удобные для быстрой модификации программы перед ее повторным пуском в процессе отладки. На заре микрокомпьютерной техники, когда жесткие диски были редкостью, интерпретатор Бейсик приобрел широкую популярность, поскольку он работает целиком в памяти; этому можно противопоставить утомительный многоступенчатый процесс компиляции. Однако сегодня быстрые диски и эффективные компиляторы снимают с нас все заботы. Любопытно отметить, что современные компиляторы часто следуют примеру интерпретирующей системы Turbo Pascal фирмы Borland и предоставляют вам «среду программирования», в которой можно без всяких усилий переходить от редактора к выполняемой программе. Если программа натыкается на ошибку, система возвращает вас в редактор и отмечает при этом неправильное предложение; такого рода системы включают отладчики, библиотекари и другие полезные и приятные средства.

Очевидным любимцем серьезных программистов является язык Си, сочетающий в себе мощность языка высокого уровня с красотой структурированных языков и гибкостью программ на языке ассемблера, обеспечивающих доступ к отдельным битам. Однако в научных приложениях львиная доля программирования все еще выполняется на языке Фортран.

Компоновщики и библиотеки. Ассемблер образует программу на машинном языке (собственно говоря, не совсем; ее часто называют «настраиваемым» или «перемещаемым» модулем) из программы на языке ассемблера, образованной компилятором, или из отдельных подпрограмм, непосредственно написанных на этом языке. Кроме этого, обычно имеются программы, используемые отдельными командами языка высокого уровня. Так, в программе на языке Си может потребоваться обратиться к математической функции вроде sqrt (вычисление квадратного корня), или к сонму функций ввода-вывода, таких как printf или fopen. Весь бюрократический кошмар получения из «библиотеки» необходимых подпрограмм (в объектной форме), а затем настройки переходов и адресаций в программе, чтобы вся эта каша разместилась в памяти должным образом, берет на себя программа, называемая компоновщиком).

В функции компоновщика входит назначение конкретных числовых значений ссылкам на ячейки памяти и адресам переменных в ассемблированной программе, и сделать это компоновщик может, только выяснив, какая программа вызывает какую и сколько места занимает каждая программа в памяти. Именно поэтому программа на машинном языке, получаемая с выхода ассемблера, должна быть настраиваемой, так же, как и ассемблированные подпрограммы, хранящиеся в различных библиотеках [обычно их несколько — библиотека встроенных функций компилятора, библиотека ввода-вывода, математическая библиотека, библиотека системных вызовов и, возможно, созданная дома (или купленная в магазине) библиотека полезных подпрограмм].

Редакторы и форматирующие программы. В доисторическую эпоху (до 1970 г.) вы могли наткнуться на программиста, несущего колоду перфокарт. Действительно, вы писали программу от руки на бланках программирования, затем пробивали, ее (или платили кому-то за пробивку) на «картах IBM» — аккуратных прямоугольниках из тонкого картона пастельных оттенков. В наши дни даже первоклашки умеют работать с текстовыми редакторами, обеспечивающими универсальный метод ввода программ в машину. Ветераны (те, кому за 30) помнят еще первые неуклюжие «интерактивные» редакторы, с помощью которых можно было создать и модифицировать текстовый файл; от этого файла по причинам, ведомым лишь самому редактору, вы всегда могли наблюдать лишь кусочек. Дан Ланкастер искушал нас своей «телевизионной пишущей машинкой», которая позволяла вывести на телевизор строку текста. И больше ничего. Ни редактирования, ни памяти, ни ничего. Поэтому легко поверить, что наш восторг не имел границ, когда мы впервые познакомились с «полноэкранным» редактором.

Хороший редактор (а сейчас они все хорошие) позволяет вам вводить и корректировать текст по мере его ввода, искать требуемые слова, изменять текст, перемещать блоки текста, открывать несколько окон для работы с несколькими файлами и создавать «макроопределения» для выполнения сложных манипуляций. Экран быстро отражает вносимые в текст изменения, даже если вы добавляете строки в начале большого файла. Даже очень большой размер файлов не замедляет процесса редактирования.

Универсальный редактор не знает, да и не интересуется тем, что вы пишите; это может быть программа, или сонет, или книга. Редактор просто создает текстовый файл в соответствии с вашими инструкциями, вводимыми с клавиатуры. Если файл состоит из предложений языка программирования, компилятор, интерпретатор или ассемблер читает его непосредственно. Если, с другой стороны, файл представляет собой текст, который вы хотите напечатать, у вас есть две возможности: прямо послать файл на принтер или дополнить его информацией о форматировании и передать форматирующей программе, которая скажет принтеру, как именно следует печатать текст. Хорошая программа форматирования заботится о полях, выравнивании строк, выделении разного места под буквы разной ширины, смене шрифтов, курсиве, жирном тексте, подчеркивании и т. д. Часто редактор и программа форматирования объединяются, причем иногда вы можете посмотреть на экране, как в действительности будет выглядеть напечатанная страница текста [это средство называется WYSIWYG (произносится «визивиг»), What You See Is What You Get-что вы видите, то вы и имеете]; однако чаще экран лишь частично отображает окончательный вид печатной страницы. Наиболее совершенные редакторы могут вставлять в текст математические и научные формулы. Для получения оригинал-макета вы вводите текст с клавиатуры наборной машины, которая сама выполняет экспонирование фотобумаги или фотопленки; лазерные или электролюминесцентные принтеры обеспечивают весьма приличное качество печати при умеренной цене и высокой скорости; ударные матричные принтеры относятся к самым дешевым, и результат оказывается соответствующим.

Редакторы, выполняющие форматирование, имеют характерные имена, например, MacWrite, Manuscript, Microsoft Word, Sprint, WordPerfect.

К популярным программам форматирования (которые могут работать и с текстом и с формулами) относятся ТЕХ и Troff. Одно предупреждение: в процессе создания текста (в противоположность программам) большинство редакторов с форматированием включают в поток редактируемого текста необычные символы, с помощью которых отмечается, например, курсив или временный конец строки. Эти символы не принимаются компиляторами или ассемблерами. Если вы не хотите, чтобы компилятор подавился вашей программой, вы должны создать текст без всяких упражнений, для чего запустить редактор в самом простом режиме «чистого» текста.

Вот еще пара бесплатных советов: а) найдите хороший редактор и держитесь его; б) не пытайтесь убедить коллег, что ваш редактор лучше какого-нибудь другого.

10.18. Операционные системы, файлы и использование памяти

Операционные системы. Из предыдущих обсуждений можно сделать вывод, что пользователю микрокомпьютера приходится часто запускать разнообразные программы, которые, к тому же, должны обмениваться между собой данными. Если, например, вам надо написать программу, то вы начинаете с запуска текстового редактора и создаете с его помощью текстовый файл, вводя строки программы с клавиатуры (хорошие программисты, насколько мы можем об этом судить, никогда не берут в руки карандаш). Сохранив на время этот файл, вы вызываете программу компилятора и компилируете сохраненный текстовый файл, чтобы получить файл с программой на языке ассемблера. Этот файл вы тоже сохраняете и запускаете ассемблер, который из файла с программой на языке ассемблера создает файл с перемещаемой программой на машинном языке. Наконец, компоновщик объединяет перемещаемую программу с другими ассемблированными подпрограммами и библиотечными программами и выдает выполнимую программу, которую вы (наконец-то!) запускаете. Для выполнения всех этих операций вам нужна сверх-программа, которая жонглировала бы всем этим хозяйством, отыскивая файлы на диске, загружая их в память и передавая управление соответствующим программам. Хотелось бы также избавиться от необходимости включения в каждую программу всех команд, требуемых для записи или чтения диска (включая обработку прерываний, загрузку регистров команд и состояний и проч.) или выполнения других операций по пересылке данных. Все это (и многое другое) входит в функции операционной системы, обширной программы, наблюдающей за загрузкой и запуском пользовательских программ (т. е. тех, которые вы пишите) и утилит (редактора, компилятора, ассемблера, компоновщика, отладчика и др.), а также управляющей вводом-выводом, системой прерываний и различными манипуляциями с файлами. Операционная система включает монитор для связи с пользователем (именно ему вы говорите, что надо вызвать редактор, или компилятор, или запустить программу) и набор «системных запросов», с помощью которых выполняемая программа может прочитать или записать строку текста на некотором устройстве, определить текущее время суток, передать управление другой программе, позволить нескольким «процессам» в многозадачной среде разделять между собой время ЦП или обмениваться данными, загружать программные «оверлеи» и т. д. Хорошая операционная система выполняет всю работу по управлению вводом-выводом, включая «спулинг» (буферизацию входных или выходных данных, позволяющую программе выполняться в то время, когда данные читаются или записываются на некотором устройстве). Выполняясь под управлением операционной системы, программа пользователя может не заботиться о прерываниях; прерывания обслуживаются системой и затрагивают ход программы только если программа сама хочет принять участие в обработке прерываний от конкретного устройства. Вершиной системного программирования является «разделение времени» (использование одного компьютера многими пользователями одновременно), когда диск служит в качестве «виртуальной памяти» для программ неограниченного размера. Примерами популярных микрокомпьютерных операционных систем являются MS-DOS (используемая на машинах IBM PC и их аналогах), OS/2 (предназначенная для машин PS/2, преемников IBM PC), UNIX (разработанная в Bell Labs и широко используемая на машинах VAX, а также на компьютерах с микропроцессором 68000), MacOS и VMS (операционная система машин VAX, предоставляемая компанией).

Файлы. В качестве среды для массовой памяти широчайшее распространение получили магнитные диски, как гибкие («флоппи»), с контактирующими головками чтения-записи, так и жесткие («винчестер»), с плавающими головками. Типичные емкости лежат в пределах 1 Мбайт для гибких дисков и 20-500 Мбайт для небольших винчестеров. Данные организуются в виде файлов. Все машинные материалы — тексты, программы пользователей, утилиты (т. е. редактор, ассемблер, компилятор), библиотеки и проч., хранятся одинаковым образом и составляют файлы. Хотя среда массовой памяти разделяется на физические блоки, или секторы жестко определенного размера (обычно размер сектора составляет 512 байт), сами файлы могут иметь любую длину. Операционная система милосердно берет на себя всю заботу об адресации к дорожкам и секторам; она извлекает требуемые данные, если вы указываете имя файла. Имеется масса любопытнейших деталей файловой организации, которые мы не можем здесь обсудить из-за недостатка места. Важно только понять, что все эти программы (редактор, компилятор и др., так же как и исходный текст, скомпилированная программа и даже данные) хранятся на некотором устройстве массовой памяти как поименованные файлы, и система умеет извлекать их для вас (прочитайте, однако, в следующем разделе об электронных дисках). Осуществляя свои служебные обязанности, система выполняет огромный объем работ по обслуживанию файлов.

Недавние прибавления семейства устройств массовой памяти имеют в своей основе потребительскую электронику и обеспечивают очень высокую плотность хранения в маленьком объеме. Сюда относятся: (а) оптические диски вроде тех, что используются в проигрывателях, с емкостью около гигабайта. Они служат в качестве ПЗУ, WORM-памяти (Write Once, Read Many — записать один раз, прочитать многократно) или как полностью стираемая память для записи/чтения; (б) видеокассеты формата VHS или 8 мм, которые позволяют иметь гигабайты памяти с возможностью записи/чтения на недорогой ленте. Основной недостаток кассет — большое время доступа. Обе упомянутые системы памяти используют изощренные методы коррекции ошибок, возникающих из-за дефектов поверхности и по другим причинам; в обычных аудио/видеоприменениях эти ошибки не имеют особого значения, однако при хранении данных или программ они, не будучи исправлены, носили бы разрушительный характер.

Использование памяти. Файлы хранятся в устройствах массовой памяти, однако программы в процессе их выполнения должны находиться в оперативной памяти. Простую автономную программу вроде той, что будет рассмотрена в следующей главе, можно загрузить почти в любое место памяти. Однако в компьютере с операционной системой всегда имеются специальные области, зарезервированные для выполнения специальных функций. Например, сама операционная система MS-DOS, вместе с ее интерпретатором команд, дисковыми буферами, стеком и прочим, обычно загружается в начало памяти, заполняя при этом векторами прерываний выделенные ячейки, адреса которых известны ЦП, в то время как часть MS-DOS, заключенная в ПЗУ, располагается в конце памяти, за областью, отведенной под видеобуферы дисплея. Если компьютер работает под управлением операционной системы, выделением памяти под программы пользователя ведает система. Понимание этого момента особенно важно при использовании ПДП; в этом случае вы должны предоставить системе возможность определить, где будет располагаться ваш буфер данных, и использовать этот адрес в качестве стартового для блочной передачи по каналу ПДП.

Ситуация еще более усложняется, если программы по ходу выполнения выгружаются и загружаются (так называемый «свопинг») или перемещаются по памяти. В памяти одновременно может находиться много программ, которым в многозадачном режиме выделяются «кванты времени» ЦП. К тому же большинство микрокомпьютеров используют «отображение памяти», при котором физические адреса памяти отображаются на различные логические адреса (т. е. те, по которым программа располагается с ее точки зрения). Если всего сказанного недостаточно, чтобы сбить вас с толку, подумайте о «виртуальной памяти», используемой в более совершенных моделях микрокомпьютеров, когда ваша программа разделяется на небольшие «страницы», каждая из которых в любой момент времени может быть, а может и не быть в памяти; программа «листает» эти страницы, гоняя их между памятью и диском в безумном пароксизме бешеной активности.

Обсуждение памяти нельзя считать законченным, если не упомянут электронный (псевдо) диск, который можно организовать даже на относительно простых машинах, если только хватит оперативной памяти. Идея псевдодиска заключается в такой организации памяти, чтобы с точки зрения операционной системы она выглядела, как диск; в эту псевдодисковую память можно затем загрузить часто используемые программы. Такая процедура может оказаться полезной при разработке программ, когда приходится постоянно обращаться к редактору, компилятору, ассемблеру и компоновщику. При использовании псевдодиска работа идет значительно быстрее, поскольку отпадает необходимость в обращениях к настоящему диску. Правда, если произойдет отказ компьютера, вы потеряете все, что сделали, так как файлы не сохраняются на диске автоматически. Схожая идея лежит в основе кеш-памяти; в этом случае область ОЗУ хранит результаты последних обращений к диску.

Драйверы. Компьютерный мир полон разнообразия — каждый месяц мы сталкиваемся с новинками технологии в области запоминающих устройств (магнитных, оптических), принтеров (лазерные, электролюминесцентные), сетей и проч. Различное электронное оборудование требует и различных управляющих сигналов с разными требованиями к временной синхронизации и т. д. Это могло бы привести к серьезным программным трудностям, так как программное обеспечение, разработанное, например, для матричного принтера, абсолютно не годилось бы для лазерного наборного автомата.

Решение лежит в использовании драйверов, специальных программ, предназначенных для организации единого программного интерфейса с разнообразным оборудованием. Так, например, наборный язык ТЕХ создает файлы в формате dvi (device-independent-не зависящий от устройств); драйвер принтера (специфический для каждого используемого вами принтера) пережевывает файл dvi и выплевывает соответствующие принтерные коды, заставляющие принтер работать должным образом. ТЕХ может работать с любым принтером, если только к этому принтеру у вас есть «dvi-транслирующий» драйвер. Сказанное относится и к устройствам массовой памяти, таким, как дисководы дисков; в результате вы можете взять любой из имеющегося на рынке множества дисков и подключить его к любому компьютеру — типа PC или Macintosh или с системой UNIX.

Драйверы являются частью системного программного обеспечения и средний пользователь компьютера может и не подозревать об их функционировании. Если, однако, вы разрабатываете новое оборудование для компьютера, вы, скорее всего, вскоре станете экспертом по драйверам, так как для того, чтобы заставить вашу аппаратуру играть заодно со всей остальной командой, вам придется написать для нее ваши собственные драйверы.

 

Принципы передачи данных 

Простая вычислительная система обычно комплектуется устройствами массовой памяти (диски, ленты), интерактивными устройствами (алфавитно-цифровой терминал), а также устройствами для получения твердой копии (принтеры, плоттеры). Кроме того, в систему может входить модем (модулятор-демодулятор), чтобы компьютер мог «позвонить» другому компьютеру по обычной телефонной линии. Наконец, все более популярными становятся локальные вычислительные сети (ЛВС). Включив компьютер в ЛВС, вы получите доступ к файлам, хранящимся на остальных компьютерах сети и, кроме того, право совместного использования дорогостоящих ресурсов (больших дисков, ленточных магнитофонов, принтеров и наборных машин). Во всех этих случаях ваш ЦП должен пересылать данные. Посмотрим, как это делается.

Несовместимость. В мрачные времена компьютерного средневековья (скажем, до 1975 г.) ситуация была довольно унылой. Каждое семейство компьютеров использовало собственную структуру магистрали и собственный протокол обмена (не говоря уже о языках программирования). Вы покупали (или иногда делали) интерфейсные платы, подходящие к данному компьютеру и связывали эти платы с самими периферийными устройствами самодельными кабелями. Такая всеобщая несовместимость распространялась и на сами периферийные устройства: ленточный магнитофон нельзя было подключить к интерфейсу диска, а терминал — к интерфейсу плоттера и т. д. Дело осложнялось еще и тем, что периферийные устройства, выпускаемые разными производителями, часто использовали разные сигналы и соглашения для передачи данных и были несовместимы «на уровне разъемов».

Совместимость. В какой-то степени отмеченная выше несовместимость была неизбежна, так как с целью повышения производительности различные периферийные устройства по-разному пересылают свои данные. Например, магнитный диск для передачи слов с высокой скоростью использует параллельный формат шириной 1 байт, а соответствующий интерфейс, как отмечалось выше, должен обладать прямым доступом к памяти; в противоположность этому клавиатура терминала передает данные в стандартном бит — последовательном алфавитно-цифровом формате с использованием более простого программного ввода-вывода по прерываниям. Хотя какая-то доля этой несовместимости сохранилась и до настоящего времени, в целом ситуация существенно улучшилась, так как большая часть выпускаемого оборудования использует ограниченное число общепринятых стандартов на передачу данных. Появление компьютеров IBM PC привело к определению магистрали и долгожданных форматов для малых машин, в то время как высокопроизводительные магистрали общего назначения вроде VME или Multibus стали основой ряда других компьютеров. Многие фирмы выпускают интерфейсы для этих магистралей (да и для других, вроде Q-bus машин фирмы DEC), что существенно упростило их использование. Что еще более важно, производители периферийного оборудования договорились об ограниченном числе стандартизованных «кабельных интерфейсов». Наиболее важными являются (а) последовательный формат RS-232, обычно используемый с алфавитно-цифровыми данными в коде ASCII; (б) формат Centronics для параллельного принтера; (в) параллельная магистраль SCSI; (г) магистраль IPI; и (д) приборная магистраль IEEE-488 (GPIB).

Рассмотрим эти стандарты, заключив главу кратким обсуждением двух популярных локальных сетей, Ethernet и локальной сети с маркерным кольцом.

10.19. Последовательная связь и коды ASCH

Как уже упоминалось, передача алфавитно-цифровой информации между компьютером и устройствами с умеренным быстродействием чаще всего выполняется с помощью 7-бит кода ASCII (American Standard Code for Information Interchange — американский стандартный код для обмена информацией), при бит-последовательной передаче по единственной линии.

В табл. 10.3 представлен список 7-бит кодов. Устройства, обменивающиеся данными с помощью последовательной ASCII-передачи, почти всегда посылают 8 бит, но этот 8-й бит не является частью кода ASCII; часто он представляет бит аппаратного контроля четности (иногда четности, иногда нечетности, хотя чаще всего он устанавливается в 0 и игнорируется), но иногда этот бит используется как «мета-клавиша» регистра для образования дополнительных 128 символов, которые могут быть греческими буквами, альтернативным шрифтом и д. Для этих дополнительных символов не существует стандарта. (Восьмой бит используется и в тех случаях, когда по последовательной связи передаются двоичные данные; это, однако, не всегда возможно, так как для аппаратуры последовательной связи столь привычно отбрасывать этот 8-й бит при передаче кодов ASCII, что она может не допустить его использования в качестве элемента данных.)

Несколько замечаний по поводу таблицы кодов ASCII. Буквы верхнего регистра (прописные) начинаются с кода 40Н; установка в 1 бита 5 генерирует соответствующие буквы нижнего регистра (строчные). Код ASCII цифры равен самой цифре плюс 30Н. Первые 32 символа ASCII являются «неотображаемыми», управляющими символами. Некоторые из них достаточно важны, чтобы удостоиться собственных клавиш на клавиатуре, например CR (клавиша «возврата каретки», которая может называться return — возврат, поскольку у клавиатур отсутствует каретка), BS (backspace — возврат на шаг), НТ (tab — табуляция) и ESC (escape — выход). Любые управляющие символы, включая и перечисленные выше, можно ввести, нажав (и не отпуская) клавишу CTRL и введя соответствующую букву на верхнем регистре; например, CR эквивалентно CTRL-M (попробуйте это на своем компьютере). Управляющие символы используются для управления печатью или выполнением программ; они могут также восприниматься в качестве управляющих программ, которые предназначены для обработки алфавитно-цифровых символов, например, программами редакторов.

Помимо отмеченных выше, к важным символам можно отнести: NUL (ноль), символ, состоящий из одних двоичных нулей, и используемый иногда для разделения символьных строк; FF (Form Feed — перевод страницы), которым начинается новая страница; EXT (End of Text — конец текста, нежно называемый «control С»), который воспринимается многими операционными системами, как команда завершения текущей программы; DC3 (control S), используемый в качестве «мягкого рукопожатия» для приостановки последовательной передачи; DC1 (control Q), символ, возобновляющий передачу. К сожалению, в таблице кодов ASCII отсутствуют индексы, показатели степени, а также греческие буквы и научные знаки. Было бы полезно иметь по меньшей мере знаки π, μ, Ω и символ градусов (°), которые часто встречаются в технических текстах. Разумеется, с помощью управляющих символов (или их последовательности) можно указать на необходимость смены шрифта или алфавита. Так обычно и делают в текстовых процессорах, где после ввода управляющего символа программа форматирования воспринимает последующие символы ASCII по-иному. Возможно, такой подход является наилучшим решением проблемы, так как при работе с техническими текстами вряд ли вам надолго хватит одного фиксированного набора ASCII-символов, даже очень большого.

Заметьте, что компьютерные клавиатуры часто конструируются так, что они не являются просто генераторами кодов ASCII (одна клавиша - один код); общепринятой методикой является генерация каждой клавишей некоторых определенных кодов при нажатии и отпускании. Специальное системное программное обеспечение («драйвер клавиатуры», см. разд. 10.18) транслирует затем эти коды в обычные коды ASCII. Такой подход существенно повышает гибкость процедуры ввода с клавиатуры, так как возникает возможность настройки драйвера клавиатуры с целью отработки автоповтора клавиш или многоклавишных комбинаций, переотображения всей клавиатуры (например, в клавиатуру Дворака) и организации «горячих клавиш» и т. д.

Бит-последовательная передача. Код ASCII (или любой другой алфавитно-цифровой код) может быть передан либо группой из 8 параллельных бит (по 8 отдельным проводам), либо последовательностью из 8 бит, один за другим. Для организации передачи со скоростями от низкой до средней более удобной является экономичная в смысле используемых проводов последовательная связь. Модем (подробнее о модемах см. ниже) преобразует последовательность бит в звуковой сигнал и наоборот (например, используя одну звуковую частоту для «1» и другую для «0»), который затем может быть послан в телефонную линию; здесь так же, естественно, используется последовательная передача. При этом используется стандартный протокол и стандартные скорости передачи. При асинхронной передаче к концам каждого 8-бит символа присоединяются старт-бит и стоп-бит (иногда два), образуя группу («кадр») из 10 бит. Передатчик и приемник используют фиксированную скорость из допустимого набора; наиболее популярны скорости передачи 300, 1200, 2400, 4800, 9600 и 19200 бод (= тактов в секунду). На рис. 10.16 приведен формат кадра последовательной передачи.

Рис. 10.16. Формат кадра при последовательной передаче данных (интерфейс RS-232 ).

Когда передача данных отсутствует, передатчик находится в состоянии «маркера» (терминология осталась еще от времен телетайпов). Каждый символ начинается со старт-бита, за которым следуют 8 бит кода ASCII, младшим битом вперед (обычно в эти 8 бит входят 7 бит данных плюс 1 необязательный бит контроля четности) и, наконец, стоп-бит; последний должен поддерживаться по меньшей мере один такт, но может длиться сколько угодно. На приемной стороне УАПП (универсальный асинхронный приемо-передатчик, см. разд. 11.11), работая с той же частотой, синхронизируется к каждой 10-бит группе и преобразует входную последовательность в 8-бит параллельные группы данных. Поскольку приемник заново синхронизируется к старт- и стоп-битам каждого символа, ему не требуется очень высокая точность тактовых сигналов; равенство и стабильность частот передатчика и приемника должны обеспечивать рассогласование не более доли длительности одного бита на длине кадра, т. е. не более нескольких процентов.

Приемный УАПП запускается фронтом старт-бита, выжидает половину длительности бита чтобы удостовериться, что старт-бит еще присутствует, а затем фиксирует значение данных в середине каждого бита. Стоп-бит завершает каждый символ и одновременно выполняет роль промежутка между кадрами, если следующий символ не посылается немедленно за предыдущим. Приемный УАПП проверяет наличие уровня стоп-бита через 10,5 длительностей бит после фронта старт-бита, что помогает удостоверить правильность посылки символа. «Разрыв» (break) представляет собой длительный пробел, который не может возникнуть в ходе нормальной передачи символов. На рынке имеются программируемые тактовые генераторы (т. е. программируемые делители частоты), которые преобразуют входную частоту от генератора в стандартный набор тактовых частот, определяющих скорость передачи, причем конкретный коэффициент деления определяется входным двоичным кодом. Большинство современных УАПП (например, двухканальная синхронно-асинхронная микросхема 8530 фирмы Zilog) включает внутренние программно-управляемые генераторы скорости передачи.

RS-232. Сами сигналы при последовательной передаче ASCII-кодов могут посылаться различными способами. Самый первый из них, предложенный еще несколько десятков лет назад, состоит в переключении, с выбранной скоростью передачи, тока величиной 20 (или иногда 60) мА. Это так называемая «токовая петля». Иногда этот способ реализуется, как альтернативный вариант, но для умеренных скоростей передачи он был вытеснен стандартом ассоциации электронной промышленности (EIA) RS-232C 1969 г. (и последующим стандартом RS-232D 1986 г.), в которых передача осуществляется биполярным напряжением. Стандарт RS-232 определяет характеристики и драйверов, и приемников. Драйвер должен создавать уровни напряжения от +5 до +15 В (логический вход низкого уровня) и от — 5 до —15 В (логический вход высокого уровня) на нагрузке от 3 до 7 кОм с крутизной перепада менее 30 В/мкс и способностью противостоять замыканию на любой другой выход даже со столь неблагоприятными характеристиками, как 5 В при 500 мА; приемник должен представлять нагрузочное сопротивление от 3 до 7 кОм, преобразующее входное напряжение от +3 до +25 В в низкий логический уровень, а входное напряжение от —3 до —25 В в высокий логический уровень. Заметьте, что логическая 1 преобразуется драйвером RS-232 в отрицательный уровень, называемый «маркером»; логический 0 представляет собой положительный уровень («пробел»). При передаче с помощью токовой петли ток течет в течение логической 1 (маркер) и прекращается на время действия логического 0 (пробел).

Для приемников RS-232 характерно наличие гистерезиса входного напряжения; некоторые приемники позволяют подключать конденсатор с целью увеличения постоянной времени и уменьшения чувствительности к шумовым импульсам. Стандартные микросхемы приемника и драйвера RS-232 описаны в разд. 9.14 и 14.17. При расстояниях 10–20 м интерфейс RS-232 обеспечивает высокое качество передачи на скоростях вплоть до 38400 бод даже при использовании неэкранированного многожильного кабеля; связь на короткие расстояния иногда осуществляют со скоростью 115200 бод.

Стандарт RS-232 определяет также тип разъема и назначение его контактов. К сожалению, это описание не полно! Это вечный источник неприятностей, потому что, вообще говоря, два устройства с интерфейсами RS-232, соединенные друг с другом, работать не будут. Это настолько неожиданно и неприятно, что читатели предыдущего издания этой книги даже обвинили нас, потому что мы не написали в книге, как бороться с этой несовместимостью. К счастью для вас, вы читаете второе издание. Разгадка состоит в следующем.

В этой истории с последовательным интерфейсом имеется два источника неприятностей: (а) Определены два типа устройств, причем входные контакты устройств одного типа соответствуют выходным контактам другого; вам может понадобиться связать между собой два устройства одного типа или два взаимно дополняющих устройства; (б) Имеется пять сигналов квитирования; одни устройства генерируют эти сигналы и ожидают их приема, другие же игнорируют соответствующие входы (и ничего не подают на выходы). Чтобы все у вас работало, в этих деталях придется разобраться. Приступим.

Интерфейс RS-232 был разработан для связи DTE (Data Terminal Equipment — оконечное оборудование данных, ООД) с DCE (Data Communication Equipment — аппаратура передачи данных, АПД). Терминал всегда выглядит, как DTE, а модем всегда выглядит, как DCE; однако другие устройства, включая микрокомпьютеры, могут быть и тем, и другим. Компьютер IBM PC выглядит как DTE и укомплектован вилочной частью разъема, но большинство больших компьютеров имеют выход типа DCE. Подключая DTE к DCE, вы просто соединяете одноименные контакты разъемов DB-25 (которые могут быть как вилочными, так и розеточными!), и, если вам повезет, все будет работать. Мы говорим «если повезет», потому что результат все еще зависит от того, какие квитирующие сигналы одно устройство ожидает от второго, и устанавливает само. (Само собой разумеется, что решив проблему с кабелем, вы еще должны выбрать скорость передачи, четность и некоторые другие программные параметры!) С другой стороны, связывая два одинаковых устройства, вы не можете соединить одноименные контакты, потому что тем самым вы соедините вместе два выхода: DTE передает через контакт 2 и принимает через контакт 3, a DCE делает как раз наоборот. Поэтому такую пару устройств следует соединять кабелем (так называемым «нуль-модемом»), в котором контакты 2 и 3 соединяются друг с другом крест-накрест. К сожалению, это еще не все

В табл. 10.4 показаны все основные линии. TD и RD - это линии передачи и приема данных; RTS и CTS — запроса передачи и готовности передачи; DTR, DSR и DCD — «оконечное оборудование данных готово», «аппаратура передачи данных готова» и «детектор принимаемого линейного сигнала». В разъеме имеются две земли: защитное заземление (или корпус, контакт 1) и сигнальное заземление (контакт 7); в большинстве машин их просто соединяют вместе. Пять сигналов, не относящихся к данным, являются управляющими сигналами квитирования. Устройство DTE устанавливает RTS и DTR, когда оно готово к передаче, а устройство DCE устанавливает CTS и DSR, когда оно готово к приему. Некоторые устройства DTE требуют, чтобы до выполнения ими любых действий был установлен их вход DCD. На всех сигнальных линиях действуют биполярные уровни RS-232, причем установленные данные (TD, RD) имеют отрицательную полярность, а установленные управляющие сигналы (RTS, CTS, DSR, DTR, DCD) — положительную.

Заметьте, что названия сигналов имеют смысл только если их рассматривать со стороны DTE. Например, контакт 2 называется TD (Transmitted Data-передаваемые данные) на обеих сторонах, несмотря на то, что DTE устанавливает данные, a DCE принимает их. Поэтому название контакта не говорит вам однозначно, вход это или выход - вам еще надо знать, рассматривает ли себя устройство, как DTE или DCE (вы можете обойти это затруднение с помощью вольтметра!).

Если бы все устройства RS-232 устанавливали все сигналы, требующие установки, и анализировали состояние всех сигналов, требующих анализа, то всегда можно было бы просто соединить соответствующие контакты (для пары DTE-DCE) или соединить соответствующие контакты крест-накрест (для пар DCE-DCE или DTE-DTE). Если, однако, вы к устройству, игнорирующему все линии квитирования, подключите устройство, реализующее полный протокол квитирования, ничего хорошего из этого не получится. Разрабатывая стратегию своих действий, вы должны опираться на реальность; иногда для этого требуется некоторая хитрость. На рис. 10.17 показаны схемы кабелей, обеспечивающих правильные соединения для всех (ну, скажем, почти всех) ситуаций.

Рис. 10.17. Кабели RS-232 , обеспечивающие правильные соединения. Указанные номера контактов соответствуют 25-контактным разъемам DB-25; разводка альтернативного 9-контактного разъема приведена на схеме д .

На схеме а показаны соединения для пары устройств DTE—DCE, когда оба устройства используют полный протокол квитирования. Одна пара квитирующих сигналов представлена линиями RTS/CTS, другая - линиями DTR/DSR. На схеме в показан кабель «нуль-модема» с перекрещенными входами и выходами для пары DTE-DTE. Тот же кабель годится и для пары DCE-DCE, только надо изменить направление стрелок на рисунке и опустить соединение контакта 8. Если, однако, одно устройство реализует протокол квитирования, а другое - нет, кабели а и в не годятся. В этом случае самое простое — распаять кабель таким образом, чтобы устройство само отвечало на свои же сигналы квитирования и разрешало самому себе переход к следующим операциям. Такое соединение показано на схеме б для пары DTE-DCE и на схеме г для пары DTE-DTE (или пары DCE-DCE, но тогда следует опустить соединение контакта 8). Как сделаться гением RS-232. Если вы распаяете эти четыре кабеля с розеткой и вилкой на каждом конце, вы сможете заставить что угодно работать с чем угодно (почти). Ваши коллеги признают в вас гения. Правда, только в том случае, если им в руки не попадется действительно профессиональная штучка — «индикаторная коробка для RS-232». Она оснащена световыми индикаторами на ЭЛД для каждой линии интерфейса, что позволяет наблюдать, какое устройство какие сигналы устанавливает, и имеет набор перемычек для соединения контактов разъемов в любом порядке. Использовать индикаторную коробку надо следующим образом. Прежде всего, наблюдая световые индикаторы, соедините правильно TD и RD, затем по состоянию индикаторов определите, какое устройство посылает сигналы квитирования. Если устройство устанавливает RTS, оно, скорее всего, ожидает ответной установки CTS. Если это делают оба устройства, соедините их друг с другом; в противном случае замкните RTS на CTS того же устройства. То же самое проделайте с сигналами DTR и DSR. Если в устройстве используется только одна пара квитирующих сигналов, то это, скорее всего, DTR/DSR. Вообще пара DTR/DSR используется для оповещения о том, что устройство на противоположной стороне подсоединено и включено, в то время как пара RTS/CTS запускает и останавливает передачу.

Если скупость не позволяет вам приобрести индикаторную коробку, можете проанализировать состояние линий с помощью вольтметра: любая линия, находящаяся под большим (> 4 В) отрицательным или положительным напряжением, несет установленный сигнал; если напряжение на линии около нуля, сигнал сброшен.

Программное квитирование. Некоторые устройства используют аппаратные сигналы квитирования RTS/CTS для индикации начала и конца передачи данных, в то время как более медленные устройства (например принтер) просто держат их установленными. Другие осуществляют программное квитирование: CTRL-S (для остановки) и CTRL-Q (для возобновления). Если вам повезет, у вас будет возможность выбора. Программный метод позволяет упростить кабель, и если устройства полностью игнорируют сигналы аппаратного квитирования, в кабеле будут лишь провода, подключенные к контактам 1, 2, 3 и 7 (вам только надо выяснить, соединять ли контакты 2 и 3 прямо или крест-накрест). Однако, даже если устройство использует CTRL-S и CTRL-Q для управления передачей, оно может требовать подключения линий аппаратного квитирования для установления связи. В этом случае вам понадобится одна из схем соединений, приведенных на рис. 10.17, б и г. Не забудьте только включить питание на обеих сторонах линий связи, так как ни одно из соединенных устройств не имеет никакой возможности определить, включено ли другое и вообще существует ли оно!

Другие стандарты на последовательную передачу: RS-422, RS-423 и RS-485. Стандарт RS-232C был введен в 1969 г., когда последовательная передача данных осуществлялась медленно. Интерфейс обеспечивает дальность связи до 15 м со скоростью до 19200 бод. Однако скорости компьютеров и периферийных устройств удваивались каждые год-два, и потребовались лучшие стандарты на последовательную передачу. Как уже отмечалось в разд. 9.14, RS-423 представляет собой улучшенный протокол для биполярных несимметричных цепей, обеспечивающий скорость передачи до 100 кбод и дальность до 1200 м (но не одновременно); он принципиально совместим с RS-232. RS-422 представляет собой протокол для однополярных симметричных цепей с граничными возможностями 10 Мбод и 1200 м (см. рис. 9.37, где приведена зависимость скорость-дальность). RS-485 подобен RS-422, но содержит дополнительные спецификации для подключения к одной линии многих драйверов и приемников. В табл. 10.5 собраны характеристики этих четырех стандартов.

Модемы. Как уже отмечалось ранее, модем («модулятор/демодулятор») используется для преобразования бит — последовательных цифровых величин в аналоговые сигналы, которые можно пересылать по телефонным линиям или другим каналам передачи данных (рис. 10.18).

Рис. 10.18. Связь через модем.

Внутренний модем вставляется в разъем (слот) вашего компьютера (либо поступает к вам уже встроенным в компьютер), в то время как внешний модем представляет собой автономный прибор, питающийся от сети переменного тока и имеющий соединитель в стандарте RS-232 для подключения к последовательному порту компьютера. Любой модем имеет выход на телефонную линию одним из двух способов: (а) с помощью прямого соединения через телефонную розетку или (б) акустически, когда телефонная трубка кладется в обрезиненное гнездо, содержащее микрофон и динамик. Модемы с акустическим подключением в настоящее время вышли из моды, хотя они могут пригодиться, например, в гостинице, где иначе вам пришлось бы лазить под кроватями в поисках телефонной розетки (возможно и несуществующей!).

В большинстве случаев требуется пересылать данные по одному телефонному каналу в обоих направлениях одновременно («полнодуплексная связь»); передача и прием совместно используют телефонную полосу частот, которая занимает область приблизительно 300 Гц-3 кГц. Широко используются три полнодуплексных формата: 300 бод FSK (Bell 103) 1200 бод дибитный PSK (Bell 212А) и 2400 бод дибитный PSK (FSK обозначает Frequency-shift Keying — частотная манипуляция, a PSK — Phase-Shift Keying — фазовая манипуляция; о дибитах см. ниже). Модем, предназначенный для передачи со скоростью, скажем, 1200 бод, обычно поддерживает и связь со скоростью 300 бод и т. д. Хотя для использования модема нет необходимости вникать в тонкости кодирования им данных, однако методы кодирования интересны сами по себе, и мы не можем удержаться, чтобы кратко не описать их.

Стандарт на 300 бод (Bell 103) использует частотную манипуляцию (FSK), при которой выбранная пара звуковых тонов обозначает маркер и пробел: 1270 Гц (маркер) и 1070 Гц (пробел) в одном направлении, 2225 Гц и 2025 Гц в другом. Модем Bell 103 очень прост и состоит из переключаемого генератора для передачи и пары звуковых фильтров для приема (рис. 10.19, а). Обратите внимание на использование гибридной цепи (рис. 10.19, б) для разделения передаваемого и принимаемого сигналов. Если принять, что импеданс телефонной линии близок к его номинальному значению 600 Ом, передаваемый сигнал модема (Тх) совершенно не проходит на выход принимаемого сигнала (Rx). На практике гибридные цепи работают не так уж хорошо, потому что импеданс телефонной линии может заметно отклоняться от номинального значения 6000 м (см. разд. 14.5). Поэтому желательно иметь узкополосный приемный фильтр, а это приводит к усложнению модема.

Рис. 10.19. Модем с частотной манипуляцией ( а ) и гибридная цепь ( б ).

Упражнение 10.5 . Разберитесь, как работает гибридная цепь на рис. 10.19. После этого вы сможете поражать коллег своей эрудицией.

Стандарт на 1200 бод (Bell 212А) работает иначе. Поток цифровых данных группируется в пары бит («дибиты»); каждый из четырех возможных дибит передается в виде заданного сдвига фазы несущей постоянной частоты (00:90°, 01:0°, 10:180° и 11:-90°), с плавным переходом фазы от одного дибита к следующему. Таким образом, скорость передачи дибит составляет 600 Гц. Частота (фазово-модулированной) несущей равна 1200 Гц в одном направлении и 2400 Гц в другом.

Приемный модем расшифровывает данные, определяя разность фаз между соседними дибитами. Эта остроумная идея имеет один недостаток, именно, приемник теряет значение относительной фазы, если поступает длинная последовательность одинаковых дибит. Для того чтобы предотвратить длинные посылки данных с неизменной фазой, передаваемый поток данных рандомизуется (скремблируется) путем выполнения над данными операции исключающего ИЛИ с псевдослучайной последовательностью (генерируемой с помощью 17-разрядного сдвигового регистра с петлей обратной связи из 14-го разряда по исключающему ИЛИ, см. разд. 9.32). На приемном конце выполняется аналогичный процесс дескремблирования.

Полно-дуплексные модемы со скоростью передачи 2400 бод также передают дибиты с фазовым кодированием, хотя и с другим набором фаз. В этих сложных устройствах обычно используются адаптивные корректоры частотных и временных ошибок на телефонной линии, а также глубоко оптимизированные фильтры для передаваемых и принимаемых сигналов. В результате частота ошибок уменьшается в незначительной степени по сравнению с ранними FSK-модемами на 300 бод.

Нет никакой необходимости разрабатывать модемы заново, так как фирмы AMI/Gould, Exar, National, Rockwell, Silicon Systems и ΤΙ выпускают микросхемы и модули модемов. Еще проще купить готовый модем, либо в виде вставной платы, либо в виде отдельного прибора с соединителем в стандарте RS-232 для подключения к компьютеру. Модемы, в зависимости от характеристик, стоят 100–300 долл. Стоит поискать «Hayes-совместимый» модем, воспринимающий стандартизованный набор команд для передачи номера абонента и проч.; эти модемы стали стандартом де-факто для всего связного программного обеспечения.

Полезный совет: передавая через модем файлы данных между компьютерами, используйте модемный протокол с проверкой блоков, например, Kermit или XMODEM. Такой протокол посылает данные блоками фиксированной длины, сопровождая каждый блок контрольной суммой. Приемный модем сравнивает контрольные суммы, автоматически запрашивая повторную передачу дефектных блоков. Принятые таким образом файлы гарантированно не имеют ошибок; напротив, файлы, посланные просто в виде набора кодов ASCII, почти наверняка будут содержать ошибки!

10.20. Параллельная связь: Centronics, SCSI, IPI, GPIB(488)

Для кабельных соединений со скоростными периферийными устройствами параллельная связь обычно оказывается удобнее последовательной. Ниже описаны популярные представители этого направления.

Centronics. Это простой байтовый однонаправленный параллельный порт с квитированием, первоначально предложенный фирмой Centronics и широко используемый для подключения принтеров. В отличие от RS-232 он всегда работает! В табл. 10.6 перечислены сигналы, выходящие на 36-контактный разъем; их полагается передавать по скрученным парам.

На рис. 10.20 показаны временные соотношения этих сигналов.

Рис. 10.20. Временные соотношения для (принтерного) интерфейса Centronics .

Базовые сигналы перечислены в первой группе: D0-D7, STROBE', ACKNLG' и BUSY. Сигнал BUSY является флагом: если он в низком состоянии, принтер не «занят», т. е. готов принимать данные; источник данных (компьютер) устанавливает тогда данные, а затем STROBF (при гарантированной достоверности данных по обе стороны этого импульса). После этого устанавливается в высокое состояние сигнал BUSY, который возвращается в низкое состояние только когда принтер готов принимать следующий байт. Компьютер должен, как это показано на рисунке, наблюдать за состоянием линии BUSY, чтобы определить момент посылки следующего байта. Сигнал ACKNLG' (который представляет собой импульс, а не уровень) можно использовать в качестве сигнала прерывания; не пытайтесь, однако, подменить им сигнал BUSY, потому что он может закончиться к тому времени, когда вы захотите считать его состояние, и вы будете ждать вечно. В состав порта входят еще несколько сигналов, позволяющие обнаружить, что в принтере нет бумаги (РЕ') или что он отключен (ERROR' или BUSY); компьютер может инициализировать принтер (INIT'), запросить автоматический перевод строк (AUTO FEED XT') или послать байт для отмены выбора принтера (установить IN' в высокое состояние, затем послать ASCII-код DC3). Обратите внимание на щедрые временные соотношения в диаграмме синхронизации, с очевидностью рассчитанные на медленные (механические) устройства, которые не могут принимать данные с высокой скоростью.

В большинстве принтеров предусмотрен какой-то объем буферной памяти, что позволяет им быстро принять первую посылку данных, однако в среднем байты можно посылать лишь со скоростью их печати. Для матричного принтера скорость посылки данных составляет 100–300 байт/с. Если вам надо разработать интерфейс Centronics для подключения к магистрали какого-либо компьютера, то самый простой способ организации всех выходных линий заключается в использовании зафиксированных («защелкнутых») данных, управляемых программным вводом-выводом. Линии D0-D7 можно выполнить в виде одного порта, а оставшиеся линии (включая STROBE') в виде второго. Входные сигналы (BUSY и др.) не фиксируйте, просто пропустите их на шину в операции программного чтения.

Полезным дополнением является использование ACKNLG' для возбуждения прерывания. На рис. 10.21 все сказанное проиллюстрировано применительно к магистрали IBM PC.

Рис. 10.21. Порт Centronics для PC.

Заметьте, что организация прерываний в этом случае не составляет труда, поскольку прерывания в PC активизируются перепадом; попросту используйте спад сигнала ACKNLG', как это показано на рис. 10.20. Для запрещения прерываний мы использовали один из фиксируемых выходных бит, как это описывалось в разд. 10.09 и 10.11. Обратите также внимание на использование сигнала магистрали RESET DRV для сброса всех выходов (и прерываний) при включении питания; именно ради этого мы выбрали микросхему `273 восьмиразрядного D-peгистра (в котором предусмотрен вход RESET).

В процессе работы с этим интерфейсом вы избирательно устанавливаете и сбрасываете выходные управляющие сигналы, подавая выходные байты с соответствующим образом установленными или сброшенными битами, в порт В. Поскольку на выходе предусмотрены фиксаторы, вы можете спокойно изменять состояние любого выходного бита, не боясь появления выбросов на других выходах. Однако храните в памяти копию байта, зафиксированного в порте В, чтобы можно было посылать в этот порт новые байты, отличающиеся единственным битом (используя операции И и ИЛИ, см. пример ниже). Импульс STROBE' следует генерировать программно, поскольку в интерфейсе нет безобразных одновибраторов. В программе 10.6 показано, как можно создать «программный импульс» на линии STROBE'.

Отметьте использование операций И и ИЛИ для сброса и установки, соответственно, одного бита. В этом примере мы не стали тратить время на модификацию текущего байта в ячейке current, поскольку в итоге он не изменяется. Если бы нам надо было изменить (и оставить измененным) какой-то другой управляющий бит, новый байт пришлось бы сохранить с помощью команды mov current, AL.

Аппаратный альтернативой хранения в памяти копии байта порта является включение в состав интерфейса порта с возможностью чтения, чтобы операция программного ввода позволила вам определить, что, собственно, зафиксировано в порте. Следующий пример позволит вам сообразить, как это делается.

Упражнение 10.6. Представьте себе, что вы полны энтузиазма и хотите добавить к схеме интерфейса Centronics порт с возможностью чтения. Сделайте так, чтобы чтение из порта В решало эту задачу. Вы будете приятно удивлены, обнаружив, как мало дополнительных цепей требует это усовершенствование.

Упражнение 10.7. Теперь перепишите программу 10.6, используя ваш новый порт и опустив ячейку current.

Порты Centronics используются практически во всех микрокомпьютерах; если вам нужен простой и быстрый параллельный выходной порт, без колебаний выбирайте Centronics. Во многих случаях (но не в IBM PC) микрокомпьютер позволит даже использовать порт в обе стороны. Обычно это делается путем посылки в порт управляющего бита, после чего изменяется направление передачи данных по единственной 8-разрядной шине данных.

SCSI и IPI. Это стандартные универсальные параллельные интерфейсы для подключения к компьютерам дисков и других высокопроизводительных периферийных устройств, как уже кратко упоминалось в разд. 10.16. SCSI (Small Computer System Interface — интерфейс малых компьютерных систем) представляет собой 8-бит параллельный кабельный интерфейс с квитированием и протоколами для обслуживания нескольких машин и нескольких периферийных устройств. В SCSI предусмотрены и синхронный, и асинхронный режимы, а также определенные программные протоколы. Вы можете найти интерфейсную плату SCSI для установки на магистраль практически любого популярного микрокомпьютера, включая VME и Multibus I и II; затем вы подсоединяете этот «главный адаптер» SCSI с помощью плоского кабеля SCSI-шины к плате периферийного контроллера (рис. 10.22). Плата контроллера часто является элементом самого периферийного устройства (т. е. располагается в дисководе жесткого диска) и взаимодействует с дисководом через «интерфейс уровня устройства», который может называться ST-506/412, ESDI или SMD.

Рис. 10.22. Магистраль SCSI с единственным периферийным устройством.

Достоинством SCSI является то, что с помощью этого интерфейса все микрокомпьютеры становятся совместимыми со всеми периферийными устройствами. Каждый разработчик считает своим долгом использовать SCSI, и в новых микрокомпьютерах этот интерфейс располагается прямо на системной плате. Со стороны периферийного устройства тоже удается избавиться от контроллера путем использования «архитектуры встроенного SCSI», когда магистраль SCSI становится одновременно и интерфейсом уровня устройства. Другими словами, вы соединяете кабелем системную плату микрокомпьютера с дисководом. SCSI обеспечивает передачу данных со скоростью до 1,5 Мбайт/с (при асинхронной передаче) или 4 Мбайт/с (при синхронной) при длине кабеля до 7 м (несимметричный) или 27 м (симметричный).

Интерфейс SCSI достаточно сложен, и мы не можем описывать здесь все его сигналы, режимы, командные протоколы и интерфейсные возможности. Ввиду его популярности, для облегчения вашей жизни, выпускаются однокристальные интерфейсные микросхемы (например, серии NCR 5380, Western Digital ЗЗС90, а также фирмами Fujitsu, Ferranti и др.).

SCSI хорошо работает с нынешними дисками. Однако для увеличения скорости передачи промышленность подумывает о переходе на 16-разрядную шину. Тогда, возможно, вступит в свои права интерфейс IPI (Intelligent Peripheral Interface- интеллектуальный периферийный интерфейс). IPI определяет 16-разрядную параллельную магистраль, работающую на скоростях до 10 Мбайт/с (частота передачи 5 МГц); как и SCSI, IPI обслуживает несколько машин и несколько периферийных устройств. Последнее время жесткие диски увеличивают свою скорость и плотность семимильными шагами; если еще принять во внимание рост скорости передачи, становится ясно, что мир быстро идет к универсальным интерфейсам (SCSI или IPI) со встроенной шиной. Через несколько лет, возможно, все остальные форматы будут забыты.

IEEE-488 (GPIB, HPIB). Когда появились первые приборы с выходами данных на задней панели, каждая компания все делала по-своему. Протоколов было почти столько же, сколько самих приборов, с параллельной или последовательной передачей, положительной или отрицательной полярностью и невообразимыми процедурами квитирования. Это был сумасшедший дом. Живо вспоминается разработка цифрового индикатора с огромными (высотой 15 см) цифрами для лекционного зала Гарвардского университета; для каждого из наших приборов у него были отдельные входные цепи!

В середине 60-х гг. фирма Hewlett-Packard решила покончить со всем этим безобразием, предложив универсальный приборный интерфейс. Фирма с присущей ей скромностью назвала его HPIB (Hewlett-Packard Interface Bus — интерфейсная магистраль Hewlett-Packard) и использовала его в качестве единственного интерфейса во всех новых разработках. HPIB позволяет подключать к магистральному кабелю (до 20 м длиной) до 15 приборов с помощью остроумно устроенных соединителей, которые можно вставлять друг в друга. По протоколу HPIB данные на магистрали имеют ширину 1 байт и передаются с квитированием; скорость передачи доходит до 1 Мбайт/с; предусмотрены программные команды, разрешающие любому устройству, подключенному к магистрали, стать «ведущим» (т. е. источником сообщений), а любой комбинации остальных устройств — «ведомыми» (т. е. приемниками сообщений). «Контроллер» диктаторски распоряжается, что делать каждому устройству.

Интерфейс HPIB оказался столь удачным, что комиссия по стандартизации Института инженеров по электротехнике и радиоэлектронике (ШЕЕ) официально признала его. В результате появился стандарт IEEE-488-1975/ANSI МС1.1, который все (кроме фирмы Hewlett-Packard) называют GPIB (General-Purpose Interface Bus-интерфейсная магистраль общего назначения), или «магистраль 488». GPIB стал универсальным цифровым интерфейсом для лабораторных приборов. С помощью GPIB можно связать вместе приборы любых компаний, да еще заставить микрокомпьютер (или настольный калькулятор) отдавать приказания. Например, вы можете задать форму сигнала, частоту и амплитуду синтезатору частот, а затем выполнить измерения напряжения в том же эксперименте или процессе.

10.21. Локальные вычислительные цепи

В доисторические времена вычисления выполнялись на больших централизованных ЭВМ в «пакетном» режиме. Это были мощные (более медленные, чем наименее мощные из современных персональных компьютеров, с крошечной памятью) и дорогие (сравнимые по цене с современными супер-ЭВМ) машины. Вы пробивали свои программы на колодах перфокарт, затем запускали задание. При удачном стечении обстоятельств к концу дня вы получали результаты аварийно завершившегося счета, и на следующее утро могли снова запустить свое задание, чтобы выловить следующую ошибку. Сегодня мы все развращены невероятной мощностью настольных компьютеров, быстрыми дисками, изящной графикой. Нам хочется большего. Нам хочется обмениваться файлами с приятелем, сидящим в соседней комнате, не вставая со стула. Нам хочется иметь мгновенный доступ к любым базам данных, принтерам и уникальной периферии. Все это доступно при наличии сетей-глобальных сетей вроде BITNET или DECNET и локальных вычислительных сетей (ЛВС) типа Ethernet или LocalTalk. Сети находятся еще в младенческом периоде своего развития, и в ближайшее десятилетие можно ожидать драматических изменений в этой области. Однако тенденции уже ясны, поэтому стоит остановиться на типах ЛВС, используемых сегодня.

Протокол CSMA/CD (Ethernet). Ethernet является типичным представителем сетей с коллективным доступом, опознанием несущей и обнаружением конфликтов (CSMA/CD). Для передачи сообщений адресуемому приемнику со скоростью 10 Мбит/с используется коаксиальный кабель. Сообщения Ethernet пересылаются «пакетами» с преамбулой и контролем ошибок. Протокол передачи выглядит примерно таким образом: (а) ждите прекращения активности в сети; (б) начинайте передачу своего пакета (см. ниже); (в) продолжая передачу, одновременно контролируйте наложение сообщений («конфликт»); (г) (1) пока наложений нет, продолжайте передавать свое сообщение, но (2) если вы обнаруживаете наложение, пошлите сигнал затора сети (чтобы все знали, что обнаружен конфликт), затем прекратите передачу, выждите случайный интервал времени и попробуйте снова; после каждой последовательной неудачи выжидайте больший по величине «случайный» интервал времени.

Сообщения сети Ethernet передаются относительно короткими пакетами (максимально 1 Кбайт), каждый из которых включает заголовок (идентифицирующий отправителя и получателя), несколько байт с информацией о длине пакета, его типе и последовательном номере, затем группу собственно байтов данных и, наконец, контрольную сумму циклического избыточного кода (CRC), с помощью которой получатель может проверить правильность передачи сообщения. Заметьте, что конфликт может произойти только в начале передачи пакета, поскольку (по правилу (а), см. выше) передача, длящаяся более удвоенного времени обхода сети, прерываться уже не будет.

Стандарт Ethernet, изобретенный фирмой Xerox, используется сейчас очень широко. Он достаточно широкополосен для большинства локальных сетей, а его производительность, благодаря протоколу случайных повторных передач, ухудшается при высокой загрузке не очень быстро. Контроллеры Ethernet можно найти для большинства серьезных микрокомпьютеров (VAX, IBM PC и т. д.) и магистралей (Multibus, VME); Ethernet является официально принятой сетью для популярных рабочих станций Sun и NeXT. Сеть Ethernet может иметь протяженность до 1 км на сегмент и содержать до 2 повторителей; можно также использовать волоконно-оптические «мосты» большей длины. Несколько настольных компьютеров могут совместно использовать многопортовый RS-232-сервер, выступающий в качестве узла на коаксиальном кабеле Ethernet. Серверы могут также обслуживать разделяемые между пользователями ресурсы, такие, как принтеры и большие диски.

Кольцевая сеть с маркерным доступом. В кольцевой сети с маркерным доступом каждый узел соединяется с соседним однонаправленной линией так, чтобы все узлы были объединены в кольцо. Конфликты здесь не допускаются, а правила игры выглядят следующим образом. Представьте себе некоторый объект (маркер); тот, у кого он имеется, может посылать сообщения, в то время как остальные могут только «слушать». В кольцевой сети с маркерным доступом маркер представляет собой короткое сообщение, передаваемое соседнему узлу, как только его владелец закончил пересылку пакета. В любой момент времени маркером владеет один из узлов; именно он имеет право посылать сообщения. Как и в сети Ethernet (да и в любой другой разумной сети), сообщения пакетизированы, причем часто используется формат SDLC (Synchronous Data Link Control — синхронное управление передачей данных: один пакет = флаг + адрес + заголовок + сообщение + контрольная сумма + флаг). Пакеты сообщений циркулируют по сети до тех пор, пока адресуемый получатель не примет их. После того, как отправитель закончил передачу всего сообщения (обычно состоящего из многих пакетов), он посылает маркер. Маркер циркулирует по кольцу до тех пор, пока какой-то другой узел в сети, желающий передать сообщение, не поглотит его, став, таким образом, новым владельцем маркера.

LocalTalk. LocalTalk (первоначально Appletalk), разработанная (угадайте, кем?) фирмой Apple Computer, представляет собой упрощенную сеть с конфликтами. Это не кольцевая сеть, а линейная. Один из узлов может передавать, остальные слушают. В качестве среды передачи используется одна симметричная пара; сигналы в стандарте RS-422 поступают на нее из узлов через трансформаторы. Формат пакета соответствует стандарту SDLC. Максимальная протяженность сети составляет 330 м, и к ней можно подключить до 32 узлов. Пропускная способность сети составляет 230,4 Кбит/с. Совместимый вариант, известный под именем PhoneNET (Farallon Computing Inc.) использует телефонные кабели и соединители и, как утверждается, работает при расстояниях до 1300 м.

Протокол сети схож с Ethernet, но проще: если вы не слышите передачу по сети, вы можете посылать свой пакет. Аппаратура сети не пытается обнаружить конфликты: она просто передает принятые пакеты с правильными контрольными суммами следующему уровню программного обеспечения. Конфликт обычно разрушает сталкивающиеся пакеты, приводя к неправильным значениям обеих контрольных сумм; в результате программное обеспечение просто не получает эти пакеты! Обнаружить ошибку — дело программного обеспечения. Например, отправитель сообщения ожидает ответ; если ответ не приходит в течение некоторого времени, отправитель инициирует идентичное сообщение и ждет снова. LocalTalk относится к сетям с протоколом CSMA/CA; СА здесь обозначает Collision Avoidance — избежание конфликтов, в противоположность обнаружению конфликтов в сети Ethernet.

В сети LocalTalk предусмотрены протоколы для совместного использования файлов и ресурсов (принтеров, модемов и проч.), а также способ наименования устройств, подключенных к сети. Можно даже раздобыть интерфейсы LocalTalk для «не-Аррlе»-компьютеров, что дает вам возможность пересылать файлы между компьютерами типов Macintosh, IBM и UNIX, а также совместно использовать такие ресурсы, как лазерный принтер.

10.22. Пример интерфейса: аппаратная упаковка данных

Если все ваши приборы подключаются к стандартной интерфейсной магистрали (например, GPIB), ваши дела блестящи: просто купите интерфейсную плату для вашего компьютера и несколько кабелей, соедините все вместе и наймите программиста. Талант тут не требуется, только деньги. Однако эта глава посвящена магистральным интерфейсам, и мы хотели бы завершить ее примером законченной разработки.

Надо полагать, что вы, как и мы, не выбрасываете все ваши работоспособные приборы, если появляется что-нибудь новенькое. Некоторые исключительно полезные приборы были созданы еще до эпохи GPIB; в них можно вдохнуть новую жизнь, смастерив к ним интерфейс для подключения к лабораторному компьютеру. Например, частотомер с 8-разрядным цифровым индикатором скорее всего имеет на задней панели «цифро-последовательный, бит-параллельный» выход, на котором появляются друг за другом индицируемые цифры в двоично-кодированном десятичном коде (BCD); весьма вероятно, что скорость вывода цифр совпадает со скоростью регенерации индикатора. Контролировать временные соотношения вы не можете; каждая достоверная цифра, вместе с ее трехбитным адресом позиции в числе, сопровождается стробом. Такого рода прибор скорее всего использует выходные уровни TTL.

На рис. 10.23 показано, как подключить такой прибор к IBM PC.

Рис. 10.23. Символьно-последовательный интерфейс.

Это законченный интерфейс, вместе с флагом состояния, прерываниями и выбираемым адресом порта ввода-вывода. Работа интерфейса начинается в левом нижнем углу рисунка, где обозначены данные, посылаемые из частотомера: последовательные цифры, их адреса (0–7) и стробирующий импульс STROBE7, говорящий о достоверности данных. Частотомер посылает цифры от самой младшей (LSD) до самой старшей (MSD), так что весь цикл заканчивается приемом самой старшей цифры (разряда 7). Восемь регистров `173 (4-разрядные D-регистры с тристабильными выходами) фиксируют последовательные цифры; для этого их информационные входы объединены, а на тактовые входы подаются отдельные сигналы с дешифратора адреса цифр. Обратите внимание на использование микросхемы `138-стробируемого дешифратора 1 из 8, с помощью которого из сигналов адреса и строба образуются тактовые сигналы для фиксации цифр.

Таким образом, выходные данные частотомера фиксируются в восьми 4-разрядных регистрах, выходы которых образуют 4 группы по 2 цифры (8 бит) в группе. PC может принять все восемь цифр четырьмя командами IN ввода данных шириной 1 байт из четырех последовательных адресов портов ввода-вывода (начиная с адреса, установленного на DIP-переключателе). Можно даже поступить еще лучше, читая данные из 16-разрядного регистра (т. е. выполняя вместо команды IN AL,DX, команду IN AX,DX), что приведет к двум последовательным операциям чтения байтов из двух соседних портов ввода-вывода. Обратите внимание на простоту схемы дешифрации адреса. 8-разрядный компаратор `682 выдает низкий уровень на выходе, когда 7 старших бит адреса совпадают с комбинацией, установленной на переключателях (при условии, что этот зануда AEN находится в низком состоянии); этим «базовым адресом» разрешается дешифратор 1 из 8 `138, стробируемый сигналом IOR', который декодирует три младшие бита адреса и генерирует отдельные импульсы ввода, соответствующие последовательным адресам портов. Это весьма распространенный способ дешифрации адресов, так как обычно вы назначаете различным регистрам интерфейса несколько последовательных адресов портов.

Флаг состояния устанавливается при приеме последней цифры числа из частотомера; состояние можно прочитать по адресу PORT + 4, где PORT — адрес, установленный на DIP-переключателях. Флаг состояния сбрасывается, когда ЦП читает последний (самый старший) байт данных (по адресу PORT + 3). Интерфейс позволяет работать и в режиме прерываний, которые через перемычку подключаются к любому из уровней IRQ2 или IRQ3, и разрешаются посылкой 1 по адресу PORT (а запрещаются посылкой 0); обратите внимание на неполную дешифрацию адреса в цепи записи, что позволило сэкономить вентили. Как и положено законопослушным гражданам, при включении питания мы сбрасываем оба триггера — и состояния, и разрешения прерываний.

Описанный интерфейс выполняет «упаковку» данных, объединяя несколько чисел в одно компьютерное слово. Если «числа» состоят из одного бита каждое, в 16-разрядное слово компьютера их можно упаковать 16 штук. Это не такое бессмысленное рассуждение, как кажется на первый взгляд: в цифровой обработке сигналов приходится иметь дело с периодическими выборками жестко ограниченных колебаний (которые можно рассматривать, как 1-бит аналого-цифровое преобразование); для повышения скорости выполнения операций ввода-вывода эти биты можно упаковать аппаратно и читать затем целыми словами. Конечно, если скорость не имеет значения, проще получать данные с помощью минимальных аппаратных средств, а всю упаковку и преобразования выполнять программно. Например, в приведенном примере можно было фиксировать и передавать в ЦП по одной цифре, если только быстродействие компьютера достаточно высоко, чтобы цифры не терялись.

Упражнение 10.8. Видоизмените схему интерфейса так, чтобы можно было программно выбирать линию запроса прерывания IRQ, используемую интерфейсом: посылкой 01Н по адресу PORT разрешать прерывания по IRQ2, посылкой 02Н по адресу PORT разрешать прерывания по IRQ3, а посылкой 0 по адресу PORT (или включением питания) запрещать и то, и другое.

Практическое замечание по поводу нашей схемы: следует избегать чрезмерной нагрузки линий шины. В приведенной схеме к каждой линии Dn подключаются выходы четырех тристабильных регистров `173, что создает чрезмерную емкостную нагрузку. Хотя наш интерфейс будет, несомненно, работать правильно, его подключение ограничит число дополнительных плат, которые можно установить на шине (особенно, если остальные разработчики окажутся грешными в том же отношении!). В нашем случае следовало использовать тристабильный 8-разрядный буфер (микросхема `244), включив его между выходами D0-D7 и шиной данных PC. Сигнал разрешения микросхемы можно получить, образовав логическое И декодированного адреса и сигнала IOR.

10.23. Форматы чисел

Формат байтов (или слов), получаемых из частотомера в рассмотренном примере, отличается от внутримашинного двоичного формата; частотомер образует двоично-кодированные десятичные коды, упакованные по две цифры в байте (или четыре цифры в слове). Чтобы с этими числами можно было выполнять какие-то вычисления, их следует преобразовать в целые числа или в числа с плавающей точкой (хотя в системе команд микропроцессора предусмотрены и команды с «десятичной коррекцией», позволяющие выполнять арифметические операции непосредственно над упакованными двоично-кодированными десятичными числами). Рассмотрим форматы чисел, обычно используемые в компьютерах (рис. 10.24), предмет, кратко затронутый нами в начале гл. 8.

Рис. 10.24. Форматы чисел. S -знак.

Целые числа. Целые числа (integer) со знаком всегда представляются, как дополнение до 2 и занимают 1,2 или 4 байт (см. рис. 10.24). Старший бит является знаковым, хотя дополнение до двух не совпадает с представлением в виде знака и числа (т. е. — 1 записывается, как 11111111, а не 10000001; см. разд. 8.03). Дополнение до 2 можно представить себе, как «смещенное» двоичное с инвертированным старшим битом; но можно рассматривать его и как целое число со значением бит, указанным на рис. 10.24. Многие компьютеры позволяют объявлять переменные, как целые без знака в дополнение к объявлению целых со знаком в виде дополнения до 2. Двухбайтовое беззнаковое целое может иметь значение от 0 до 65535.

Числа с плавающей точкой. Числа с плавающей точкой, называемые также действительными числами (real), обычно занимают 32 бит («одинарная точность») или 64 бит («двойная точность»), однако иногда для промежуточных результатов вычислений используется дополнительный 80-бит формат. К сожалению, имеется несколько употребительных представлений этих чисел. Наиболее распространен формат IEEE (официальное название ANSI/IEEE Std 754-1985), который реализован почти во всех микропроцессорных наборах с плавающей точкой (включая Intel 8087/287/287, Motorola 68881, а также наборы фирм AMD, Weitek и др.) и по этой причине является стандартным для микрокомпьютеров, использующих эти наборы (в том числе IBM PC).

На рис. 10.24 показаны 32-бит и 64-бит форматы IEEE. 32-бит формат одинарной точности предусматривает 1 знаковый бит, 8 бит порядка и 23 бит мантиссы. Порядок определяет степень 2, на которую следует умножить мантиссу (см. ниже). Порядок «смещен» путем прибавления 127, так что поле порядка 01111111 соответствует порядку 0; в результате диапазон порядка составляет от —127 до +128. Мантисса также записывается любопытным способом, который был впервые использован фирмой DEC в своем формате с плавающей точкой. Двоичное число с плавающей точкой всегда можно записать в виде f.fff x 2е , где f.fff — мантисса (по основанию 2) («значащая часть»), а е — порядок (степень 2). Для того чтобы получить при заданном числе бит мантиссы максимальную точность, она «нормализуется» путем сдвига влево (с соответствующим декрементом порядка), пока лидирующий бит не станет равен 1, в результате чего мантисса представляется в виде 1.fff x 2е . Далее, используется прием «скрытого бита». Поскольку результирующая значащая часть мантиссы всегда имеет ненулевой старший бит, хранить его в памяти было бы избыточно; вместо 1fff можно записать просто fff, где лидирующая 1 подразумевается. В результате точность числа возрастает, так как его представление увеличивается на 1 бит, образуя диапазон от ±1.2·10-38 до ±3.4·1038.

Упражнение 10.9. Сконструируйте на бумаге минимальное и максимальное нормализованные числа с плавающей точкой и убедитесь, что приведенные выше предельные значения соответствуют истине.

Формат IEЕЕ с двойной точностью образуется аналогично, но точность мантиссы более чем удваивается (увеличиваясь на 29 бит), а порядок получает дополнительные 3 бит. Диапазон чисел указан на рисунке. Формат IEEE допускает также хранение ненормализованных чисел, что несколько увеличивает диапазон со стороны маленьких чисел (за счет уменьшения точности); «ненормализованные» числа могут доходить до величины ±1.4·10-45. Стандарт также определяет нуль (е = fff = 0; таким образом, есть 2 нуля, +0 и — 0), бесконечность (е = все единицы, fff = 0; поэтому оба знака), а также любопытный класс зарезервированных величин, имеющих официальное название «не число» (NAN = Not A Number).

Другой важный микрокомпьютерный формат чисел с плавающей точкой принадлежит фирме DEC и используется в компьютерах Micro VAX и LSI-11 (а также в их предках, мини-ЭВМ VAX и PDP-11). Он почти совпадает со стандартом IEЕЕ, имея то же число бит в порядке и мантиссе (включая использование скрытого бита) чисел с одинарной точностью. Отличия заключаются в другом значении смещения (128 вместо 127), а также в отсутствии лидирующих бит в мантиссе, которая представляется в виде.1fff (со скрытой 1). DEC определяет только один нуль (все биты которого равны 0); и не допускает ненормализованных чисел и бесконечности; имеются, однако, величины, аналогичные «не числам» IEEE. DEC также определяет 64-бит формат удвоенной точности.

Последние два формата, приведенные на рис. 10.24, используются не в микрокомпьютерах, а в больших ЭВМ или в машинах специального назначения. Формат «IBM» в течение некоторого времени использовался в универсальных ЭВМ фирмы IBM и даже в некоторых мини-ЭВМ, например, Nova фирмы Data General. 7-бит смещенный порядок определяет степень 16, а не 2, увеличивая диапазон чисел. Мантисса в результате может иметь до трех лидирующих нулей, т. е. нормализованная часть содержит ненулевую старшую шестнадцатеричную цифру.

Упражнение 10.10. Чтобы понять смысл последней фразы, напишите представление числа 1.0 в формате IBM. После этого напишите следующее меньшее число в том же формате.

Использование в формате IBM числа 16 в качестве основания увеличивает динамический диапазон, но уменьшает точность. Более того, точность несколько изменяется от числа к числу из-за переменного количества лидирующих двоичных нулей; это явление известно, как «качание» (wobble). В формате IBM отсутствуют «не числа» и бесконечность, и имеется только один нуль (все биты нули); не нормализованные числа не допускаются. Имеется формат IBM и для чисел с двойной точностью (64 бит). Последний формат на рис. 10.24, MIL STD-1750A, используется в военных системах. Он необычен в том отношении, что вместо знака и величины числа в нем записывается мантисса в форме дополнения до двух и порядок тоже в форме дополнения до двух (строго говоря, предыдущие форматы характеризуются записью мантиссы в форме знак/величина, а порядка в форме смещенного двоичного). В формате отсутствуют бесконечности, «не числа» и не нормализованные числа; имеется вариант для чисел с удвоенной точностью.

Хранение чисел в памяти. Разработчики микропроцессоров любят выражать свою индивидуальность, предусматривая хранение чисел в памяти в своеобразном порядке. Микропроцессоры 8086/8 (а, следовательно, и компьютеры IBM PC и совместимые с ними) записывают числа в память, начиная с самого младшего байта, который располагается в байте памяти с наименьшим номером; для семейства 68000 характерен обратный порядок. Вот счастье-то!

Преобразование данных в процессе ввода-вывода. Нам пришлось уже обсуждать форматы данных в контексте аппаратного интерфейса, который выдавал упакованные двоично-десятичные числа. Каков наиболее оптимальный способ работы с 8-разрядными данными, получаемыми из такого интерфейса? В зависимости от типа входных данных, числа значащих цифр, диапазона их изменения и проч. может оказаться удобным преобразовывать входные данные в числа с плавающей точкой (для получения максимального динамического диапазона), или в целые числа (для получения максимального разрешения), или выполнить какие-то другие числовые процедуры (например, вычисление отклонений от среднего значения или разностей последующих отсчетов). Все это можно делать в программном «драйвере» конкретного устройства, т. е. в программном модуле, который управляет вводом данных. Мы видим, таким образом, что оптимизация программного обеспечения не может быть выполнена без понимания особенностей аппаратуры и смысла принимаемых данных. Еще одна причина, по которой столь важно освоиться в этом чудесном мире электронной аппаратуры!