Проблемы быстрой реакции на события решаются организацией системы прерываний. Она подразумевает, что для каждого такого события разрабатывается отдельный «кусок» кода, который формирует реакцию МК на него. Этот «кусок» кода называют подпрограммой обработки запроса на прерывание (для краткости часто используют термин подпрограмма прерывания) и размещают в памяти программ по известному адресу. В момент возникновения заданного события сигнал об этом поступает на вход контроллера прерываний. Последний представляет собой устройство, устанавливающее однозначное соответствие между входным сигналом о происшедшем событии и адресом программной памяти, по которому размещена точка входа в подпрограмму обработки запроса прерывания от данного события. Контроллер прерывает выполнение ЦП текущей программы и инициирует его переход на выполнение подпрограммы обработки прерывания. Время, прошедшее с момента возникновения события до начала выполнения первой инструкции подпрограммы прерывания, называют временем реакции МК на событие. После окончания обработки ЦП автоматически возвращается к выполнению прерванной программы.
Другая функция контроллера прерываний – установка приоритетов событий. Понятие приоритет означает, что выполняемая подпрограмма прерывания может быть прервана другим событием только при условии, что оно имеет более высокий приоритет, чем текущее. В противном случае ЦП перейдет к обработке нового события после окончания обработки предыдущего. Контроллер прерываний, входящий в состав МК 8051, имеет пять входов событий: два от внешнихустройств, два от таймеров и один от последовательного канала.
Обычно, когда говорят о каком-либо МК, то всегда упоминают семейство, к которому он принадлежит. К одному семейству относят изделия, имеющие одинаковое ядро, под которым понимают совокупность таких понятий, как система команд, циклограмма работы ЦП, организация памяти программ и памяти данных, система прерываний и базовый набор периферийных устройств. Фактически на рис. 1представлено ядро, ставшее основой для создания сотен других модификаций семейства 8051.
Отличия между его различными представителями заключаются, в основном, в составе периферийных устройств и объёме памяти программ или данных. Поскольку диапазон задач, решаемых МК, чрезвычайно широк, их производители стараются выпустить столько модификаций, чтобы удовлетворить самые разнообразные запросы потребителей. Во многих семействах число модификаций приближается к сотне или даже превышает это значение.
Наиболее важная особенность семейства – программная совместимость на уровне двоичного кода всех входящих в него МК. Это позволяет разработчикам систем заменять одни МК семейства другими без потери наработок своего программного обеспечения. Естественно, чем большее число разновидностей входит в семейство, тем больше шансов выбрать оптимальный вариант, тем привлекательнее это семейство для разработчика. Вопрос правильного выбора семейства МК для новой разработки является стратегическим, так как проблема переноса программного обеспечения между изделиями разных семейств чрезвычайно сложна и даже использование языков высокого уровня не всегда позволяет решить её без больших потерь. К вопросу о критериях выбора мы вернемся в следующих статьях цикла.
Разработка программы – один из наиболее важных этапов в создании устройства на базе МК. Без неё он «мёртв», не реагирует на внешние воздействия и не выдаёт управляющих сигналов.
При включении питания МК немедленно начинает исполнять программу, находящуюся в подключенной к нему памяти программ (обычно это ПЗУ). Её выполнение начинается с некоторого фиксированного адреса, чаще всего нулевого. Адрес – это просто номер ячейки ПЗУ. Процесс осуществляется следующим образом: МК считывает число, хранящееся в памяти программ, и в зависимости от его значения, называемого машинным кодом, выполняет определённые действия над содержимым регистров АЛУ, памяти, портов и т.д. Например, прочитав из памяти программ число 32Н, МК «соображает», что нужно считать значение из входного порта номер 2 и поместить его в регистр-аккумулятор. Часто одного байта для описания действия МК не хватает, и тогда МК считывает из памяти дополнительные байты.
После выполнения действия МК считывает значение из следующей по порядку ячейки памяти и т.д. Совокупность байтов, описывающих одно выполняемое МК действие, называют машинной командой (инструкцией), а совокупность таких команд, которые «понимает» МК, – его системой команд или набором инструкций (InstructionSet). МК разных семейств имеют разные системы команд, то есть машинные коды у них имеют разные значения, хотя и выполняют похожие действия.
Итак, программа для МК представляет собой последовательность чисел, значения которых указывают ему, какие действия выполнять. Результатом разработки программы является компьютерный файл, содержащий эти машинные коды. С помощью программатора ПЗУ его заносят («зашивают») в память программ МК.
Каким же образом составляется эта последовательность машинных кодов – программа для МК? Неужели разработчику необходимо помнить значения машинных кодов и вручную задавать их последовательность? Первые программы для МК создавались именно так, и называлось это программированием в машинных кодах. Ясно, что такой способ разработки программ очень трудоёмок и неэффективен.
Первым шагом в облегчении процесса создания программ была компьютерная программа – так называемый транслятор с языка ассемблера. Идея состояла в том, чтобы выражать выполняемые МК действия на более понятном человеку языке и затем преобразовывать эти выражения в машинные коды. В приведённом выше примере машинной инструкции, которая считывает значение порта 2 и помещает его в аккумулятор, выполняемые действия можно условно обозначить как MOVA, P2.
Здесь слово MOV (от англ. move), называемое мнемоникой инструкции, обозначает пересылку значения, а A и P2, именуемые операндами, указывают, откуда взять значение и куда его поместить. Система подобных обозначений называется языком ассемблера. Программа, написанная на нём, обрабатывается транслятором, который преобразует конструкции языка ассемблера в машинные коды.
Программирование на ассемблере широко распространено по сей день. Трансляторы с языка ассемблера для всех популярных семейств микроконтроллеров бесплатны.
Несмотря на очевидные преимущества программирования на ассемблере перед программированием в машинных кодах, во многих случаях ассемблер недостаточно эффективен для реализации задач разработчика. Дело в том, что МК способен выполнять лишь простейшие действия вроде арифметических операций над целыми числами, пересылок, сравнений и т.п. Для более сложных задач, например, для операций над числами с плавающей запятой, разработчикам приходилось писать специальные подпрограммы, пользоваться которыми неудобно и громоздко. Следующим шагом в разработке программ для МК стало создание специальных компьютерных программ – трансляторов с языков программирования высокого уровня, или компиляторов. Наибольшее распространение получил язык программирования Си.
С появлением трансляторов разработка программ для МК резко упростилась. Если, например, нужно сложить в программе два числа, то теперь достаточно просто написать
a=b + c;
а транслятор преобразует это выражение в необходимую последовательность машинных команда зависимости от типов переменных a, b и c.
Использование языка высокого уровня позволяет разработчику отвлечься от системы команд конкретного МК и оперировать более простыми и понятными человеку категориями. От разработчика требуется только знание общей архитектуры МК, принципов работы необходимых для решения поставленной задачи встроенных периферийных устройств и навыки программирования на языке Си. Функциональное наполнение программы реализуется с помощью средств языка Си, который содержит большое число разнообразных подпрограмм (функций): арифметических, для работы с символьными строками и многих других.