Юрий Ревич - Занимательная электроника
Для обеспечения работы трехстабильного порта по схеме «монтажное ИЛИ» применяют хитрый прием: всю линию «подтягивают» к напряжению питания с помощью внешнего резистора (во многих МК существует встроенный отключаемый резистор, установленный аналогично R1 в схеме рис. 18.3, а), и нормальное состояние всех участвующих трехстабильных портов — работа на вход в третьем состоянии. В этом режиме на линии всегда будет логическая единица. На выход же линию переключают только, когда надо выдать логический ноль. В этом случае, даже при одновременной активности нескольких портов, конфликтов не возникнет.
Лечение амнезииВ 1965 году в Иллинойсском университете был запущен один из самых передовых компьютеров по тому времени — ILLIAC–IV. Он стал первым компьютером, в котором использовалась быстрая память на микросхемах, — каждый чип (производства Fairchild Semiconductor) имел емкость 256 битов, а всего было набрано 1 Мбайт. Стоимость этой памяти составила ощутимую часть от всей стоимости устройства, обошедшегося заказчику — NASA — в $31 млн. Через 10 лет один из первых персональных компьютеров Altair 8800 (1975 год), продававшийся в виде набора «сделай сам», при стоимости порядка $500 имел всего 256 байтов (именно байтов, а не килобайт) памяти. В том же году для распространения языка Basic for Altair Биллом Гейтсом и Полом Алленом была создана фирма, получившая первоначальное название Micro-Soft. Одна из самых серьезных проблем, которую им пришлось решать, — нехватка памяти, потому что созданный ими интерпретатор Basic требовал аж 4 Кбайт!
Проблема объемов памяти и ее дороговизна преследовала разработчиков достаточно долго — еще в конце 1990-х стоимость памяти для ПК можно было смело прикидывать из расчета 1 доллар/Мбайт, что при требовавшихся уже тогда для комфортной работы объемах ОЗУ порядка 128–256 Мбайт могло составлять значительную часть стоимости устройства. Сейчас 4 гигабайта памяти в настольном ПК или ноутбуке уже стали фактическим стандартом. Это привело, в частности, к кардинальным изменениям в самом подходе к программированию — если еще при программировании под DOS о компактности программ и экономии памяти в процессе работы нужно было специально заботиться, то теперь это практически не требуется.
Но в программировании для микроконтроллеров это все еще не так. Хотя гейтсовский интерпретатор Basic влезет в большинство современных однокристальных МК, но экономная программа легче отлаживается (а, значит, содержит меньше ошибок) и быстрее выполняется. Три-четыре потерянных на вызове процедуры такта могут стать причиной какой-нибудь трудновылавливаемой ошибки времени выполнения — например, если за это время произойдет вызов прерывания. Поэтому память в МК стоит экономить, даже если вы располагаете заведомо достаточным ее объемом. Этот призыв, конечно, пропадает впустую, когда мы сталкиваемся с программированием на языках высокого уровня, где от нас зависит гораздо меньше, чем от разработчиков компиляторов.
Далее мы рассмотрим основные разновидности памяти, используемые как в составе микроконтроллеров, так и во внешних узлах. И начнем с того, что попробуем сами сконструировать устройство долговременной памяти — ПЗУ (постоянное запоминающее устройство). Как мы увидим, любая память в принципе есть не что иное, как преобразователь кодов.
Изобретаем простейшую ROMВсем известно сокращение ROM — Read-Only Memory — английское название постоянного запоминающего устройства, ПЗУ. На самом деле это название (память только для чтения) не очень точно характеризует суть дела, отечественное название есть более корректный термин, самое же правильное называть такую память энергонезависимой. Ведь ПЗУ отличается от других типов памяти не тем, что его можно только читать, а записывать нельзя (практически все современные устройства ROM имеют возможность записи), а тем, что информация в нем не пропадает при выключении питания.
Тем не менее, первыми разновидностями ПЗУ, изобретенными еще в 1956 году, были именно нестираемые кристаллы, которые носят наименование ОТР ROM — One-Time Programmable ROM, однократно программируемое ПЗУ. До недавнего времени на них делали память программ МК для удешевления серийных устройств — вы отлаживаете программу на перезаписываемой памяти, а в серию пускаете приборы с «прожигаемой» ОТР ROM. И лишь в последние годы «прожигаемая» память стала постепенно вытесняться более удобной flash-памятью, поскольку последняя подешевела настолько, что смысл в использовании одноразовых кристаллов пропал.
Мы сконструируем подобие «прожигаемого» ПЗУ с помощью диодов. Простейший вариант такого ПЗУ показан на рис. 18.4. В данном случае он представляет собой не что иное, как преобразователь из десятичного кода в семисегментный. Если на входе поставить дешифратор типа 561ИД1, переводящий двоичный код в десятичный, то мы получим аналог микросхемы 561 ИД5.
Рис. 18.4. Простейшее ПЗУ — преобразователь кода
Чтобы понять, как это работает, представьте себе, что первоначально на всех пересечениях между строками и столбцами диоды присутствовали — это аналог незаполненной памяти, в которой записаны все единицы. Затем мы взяли и каким-то образом (например, подачей высокого напряжения) разрушили те диоды, которые нам не нужны, в результате чего получили нужную конфигурацию.
Эта схема не содержит активных элементов, и потому возможности ее ограниченны, — например, выходы устройства, подающего активный высокий уровень по входным линиям, должны «тащить» всю нагрузку по зажиганию сегментов. Обычная микросхема ПЗУ построена на транзисторных ячейках и поэтому без всяких хитростей принимает и выдает обычные логические уровни. К тому же она включает в себя и дешифрирующую логику, поэтому на вход подается двоичный, а не десятичный код.
Постойте, а причем тут ПЗУ вообще? Дело в том, что входной код здесь можно рассматривать, как адрес ячейки, в выходной — как ее содержимое. И любое ПЗУ можно представить, как универсальный преобразователь кодов. Причем удобство состоит в том, что изначально в ПЗУ не записано ничего (одни нули или единицы), и мы можем реализовать на нем любую логическую функцию — все зависит только от его емкости. В том числе, такую простую, как преобразователь кодов десятичный-семисегментный, или же такую сложную, как операционная система Windows.
Последнее мы каждый раз и делаем, когда устанавливаем Windows на компьютер, причем в качестве ПЗУ выступает жесткий диск. Из этого примера отчетливо видно, что каким бы сложным ни был алгоритм, он все равно в конечном итоге сводится к совокупности однозначных логических уравнений, которые можно реализовать как через ПЗУ с записанной программой, так и с помощью цифрового устройства любого другого типа.
Общее устройство памятиОбщее устройство фрагмента памяти любого типа показано на рис. 18.5.
Рис. 18.5. Схематическое устройство ЗУ с однобитным последовательным выходом
Из рисунка видно, что память всегда представляет собой матричную структуру. В данном случае матрица памяти имеет 8x8 = 64 однобитных ячейки. Рисунок 18.5 демонстрирует, как производится вывод и загрузка информации в память с помощью мультиплексоров/демультиплексоров (вроде 561КП2, см. главу 15). Код, поступающий на мультиплексор слева (х3 - х5), подключает к строке с номером, соответствующим этому коду, активирующий уровень напряжения (это может быть логическая единица, как показано на рисунке, или ноль, неважно). Код на верхнем демультиплексоре (х0 - х2) выбирает столбец, в результате к выходу этого демультиплексора подключается ячейка, стоящая на пересечении выбранных строки и столбца.
Легко заметить, что сама по себе организация матрицы при таком однобитном доступе для внешнего мира не имеет значения. Если она будет построена как 4х16, или 32x2, или даже вытянута в одну линеечку 64x1 — в любом случае код доступа (он называется адресным кодом) будет 6-разрядным, а выход один-единственный. Поэтому всем таким ЗУ приписывается организация TVxl бит, где N — общее число битов. Для того чтобы получить байтную организацию, надо просто взять 8 таких микросхем и подать адресный код на них параллельно, тогда на выходах получим параллельный восьмибитный код, соответствующий байту. Общая емкость такой памяти составит 64 х 8 = 512 битов или 64 байта. У нас получается хорошая модель типового модуля памяти, вроде тех, что используются в компьютерном ОЗУ.