PIC-микроконтроллеры. Все, что вам необходимо знать

Катцен Сид

Часть I

ОСНОВЫ

 

 

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

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

• Цифровые коды.

• Двоичную арифметику.

• Основы цифровой схемотехники.

• Архитектуру вычислительных устройств и их программирование.

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

Заглядывая внутрь микросхемы

 

Глава 1

Цифровое представление

Как для компьютера, так и для микроконтроллера окружающий мир представляется в виде различных чисел. В десятичной системе счисления числовые величины описываются с помощью десяти цифр: 0, 1…., 9. Используя при необходимости символы «+», «—» и «.», можно выразить любое число из диапазона . На самом деле, с помощью чисел можно выражать даже нечисловые понятия. К примеру, в коде ASCII (американский стандартный код обмена информацией) символу «А» соответствует число 65, символу «В» — 66…., «Z» — 90, «а» — 97, «Ь» — 98…., «z» — 122 и т. д. Соответственно, слово «Microcontroller» можно закодировать в виде последовательности чисел «77, 105, 99, 114, 111, 99, 111, 110, 116, 114, 111, 108, 108, 101, 114». При условии, что нам известен контекст, т. е. какие числа описывают реальные числовые величины, а какие — текст, с их помощью можно закодировать практически любые символы.

Электронные схемы не очень хорошо подходят для хранения и обработки множества различных значений. Да, первая американская цифровая вычислительная машина ENIAC (электронный цифровой интегратор и калькулятор), созданная в 1964 году, выполняла арифметические операции в десятичном виде, однако все компьютеры, появившиеся впоследствии, оперировали уже данными в двоичной (с основанием 2) системе. В действительности десятичная система счисления удобна только для человека, поскольку у нас на руках 10 пальцев. Так что в этой главе мы будем рассматривать исключительно свойства двоичных разрядов, их группирование, а также операции над двоичными числами. Прочитав главу, вы:

• Поймете, почему двоичное представление данных является наиболее удобным для цифровых схем.

• Узнаете, как одну и ту же величину можно выразить в двоичном, шестнадцатеричном и двоично-десятичном (BCD) виде.

• Научитесь выполнять сложение и вычитание двоичных чисел.

• Узнаете, как выполнять умножение посредством сдвига влево.

• Узнаете, как выполнять деление посредством сдвига вправо с копированием знакового бита.

• Познакомитесь с логическими операциями НЕ, И, ИЛИ и Исключающее ИЛИ.

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

Двоичная система — это универсальный способ представления данных, поскольку простейшим устройством, которое можно реализовать на одном транзисторе, является электронный ключ. Такие ключи, имеющие только два состояния, очень малы; они способны очень быстро изменять свое состояние и потребляют незначительный ток. Более того, поскольку требуется различать только два состояния, очевидно, что двоичное представление менее подвержено воздействию помех. Из сказанного становится ясно, что и плотность компоновки элементов на кристалле, и скорости переключения этих элементов могут достигать очень больших значений. Хотя сам ключ как таковой не обладает какой-либо вычислительной мощностью, 5 миллионов ключей, переключающихся 100 миллионов раз в секунду, способны продемонстрировать, по крайней мере, видимость интеллекта!

Два состояния бита обычно называются логическим нулем (лог. 0) к логической единицей (лог. 1) или просто 0 и 1. Один бит может быть представлен двумя состояниями любой физической величины, например напряжения или силы электрического тока, освещенности, давления воздуха. В большинстве микроконтроллеров состоянию лог. 0 соответствует напряжение 0 В (или «земля»), а состоянию лог. 1 — напряжение +3…5 В, хотя это правило и не универсально. Например, в последовательном порту RS-232 вашего ПК для индикации состояния лог. 0 используется напряжение +12 В, а для индикации состояния лог. 1 — напряжение -12 В.

Итак, один бит может представлять только два состояния. Более сложные элементы можно выразить с помощью комбинаций битов. Например, обычные алфавитно-цифровые символы можно представить с помощью 7-битных групп двоичных разрядов, как показано в Табл. 1.1. Таким образом, ASCII-представление строки «Microcontroller» будет иметь вид

1001101 1101001 1100011 1110010 1101111 1100011 1101111 1101110

1110100 1110010 1101111 1101100 1101100 1100101 1110010

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

Код ASCII называется невзвешенным, поскольку отдельные биты не несут какого-либо смысла; значение имеет только вся совокупность битов. В качестве других примеров невзвешенных кодов можно отметить код значения на гранях игральной кости и семисегментный код, изображенный на Рис. 6.8 (стр. 183). Мы же в основном будем работать с обычным двоичным взвешенным кодом, в котором позиция бита определяет его величину или, иначе, вес. В целом двоичном числе самый правый бит имеет вес 20 = 1, находящийся слева от него — 21 = 2 и так далее до n-й позиции, бит в которой имеет вес 2n -1 . В частности, десятичное число 1998 представляется таким образом:

103 102 101 100

1     9    9    8

т. е. 1х103 + 9х102 + 9х101 + 8х100, или 1998. В обычном двоичном коде то же самое число представляется следующим образом:

210 29 28 27 26 25 24 23 22 21 20

1   1   1   1   1   0   0  1  1  1  0

т. е. 1х210 + 1х29+ 1х28 + 1х27 + 1х26 + 0х25 + 0х24 + 1х23 + 1х22 + 1х21 + 0x20, или b’111111001110’. Точно так же можно представлять и дробные числа, при этом позициям, расположенным справа от десятичной точки, соответствуют отрицательные степени двойки. Так, двоичное число b’1101.11’ эквивалентно десятичному 13.75. Из примера видно, что двоичное представление чисел гораздо длиннее их десятичных эквивалентов — в среднем не менее чем в 3 раза. Однако 2-позиционный ключ гораздо проще 10-позиционного, поэтому двоичное представление предпочтительнее.

Биты любой n-разрядной двоичной последовательности могут образовывать в общей сложности 2n комбинаций. При этом большинство компьютеров хранят и обрабатывают биты группами. Например, первый микропроцессор Intel 4004 обрабатывал данные по четыре бита (полубайт) за раз. Большинство современных процессоров оперируют с 8-битными (байт), 16-битными (слово), 32-битными (двойное слово) и 64-битными (счетверенное слово) блоками. Характеристики некоторых из указанных групп перечислены в Табл. 1.2. Приведенные названия являются в какой-то мере стандартом де-факто, однако иногда встречаются и другие варианты.

Как и в десятичной системе счисления, большие двоичные числа часто выражаются с использованием приставок К (кило), М (мега) и Г (гига). В двоичной системе приставка «кило» соответствует множителю 210, например 64 Кбайт (или КБ) памяти. Аналогично, приставка «мега» соответствует множителю 220= 1 048 576, например дискета объемом 1.44 Мбайт (или МБ). Точно так же емкость 20 Гбайт (или ГБ) винчестера составляет 20х230= 21 474 836 480 байт. Естественно, 1-й вариант записи предпочтительнее.

Длинные двоичные числа очень неудобны для человеческого восприятия. В Табл. 1.2 двоичные числа специально были разбиты на 4-битные группы, чтобы их удобнее было читать. Предположим теперь, что адрес какого-либо элемента в памяти равен Ь’1000 1100 0001 0100 0000 1010’. Если каждой комбинации из четырех битов сопоставить свой символ (0…9 и A…F, как показано в Табл. 1.3), то этот адрес можно будет записать в виде h’8СН0А’, что гораздо удобнее. Этот код называется шестнадцатеричным, поскольку для обозначения разрядов в нем используется 16 символов. Шестнадцатеричные числа (числа с основанием 16) — это вполне жизнеспособные самостоятельные числа, а не просто какое-то дополнительное представление двоичных чисел. Разряды шестнадцатеричного числа имеют веса соответственно 160, 161, 162…., 16n .

Двоично-десятичный код (Binary-Coded Decimal — BCD) является гибридом двоичного и десятичного представлений, широко используемым при работе с портами ввода/вывода цифровых устройств (см. Пример 11.5 на стр. 360). При таком представлении каждый десятичный разряд заменяется своим двоичным эквивалентом. Так, число 1998 записывается в виде (0001 1001 1001 1000)BCD. Это представление очень сильно отличается от эквивалентного обычного двоичного кода, несмотря на то, что при его записи тоже используются только нули и единицы. Как и следовало ожидать, выполнение арифметических операций с числами, записанными таким образом, представляет собой не простую задачу. Поэтому, как правило, на входе системы BCD-числа преобразовываются в обыкновенные двоичные числа, а после обработки преобразовываются обратно (см. Программу 5.7 на стр. 159).

Двоичная арифметика подчиняется тем же правилам, что и более привычная для вас арифметика по основанию 10. Более того, это утверждение справедливо для любой системы счисления. Простейшей арифметической операцией является операция сложения, представляющая сокращенную форму записи операции нахождения общего количества чего-либо по сравнению с более примитивным процессом счета или прибавления единицы. Так, запись 2 + 4 = 6 гораздо удобнее, чем 2 + 1 = 3, 3 + 1 = 4, 4 + 1 = 5, 5 + 1 = 6. Однако при этом необходимо помнить правила сложения. Для десятичных чисел существует 45 правил, если учесть, что порядок слагаемых не важен, — от 0 + 0 = 0 до 9 + 9 = 18. Двоичное сложение гораздо проще, поскольку подчиняется всего трем правилам:

Сначала эти правила применяются к самым младшим значащим битам (Least Significant Bit — LSB); при возникновении переноса он передается в бит, расположенный левее. Процесс вычисления заканчивается старшими значащими битами (Most Significant Bit — MSB). Если из этой позиции происходит перенос, то именно он становится самым старшим битом суммы. Например:

Подобно тому как при сложении осуществляется прямой счет, операция вычитания соответствует обратному счету, при котором от исходного значения отнимаются единицы. Так, операция 8–5 = 3 эквивалентна последовательности операций 8–1 = 7, 7–1 = 6, 6–1 = 5, 5–1 = 4, 4–1 = 3.

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

0 — 0 = 0

10 — 1 = 1 Из старшего бита занимается 1

1 — 0 = 1

1 — 1 = 0

Например:

Несмотря на то что эти знакомые методы прекрасно работают, при реализации их в цифровых схемах возникает ряд проблем:

• Что делать, если вычитаемое меньше уменьшаемого?

• Как нам различать положительные и отрицательные числа?

• Можно ли выполнить вычитание с помощью блока суммирования?

Чтобы понять суть описанных проблем, взгляните на следующий пример:

Обычно, если мы знаем, что уменьшаемое меньше вычитаемого, мы меняем операнды местами и добавляем знак минуса к результату, т. е. вычисляем выражение — (вычитаемое — уменьшаемое). Если мы не выполним такой перестановки, как показано в примере (а), приведенном выше, то результат окажется неверным. На самом деле число 41 является правильным в том смысле, что представляет собой разность между числом 59 (правильный результат) и 100. То есть число 41 представляет собой дополнительный код числа 59 в десятичной системе (10’s complement). Более того, сам факт заема из старшего разряда числа указывает на то, что результат операции отрицателен и представлен соответственно в дополнительном коде. Для преобразования числа, представленного в дополнительном коде, в «нормальный» вид достаточно просто проинвертировать каждый десятичный разряд и к полученному значению прибавить единицу. Инвертирование десятичного разряда заключается в вычитании его значения из 9. Таким образом, дополнительный код числа 3941 в десятичной системе равен —6059:

Как бы там ни было, единственной причиной, по которой мы не оставляем отрицательные числа в дополнительном коде, является непривычность для нас такого представления чисел.

Разумеется, использование дополнительного кода для представления отрицательных значений применимо и к двоичным числам. Причем, простота инвертирования (0 —> 1, 1 —> 0) делает этот метод очень привлекательным. Обратимся к приведенному выше примеру:

И опять же отрицательные числа следует оставлять в дополнительном коде (2’s complement). Обратите внимание, что операция преобразования в дополнительный код является обратимой, т. е.

дополнительный код <=> прямой код.

При работе с десятичными числами для обозначения положительных и отрицательных чисел используются знаки «+» и «—» соответственно. В системе же с двумя состояниями мы можем оперировать только единицами и нулями. Тем не менее, взглянув на последний пример, можно получить ключ к решению этой проблемы. Как уже было сказано, отрицательное значение получается в результате заема в старший разряд числа. Так что мы можем использовать этот разряд в качестве знакового бита (sign bit), причем 0 будет эквивалентен знаку «+», а 1 — знаку «—». Таким образом, число Ь’11000101’ будет соответствовать значению —59, а Ь’00111011’ — значению +59 (в примерах знаковый бит выделен полужирным шрифтом). Преимущество такого представления заключается в том, что при любых арифметических операциях с ним можно обращаться так же, как и с обычным битом. При этом результат операции будет иметь верный знак:

Из примера видно, что если отрицательное число представлено в дополнительном коде, то нам не нужно изобретать аппаратный «вычитатель», поскольку прибавление отрицательного числа эквивалентно вычитанию положительного. Другими словами, А — В = А + (—В). Более того, если числа будут записаны в дополнительном коде, результаты всех последующих арифметических операций также будут в дополнительном коде.

С арифметическими операциями над отрицательными числами, представленными в дополнительном коде, связаны две проблемы. Первая из этих проблем — переполнение (overflow). Она заключается в том, что при сложении двух положительных или двух отрицательных чисел может возникнуть переполнение в знаковом бите, например:

а) Сумма двух положительных чисел б) Сумма двух отрицательных чисел получается отрицательной получается положительной

В примере (а) результат сложения (+8) + (+11) равен —13. В данном случае произошло переполнение из четвертого значащего бита в знаковый (в действительности число 10011b = 19 является корректным результатом). В примере (б) показана та же ситуация при сложении двух отрицательных чисел. Переполнение может возникнуть только в том случае, если оба операнда имеют одинаковые знаковые биты. Поэтому для обнаружения переполнения следует отслеживать значение знакового бита результата, отличающееся от значения знаковых битов операндов. Логическая схема, реализующая обнаружение переполнения, показана на Рис. 1.5.

Вторая проблема касается выполнения арифметических операций над знаковыми операндами разной разрядности, например:

В обоих примерах показано сложение 8-битного числа с 16-битным. Если первый операнд положителен, его разрядность можно увеличить до 16 бит, заполнив свободные позиции нулями. Если же требуется расширить отрицательное число, то решение уже не так очевидно. В этом случае расширение числа производится путем заполнения пустых разрядов единицами. Общее правило звучит так: при расширении данных дополнительные разряды слева следует заполнять знаковым битом. Этот метод называется расширением знака (sign extension).

Умножение числа на n-ю степень двойки реализуется сдвигом исходного значения на n позиций влево. Таким образом, последовательность операций 00110 (6) << 01100 (12) << 11000 (24) эквивалентна умножению числа 6 на 22; оператор «<<» используется для обозначения сдвига влево. Это же правило применимо и к отрицательным числам:

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

Умножение на число, не являющееся степенью двойки, можно реализовать, комбинируя операции сдвига и суммирования. В частности, как показано в предыдущем примере (в), выражение 3x10 вычисляется следующим образом:

(3 х 8) + (3 х 2) = (3 х 10) или (3 << 3) + (3 << 1).

Аналогичным образом деление числа на n-ю степень двойки реализуется сдвигом значения на n позиций вправо, т. е. 1100 (12) >> 0110 (6) >> 0011 (3) >> 0001.1 (1.5). Этот же способ применим к знаковым числам:

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

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

Арифметические действия — не единственные операции, которые можно осуществлять над двоичными числами. Английский математик Джордж Буль (George Boole) в середине 19-го столетия создал раздел алгебры, касающийся символической обработки логических отношений. Этот раздел алгебры, называемый Булевой алгеброй, оперирует величинами, которые могут иметь только два состояния: истина или ложь. В 30-х годах стало понятно, что этот раздел математики может быть с успехом использован для анализа коммутационных схем и, соответственно, устройств двоичной логики. Мы ограничимся рассмотрением базовых логических операций этой алгебры переключательных схем.

Инверсия, или операция НЕ (NOT), обозначается символом надчеркивания. Таким образом, выражение f = А¯ означает, что переменная f является обратной величиной переменной А. То есть если А = 0, то f = 1, и, наоборот, если А = 1, то f = 0. На Рис. 1.1, а эта зависимость представлена в виде таблицы истинности (truth table). По определению двойная инверсия переводит переменную в первоначальное состояние: f= = f.

Рис. 1.1. Операция НЕ ( NOT )

Как правило, реализации логических функций представляются с помощью абстрактных символов, а не подробных электрических схем. Общепринятое изображение элемента НЕ приведено на Рис. 1.1, б. Кружок на изображении логических схем всегда означает инверсию и очень часто используется в сочетании с другими логическими элементами (см., например, Рис. 1.2, в).

Оператор И (AND) реализует функцию «все или ничего». Результат операции будет истинным только в том случае, если все n входов истинны. На Рис. 1.2 имеется две входные переменные, и выражение для выходного значения записывается как f = В∙А, где символ «» — булевый оператор И. Количество входных переменных может быть любым, и в общем случае f = А(0)∙А(1)∙А(2)∙…∙А(n). Операцию И иногда называют операцией логического умножения, поскольку (по аналогии с обычным умножением) результат этой операции между любым битом и 0 всегда будет равен 0.

Рис. 1.2. Операция И ( AND )

Если предположить, что вход В является управляющим входом, а вход А — входом данных, то, обратившись к таблице истинности, мы увидим, что при В = 1 на выходе будут присутствовать входные данные, а при В = 0 на выходе постоянно будет 0. Таким образом, эту схему можно рассматривать как управляемый вентиль. В общем случае термин вентиль применим к любой логической схеме, реализующей базовые логические операции.

В большинстве практических реализаций вентиля И используется инвертированный выход. Логическая функция такого элемента называется И-НЕ (NOT AND, или NAND), а ее изображение приведено на Рис. 1.2, в.

Действие оператора ИЛИ (OR) можно описать словом «что-нибудь». Результат этой операции будет истинным, если истинно хотя бы одно из входных значений (поэтому на символе изображено «>= 1»). Хотя элемент, показанный на Рис. 1.3, имеет только два входа, операция ИЛИ применима к любому числу входных переменных. Часто операцию ИЛИ называют логическим сложением, соответственно в качестве математического оператора используется знак «+»:

Рис. 1.3. Операция ИЛИ ( OR )

Если предположить, что вход В является управляющим входом, а вход А — входом данных (или наоборот), то из Рис. 1.3, а видно, что данные проходят через вентиль при В = 0 и задерживаются (на выходе постоянно присутствует 1) при В = 1. Такое поведение отчасти похоже на инверсное действие функции И. В самом деле, функция ИЛИ может быть выражена через функцию И посредством двойственного соотношения . Из этого соотношения следует, что функцию ИЛИ-HE можно реализовать инвертированием сигналов, подаваемых на вход элемента И.

Мы познакомились с тремя основными логическими операторами: И, ИЛИ и НЕ. Однако существует еще одна операция, часто используемая в электронике, — операция Исключающее ИЛИ (exclusive OR — XOR). Функция XOR истинна, если истинен только один из входов (поэтому на символе изображено «=1», см. Рис. 1.4, б). В отличие от обычной операции ИЛИ, при 1 на обоих входах на выходе будет 0.

Рис. 1.4. Операция Исключающее ИЛИ ( XOR )

Если предположить, что вход В — управляющий, а вход А — вход данных (или наоборот), тогда

• Если В = 0, то f = А — данные с входа передаются на выход.

• Если В = 1, то f = А¯ — выходной сигнал представляет собой инвертированный входной сигнал.

Таким образом, вентиль Исключающее ИЛИ может использоваться в качестве программируемого инвертора.

Другим полезным применением функции Исключающее ИЛИ можно назвать использование ее в качестве логического дифференциатора. Из таблицы истинности (Рис. 1.4, а) видно, что выход элемента Исключающее ИЛИ истинен только тогда, когда состояния обоих входов различны. Аналогично, из таблицы истинности оператора Исключающее ИЛИ-HE (XNOR), показанной на Рис. 1.4, в, видно, что выход такого элемента истинен при одинаковых сигналах на обоих входах. Таким образом, вентиль Исключающее ИЛИ-HE можно рассматривать в качестве 1-битного компаратора. Равенство двух «-битных значений можно проверить, объединив по И набор вентилей Исключающее ИЛИ-HE (см. Рис. 2.7 на стр. 37), каждый из которых реализует функцию , т. е.

В качестве простого примера использования элементов Исключающее ИЛИ и Исключающее ИЛИ-HE рассмотрим задачу определения переполнения в знаковом бите (см. стр. 24). Эта ситуация возникает, если знаковые биты обоих операндов одинаковы , а знаковый бит С результата отличается от них, скажем . Схема такого детектора, показанная на Рис. 1.5, описывается логической функцией:

И наконец, функцию Исключающее ИЛИ можно использовать для определения четного количества истинных входов. При каскадном соединении n + 1 вентилей Исключающее ИЛИ выходной сигнал будет равен 1, если входное n-битное число содержит четное число единичных битов. Добавляя к слову данных дополнительный бит, так чтобы общее число битов было четным, можно реализовать простейшую защиту от ошибок. Приемное устройство будет контролировать четность принимаемых данных, и любое несоответствие будет означать их повреждение.

Рис. 1.5. Обнаружение переполнения в знаковом бите

 

Глава 2

Логические схемы

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

Прочитав эту главу, вы:

• Познакомитесь с областями применения и характеристиками выходных каскадов с активной подтяжкой (двухтактный выход), с открытым коллектором и с тремя состояниями.

• Поймете логическую структуру и назначение дешифратора.

• Познакомитесь с интегральной микросхемой, представляющей собой набор элементов Исключающее ИЛИ-HE и использующейся для определения равенства двух значений.

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

• Разберетесь, почему АЛУ имеет такое большое значение для программируемых систем.

• Ознакомитесь со структурой и областями применения постоянных запоминающих устройств (ПЗУ).

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

• Разберетесь, чем отличается D-защелка от D-триггера.

• Поймете, как из набора D-триггеров или защелок можно реализовать регистр.

• Узнаете, как с помощью каскадного соединения D-триггеров можно реализовать сдвиговый регистр.

• Поймете, как можно использовать D-триггер в качестве делителя на 2 и как посредством каскадного соединения D-триггеров можно реализовать двоичный счетчик.

• Узнаете, как с помощью связки АЛУ/регистр можно реализовать блок аккумулятора процессора.

• Разберетесь в принципах работы оперативного запоминающего устройства (ОЗУ).

В первых интегральных микросхемах, появившихся в конце 60-х годов, реализовывались главным образом логические элементы И-НЕ, ИЛИ-HE и НЕ. Наиболее популярным семейством логических микросхем тогда были, да и сейчас в какой-то мере остаются микросхемы 74-й серии, построенные по технологии ТТЛ (транзисторно-транзисторная логика). Эта серия была разработана фирмой Texas Instruments и впоследствии скопирована всеми ведущими производителями микросхем.

Микросхема 74LS00 содержит четыре двухвходовых элемента И-НЕ, объединенные в 14-выводном корпусе. Для питания микросхемы используется напряжение 5 ±0.25 В, прикладываемое между выводами Vcc (обычно около 5 В) и GND. Напряжения логических уровней для этой серии составляют: 2.4…5 В — для ВЫСОКОГО уровня и 0…0.4 В — для НИЗКОГО. Для большинства семейств логических микросхем требуется напряжение питания 5 В, однако существуют и 3-вольтовые версии. При этом большинство КМОП-микросхем могут работать в диапазоне питающих напряжений от 3 до 15 В.

Цоколевка микросхемы 74LS00 в корпусе DIP показана на Рис. 2.1, а. Функция этой микросхемы полностью описывается четырьмя двухвходовыми элементами И-НЕ в положительной логике, поскольку НИЗКИЙ и ВЫСОКИЙ логические уровни эквивалентны логическим значениям 0 и 1. Если же принять, что 0 соответствует ВЫСОКОМУ уровню, а 1 — НИЗКОМУ (отрицательная логика), то микросхема будет выполнять функцию четырех двухвходовых элементов ИЛИ-НЕ. На изображениях логических элементов по стандарту ANSI/IEC НИЗКИЙ уровень обозначается символом полярности  (см. Рис. 2.1, б). Таким образом, изображение символа И-НЕ по стандарту ANSI/IEC основано на реальном функционировании схемы. В данном случае логика работы схемы совпадает с функцией И-НЕ в терминах положительной логики. Оператор & (И), изображенный в верхнем прямоугольнике, относится и к остальным трем элементам.

Рис. 2.1. Микросхема 74LS00 ( K555ЛA3 )

Выходы логических элементов микросхемы 74LS00 построены по двухтактной схеме. При такой структуре выходного каскада каждый из уровней формируется путем подключения выхода через низкоомный ключ к линии Vcc или GND соответственно. На Рис. 2.2, а эти ключи изображены в виде обычных переключателей, хотя на самом деле они, разумеется, выполнены на транзисторах.

Рис. 2.2. Типы выходных каскадов

В логических микросхемах (например, таких как 74LS00) изменение состояния выхода происходит за время около 10 нс. Чтобы получить такие значения, емкости всех соединительных проводников и входов других микросхем должны быстро разряжаться. Главным образом именно по этой причине в большинстве цифровых микросхем используется двухтактный выход (называемый также выходом с активной подтяжкой — active pull-up). Однако в некоторых ситуациях преимущество имеют выходные каскады других типов. Конфигурация открытый коллектор (или открытый сток), показанная на Рис. 2.2, б, обеспечивает «жесткий» НИЗКИЙ уровень, при этом состояние ВЫСОКОГО уровня соответствует разомкнутой цепи. Напряжение ВЫСОКОГО уровня может формироваться подключением внешнего резистора либо к линии Vcc, либо к отдельной шине питания. Роль подобного резистора могут выполнять некоторые устройства, такие как реле, лампы накаливания или светодиоды. Выходной транзистор таких каскадов часто имеет большую, чем обычно, нагрузочную способность по напряжению и/или току.

Один из наиболее интересных для нас вариантов применения выхода с открытым коллектором показан на Рис. 2.3. В этой схеме четыре элемента с выходом типа «открытый коллектор» подключены к одному и тому же подтягивающему резистору. Обратите внимание на символ , используемый для обозначения выхода с открытым коллектором. Предположим, что на рисунке изображены четыре периферийных устройства, любое из которых может обращаться к процессору (компьютеру или микроконтроллеру). Если этот процессор имеет только один вход для внешнего сигнала прерывания, то четыре сигнальные линии от устройств должны быть объединены вместе по схеме монтажное ИЛИ, как показано на рисунке. Когда все сигнальные линии находятся в неактивном состоянии (лог. 0), выходы всех буферных элементов НЕ выключены (ВЫСОКИЙ уровень) и общая линия подтянута к Vcc резистором RL. Если какая-либо из сигнальных линий становится активной (лог. 1), скажем, линия Sig_1, то на выходе соответствующего буфера появляется НИЗКИЙ уровень. В результате, независимо от состояния остальных сигнальных линий, общая линия переключается в состояние НИЗКОГО уровня, прерывая таким образом работу процессора.

Рис. 2.3. Буферы с открытым коллектором управляют общей линией

Выходной каскад третьего типа (с тремя состояниями), приведенный на Рис. 2.2, в, обладает свойствами выходов обоих рассмотренных типов. При разрешенном выходе логические состояния формируются обычным образом, т. е. выдачей ВЫСОКОГО и НИЗКОГО напряжения. При запрещении выхода он становится разомкнутой цепью, независимо от функционирования внутренней логической схемы и любых изменений на ее входах. Выход с тремя состояниями обозначается символом .

В качестве примера использования выхода указанного типа рассмотрим ситуацию, показанную на Рис. 2.4. В данном случае основному контроллеру требуется прочитать данные с одного из нескольких устройств, подключенных к нему группой общих линий. Поскольку эта магистраль, или, иначе, шина данных, является общим ресурсом, в любой момент времени доступ к шине предоставляется только выбранному устройству. Доступ должен быть закрыт сразу же после считывания данных, с тем чтобы шиной могло воспользоваться другое устройство. Как показано на рисунке, все выходы, подключаемые к шине, обозначаются символом . После выбора устройства управление линиями шины будет осуществляться только активными логическими уровнями. Микросхема сдвоенного 4-битного буфера с тремя состояниями 74LS2441 имеет выходы с повышенной нагрузочной способностью (обозначаемые символом [>), специально предназначенные для работы на длинных линиях, имеющих большую емкость.

Рис. 2.4. Совместное использование шины

Интегральные микросхемы, содержащие до 12 логических элементов, относятся к микросхемам малой степени интеграции. Если в корпусе микросхемы содержится до 100 логических элементов, то она относится к классу микросхем средней степени интеграции; до 1000 — к классу больших интегральных схем или, сокращенно, БИС. Все микросхемы, имеющие более 1000 логических элементов, относятся к классу сверхбольших интегральных схем (СБИС). К последнему классу, в частности, относятся микросхемы памяти и микроконтроллеры.

Изображенные на Рис. 2.5 микросхемы, содержащие определенным образом соединенные элементы И-НЕ, являются типичным примером интегральных микросхем средней степени интеграции. Если вспомнить, что на выходе элемента И-НЕ лог. 0 присутствует только в том случае, если на всех его входах присутствует лог. 1 (см. Рис. 1.2, в на стр. 27), то можно увидеть, что при любых сочетаниях сигналов на входах выборки В А (21 20) (Рис. 2.5, а) сигнал лог. 0 будет присутствовать на выходе только одного вентиля. Так, выход Y¯2 будет активным при В А = 10. После рассмотрения таблицы истинности становится понятно, что данная схема декодирует двоичный адрес В А таким образом, что при подаче адреса n становится активным выход Y¯n. Полностью название микросхемы 74LS139 звучит так: сдвоенный натуральный дешифратор 2 на 4. Сдвоенным он называется потому, что в одном корпусе расположены две такие схемы. Символ X/Y обозначает преобразование кода X (натуральное двоичное число) в код Y (унарный — один из n). Вход разрешения G¯ подключен параллельно ко всем элементам. Таким образом, дешифратор выполняет свои функции только в том случае, если на входе G¯ присутствует НИЗКИЙ уровень (лог. 0). Если на входе G¯ присутствует ВЫСОКИЙ уровень, то независимо от состояния входов В и А (в таблице истинности эта ситуация обозначается символом «X» — безразличное состояние) все выходы устанавливаются в неактивное состояние (лог. 1). Пример использования микросхемы 74LS139 приведен на Рис. 2.25 (стр. 54).

Рис. 2.5. Микросхемы дешифраторов 74LS138 (К555ИД7) и 74LS139 (К531ИД14)

Микросхема 74LS138, показанная на Рис. 2.5, б, похожа на только что рассмотренную, однако выполняет функцию дешифратора 3 на 8. При n-м значении на линиях адреса C B А (22 21 20) активным становится только один из восьми выходов Y¯n. Микросхема 74LS138 имеет три входа стробирования, формирующие внутренний сигнал разрешения . То есть функционирование микросхемы разрешено только в том случае, если на обоих входах  и  присутствует НИЗКИЙ уровень, а на входе G1 — ВЫСОКИЙ. Микросхема 74LS138 используется в схеме на Рис. 11.12 (стр. 350) в качестве дешифратора линий порта микроконтроллера для подключения к одному порту нескольких устройств.

Приоритетный шифратор 74LS148, показанный на Рис. 2.6, выполняет обратное преобразование. Подача на один из входов НИЗКОГО уровня вызывает появление на выходе эквивалентного 3-битного значения. Так, если вход 5¯ = 0, то а¯2а¯1а¯0 = 010 (число 101 в инверсной логике).

Рис. 2.6. Микросхема приоритетного шифратора 74LS148

Если активный сигнал присутствует на нескольких входах, то выходное значение соответствует входу с наибольшим номером. Так, если НИЗКИЙ уровень присутствует на обоих входах 5¯ и 3¯, то выходное значение все равно будет составлять 010. Символы HPRI на условном обозначении микросхемы, приведенной на Рис. 2.6, означают «наивысший приоритет» (Higest PRIority). Работа микросхемы разрешается при НИЗКОМ уровне на входе E¯in. Выходы E¯out и G¯S¯ используются при каскадном соединении микросхем для увеличения количества линий.

Большой класс ИС реализует различные арифметические операции. Матрица логических элементов, показанная на Рис. 2.7, используется для обнаружения равенства между двумя 8-битными числами Р и Q. Каждый из восьми элементов Исключающее ИЛИ-HE формирует лог. 1, если оба входных бита Рn и Qn одинаковы (мы уже встречались с этим элементом на стр. 28). Соответственно, НИЗКИЙ уровень на выходе элемента И-НЕ появится только в том случае, если все 8 пар битов одинаковы. Микросхема компаратора 74LS688 имеет также вход G¯, сигнал с которого подается на один из входов элемента И-НЕ и выполняет функцию глобального разрешения.

На условном обозначении микросхемы по стандарту ANSI/IEC, приведенном на Рис. 2.7, б, функция сравнения указывается аббревиатурой СОМР. Префикс «1» в обозначении выхода указывает на то, что выполнение операции «Р = Q» зависит от входа, обозначенного тем же номером, т. е. G1. Таким образом, вход разрешения G1 управляет выходом IP = Q (и вход, и выход — с активным НИЗКИМ уровнем).

Рис. 2.7. Микросхема 8-битного компаратора 74LS688

Одной из первых функций, реализованных в ИС помимо обычных логических элементов, было сложение. В таблице истинности, показанной на Рис. 2.8, а, приведены значения бита суммы S и флага переноса С1, образующихся при сложении двух битов А и В и бита переноса из предыдущего разряда С0. Например, из 6-й строки таблицы следует, что при сложении двух единиц и 0-го переноса сумма будет равна 0, а перенос — 1 (1 + 1 + 0 = 10). Для реализации этой строки таблицы нам нужно распознать комбинацию битов 110, описываемую уравнением А∙В∙C¯0. Эту операцию выполняет 6-й элемент схемы. Таким образом, мы просто объединяем по ИЛИ все возможные комбинации входных переменных:

S = (A¯∙B¯∙C 0 ) + (A¯∙B∙C¯ 0 ) + (A∙B¯∙C¯ 0 ) + (A∙B∙C 0 )

С 1 =(A¯∙B∙C 0 ) + (A∙B¯∙C 0 ) + (A∙B∙C¯ 0 ) + (A∙B∙C 0 )

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

На Рис. 2.8, б показана структурная схема микросхемы 74LS283, которая складывает два 4-битных числа за 25 нc. На практике для формирования итогового бита переноса С4 используется дополнительная схема, чтобы избежать задержек, вызванных прохождением битов переноса через все стадии суммирования, от младшего бита к старшему. Несколько (n) микросхем 74LS283 можно каскадировать для реализации функции сложения слов разрядностью 4хn. Таким образом, две микросхемы 74LS283 выполняют 16-битное сложение за 45 нc (учитывая дополнительную задержку распространения переноса между двумя микросхемами).

Рис. 2.8. Сложение

Разумеется, сумматоры можно использовать и для вычитания, если перевести операнды в дополнительный код. Схему сумматора/вычитателя можно реализовать при помощи набора логических элементов Исключающее ИЛИ, выступающие в роли программируемых инверторов (см. стр. 28). Вход выбора режима , управляющий этими инверторами в схеме на Рис. 2.9, подключен также к входу переноса, что вызывает добавление единицы в режиме вычитания.

Рис. 2.9. Реализация программируемого сумматора/вычитателя

Расширяя набор аргументов, мы постепенно придем к арифметико-логическому устройству (АЛУ). АЛУ представляет собой схему, выполняющую определенный набор арифметических и логических операций над входными данными в соответствии со значением на входах выбора режима. Микросхема 74LS382, показанная на Рис. 2.10, выполняет 8 операций над двумя 4-битными числами. Выполняемая операция задается тремя битами выбора режима S0S1S2 (Рис. 2.10, а). Кроме сложения и вычитания, это АЛУ выполняет также операции И, ИЛИ и Исключающее ИЛИ. Микросхема формирует даже признак переполнения дополнительного кода (см. стр. 24).

Рис. 2.10. Микросхема АЛУ 74LS382

Как мы увидим чуть позже, АЛУ является «сердцем» любого компьютера или микропроцессора. Подавая на входы выбора режима некоторую последовательность двоичных значений, можно заставить АЛУ выполнить соответствующую последовательность операций. Эти коды операций хранятся во внешней памяти и последовательно считываются схемами управления.

Обычно последовательность кодов операций, составляющих программу, хранится в какой-либо БИС ПЗУ Обратимся к структуре, показанной на Рис. 2.11. На этом рисунке изображен дешифратор 3 на 8, управляющий матрицей диодов 8x2. Для каждой n-й комбинации сигналов, подаваемых на вход адреса, выбирается п-я строка. Если к этой строке подключен диод, то он открывается и на линии соответствующего столбца появляется НИЗКИЙ уровень. Соответственно, инвертирующий буфер с тремя состояниями формирует ВЫСОКИЙ уровень для каждого подключенного диода и НИЗКИЙ уровень для разомкнутой цепи. Таким образом, для каждого входного кода совокупность подключенных диодов определяет выходной код. Для наглядности матрица запрограммирована на реализацию полного 1-битного сумматора, изображенного на Рис. 2.8, а, однако может быть задана и любая другая функция трех переменных.

Рис. 2.11. Реализация 1-битного сумматора на ПЗУ

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

При реализации СБИС ППЗУ больших объемов, необходимых для хранения программ, плавкие перемычки очень неудобны. Например, небольшое ППЗУ 27С64, показанное на Рис. 2.12, имеет объем, для формирования которого потребовалось бы 65 536 пар «перемычка — диод». То есть это относительно небольшое устройство способно хранить 8192 байта данных. В микросхеме 27С64 в качестве программируемой перемычки используется электрический заряд на плавающем затворе МОП-транзистора. Второй МОП-транзистор выполняет роль диода. Как и в варианте с плавкими перемычками, инжекция заряда в изолированный затвор осуществляется с помощью высокого напряжения. Образующееся электрическое поле удерживает МОП-транзистор в состоянии проводимости. Для полного рассасывания этого заряда требуется достаточно длительный срок в несколько десятков лет, однако это значение можно уменьшить до 20 мин, подвергая затвор интенсивному ультрафиолетовому излучению. Поэтому устройства, подобные 27С64, называют стираемым ППЗУ (СППЗУ). В корпусе микросхем, предусматривающих многократное использование, напротив кристалла размещается кварцевое окошко (см. Рис. 2.12), которое можно увидеть на фотографии, приведенной на стр. 15.

Рис. 2.12. Микросхема стираемого ППЗУ (СППЗУ) 27С64 ( К573РФ4/6 )

Программирование таких микросхем осуществляется специальными устройствами — программаторами. Версии микросхем без окошка называются однократно-программируемыми ПЗУ, поскольку их нельзя стереть после программирования. Однако они намного дешевле и поэтому используются в мелко- и среднесерийном производстве.

На Рис. 2.13 приведена упрощенная схема перемычки на МОП-транзисторе с плавающим затвором. Вместо диода узлом матрицы является n-канальный МОП-транзистор VT1. Затвор этого транзистора подключен к линии X, а его исток S1 — к линии Y. Если сток D1 транзистора подключен к источнику положительного напряжения и выбрана линия X, то на линии Y тоже появляется ВЫСОКИЙ уровень (лог. 1 в терминах положительной логики). Однако если VT1 отключен от VDD, то он не проводит ток, и на линии Y присутствует лог. 0. Транзистор VT2 включается последовательно с линией VDD и, таким образом, выполняет роль программируемого элемента. Этот транзистор имеет дополнительный, никуда не подключенный затвор, скрытый в слое изолирующего диоксида кремния. В нормальном состоянии заряд на затворе отсутствует, и транзистор VT2 закрыт. Если на затвор подать импульс напряжения программирования величиной 20…25 В, то отрицательные заряды туннелируются через очень тонкий слой изолятора, окружающий скрытый затвор. В результате транзистор VT2 перейдет в открытое состояние и таким образом подключит VT1 к шине питания. Это приведет к появлению лог. 1 на линии Y при выборе данной ячейки внутренним дешифратором.

Рис. 2.13. Перемычка на МОП-транзисторе с плавающим затвором

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

Существуют также структуры ППЗУ, которые можно стереть электрическим путем, причем часто непосредственно в устройстве. Наиболее распространены две разновидности структур — электрически стираемые ППЗУ (ЭСППЗУ, или EEPROM) и FLASH-ППЗУ. В первом случае импульс отрицательного напряжения КРР большой амплитуды приводит к просачиванию электронов из плавающего затвора. Обычно отрицательное напряжение формируется схемами, расположенными непосредственно на кристалле, что исключает необходимость в дополнительном источнике питания. FLASH-вариант ЭСППЗУ основан на эффекте инжектирования горячих электронов в затвор. Площадь, занимаемая ячейкой, в этом случае почти в 2 раза меньше обычной ячейки ЭСППЗУ, что увеличивает плотность упаковки памяти. Одна из промышленно выпускаемых микросхем EEPROM-памяти показана на Рис. 12.26 (стр. 439).

Большинство современных ЭППЗУ/ЭСППЗУ довольно быстрые, со временем доступа около 150 не. Процесс программирования происходит гораздо медленнее, около 10 мс на слово, однако это достаточно редкая операция. Программирование FLASH-памяти осуществляется почти в 1000 раз быстрее (на одну ячейку требуется около 10 мкс).

* * *

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

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

Сравним эту кнопку с не менее обыкновенным выключателем. Вы нажимаете на него и свет загорается. Более того, он продолжает гореть даже тогда, когда вы убираете управляющее воздействие (палец). Чтобы выключить свет, вы должны перевести выключатель в выключенное состояние, и опять же, он останется в этом состоянии даже при отсутствии входного воздействия. Ключи такого типа называются бистабильными, поскольку они имеют два устойчивых состояния. Каждый такой ключ ведет себя как 1-битная ячейка памяти, которая может запоминать либо включенное, либо выключенное состояние.

В микросхемах оперативной памяти, таких как 6264 (Рис. 2.26), каждая бистабильная ячейка формируется с помощью двух перекрестно включенных транзисторов. Здесь мы не будем касаться конкретной реализации этих ячеек. Вместо этого рассмотрим два логических элемента ИЛИ-HE, объединенных перекрестными обратными связями (Рис. 2.14). Вспомним, что при появлении лог. 1 на каком-либо входе элемента ИЛИ-HE на его выходе появляется лог. 0 независимо от состояния остальных входов. Вооружившись этим знанием, попытаемся проанализировать схему:

• Если на вход S подать 1, то выход Q¯ переключится в 0. На обоих входах верхнего элемента появится 0, что приведет к появлению 1 на выходе Q. Если теперь на входе S снова появится 0, то нижний элемент останется в 0 (поскольку на входе обратной связи с вывода Q присутствует 1) и состояние выхода верхнего элемента также не изменится. Таким образом, триггер устанавливается при подаче положительного импульса на вход S.

• Если на вход R подать 1, то выход Q переключится в 0. На обоих входах нижнего элемента появится 0, что приведет к появлению 1 на выходе Q¯. Если теперь на входе R снова появится 0, то верхний элемент останется в 0 (поскольку на входе обратной связи с вывода Q¯ присутствует 1) и состояние выхода нижнего элемента также не изменится. Таким образом, триггер сбрасывается при подаче положительного импульса на вход R.

При нормальном функционировании (предполагается, что оба входа не могут быть активными в один и тот же момент времени оба выхода дополняют друг друга, что отражено на условном графическом изображении триггера (Рис. 2.14, б).

Рис. 2.14. RS -триггер

Существует много различных реализаций бистабильных ячеек. Например, замена элементов ИЛИ-HE на элементы И-НЕ приведет к образованию -триггера, в котором активным входным сигналом является лог. 0. В схеме, приведенной на Рис. 2.15, такой триггер используется для подавления дребезга контактов механического переключателя. Переключатели часто используются для управления входами логических схем. Однако большинство металлических контактов не могут замыкаться мгновенно, и при нажатии происходит их многократное размыкание/замыкание в течение нескольких десятков миллисекунд. То есть при использовании механического ключа, скажем, для прерывания работы компьютера/микроконтроллера результат будет совершенно непредсказуем.

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

Рис. 2.15. Использование RS -триггера для подавления дребезга контактов

Дальнейшим развитием RS-триггера является D-защелка. В этом элементе выходной сигнал (Q) повторяет входной (D), если на входе управления С присутствует активный уровень (в данном случае — ВЫСОКИЙ), и сохраняет предыдущее значение при неактивном уровне на входе управления. Таким образом, D-защелку можно рассматривать как 1-битную ячейку памяти, запоминающую значение, которое присутствует на ее входе на момент завершения импульса управления.

На Рис. 2.16, б взаимное влияние входов D и С обозначается символами «С1» и «1D». Префикс «1» у D указывает на то, что этот вход зависит от любого сигнала, в обозначении которого имеется суффикс «1», в данном случае — от входа С. То есть фиксация значения 1D происходит по сигналу С1.

Триггер тоже представляет собой 1-битную ячейку памяти, однако в нем данные передаются на выход только по активному фронту сигнала на управляющем (тактовом) входе. D-триггер, таблица истинности которого приведена на Рис. 2.16, в, переключается по нарастающему фронту (в таблице истинности это обозначается символом «»), однако часто встречаются и триггеры, переключающиеся по спадающему фронту. Импульсный вход на условном обозначении триггера по стандарту ANSI/IEC обозначается символом >, как показано на Рис. 2.16, г.

Рис. 2.16. D- защелка и D -триггер

Микросхема малой степени интеграции 74LS74, показанная на Рис. 2.17, содержит два D-триггера. Каждый триггер имеет входы сброса R¯ и установки S¯, которые являются асинхронными, т. е. их функционирование не зависит от тактового сигнала. Среди микросхем средней степени интеграции встречаются наборы из 4, 6 и даже 8 триггеров, имеющих общий тактовый вход.

Рис. 2.17. Микросхема сдвоенного D -триггера 74LS74 ( К555ТМ2 )

Микросхема 74LS377, показанная на Рис. 2.18, состоит из восьми D-триггеров, тактируемых одним сигналом С, который, в свою очередь, управляется сигналом G¯. То есть 8 бит данных 8D…., 1D защелкиваются по нарастающему фронту на входе С при НИЗКОМ уровне на входе G¯. На условном обозначении микросхемы по стандарту ANSI/IEC, приведенном на Рис. 2.18, б, эта зависимость обозначена как G1 —> 1С2 —> 2D, т. е. вход G¯ разрешает работу тактового входа С, который, в свою очередь, воздействует на входы данных.

Рис. 2.18. Микросхема 8-битного параллельного регистра 74LS377 ( К555ИР27 )

Наборы D-триггеров обычно называются регистрами, т. е. устройствами памяти, хранящими одно слово данных. Полное название микросхемы 74LS377 — регистр с параллельным входом и параллельным выходом (PIPO-регистр), поскольку данные загружаются в него и считываются из него параллельно (т. е. одновременно).

Выпускаются также микросхемы, содержащие массив D-защелок. В качестве примера можно указать 8-битный регистр-защелку 74LS373, показанный на Рис. 2.19, в котором вместо восьми D-триггеров используется восемь D-защелок. Кроме того, выходы защелок могут устанавливаться в третье состояние. Эта возможность используется в тех случаях, когда данные сначала защелкиваются в регистре, а затем выставляются на общую шину для последующего их считывания компьютером.

Рис. 2.19. Микросхема 8-битного параллельного регистра-защелки 74LS373 ( К555ИР22 )

Подходящий пример использования PIPO-регистра приведен на Рис. 2.20. На этой схеме к входу 8-битного регистра подключен выход АЛУ. Выходы регистра, в свою очередь, подключены к одному из входов АЛУ. Этот регистр служит для накопления результата последовательных операций и обычно называется аккумулятором, или рабочим регистром. Чтобы разобраться в работе этой схемы, рассмотрим процесс сложения двух слов — А и В. Если предположить, что АЛУ представляет собой две каскадно-соединенные микросхемы 74LS238, то последовательность операций может быть следующей:

1 . Шаг программы

• Режим = 000 (сброс).

• По импульсу на входе «Исполнение» значение с выхода АЛУ (00000000) загружается в регистр.

• Выходные данные — ноль (00000000).

2 . Шаг программы

• Значение слова А подается на вход АЛУ.

• Режим = 011 (сложить).

• По импульсу на входе «Исполнение» значение с выхода АЛУ (слово А +ноль) загружается в регистр.

• Выходные данные — слово А.

3 . Шаг программы

• Значение слова В подается на вход АЛУ.

• Режим = 011 (сложение).

• По импульсу на входе «Исполнение» значение с выхода АЛУ (слово В + слово А) загружается в регистр.

• Выходные данные — сумма слов В и А.

Рис. 2.20. 8-битный блок обработки (АЛУ/рабочий регистр)

Последовательность кодов операций (000–100–100) и составляет программу. На практике каждая команда будет также содержать (при необходимости) адрес обрабатываемых данных; в данном случае — местонахождение слов А и В.

Результат любой операции характеризуется некоторым набором свойств. К примеру, результат может быть равен нулю или же при его вычислении может произойти переполнение. Эти свойства могут потребоваться при дальнейшем выполнении программы. В рассматриваемой схеме для сбора такой информации используются два D-триггера, тактируемые сигналом «Исполнение». В данном контексте состояния этих триггеров называются флагами (реже — семафорами). Таким образом, у нас имеются флаг нуля Z и флаг переноса из 7-го бита С, образующие регистр состояния (STATUS).

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

Рис. 2.21. 8-битный блок обработки (АЛУ/рабочий регистр) на системном уровне

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

Значение с выхода АЛУ может быть загружено обратно в рабочий регистр W по сигналу «Исполнение» либо передано вовне по шине данных. Такая структура показана на Рис. 3.2 (стр. 60).

Существуют также и другие разновидности регистров. Четырехбитный сдвиговый регистр, показанный на Рис. 2.22, а, является примером структуры с последовательным вводом и последовательным выводом (SISO). В данном случае бит данных, хранящийся в n-м D-триггере, поступает на вход следующего ((n + 1) — го) каскада. При подаче тактового импульса (или, в данном контексте, импульса сдвига) этот бит перегружается в (n + 1) — й триггер, т. е. сдвигается с n-й позиции в позицию n + 1. Поскольку все триггеры тактируются одним сигналом, по каждому импульсу сдвига все слово данных сдвигается вправо.

Рис. 2.22. Сдвиговый регистре последовательным вводом и выводом

В примере, приведенном на Рис. 2.22, б, по тактовому сигналу в левую позицию побитно вдвигается 4-битное число. После 4-го импульса новое слово полностью окажется в регистре. Для его считывания потребуется еще четыре импульса, во время которых произойдет побитная выдача содержимого сдвигового регистра. Если обеспечить доступ к выходу каждого триггера, чтобы данные можно было считать за один раз, получим структуру с последовательным входом и параллельным выходом (SIPO).

На Рис. 2.22, в символ «->» в обозначении тактового входа используется для указания операции сдвига. Аббревиатура SRG4 означает «4-битный сдвиговый регистр». Пример 8-битного сдвигового регистра приведен на Рис. 12.2 (стр. 370).

Существуют и другие разновидности структур, в том числе структура с параллельным входом и последовательным выходом (PISO), часто применяемая для преобразования параллельного кода в последовательный. Инкрементирование или декрементирование счетных регистров (счетчиков) производится по каждому импульсу тактового сигнала в соответствии с двоичной последовательностью. Обычно n-битный счетчик может отсчитывать 2n состояний. Некоторые счетчики можно загружать в параллельном режиме, т. е. использовать как память.

Рассмотрим D-триггер, тактируемый по спадающему фронту (Рис. 2.23), инверсный выход Q¯ которого подключен к входу 1D. По каждому спадающему фронту на входе С1 данные с входа 1D будут защелкиваться и появляться на выходе Q. Поскольку инверсный сигнал этого выхода подается обратно на вход, то в следующий раз триггер переключится в противоположное состояние. Это периодическое переключение между двумя состояниями помечено на временной диаграмме символом «Т». В результате при подаче на вход триггера сигнала некоторой частоты на его выходе будет сформирована последовательность импульсов, частота которых в 2 раза ниже. Если частота входного сигнала не изменяется, то выходной сигнал представляет собой точный прямоугольный сигнал (меандр). Иногда такой Т-триггер называют триггером счетного типа или делителем на два.

Рис. 2.23. Т -триггер

Разумеется, Т-триггеры тоже можно каскадировать, как показано на Рис. 2.24, а. В данном случае 4 триггера с запуском по спадающему фронту соединены таким образом, чтобы выход n-го разряда управлял тактовым входом разряда n + 1. Соответственно, если частота сигнала на входе С равна 8 кГц, то на выходе QA будет прямоугольный сигнал частотой 4 кГц, на выходе QB — 2 кГц, на QC — 1 кГц и на QD — 500 Гц. Сигнал QA на Рис. 2.24, б формируется так же, как и на Рис. 2.23. Выход QB переключается по каждому спадающему фронту сигнала QA.

Аналогично функционируют и остальные выводы. Сопоставив ВЫСОКОМУ уровню лог. 1, а НИЗКОМУ — лог. 0, получим 24 (16) двоичных комбинаций в положительной логике, сдвинутых по фазе друг относительно друга. При достижении максимального значения счет начинается с 0 и так до бесконечности. Каждая комбинация остается в регистре до появления активного фронта следующего тактового импульса (в данном случае — спадающего фронта). Если взглянуть на формируемую последовательность, то можно увидеть, что она представляет собой последовательность натуральных двоичных чисел от Ь’0000’ до b’1111’. Вообще говоря, такая схема называется двоичным счетчиком по модулю 16. При счете по модулю n используются только первые n формируемых значений.

Рис. 2.24. Счетчик со сквозным переносом по модулю 16

Теоретически нет никаких ограничений на количество каскадов, соединяемых указанным образом. То есть, используя 8 Т-триггеров, мы получим счетчик по модулю 256 (28). На практике же каждый триггер переключается с некоторой задержкой, что ограничивает максимально возможную частоту счетчика. К примеру, у сдвоенного D-триггера, показанного на Рис. 2.17, максимальная задержка распространения сигнала от фронта тактового импульса до появления выходного значения составляет 25 нc. Максимальная частота переключения одного каскада, например, такого как показан на Рис. 2.23, составляет 25 МГц. Соответственно, максимальная задержка в 8-битном счетчике составит 200 нc. Если такой счетчик со сквозным переносом будет тактироваться сигналом с частотой 5 МГц (равной 1/200 нс), то возникнет ситуация, при которой новое значение будет формироваться до установления предыдущего. Это представляет серьезную проблему, если различные состояния счетчика декодируются и используются для управления другими схемами. Схема декодирования, например, такая как приведена на Рис. 2.25, может отреагировать на это кратковременное переходное состояние непроизвольным образом, что вызовет сбой в работе устройства. В таких случаях лучше использовать более сложный синхронный счетчик, в котором все триггеры переключаются одновременно.

Рис. 2.25. Формирование временных диаграмм

Рассмотренные схемы осуществляли прямой счет. Если в качестве выходов использовать инверсные (Q¯), то счет будет осуществляться в обратном направлении (обратный счет). Того же результата можно достичь, если в качестве элемента памяти использовать триггеры, переключающиеся по нарастающему фронту, такие как сдвоенный триггер 74LS74.

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

Наряду с наиболее очевидным использованием счетного регистра для накопления числа событий, например, таких как количество консервных банок, прошедших через конвейер, существуют и другие варианты его использования. Одним из таких применений является разнесение во времени некоторых операций. На Рис. 2.25 счетчик по модулю 4 используется для управления одной из секций дешифратора 2 на 4 в микросхеме 74LS139 (Рис. 2.5, а). Этот дешифратор детектирует 4 состояния счетчика и формирует четыре сигнала, сдвинутых во времени друг относительно друга, которые могут использоваться, скажем, для задания последовательности операций, выполняемых управляющей логикой компьютера. Для адресации дешифратора используется инверсный выход триггеров. Это сделано специально, поскольку в противном случае по нарастающему фронту тактового сигнала осуществлялся бы обратный счет. Счетчики с большей разрядностью могут использоваться для формирования более сложных последовательностей управляющих операций.

Термин «регистр», как правило, используется применительно к элементу оперативной памяти, который может хранить одно двоичное слово, обычно разрядностью от 4 до 64 бит. Память большего объема можно реализовать, группируя n таких регистров и выбирая один из них. Подобная структура обычно называется регистровым файлом. Например, микросхема 74LS670 представляет собой регистровый файл 4 х 4 с раздельными входом и выходом 4-битных данных, а также отдельными входами 2-битного адреса для операций чтения и записи. Это означает, что любой регистр этого файла может быть считан в любой момент времени независимо от одновременно осуществляемой записи.

Память бóльших объемов называется оперативной памятью произвольного доступа или сокращенно ОЗУ. Словосочетание «произвольный доступ» означает, что для выбора любого слова памяти требуется одно и тоже время, не зависящее от расположения этого слова в матрице. Этим ОЗУ отличается от памяти на магнитной ленте, в которой бобина должна прокрутиться до требуемого сектора. А если этот сектор находится в конце ленты…

Для примера на Рис. 2.26 показана микросхема ОЗУ 6264. Она содержит матрицу из 65 536 (216) бистабильных ячеек, организованных в виде матрицы из 8192 (213) 8-битных слов. Слово n выбирается при подаче на линии адреса А0…А12 двоичного числа n.

В режиме чтения (R/W¯= 1) на выходы I/O7…I/O0 выдается n-е слово данных, определяемое n-й комбинацией битов адреса. Символ «А» в обозначении входов/выходов (как и на Рис. 2.12) указывает на эту взаимосвязь. Для включения выходных буферов с тремя состояниями на входе  должен быть НИЗКИЙ уровень.

Адресованное слово записывается в память при R/W¯ = 0. Байт данных, который должен быть записан в n-ю ячейку, подается на входы I/O7…I/O0. Такая двунаправленная передача данных является отличительной особенностью компьютерных шин.

В обоих случаях микросхема ОЗУ должна быть выбрана подачей лог. 0 на вывод  и лог. 1 — на вывод CS2. В зависимости от версии микросхемы интервал между подачей сигналов выборки и началом обращений к ней составляет от 100 до 150 нc. Если напряжение питания не пропадает, время хранения данных не ограничено. По этой причине микросхема 6264 называется статическим ОЗУ (SRAM). Вместо того чтобы использовать для хранения одного бита пару транзисторов, данные можно хранить в виде заряда емкости затвор-исток одного полевого транзистора. Время рассасывания подобного заряда составляет несколько миллисекунд, поэтому заряд необходимо периодически обновлять. Такая динамическая память (DRAM) дешевле в изготовлении, и микросхемы данного типа имеют большую емкость. Обычно память подобного типа используется там, где требуется очень большой объем памяти, например в персональных компьютерах. В этом случае стоимость схемы регенерации компенсируется дешевизной микросхем памяти.

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

Рис. 2.26. Микросхема ОЗУ 6264 (8196х8 бит)

 

Глава 3

Обработка хранимой программы

В предыдущей главе мы с вами разработали простейший процессор, состоящий из арифметико-логического устройства (АЛУ) и регистра с параллельным вводом/выводом данных. Собственно АЛУ выступает в роли «числодробилки», а рабочий регистр используется для хранения операндов, а также результатов всех операций. В нашем примере, описанном на стр. 33, мы складывали вместе два числа, накапливая результат в рабочем регистре. Если задавать код режима работы АЛУ перед каждым шагом, то мы в принципе можем заставить наше вычислительное устройство выполнить любую задачу, которая может быть описана последовательностью арифметических и логических операций. Эта совокупность кодов команд (например, «сложить», «вычесть», «логическое И»…) может храниться во внешней памяти. Там же могут находиться различные операнды, передаваемые в АЛУ, а также результаты выполнения команд. Таким образом, эти коды включают в себя как собственно программу программируемого устройства, так и различные операнды, или данные. Извлекая (fetch) эти команды по очереди, мы можем выполнять заданную программу. Такая структура вместе с соответствующими каналами передачи данных, дешифраторами и логическими схемами обычно называется цифровым компьютером или цифровой вычислительной машиной.

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

Прочитав эту главу, вы:

• Познакомитесь с фон-неймановской архитектурой и узнаете ее недостатки.

• Познакомитесь с гарвардской архитектурой, с ее параллельно работающими блоками выборки и дешифрации, а также раздельными адресными пространствами.

• Поймете, какая взаимосвязь существует между цифровым компьютером, микропроцессором и микроконтроллером.

• Познакомитесь со структурой памяти программ, а также ее взаимодействием со счетчиком команд и конвейером.

• Узнаете формат типичных команд.

• Познакомитесь с назначением и структурой памяти данных.

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

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

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

Рис. 3.1. Элементарная фон-неймановская вычислительная машина (шина адреса не показана)

В первое послевоенное десятилетие в Гарвардском университете было создано несколько компьютеров семейства «Марк», от «Марк 1» до «Марк 4», в которых память программ была полностью отделена от памяти данных (в первых машинах «Марк 1» и «Марк 2» программа считывалась с бумажной перфоленты). Такая концепция была более эффективной, чем фон-неймановская (или, как ее иногда называют, принстонская архитектура, поскольку код программы мог считываться из памяти программ одновременно с обменом между ЦПУ и памятью данных или с операциями ввода/вывода. Однако такие машины были намного сложнее и дороже в изготовлении. А с учетом уровня технического развития 50-х годов, да еще и после проигрыша в конкурсе на создание компьютера для контроля сети континентальных радиолокационных станций, устроенного Министерством обороны США, они и вовсе не получили широкого распространения. Однако с развитием сложных интегральных схем эта гарвардская архитектура снова оказалась в центре внимания.

На Рис. 3.2 показаны две физически разделенные шины, используемые для передачи информации между ЦПУ и этими неперекрывающимися областями памяти. Каждая память имеет собственную шину адреса, поэтому адрес ячейки памяти программ никоим образом не связан с адресом ячейки памяти данных. В таком случае говорят, что обе области памяти находятся в различных адресных пространствах. Память данных иногда называют файловой памятью, в этом случае n-я ячейка обозначается как файл n .

Рис. 3.2. Элементарная гарвардская вычислительная машина (шины адреса не показаны)

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

Центральный процессор

Центральный процессор состоит из связки АЛУ/рабочий регистр и соответствующей управляющей логики. По сигналам схемы управления команды программы выбираются из памяти, дешифруются и исполняются. Данные, которые получаются или используются во время выполнения программы, также располагаются в памяти. Этот цикл «выборка — исполнение» образует рабочий ритм вычислительной машины и повторяется непрерывно в течение всего времени, когда система находится в активном состоянии.

Память

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

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

Память программ

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

Память данных

В памяти данных хранятся данные, используемые во время работы программы. И опять же быстродействие этой памяти обычно сравнимо с быстродействием ЦПУ. Также в адресном пространстве памяти данных могут располагаться специальные регистры, например порты ввода/вывода.

Интерфейсные порты

Независимо от своего назначения компьютер должен иметь возможность взаимодействовать с окружающим миром. Хотя обычно вспоминаются такие устройства, как клавиатура и монитор, можно считывать и изменять состояние практически любого физического устройства. Так, данные об объеме топлива, впрыскиваемого в цилиндр двигателя, в совокупности со значением скорости вращения вала могут использоваться для управления моментом зажигания искры в камере сгорания бензинового двигателя.

Шина данных

Все элементы фон-неймановского компьютера соединяются между собой одной общей магистралью передачи данных, или шиной (понятие шины было введено во 2-й главе, см. Рис. 2.4 на стр. 34). Вся информация передается по этим общим линиям в обоих направлениях, при этом ЦПУ играет роль главного контроллера. В компьютере с гарвардской архитектурой память программ имеет отдельную шину данных, что позволяет осуществлять выборку команд одновременно с действиями на шине данных памяти программ. Другие шины используются для передачи адресов различным областям памяти, а также управляющей информации и информации о состоянии (см. Рис. 3.4).

* * *

Микроконтроллеры, которым посвящена эта книга, имеют гарвардскую архитектуру, поэтому дальше мы будем рассматривать только ее. Взяв за основу ЦПУ, показанный на Рис. 2.20 (стр. 49), и добавив к нему память программ, память данных, а также схемы управления и дешифрации, мы получим примитивный компьютер с гарвардской архитектурой (Рис. 3.3). Серым цветом на рисунке выделены элементы исходной схемы с Рис. 2.21, приведенного на стр. 50.

Благодаря подключению шины данных АЛУ к памяти данных, мы получаем возможность считывать из памяти первый операнд, а также при необходимости помещать в нее результат операции. Адрес этого операнда является частью кода команды, считанного из памяти программ и дешифрованного устройством управления. Это же устройство управления формирует сигналы выбора режима АЛУ, который зависит от текущей команды. Результат, получаемый на выходе АЛУ, может быть загружен либо в рабочий регистр (устройство управления формирует импульс на линии W), либо обратно в ту же ячейку памяти, откуда был считан операнд (устройство управления формирует импульс на линии F). Информация об адресате результата операции также содержится в коде команды.

Команды (в виде кодовых слов) обычно располагаются в памяти программ последовательно. Для поочередной адресации каждой команды используется двоичный суммирующий счетчик (см. Рис. 2.24 на стр. 53). Если, предположим, при сбросе компьютера счетчик команд (Program Counter — PC) обнуляется, то первая команда будет расположена по адресу h’000’ памяти программ, вторая — по адресу h’001’ и т. д. (см. Рис. 3.4). Устройство управления просто инкрементирует счетчик после выборки каждой команды. Непосредственно загружая новый адрес в счетчик команд, можно осуществить переход к другому участку кода.

Рис. 3.3. Структура элементарного гарвардского компьютера на системном уровне

Последовательность операций «выборка команды/ее дешифровка/исполнение», т. е. так называемый цикл выборки — исполнения команды, является фундаментальным понятием, необходимым для понимания работы компьютера. Чтобы проиллюстрировать этот рабочий ритм, рассмотрим простую программу, которая считывает переменную NUM_1, прибавляет к ней число 4 и записывает результат в переменную NUM_2. На языке высокого уровня Си эту операцию можно записать следующим образом:

NUM_2 = NUM_1 + 4;

Несколько более подробно структура нашего компьютера, который я назвал BASIC (аббревиатура от Basic All-purpose Stored Instruction Computer — базовый универсальный компьютер с хранимой программой), изображена на Рис. 3.4. На этом рисунке показаны ЦПУ и обе области памяти со своими шинами данных и соответствующими шинами адреса.

Рис. 3.4. Состояние ЦПУ в момент выполнения первой команды при одновременной выборке второй команды. Все адреса/данные представлены в шестнадцатеричной системе

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

Сначала разберемся с процессом выборки команд.

Счетчик команд

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

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

Конвейер

В двух регистрах команд содержатся коды команд, считанные из памяти программ. В начало конвейера (в первый регистр команд, IR1) загружается код n-й команды и хранится там для обработки в следующем цикле. Это позволяет исполнять команду n - 1, находящуюся в конце конвейера (во втором регистре команд, IR2) одновременно с выборкой n-й команды и загрузкой ее в конвейер. Работа конвейера показана на Рис. 3.7.

Дешифратор команд

Дешифратор команд ID является «мозгами» ЦПУ — он дешифрует код команды, находящийся в регистре IR2, и формирует в определенной последовательности сигналы для исполнительного блока, необходимые последнему для определения местоположения операнда (если таковой имеется) в памяти данных и для переключения АЛУ в заданный режим. На Рис. 3.4 показано выполнение команды movf h’25’,w (копирование содержимого регистра данных с адресом h’25’ в рабочий регистр).

* * *

Исполнительный блок осуществляет обращения к памяти данных и конфигурирование АЛУ. Работой исполнительного блока управляет дешифратор команд, функционирование которого, в свою очередь, зависит от значения кода команды n — 1, находящегося в регистре команд IR2.

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

Регистр адреса

Когда ЦПУ собирается обратиться к ячейке (регистру) памяти данных, он помещает адрес этой ячейки в регистр адреса FAR. При этом производится непосредственная адресация памяти данных по ее шине адреса. Как показано на Рис. 3.4, из памяти данных считывается регистр с адресом h’25’, и его содержимое защелкивается во внутреннем регистре данных FDR процессора.

Регистр данных

Этот «двунаправленный» регистр выполняет две функции:

• Хранит содержимое адресованного регистра данных, если ЦПУ осуществляет цикл чтения. Именно это происходит при выполнении 1-й команды (movf h’25’,w), которая пересылает (копирует) содержимое регистра с адресом h’25’ в рабочий регистр.

• Хранит данные, которые ЦПУ собирается записать в адресованный регистр данных. Такой цикл записи, в частности, имеет место при выполнении команды movwf h’26’, которая пересылает (копирует) содержимое рабочего регистра в регистр с адресом h’26’.

Арифметико-логическое устройство

АЛУ выполняет арифметические и логические операции, определяемые значением кода режима (см. Рис. 2.10 на стр. 39), который извлекается из кода команды дешифратором команд.

Регистр состояния

Этот регистр содержит флаги нуля Z и переноса С, которые устанавливаются соответственно, если результат операции равен нулю и если в результате сложения возник перенос.

Рабочий регистр

В рабочем регистре АЛУ (W) обычно находится один из операндов команды — либо источник, либо адресат. Например, команда addwf h’20’,w складывает содержимое рабочего регистра с содержимым регистра h’20’ и помещает сумму обратно в рабочий регистр W. В некоторых компьютерах этот регистр называется также аккумулятором.

* * *

Помимо ЦПУ, в нашем компьютере имеется две области памяти, предназначенные для хранения кода программы и данных.

Память программ

Каждая позиция (или ячейка) памяти программ может содержать одну команду, которая кодируется 14-битным словом. Из Рис. 3.4 видно, что каждая из этих ячеек имеет свой адрес, выставляемый счетчиком команд на шину адреса памяти программ. На этом рисунке содержимое PC равно h’001’ (или Ь’0000000000000’), что приводит к выдаче содержимого ячейки h’001’ на шину данных памяти программ и, следовательно, загрузке его в начало конвейера. В рассматриваемом примере считанное значение равно h’3E04’ (или b’11111000000100’), что является машинным кодом команды addlw 04. В конечном счете дешифратор команд интерпретирует этот код как операцию сложения константы «4» с рабочим регистром.

Память данных

Каждая ячейка (или регистр) памяти данных содержит один байт (восемь битов) данных. Адрес регистра формируется исполнительным блоком в регистре адреса FAR и выставляется на шину адреса памяти данных. Содержимое адресованного регистра либо считывается в регистр данных FDR, либо перезаписывается находящимся в нем значением.

Шины адреса и данных памяти данных совершенно независимы от одноименных шин памяти программ, что позволяет одновременно обращаться к обеим областям памяти. Таким образом, адреса памяти программ и памяти данных имеют различный смысл, т. е. адрес h’25’ в памяти программ совсем не то же самое, что адрес h’25’ в памяти данных, который соответствует регистру h’25’.

* * *

Теперь, когда у нашего ЦПУ появилась память программ и память данных, рассмотрим более подробно саму программу. Наша иллюстративная программа состоит всего из трех команд и, как уже упоминалось, предназначена для копирования увеличенного на 4 значения однобайтной переменной, расположенной по адресу NUM_1, в ячейку с адресом NUM_2. Из Рис. 3.4 видно, что переменная NUM_1 представляет собой псевдоним для обозначения содержимого регистра данных h’25’. Аналогично, имя NUM_2 является символическим выражением для указания содержимого регистра данных h’26’.

А теперь рассмотрим используемые в программе команды.

∙ movf

Эта команда (MOVe File) копирует содержимое заданного регистра данных в рабочий регистр (как правило) или же обратно в тот же регистр данных (см. стр. 141). Таким образом, команда movf num_1,w загружает байт, расположенный по адресу h’25’ памяти данных, в рабочий регистр. Если содержимое указанного регистра равно нулю, то при выполнении команды устанавливается флаг Z, в противном случае этот флаг будет сброшен.

∙ addlw

Эта команда (ADD Literal to Working register) прибавляет однобайтную константу к содержимому рабочего регистра. Таким образом, команда addlw 04 прибавляет число 4 к содержимому рабочего регистра и записывает результат обратно в этот же регистр. Если возникает переполнение, то устанавливается флаг С, а если результат равен нулю — флаг Z.

∙ movwf

Эта команда (MOVe Working register to File) копирует содержимое рабочего регистра в заданный регистр данных. Таким образом, команда movwf NUM_2 сохраняет содержимое рабочего регистра по адресу h’26’ памяти данных. На состояние флагов данная команда не влияет.

Описывая команды, мы использовали мнемонические обозначения, такие как addlw. Разумеется, реальные логические схемы, декодирующие эти команды, работают исключительно с двоичными кодами. Мнемонические обозначения просто играют роль своеобразных «памяток» для программиста. Хотя крайне маловероятно, что кто-либо станет писать программы в машинных кодах, двоичный формат всех команд имеет логическую основу, и его знание будет полезно для понимания недостатков и ограничений набора команд и реальных аппаратных средств, которые мы будем обсуждать в следующих двух главах.

Пока мы рассмотрим две категории команд.

Прямая адресация регистра данных #_32.jpg_0

Данный способ адресации используют команды, в которых указывается адрес регистра данных, являющийся их операндом. Например, в команде movf h’25’,w операндом является регистр h’25’.

Из Рис. 3.5 видно, что 14-битный код команды состоит из трех частей:

• Шесть старших битов (13…8) называются кодом операции или, сокращенно, КОП. Каждая команда имеет уникальный КОП, и именно по его значению схема дешифратора определяет тип обрабатываемой команды.

• Седьмой бит кода команды, обозначенный символом «d», определяет адресата результата операции. Например, команда addwf h’30’,w означает «сложить содержимое рабочего регистра с регистром h’30’ и поместить результат обратно в рабочий регистр», тогда как команда addwf h’30’,f означает «сложить содержимое рабочего регистра с регистром данных h’30’ и поместить результат обратно в регистр h’30’». В первом случае адресатом операции является рабочий регистр W и бит d равен 0, а во втором случае адресатом является регистр данных и бит d равен 1. Мы еще вернемся к этой команде в пятой главе. В символической записи команды символы «,w» соответствуют сброшенному биту адресата d, а символы «,f» соответствуют установленному биту d.

• Младшие семь битов (6…0) определяют адрес регистра данных. Так, в нашем примере используется регистр h’25’, поэтому в указанном поле содержится значение Ь’0100101’. Так как размер поля адреса равен семи битам, то посредством прямой адресации можно адресовать только один банк памяти, вмещающий в себя 27 = 128 регистров, т. е. с регистра h’00’ по регистр h’7F’ (см. Рис. 4.7 на стр. 97).

Рис. 3.5. Формат кода команд, использующих прямую адресацию

Операции с константами #_34.jpg_0

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

Рис. 3.6. Формат слова команд операций с константами

Код операции команды из нашего примера (addlw 04) равен Ь’111110’, а константа равна Ь’00000100’. Значение константы должно лежать в диапазоне Ь’00000000’…Ь’11111111’ (h’00’…h’FF’ или, в десятичной системе, 0…255), что вполне логично, поскольку рабочий регистр, как и все внутренние регистры исполнительного блока, является восьмибитным.

* * *

Не только команды могут иметь мнемонические обозначения. Как мы видели, символические имена можно присваивать и ячейкам памяти данных. Так, на Рис. 3.4 идентификатор NUM_1 используется для указания содержимого регистра данных h’25’, a NUM_2 — регистра данных h’26’. Таким образом, нашу программу можно символически записать следующим образом:

NUM_2 = NUM_1 + 4;

Возвращаясь к собственно компьютеру, мы видим, что, начиная с адреса h’000’, наша программа имеет вид

00100000100101

11111000000100

00000010100110

Если только вы не киборг, то чтение такой программы — весьма сомнительное удовольствие.

Если мы воспользуемся шестнадцатеричной системой, то будет уже удобнее:

0825

ЗЕ04

00А6

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

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

movf NUM_1,w ; Копируем содержимое NUM_1 в W

addlw 4 ; Прибавляем к нему число 4

movwf NUM_2 ; Копируем NUM_1 + 4 в NUM_2

Текст после символов «;» называется комментариями, которые используются для облегчения понимания программы.

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

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

* * *

В основе работы любого вычислительного устройства лежит периодическое выполнение цикла выборка — исполнение. При этом каждая команда поочередно выбирается из памяти программ, интерпретируется и исполняется. Поскольку память, к которой обращается программа в процессе выполнения, является памятью данных, а каждое устройство памяти имеет собственные шины, операции выборки и исполнения могут осуществляться параллельно. Таким образом, во время выборки n-й команды исполняется команда n — 1. На Рис. 3.4 показано, что коды обеих команд, как следующей, так и текущей, хранятся в двух внутренних регистрах команд — IR1 и IR2 соответственно. Команды, считанные из памяти программ, загружаются в начало этого конвейера и «выталкиваются» в дешифратор команд с конца конвейера. На Рис. 3.7 изображен развернутый во времени процесс выполнения нашей команды, разбитый на машинные циклы. Во время каждого цикла, за исключением самого первого, выборка новой команды и исполнение предыдущей осуществляются одновременно.

Рис. 3.7. Параллельные потоки выборки и исполнения команд

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

* * *

Выборка (Рис. 3.4) ……Цикл 2

• Инкрементируется счетчик команд, чтобы указать на 2-ю команду.

• Одновременно код 1-й команды перемещается по конвейеру (из регистра IR1 в регистр IR2).

• Содержимое счетчика команд (h’001’) выставляется на шину адреса памяти программ.

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

Исполнение (Рис. 3.4) …..Цикл 2

• Адрес операнда h’25’ (т. е. NUM_1) заносится в регистр адреса FAR и выставляется на шину адреса памяти данных.

• Искомое значение, находящееся по адресу NUM_1, выставляется на шину данных памяти данных, после чего загружается в регистр FDR.

• АЛУ переключается в режим пропуска, в котором аргумент с входа АЛУ без изменений копируется в рабочий регистр.

* * *

Выборка ….. Цикл 3

• Инкрементируется счетчик команд, чтобы указать на 3-ю команду.

• Одновременно код 2-й команды перемещается по конвейеру (из регистра IR1 в регистр IR2).

• Содержимое счетчика команд (h’002’) выставляется на шину адреса памяти программ.

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

Исполнение ….. Цикл 3

• АЛУ переключается в режим сложения, в котором константа, содержащаяся в коде 2-й команды, прибавляется к содержимому рабочего регистра.

• Результат операции NUM_1 + 4 с выхода АЛУ помещается обратно в рабочий регистр.

* * *

Выборка ….. Цикл 4

• Инкрементируется счетчик команд, чтобы указать на 4-ю команду.

• Одновременно код 3-й команды перемешается по конвейеру (из регистра IR1 в регистр IR2).

• Содержимое счетчика команд (h’003’) выставляется на шину адреса памяти программ.

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

Исполнение ….. Цикл 4

• Адрес операнда h’26’ (т. е. NUM_2) заносится в регистр адреса FAR и выставляется на шину адреса памяти данных.

• АЛУ переключается в режим пропуска, в котором содержимое рабочего регистра без изменений копируется в регистр FDR и выставляется на шину данных памяти данных.

• Содержимое регистра FDR заносится в память данных по адресу, выставленному на шину адреса, т. е. в регистр NUM_2.

* * *

Обратите внимание на автоматическое изменение счетчика команд на этапе выборки каждого цикла. Такой последовательный характер изменения его содержимого будет сохраняться до тех пор, пока не встретится команда, напрямую модифицирующая этот счетчик, например команда goto h’200’. При выполнении этой команды адрес h’200’ помещается в счетчик команд, нарушая обычный процесс инкрементирования, в результате чего ЦПУ перейдет к команде, расположенной по адресу h’200’. Далее изменение счетчика команд снова примет линейный характер.

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

* * *

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

Так что же это такое — микроконтроллер? Кратко говоря, микроконтроллер — это микропроцессор, который объединен с памятью и различными устройствами ввода/вывода в одной интегральной микросхеме. То есть по сути дела это микропроцессор со встроенными вспомогательными узлами. Так что нам придется совершить небольшое путешествие во времени к моменту рождения микропроцессора. Вся эта история началась в 1968 году, когда Роберт Нойс (один из изобретателей интегральных микросхем), Гордон Мур и Эндрю Грув уволились из компании Fairchild Corporation и основали свою собственную компанию, назвав ее Intel. В течение трех лет новая компания освоила выпуск полупроводниковой памяти всех основных типов, используемых в настоящее время, — динамического и статического ОЗУ, а также микросхем EEPROM.

Одним из неосновных направлений деятельности компании была разработка интегральных микросхем большой степени интеграции (БИС) по спецификациям заказчика. В 1970 году к Intel обратились представители японской корпорации Busicom с предложением изготовить подходящий набор микросхем (так называемый чипсет) для линейки калькуляторов. В то время рынок калькуляторов развивался очень динамично, поэтому любые микросхемы пришлось бы менять каждые несколько лет. Естественно, при этом снижалась рентабельность производства БИС и увеличивалась их стоимость. И вот инженеру Тэду Хоффу пришла в голову революционная идея: а почему бы не создать простой ЦПУ на кристалле? Его можно было бы запрограммировать на реализацию функций калькулятора, а для расширения функциональности устройства по мере появления новых требований достаточно будет просто усовершенствовать его программное обеспечение. Все это значительно увеличивало срок жизни такой микросхемы и ее рентабельность. Кроме того, не следует забывать, что основной сферой деятельности компании Intel было производство микросхем памяти, а компьютероподобные архитектуры требуют ее очень много! Это была поистине блестящая мысль. Разумеется, в конце 1969 года японские заказчики одобрили предложение компании Intel, поскольку оно было простым и гораздо более гибким, нежели традиционные решения.

Весной 1970 года в Intel появился Федерико Фаггин, а уже к концу года были изготовлены рабочие образцы первого в мире чипсета. Эксклюзивными правами на его приобретение обладала компания Busicom. Однако к середине 1971 года у нее возникли серьезные финансовые затруднения, и компания Intel, возместив затраты на разработку этого чипсета в размере 65 000 долл., получила права на его продажу всем желающим. В то время рыночные перспективы этого изделия были достаточно туманны, но Intel все же решила рискнуть и опубликовала в ноябрьском номере журнала «Electronic News» за 1971 год рекламу своего «микропрограммируемого компьютера на кристалле», получившего обозначение 4004 (термин микропроцессор вошел в обиход только после 1972 года). Появление процессора 4004 вызвало бурный интерес, поскольку он позволял внедрить «интеллект» в электронную технику.

Микропроцессор 4004 имел фон-неймановскую архитектуру с 4-битной шиной данных и позволял напрямую адресовать до 512 байт памяти. Он работал на частоте 108 кГц и содержал 2300 транзисторов. Годом позже был выпущен 8-битный микропроцессор 8008, работавший на частоте 200 кГц и позволявший адресовать 16 Кбайт памяти. Эта микросхема состояла уже из 3500 транзисторов. Если четырех битов было вполне достаточно для работы с BCD-числами, использующимися в калькуляторах, то 8-битная архитектура уже годилась для создания интеллектуальных терминалов (наподобие кассовых аппаратов), в которых требовалась поддержка разнообразных алфавитно-цифровых символов. В 1974 году на смену 8008 пришел микропроцессор 8080, а в 1976 году появился слегка модифицированный вариант последнего — 8085. Нужно сказать, что 8-битный микропроцессор 8085 до сих пор выпускается компанией Intel.

Идея микропроцессора оказалась настолько удачной, что множество других производителей электронных компонентов тоже поспешили застолбить место на этом рынке. Более того, многие бывшие разработчики открывали собственные компании, взять, к примеру, ту же Zilog. К 1976 году было выпущено или хотя бы анонсировано 54 различных моделей микропроцессоров. Так, родоначальником одного из семейств, имевших наибольший успех на рынке, был микропроцессор 6800, разработанный компанией Motorola. Этот микропроцессор имел ясную и гибкую фон-неймановскую архитектуру, мог работать на частоте 2 МГц и адресовать до 64 Кбайт памяти. В модели 6802 (1977) была даже встроенная память объемом 128 байт и внутренний тактовый генератор. В 1979 году была выпущена усовершенствованная модель 6809, ставшая последним представителем этого семейства 8-битных микропроцессоров. Основными ее конкурентами были такие микропроцессоры, как 8085 компании Intel, Z80 компании Zilog и 6502 компании MOS Technology.

Вообще говоря, изначально микропроцессоры не предназначались для использования в обычных компьютерах. Но в 1975 году небольшая компания — производитель калькуляторов MITS, оказавшись на грани банкротства, совершила рискованный ход и переориентировалась на изготовление и продажу компьютеров. Примитивная вычислительная машина, разработанная инженером Эдом Робертсом (Ed Roberts), была построена на базе микропроцессора 8080 компании Intel. Взаимодействие с оператором осуществлялось посредством переключателей и лампочек, располагавшихся на передней панели, — никакой клавиатуры и монитора. В течение нескольких недель после начала рекламной акции компания получила около 650 предварительных заказов на этот компьютер, названный «Альтаир» (сумма каждого заказа составляла около 400 долл.). В результате вместо долга на сумму 400 000 долл. компания получила прибыль в размере 250 000 долл.

Этот первый персональный компьютер (ПК) породил целое поколение компьютерных фанатов. Так, однажды, в декабре 1975 года, никому доселе не известный 19-летний студент факультета вычислительной техники Гарвардского университета Билл Гейтс (Bill Gates) и зашедший к нему в гости приятель Пол Аллен (Paul Allen) увидели фотографию «Альтаира» на обложке журнала «Popular Electronics» и решили заняться написанием программного обеспечения для этого ПК. Они связались по телефону с Эдом Робертсом и сообщили ему, что у них есть уже почти завершенный транслятор языка Бейсик для «Альтаира» (вообще-то это была, мягко говоря, неправда). Так на свет появилась корпорация Microsoft.

Примерно двумя месяцами позже насколько десятков человек основали в Сан-Франциско своеобразный компьютерный клуб, приобретя в складчину один «Альтаир» на всех. В числе членов этого клуба были Стив Джобс (Steve Jobs) и Стив Возняк (Steve Wozniak). В качестве демонстрации работы клуба они собрали собственный ПК, назвав его «Apple». К 1978 году объем продаж компьютеров «Apple II» составил 700 000 долл.; в течение 1979 года этих компьютеров было продано на сумму 7 млн долл., в следующем году — на сумму 48 млн долл…

Компьютер «Apple II» был построен на базе недорогого микропроцессора 6502 производства компании MOS Technology. Разработчиком этого процессора (и одним из основателей компании) был Чак Педцл (Chuck Peddle), ранее служивший в компании Motorola и отвечавший там за разработку процессора 6800. Неудивительно, что микропроцессор 6502 до боли напоминал это предыдущее детище Чака. Компания Motorola даже подала в суд с требованием запретить продажу микропроцессора 6501, тем более что его цоколевка полностью совпадала с цоколевкой их процессора 6800. Вплоть до конца 70-х годов микропроцессор 6502 оставался одним из основных игроков на рынке ПК, будучи, помимо всего прочего, «сердцем» таких известных в то время компьютеров, как «ВВС Micro» и «Commodore PET».

Основным фактором, реально повлиявшим на популярность компьютера «Apple II», было наличие у последнего пакета программ «VisiCalc» для работы с электронными таблицами. Когда бизнес-сообщество осознало, что ПК — это не просто игрушка и что с его помощью можно решать «реальные» задачи, объем продаж этих компьютеров резко подскочил. То же самое произошло и с компьютерами IBM PC. Этот ПК, представленный компанией IBM в 1981 году, был построен на базе микропроцессора 8088, работавшего на частоте 4.77 МГц. В компьютере имелось ОЗУ объемом 128 Кбайт, два дисковода для дискет объемом 360 Кбайт и монохромный дисплей, работавший в текстовом режиме. В качестве операционной системы в нем использовалась ОС PC/MS-DOS версии 1.0 компании Microsoft. В комплекте с ней поставлялся пакет программ для обработки электронных таблиц «Lotus 1-2-3».

Уровень развития технологии изготовления кремниевых СБИС, достигнутый к концу 70-х, сделал возможным размещение на одном кристалле нескольких десятков и даже сотен тысяч транзисторов. И сразу же перед разработчиками микропроцессоров встал вопрос: каким образом использовать эту возможность? Наиболее очевидным и, соответственно, наиболее популярным направлением совершенствования микроконтроллеров было увеличение разрядности АЛУ и емкости шин/памяти. По этому пути, в частности, пошла компания Intel, выпустив в 1978 году микропроцессор 8086 (16-битный вариант микропроцессора 8085), имевший в своем составе 29 000 транзисторов.

При его разработке особое внимание было уделено программной и аппаратной совместимости с его 8-битным предшественником. С коммерческой точки зрения это было очень мудрым решением, поскольку позволяло удержать многочисленных потребителей процессора 8085 от перехода к изделиям конкурентов. В то же время это решение было весьма неоднозначным с технической точки зрения. Так или иначе, но выпуск этого микропроцессора оказался несколько преждевременным, поэтому в оригинальных компьютерах IBM PC компании IBM использовалась модифицированная версия 8086 — процессор 8088, имевший урезанную 8-битную шину данных и 20-битную шину адреса.

В 1979 году компания Motorola представила свой вариант 16-битного микропроцессора, получившего название 68000, а также его модификацию 68008 с 8-битной шиной данных. Однако внутренняя организация всех этих микропроцессоров была 32-битной, за счет чего удалось обеспечить их совместимость с более поздними моделями, вплоть до выпущенного в 1995 году микропроцессора 68060, а также RISC-процессора ColdFire, появившегося в 1997 году. Микропроцессоры семейства 68000 представляли собой совершенно новую разработку и технически были более прогрессивными по сравнению со своими конкурентами семейства 80x86.

Компания Apple решила использовать процессор 68000 в своих новых ПК «Macintosh». Однако, несмотря на все преимущества этого процессора, объем продаж компьютеров Apple Mac составил менее 5 % от объема продаж IBM PC. Гораздо больших успехов компания Motorola добилась на рынке микропроцессоров для встраиваемых систем — начиная от яйцеварок и заканчивая системами управления самолетов. Конечно же, микропроцессоры изначально были разработаны именно для этой области, поэтому количество микропроцессоров, проданных для использования во встраиваемых системах, более чем на порядок превысило количество, проданное для нужд компьютерного рынка.

В таких устройствах микропроцессор «спрятан» в недрах системы вместе с памятью и различными интерфейсными схемами ввода/вывода. То есть он выступает в роли центрального контроллера, управляя системой в соответствии с программой, зашитой в его памяти программ. Ежегодно для использования во встраиваемых системах продается свыше 3.5 млрд микропроцессоров и сопутствующих микросхем, что составляет более 95 % всего рынка микропроцессоров.

Другое направление совершенствования микроконтроллеров, ставшее возможным в конце 70-х, заключалось в сохранении относительно простого ЦПУ и использовании оставшихся ресурсов кристалла для реализации встроенной памяти и интерфейсов ввода/вывода. Это дало возможность создавать простые встраиваемые системы управления на одной-единственной микросхеме, значительно уменьшая таким образом общее число микросхем, необходимое для реализации заданной функции. Для реализации подавляющего большинства задач управления большой вычислительной мощности не требуется, а вот уменьшение размера готовых устройств и, соответственно, их стоимости крайне желательно. В качестве простого примера можно привести смарт-карту с интегрированным процессором. Такие микропроцессорные устройства получили название микроконтроллеров. Например, в каждом доме, незаметно для нас, обитает несколько сот микроконтроллеров. Они есть повсюду — в бытовой технике, аудио- и видеоаппаратуре, персональных компьютерах, телекоммуникационных устройствах, смарт-картах и, в том числе, в автомобилях.

Если микропроцессор с точки зрения архитектуры (см. Рис. 3.1 и Рис. 3.2) представляет собой только блок центрального процессора, то микроконтроллер уже является законченной самодостаточной компьютероподобной системой. Рассмотрим в качестве примера электронную часть системы контроля автомобильного одометра, которая отображает общий пробег автомобиля с момента изготовления, а также дальность последней поездки (так называемый путевой одометр). Основным входным сигналом системы является сигнал от автомобильного тахометра, который формирует импульсы при каждом обороте маховика двигателя. Подсчитав суммарное количество этих импульсов, можно определить количество оборотов двигателя, а по интервалу между импульсами можно вычислить скорость движения автомобиля. Разумеется, реальный путь, проходимый автомобилем, зависит от передаточного числа коробки передач, поэтому нам необходимо знать о том, какая из пяти передач была включена водителем в каждый момент времени. Эта информация поступает из коробки передач по линиям G5, …, G1 (обычно обозначаемым как G[5:1]). Включенной передаче соответствует напряжение ВЫСОКОГО уровня на соответствующей линии (передача заднего хода не учитывается). Два дополнительных входа предназначены для задания единицы измерения отображаемых значений (мили или километры) и для обнуления путевого одометра.

Собственно дисплей одометра представляет собой семиразрядный 7-сегментный индикатор (см. Рис. 6.8 на стр. 183), который может отображать значения до . Поскольку общее число сегментов довольно велико (целых 49), то для управления индикатором используется сдвиговый регистр (см. Рис. 2.22 на стр. 51), данные в который передаются по одной линии (Рис. 3.8). По второй лини передаются тактовые импульсы — для полного обновления содержимого дисплея необходимо 49 импульсов.

Рис. 3.8. Пример микроконтроллерной системы

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

Для реализации этой системы нам потребуются следующие ресурсы (так называемый бюджет ресурсов):

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

• Семь цифровых входов для ввода текущего передаточного отношения, задания единицы отображения (мили/км) и для сброса путевого одометра.

• Четыре цифровых выхода для тактирования двух сдвиговых регистров и передачи информации о сегментах.

• Микропроцессор для выполнения вычислений, считывания входных сигналов и формирования выходных.

• • Память программ, обычно ПЗУ какого-либо типа.

• Память данных для хранения рабочих переменных программы, обычно статическое ОЗУ.

• Энергонезависимая память для долговременного хранения информации, такой как суммарный путь, пройденный автомобилем, и расстояние, пройденное с момента последнего сброса путевого одометра.

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

• Модули приема/передачи данных по последовательным каналам с использованием разнообразных синхронных и асинхронных протоколов.

• Модули счетчиков/таймеров для подсчета числа внешних событий и формирования цифровых сигналов с точными временными параметрами.

• Модули аналого-цифрового преобразователя для считывания и оцифровки входных аналоговых сигналов.

• Модули цифро-аналогового преобразователя для формирования выходных аналоговых сигналов.

Модули специализированного интерфейса для управления многоразрядными жидкокристаллическими индикаторами (ЖКИ).

Такое использование дополнительных ресурсов кристалла привело к появлению в конце 70-х годов первых микроконтроллеров. К примеру, микроконтроллер Motorola 6801 (35 000 транзисторов), разработанный специально для использования в автомобилях, был построен на базе существующего микропроцессора 6800. Этот микроконтроллер имел ПЗУ программ объемом 2048 байт, ОЗУ данных объемом 128 байт, 29 линий ввода/вывода и 16-битный таймер. После того как микроконтроллеры доказали свою жизнеспособность, все ведущие производители микропроцессоров выпустили на рынок различные семейства микроконтроллеров. Каждое из этих семейств базировалось на определенном ядре, при этом различные представители одного и того же семейства отличались набором периферийных устройств. Например, в семействе 68НС11 компании Motorola (дальнейшее развитие микроконтроллера 6801) было использовано слегка модернизированное ядро 6800. Семейства 68НС12 и 68НС16 имели уже 16-битные ядра, которые, однако, обеспечивали совместимость с предыдущим 8-битным семейством 68НС11. Вскоре выяснилось, что во многих встраиваемых приложениях вовсе не требуются все вычислительные возможности древнего ядра 6800, поэтому было выпущено новое семейство 68НС05, представители которого имели значительно урезанное ядро и, соответственно, меньшую стоимость. Как это ни удивительно, но 4-битные микроконтроллеры, такие как TMS1000 компании Texas Instruments, лидировали по объему продаж среди всех остальных разновидностей процессоров вплоть до начала 90-х (и до сих пор продолжают пользоваться устойчивым спросом). Похоже, что и 8-битным микроконтроллерам, ставшим в последнее время наиболее популярными, в обозримом будущем уготована та же судьба. Кстати говоря, процессор 14500 компании Motorola вообще был однобитным!

В основе всех этих микропроцессоров и микроконтроллеров лежала фон-неймановская архитектура, используемая в универсальных ЭВМ. Альтернативная гарвардская архитектура впервые возродилась в микропроцессоре 8X300 компании Signetics, который в середине 70-х был приспособлен компанией General Instruments для работы в качестве периферийного интерфейсного контроллера (Peripheral Interface Controller — PIC). Компания собиралась использовать этот контроллер как программируемый порт ввода/вывода для своего 16-битного микропроцессора СР1600. После того как в 1988 году компания General Instruments продала свое подразделение интегральных микросхем молодой компании, названной Arizona Microchip Technology, это устройство вновь появилось на свет, но уже в виде самостоятельного микроконтроллера. Именно данному семейству микроконтроллеров и посвящена оставшаяся часть книги.

Примеры

Пример 3.1

Контроллер теплицы должен контролировать аналоговый сигнал от датчика влажности почвы и, если его величина ниже некоторого порогового значения, открывать водяной клапан на пять секунд с последующей 5-секундной паузой. В резервуаре с водой имеется поплавковый датчик, который замыкает контакты при снижении уровня воды ниже порогового значения. В этом случае должен включаться звуковой сигнализатор для индикации тревоги.

Можете ли вы придумать систему на базе микроконтроллера, реализующую указанные функции?

Решение

В решении, приведенном на Рис. 3.9, используется автомобильный одометр с Рис. 3.8. Единственным новым периферийным устройством является аналоговый порт, используемый для считывания и оцифровки аналогового сигнала отдатчика влажности почвы. В основе работы этого датчика лежит зависимость сопротивления почвы от ее влажности. Электроды датчика, включенные последовательно с постоянным резистором, образуют делитель напряжения, выходное напряжение которого будет меняться в зависимости от влажности почвы. Микроконтроллер может преобразовать это аналоговое напряжение в соответствующий цифровой код, который затем будет сравниваться в программе с предустановленным значением. Также порт ввода может представлять собой обыкновенный аналоговый компаратор, формирующий на выходе лог. 1 или лог. 0, если входное напряжение превышает определенное значение, которое может задаваться программно.

Рис. 3.9. Климатический контроллер теплицы

Глядя на Рис. 3.9, мы можем оценить требуемые ресурсы:

• Вход для внешнего генератора, подключенный к счетчику/таймеру. Это необходимо для того, чтобы микроконтроллер мог отсчитывать временные интервалы. На практике такие таймеры очень часто работают от внутреннего тактового сигнала микроконтроллера.

• Один аналоговый вход для измерения уровня аналогового сигнала от датчика влажности.

• Один цифровой вход для контроля уровня воды в резервуаре.

• Один цифровой выход для открытия и закрытия водяного клапана.

• Один цифровой выход для управления звуковым сигнализатором.

• Микропроцессор для вычислений, считывания входных и формирования выходных сигналов.

• • Память программ, обычно ПЗУ какого-либо типа.

• Память данных для хранения рабочих переменных программы, обычно статическое ОЗУ.

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

Пример 3.2

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

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

Решение

1. Подойти к переходу и остановиться.

2. Посмотреть на светофор.

3. Принять решение — не горит ли в нашем направлении зеленый сигнал?

4. ЕСЛИ сигнал красный, ТО перейти к шагу 2, ИНАЧЕ продолжить.

5. Посмотреть налево.

6. Едут ли машины?

7. ЕСЛИ да, ТО перейти к шагу 5, ИНАЧЕ продолжить.

8. Посмотреть направо.

9. Едут ли машины (вообще-то все машины уже должны были остановиться, но кто знает!)?

10. ЕСЛИ да, ТО перейти к шагу 5, ИНАЧЕ продолжить.

11. Перейти через дорогу — задача решена!

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

Рис. 3.10. Блок-схема алгоритма перехода через дорогу

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

Разумеется, робот не будет иметь ни малейшего понятия о том, что ему делать после перехода на другую сторону, если только мы не сообщим ему об этом. Что же касается человека, то он уже, образно говоря, «запрограммирован» — у него есть опыт!

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

Вопросы для самопроверки

3.1. Можете ли вы предложить вариант инкрементирования и декрементирования содержимого рабочего регистра, показанного на Рис. 3.4, с использованием трех команд, рассмотренных в этой главе?

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

3.3 Компьютер BASIC, структура которого изображена на Рис. 3.4, может одновременно осуществлять выборку одной команды и исполнять другую команду. Объясните, за счет чего он может выполнять эти операции параллельно.

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

3.5. Для подключения коробки передач к микроконтроллерной системе, показанной на Рис. 3.8, требуется пять выводов микросхемы. Многие микроконтроллеры выпускаются в корпусах с малым числом выводов (см., например, Рис. 10.2 на стр. 304). Подумайте, как можно уменьшить требуемое число выводов, а также будет ли ваше решение экономически оправданным? Подсказка: взгляните на Рис. 2.6 (стр. 36).

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