3.2. Разработка и отладка многомодульных программ
3.2.1. При разработке МК могут быть использованы два способа организации прикладных программ: монолитный и модульный. При первом способе вся прикладная программа МК разрабатывается как единое целое, а при втором строится из отдельных программных блоков, каждый из которых реализует некоторую процедуру обработки данных или управления. Взаимосвязь блоков определяется разработчиком при монтаже из этих блоков блок-схемы алгоритма (БСА) законченной прикладной программы.
Отдельные фрагменты прикладной программы МК могут быть получены в виде линейной последовательности блоков, другие (многократно используемые) обычно оформляются в виде подпрограмм, к которым прикладная программа, называемая основной, имеет возможность обращаться по мере необходимости. Подпрограмма должна обладать следующими свойствами: выполнять заложенную процедуру обработки данных, иметь только один вход и один выход.
Обращение к подпрограмме осуществляется по команде вызова CALL MARK, где MARK – символическое имя процедуры. Имя процедуры используется в качестве метки, отмечающей одну из команд (чаще всего первую) подпрограммы.
Для успешной работы любой подпрограммы необходимо однозначно определить способ передачи в нее исходных данных и способ вывода результатов ее работы. Подпрограмма, которой требуется дополнительная информация в виде параметров ее настройки или операндов, называется параметризуемой. Примером параметризуемой программы может служить подпрограмма временной задержки, если основной программе требуется реализация временных задержек различной длительности. Основная программа при этом должна обеспечить передачу в подпрограмму уставок, обеспечивающих требуемое время задержки.
Получили распространение три способа передачи параметров: через память, через регистры общего назначения и через регистр флагов.
Использование процедур, оформленных в виде подпрограмм, при разработке программного обеспечения имеет ряд достоинств. Прежде всего, относительно простые модули, выделенные из сложной программы, могут программироваться несколькими разработчиками с целью сокращения времени проектирования. Еще более важным является то, что любая подпрограмма допускает автономную отладку. Это, как правило, многократно сокращает время отладки всего прикладного программного обеспечения. И, наконец, механизм использования подпрограмм, реализующих требуемый набор процедур, уменьшает длину прикладной программы, что приводит к уменьшению требующейся емкости памяти программы.
Существенным является и то обстоятельство, что отлаженные процедуры часто организуются разработчиками в библиотеки подпрограмм и могут быть многократно использованы в проектной работе.
3.2.2. Разработка и ассемблирование многомодульной программы. Рассмотрим процесс разработки многомодульной программы на следующем примере.
Микроконтроллер должен вводить 8-разрядный двоичный код из объекта контроля, полученный помощью АЦП, через порт ввода, запоминать этот код в ОЗУ и выводить код в десятичном формате на дисплей из семисегментных индикаторах. Так как двоичный код может изменяться от 0 до FFH, это соответствует десятичному эквиваленту от 0 до 255. Поэтому дисплей должен иметь 3 индикатора. Структурная схема микроконтроллера, выполняющего рассмотренные функции, приведена на рис.1. Индикатор HG1 предназначен для вывода единиц десятичного кода (цифра ц1), индикатор HG2 – для вывода десятков (ц2), а HG3 – для сотен (ц3). Выходные буферы предназначены для сопряжения выходов портов вывода с индикаторами (усиление по току или согласование уровней напряжения). В ПЗУ находится программа работы МК, в ОЗУ хранятся промежуточные данные, и располагается стек.
Блок-схема алгоритма программы работы МК приведена на рис.2. Программа использует две подпрограммы: PR810 – для преобразования двоичного числа в двоично-десятичное и CROSSCOD – для получения семисегментного кода. Результатом работы подпрограммы PR810 будет трехразрядное десятичное число в упакованном формате, которое размещается в регистровой паре HL, как это показано на рис.3. Обычно в программах на языке ассемблера портам и ячейкам памяти, которые используются в командах, даются символические имена. Это облегчает чтение программы, позволяет быстро вносить в нее изменения. В рассматриваемой программе порту ввода присвоено имя IPORT, портам вывода – имена OPORT1, OPORT, OPORT3. Ячейка ОЗУ, предназначенная для хранения входного кода, имеет имя SAVE. Начальный адрес массива для хранения десятичных цифр ц1, ц2, ц3 имеет имя BASE. Десятичные числа в этом массиве хранятся в неупакованном формате: в младшей тетраде байта находится цифра, а в старшей тетраде – нули. Ячейка с именем STACKTOP является начальным адресом стека (вершиной стека).
В рассматриваемом МК используется небольшое ОЗУ объемом 512 байт. Начальный адрес ОЗУ равен 0800H, конечный адрес 09FFH. На рис.4. приведена карта ОЗУ. Показаны ячейки, используемые в программе, их символические имена и действительные адреса в HEX-коде.
Из анализа блок-схемы алгоритма на рис.2 следует, что программа работы МК будет состоять из трех модулей: главной программы и двух подпрограмм (PR810 и CROSSCOD), которые вызываются из нее. Назовем главную программу именем MAIN (от англ. главный).
При разбиении программного обеспечения на отдельные модули в них могут появиться метки и переменные, определяемые в других модулях. Все метки и символические имена, к которым осуществляется обращение в данном модуле, но определяемые вне его, должны быть указаны через запятую в псевдокоманде (директиве ассемблера) EXTERN (внешние). Все метки и имена переменных, определяемые в данном модуле и используемые также вне этого модуля, должны быть указаны через запятую в псевдокоманде PUBLIC (общие). Таким образом, метки и имена, применяемые для связи между модулями, могут быть указаны в псевдокоманде PUBLIC только в одном модуле. В остальных модулях они указываются в псевдокомандах EXTERN.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.