Главная | |
Материал взят из книги![]() Скачать оригинал КНИГИ в хорошем качествеПроцедура динамической индикации Как уже много раз говорилось, процедура динамической индикации, по сути дела, является процедурой обработки прерывания от счетчика/таймера ТО. Счетчик/таймер настраивается таким образом, что прерывание вызывается с постоянным периодом, равным 20 мс. В результате частота смены изображения на индикаторах равняется 50 Гц. Это самая минимальная частота, при которой человеческий глаз еше не видит мельканий. Блок-схема алгоритма процедуры динамической индикации приведена на рис. 48. Рассмотрим подробнее этот атгоритм. Описываемая процедура, как и любая процедура обработки прерывания, начинается с сохранения содержимого рабочих регистров в стековой памяти. Причем сохраняются только те регистры, которые текущая процедура будет использовать для своих целей. В конце процедуры содержимое всех сохраненных регистров восстанавливаются. Основная часть процедуры начинается с проверки условия. То есть прямо с самого начала алгоритм разветвляется. Дальнейший ход выполнения программы зависит от того, в каком из двух режимов работы находится позиционер в данный момент: 11-------- ,.------^ основной части режима. Как вид-рис. 48, в основ-процедура также /етдве параллель-з ветвей соответ-боты программы. : этих фаз следу-1ужит для вывода икатора, а вторая пего. Программа 1у из этих ветвей, гствует текущей следующем вызо-ической индика-ждом запросе на за ТО, фаза меня-ультате две фазы ![]() В каждой фазе, кроме основных команд, связанных с выводом информации на индикатор, выполняются дополнительные действия. В первой фазе дополнительно выполняется блок команд, осуществляющий опрос клавиатуры. В ходе этого опроса считывается код состояния клавиатуры и помещается в буфер клавиатуры. Сразу после опроса клавиатуры, происходит вывод символа в старший разряд индикатора. Код, соответствующий этому символу, помещается в порт РЗ и находится там все время, пока таймер ТО не отсчитает положенную задержку и не вызовет процедуру динамической индикации очередной раз. При этом, благодаря дешифратору ЭОЗ и ключу УТ4, изображение высвечивается на индикаторе НЫ. Во второй фазе в качестве дополнительной операции включены ряд команд, которые производят вывод управляющего сигнала на двигатель. К этому времени код управляющего сигнала уже хранится в буфере управления мотором. Программа лишь извлекает его оттуда и записывает во внешний регистр 004. Затем программа выполняет свое основное действие. Она выполняет вывод в младший разряд индикатора. В этом случае код, соответствующий выводимому символу, также хранится в регистре РЗ. Однако высвечивается он на индикаторе НЬ2. Старший разряд будет высвечиваться также все время, пока таймер ТО отсчитывает очередную задержку. Теперь остановимся немного на дежурном режиме. В дежурном режиме выполнение процедуры пойдет по-другому, гораздо более короткому пути. Вывод символов на экран и управление мотором в этом режиме не производятся. Мотор будет остановлен, а индикаторы потушены. Посмотрите на рис. 48. Ветвь дежурного режима начинается с ответа «нет» в самом первом модуле принятия решений. Она содержит всего два элемента. Первый из них осуществляет проверку нажатия клавиши 57. Если клавиша не нажата, то вся процедура сразу переходит к своему завершению. Если клавиша оказалась нажатой, то моментального перехода к выполнению команд основного режима не происходит. Программа лишь устанавливает флаг, управляющий режимами работы в положение, соответствующее основному режиму, и на этом завершается. И лишь при следующем вызове процедуры динамической индикации ее выполнение пойдет по основной ветви алгоритма. Рассмотренный выше алгоритм описывает работу программы лишь в общих чертах. На самом же деле алгоритм намного сложнее. Прежде, чем перейти к рассмотрению текста программы этой процедуры, я хотел бы уточнить некоторые подробности. Начнем с механизма вызова прерывания. Счетчик/таймер в выбранном режиме работы считает поступающие на его вход импульсы от внутреннего генератора. Каждый такой импульс увеличивает значение регистра ТО. После того, как значение этого регистра достигнет максимально возможного (ОРТРБН), следующий счетный импульс вызовет переполнение. Переполнение счетчика/таймера послужит запросом на соответствующее прерывание. В нашем случае будет вызвана процедура динамической индикации. Первое, что должна сделать вызванная процедура, это заново записать в регистр ТО значение коэффициента пересчета. Это нужно для того, чтобы следующий вызов прерывания произошел через такой же промежуток времени, что и предыдущий. Еще один момент, о котором нужно рассказать подробнее, это метод вывода символов на индикатор. Индикатор позиционера, кроме цифр, обозначающих номер текущего выбранного канала, должен отображать различные служебные символы. Это могут быть некоторые буквы и специальные знаки. В общем случае желательно предусмотреть вывод любых знаков, которые способен отобразить семисегментный индикатор. Весь набор символов для вывода на экран продумывается заранее. Каждому символу присваивается свой рабочий код. Удобно, чтобы рабочие коды символов, отображающих цифры, соответствовали самим отображаемым цифрам. То есть символ, отображающий единицу, должен иметь рабочий код 1. Символ двойки — код 2, и так далее. Остальным символам присваиваются все оставшиеся коды, от 10 и выше. Рабочие коды для символов мы присваивали из соображений удобства обработки. Однако для каждого символа существует еще один код — код вывода. Это тот самый код, который нужно вывести в порт РЗ для того, чтобы на индикаторе высветился соответствующий символ. Код этот определяется очень просто. Каждый разряд порта РЗ подключен к своему сегменту индикатора. Как видно из схемы (рис. 44) ноль в соответствующем разряде кода вывода вызовет зажигание соответствующего сегмента индикатора, а единица потушит соответствующий сегмент. Основная программа работает с рабочими кодами. Именно их она записывает в буфер экрана. Такой способ кодировки позволяет легко вычислять требуемый код. Однако при выводе на индикатор необходима перекодировка. Вместо рабочего кода символа на индикатор нужно вывести соответствующий код вывода. Для перекодировки кода символа в код вывода применяется кодировочная таблица. Таблица хранится в программной памяти микроконтроллера вместе с управляющей программой. Таблица представляет собой часть программной памяти, куда помещены коды вывода всех символов. Причем коды помещены в таблицу таким образом, что соответствующие им символы располагаются в порядке возрастания их рабочих кодов. Фрагмент №8 текста программы позиционера представляет собой то самое место этой программы, где описывается таблица перекодировки символов. Для описания кодов таблицы применяется оператор описания данных DB. Суть этого оператора в том, что он помещает в текущий сегмент памяти процессора один или несколько кодов. Коды, которые нужно поместить в выбранное место памяти, указываются в правой части оператора в качестве его параметров. Оператор может содержать любое число параметров. Их количество ограничено лишь разумной длиной строки. Слишком много параметров указывать просто неудобно. Проще в новой строке поставить еще один оператор DB и продолжить нужную последовательность. Все параметры должны разделяться запятой. Каждый из параметров представляет код, который нужно поместить в очередную ячейку памяти. Код может быть задан в любой допустимой форме: десятичной, шестнадцатеричной, двоичной. Вот пример применения оператора DB для записи в память пяти различных кодов: DB 10, 12, 0F3H, 001101В, 105Н Кроме того, коды могут задаваться в символьном виде. В этом случае в память помещаются ASCII-коды соответствующих символов. При таком способе задания кодов символьные строки заключаются в кавычки: DB “Proba”, "Test” Однако в программе позиционера символы в ASC11-кодировке не применяются и описываемый метод определения констант не используется. Но вернемся к нашей таблице символов. Посмотрите внимательно на фрагмент №8. Описание таблицы начинается с оператора ORG. Оператор ORG помещает указатель текущего сегмента в адрес 0700Н. Текущим сегментом является программная память микроконтроллера. Это приводит к тому, что первый из операторов DB поместит свой код в программной памяти по адресу 700Н. Таким образом, таблица символов всегда будет находиться по фиксированному адресу. ![]() ![]() В начале таблицы стоит метка Шсйг. Эта метка будет использоваться для доступа к таблице в процедуре перекодировки. Коды из таблицы извлекаются по их порядковому номеру. Например, для того, чтобы вывести на индикатор символ «Р» с рабочим кодом, равным 18, нужно извлечь код из восемнадцатой ячейки от начала таблицы и поместить его в порт РЗ. Очевидно, адрес ячейки, в которой находится код вывода указанного символа, вычисляется как Й>с11Г+18. Все коды вывода для удобства восприятия заданы в двоичной форме. Такая форма записи дает возможность сразу увидеть состояние каждого бита. В конце таблицы символов имеется еще один оператор, который описывает константу попе. Эта константа имеет прямое отношение к .таблице символов. Константа попе записывается в порт РЗ тогда, когда требуется выключить индикатор. В процедуру динамической индикации включено еще несколько вспомогательных операций. Это специальные операции, служащие для организации трех программных счетчиков. Мы уже частично упоминали о некоторых из них. Первый из счетчиков служит для формирования периода мерцаний в режиме записи. Второй служит для формирования времени индикации спецсимволов. А тре(тий задает время удержания кнопки «Запись/стирание», необходимое для включения режима стирания. Все вышеперечисленные виды задержки относятся к разряду сверхдлинных (по сравнению с задержками, формируемыми при помощи системных таймеров). Такие задержки сформировать при помощи таймеров невозможно. Шестнадцать разрядов для этого слишком мало. Поэтому, для формирования таких интервалов удобнее использовать программные счетчики, с управлением от процедуры динамической индикации. Процедура динамической индикации вызывается с постоянным периодом, примерно равным 50 Гц. Поэтому, если при каждом вызове процедуры будет производиться итерация (увеличение или уменьшение на единицу) содержимого регистра счетчика, то работа такого счетчика будет строго синхронизирована во времени. И последняя тонкость, о которой хотелось бы упомянуть перед тем, как перейти к рассмотрению текста программы. В реальной программе алгоритм дежурного режима немного отличается от алгоритма, изображенного на рис. 48. Основные операции в этом режиме полностью не прекращаются. Просто они идут в немного измененном виде. Программа опрашивает состояние клавиатуры, производит вывод управляющего сигнала на мотор. Работает даже вывод символов на индикатор. Правда в этом случае в оба разряда индикатора выводится символ с рабочим кодом ЮН. Это так называемый символ пробела. При выводе этого символа все сегменты индикатора гаснут. В качестве управляющего сигнала мотора выводится сигнал «Стоп» (ООН). А программа опроса клавиатуры используется только для того, чтобы проверить состояние всего лишь одной кнопки. Кнопки 57. Теперь обратимся к тексту процедуры динамической индикации. Этот текст приведен ниже (см. фрагмент №9). ![]() ![]() ![]() Процедура начинается с сохранения содержимого регистров в стековой памяти. Для этого используются оператор push. Каждый такой оператор помещает в стек содержимое одного из регистров контроллера. Команда push PSW сохраняет в стеке содержимое регистра флагов. Команда push ACC сохраняет в стеке содержимое аккумулятора. АСС — это второе название регистра аккумулятора. Это название применяется в том случае, когда к аккумулятору обращаются, как к ячейке памяти. Две последующие команды сохраняют по очереди каждую из двух половинок шестнадцатиразрядного регистра DPTR. Регистры общего назначения не могут быть сохранены в стековой памяти. Таких команд в описываемом микроконтроллере не предусмотрено. Поэтому сразу после сохранения регистров программа выполняет переключение банков РОН. Переключение делается очень просто. При помощи команды mov PSW,#bankl в регистр флагов записывается константа, значение которой соответствует нужному банку. Еще на этапе предварительной разработки банки РОН были распределены между основными процедурами. Для процедуры динамической индикации было решено использовать банк номер 1. За командой выбора банка следует команда перезапуска таймера. Для этого в старп1ую половину регистра таймера ТО записывается старший байт коэффициента пересчета, соответствующего задержке в 20 мс. Так как в данном случае не требуется высокой точности в отработке задержки, младший байт коэффициента пересчета не загружается. Далее идет команда проверки флага flonoff. Этот флаг служит для переключения позиционера из основного режима в дежурный. В зависимости от значения этого флага программа либо выполняет ветвь дежурного режима, либо обходит ее. В том случае, если значение флага равно нулю, перехода не происходит и программа начинает переходить к обработке дежурного режима. Ветвь дежурного режима. Эта часть программы начинается с проверки значения буфера клавиатуры. Причем программу интересует только бит 7 записанного там числа. Если этот бит равен нулю, то это означает, что кнопка S7 еще не отпущена после того, как она была нажата для включения дежурного режима. Пока это так, программа будет обходить остальные команды дежурного режима. То есть дежурный режим включится только после отпускания кнопки S7. Вся операция оценки состояния кнопки S7 выполняется в две команды. Сначала значение кода состояния клавиш помещается в аккумулятор. Затем применяется команда условного перехода (jib). Такая команда вызывает передачу управления в том случае, если проверяемый бит равен нулю. Выражение acc.bitonof позволяет обратиться к биту номер ЬйопоГ аккумулятора. Как мы уже говорили ранее, константа ЬкопоГ равна 7 и специально введена для того, чтобы описать номер бита, связанного с кнопкой «Вкл/Выкл». Основная часть ветви обработки дежурного режима занимается ожиданием нажатия кнопки «Вкл/Выкл». Для этого в эту часть программы включена своя собственная процедура чтения состояния клавиатуры. Процедура чтения начинается с команд подготовки схемы позиционера к этому режиму. В порт р1 записывается код ЗЯН. Два старших разряда такого числа равны нулю. Эти два нуля поступают на дешифратор ЭИЗ (см. рис. 44) и переключат его в режим выбора клавиатуры. Затем в порт рЗ записывается код ОРТН. В результате все выходы порта установятся в единичное состояние, и порт подготавливается к работе в режиме ввода. Следующая команда читает состояние клавиатуры из порта рЗ и записывает его в аккумулятор. На этом процедура чтения состояния клавиатуры заканчивается. После чтения состояния клавиатуры производится оценка бита, соответствующего кнопке «Вкл/Выкл». Обращение к соответствующему биту происходит точно так же, как и в начале ветви дежурного режима. Но теперь вместо ,|пЬ используется оператор ДО. Этот оператор наоборот выполняет переход только в случае, когда проверяемый бит равен единице. Если кнопка «Вкл/Выкл» оказалась не нажата, значение бита будет равно единице и программа выполнит переход по адресу ои5. А это означает, что операторы, переводящие систему в основной режим, не будут выполнены. Как только кнопка вновь окажется нажатой, очередная процедура динамической индикации, дойдя до этого места, перейдет к выполнению команд перехода в основной режим работы. Эти команды объединены в два блока, озаглавленные в тексте программы как: «Выход из дежурного режима» и «Включение дисплея». Выход из дежурного режима. Эта группа команд производит запись только что считанного кода состояния клавиатуры в основной и дополнительный буферы клавиатуры. Затем флаг ПопоГГ устанавливается в единичное состояние. Включение дисплея. При переходе в основной режим работы необходимо возобновить вывод изображения на дисплей. Конечно, для этого достаточно вывести на дисплей номер текущего выбранного канала. Однако в программе позиционера заложено небольшое усложнение, вызванное соображениями удобства пользования. Дело в том, что для позиционера различают еще два режима работы: «Работа» и «Установка». Эти два режима отличаются тем, что в режиме установки включены все возможности по записи и корректировке каналов, а в рабочем режиме все эти возможности заблокированы. Все это нужно для того, чтобы обезопасить позиционер от случайной порчи настроек. Для переключения режимов «Работа/Установка» применяется флаг flru. Если позиционер находится в режиме «Установка», то в момент включения на дисплей выводится предупреждающая надпись «УС». Проверкой флага flru занимается оператор jnb. Если флаг имеет единичное значение, это значит, что позиционер находится в режиме установки. Управление передается по адресу inidl, где в буфер дисплея записываются коды букв «У» (19) и «С» (24). В противном случае в буфер дисплея записываются старший и младший разряды номера канала из той ячейки памяти, где хранится его исходное значение. То есть из ячейки nk и ячейки nk+1. Завершается ветвь обработки дежурного режима командой вывода процессора из режима пониженного потребления, которая записывает нулевой байт в регистр рсоп. Счетчик мерцаний. Для организации счетчика мерцаний выделена специальная ячейка памяти iflash. Сам счетчик мерцаний работает постоянно, независимо от того, отключено мерцание в данный момент или нет. Для итерации счетчика применена уже знакомая нам программа организации цикла djnz. В данном случае она применяется нестандартным образом. Каждый раз, когда выполнение программы дойдет до этого места, команда djnz уменьшает содержимое ячейки iflash на единицу. Если после этого содержимое ячейки еще не равно нулю, тот же самый оператор передает управление по адресу оиб и таким образом продолжает выполнение программы. Если в результате уменьшения содержимое ячейки iflash оказалось равно нулю, то перехода не происходит и команда mov производит загрузку в ячейку счетчика его начального значения (tflash). Таким образом, счетчик мерцаний работает на протяжении всего времени, пока включено питание позиционера и считает по кругу, от максимального значения до нуля и опять сначала. Константа tflash определяет период мерцания. Для осуществления самого процесса мерцания служит процедура проверки условий мерцания. Задача этой процедуры — отслеживать значение счетчика мерцания, и в случае, когда его значение меньше tflash/2, устанавливать флаг flifl в единицу. А при значениях счетчика больших tflash/2, устанавливать флаг flifl в ноль. Флаг flifl называется «гореть/не гореть». Его значение используется затем в программе вывода символа. Если значение флага равно нулю, изображение на индикатор не выводится, и он остается погашенным. Для включения и отключения мерцания служит флаг flflh. Если значение этого флага равно единице — мерцание включено. Если нулю — выключено. Процесс проверки условий мерцания начинается с установ-ки флага «гореть/не гореть» в положение «гореть». Затем происходит проверка флага разрешения мерцания (flflh). Если его значение оказалось равно нулю (мерцание выключено), то управление передается по адресу ои2. Дальнейшая проверка условий мерцания прекращается и флаг «гореть/не гореть» остается в положении «гореть». Если мерцание включено, то выполняется процедура сравнения. Сравнение производится путем вычитания из текущего значения счетчика мерцаний константы, значение которой равно tflash/2. Здесь опять используются возможности препроцессора. Транслятор вычислит выражение и подставит вместо него число, равное целой части результата деления константы tflash на два. Далее, оператор je производит проверку признака переноса. В случае, если результат вычитания отрицательный произойдет переход по адресу ои2. В случае положительного результата перехода не будет и оператор clr выполняет сброс флага flifl в ноль. После программного счетчика мерцаний начинается разветвление процедур на два пути, соответствующих двум фазам процедуры динамической индикации. При первом вызове, программа пойдет по пути индикации старшего разряда, при последующем вызове, она пойдет по-другому пути, и будет выполнять операции по индикации младшего разряда. Так как в обоих случаях будет применяться перекодировка по таблице символов, в регистр DPTR заранее загружается адрес начала этой таблицы. Далее производится проверка содержимого буфера указателя текущего разряда индикатора (ibuf). В этом буфере хранится код, который нужно выдать в порт Pl для того, что бы дешифратор DD3 переключился в режим индикации соответствующего разряда индикатора. При индикации старшего разряда в буфере хранится число 7FH, а при индикации младшего — 0BFH. Оператор cjne проверяет содержимое этого буфера и передает управление либо на процедуру обработки первой фазы индикации, либо на процедуру обработки второй фазы. Если содержимое буфера ibuf не равно 7FH, то программа переходит к обработке первой фазы (вывод младшего разряда). В противном случае выполняется вывод старшего разряда. Ветвь вывода старшего разряда начинается с процедуры ввода состояния клавиатуры. Данная процедура аналогична подобной процедуре, которую мы уже рассматривали в составе команд ветви дежурного режима. Отличие этой новой процедуры лишь в том, что код состояния клавиатуры записывается только в основной буфер (bufkl). В дополнительном буфере остается код предыдущего состояния клавиатуры. Сразу после команд опроса клавиатуры начинается процедура вывода символа. Сначала код символа из старшего разряда буфера экрана помешается в аккумулятор. Далее происходит перекодировка. Для перекодировки применяется оператор чтения константы из программной памяти move. Этот оператор устроен таким образом, что читает код из программного сегмента памяти CSEG по адресу, который вычисляется как сумма шестнадцатиразрядного числа в регистре DPTR и содержимого аккумулятора. Прочитанный код также помешается в аккумулятор. В регистре DPTR у нас находится адрес начала таблицы символов. Это значит, что команда move извлечет из памяти код, порядковый номер которого в таблице символов соответствует содержимому аккумулятора. А оно, в свою очередь, равно рабочему коду символа, поступившему из буфера экрана. Извлеченный код временно сохраняется в аккумуляторе. А программа приступает к процедуре вывода на индикатор. Сначала в порт рЗ засылается константа попе. При выводе этой константы все сегменты индикатора окажутся погашенными. Это делается для того, чтобы в момент переключения на индикатор не попал случайный код. Далее в порт pi записывается сигнал из буфера ibuf. Два его старших разряда поступают на дешифратор DD3 и переключают в режим индикации старшего разряда. Далее идет оценка флага flifl («гореть/не гореть»). Если значение флага равно нулю, то вывод кода не производится и индикатор так и остается не включенным. Если гореть разрешено, то код вывода из аккумулятора помешается в порт pi, где он находится вплоть до следующего вызова процедуры динамической индикации. В заключение программа меняет содержимое буфера ibuf на 0BFH для того, чтобы при следующем вызове процедура пошла по-другому пути и выполнила ветвь вывода младшего разряда. Безусловный переход передает управление по адресу flh2, где заканчиваются обе ветви динамической индикации. Ветвь вывода младшего разряда построена аналогично ветви вывода старшего. Однако вместо процедуры опроса клавиатуры ветвь начинается процедурой вывода управляющего сигнала на мотор. Для этого команда управления мотором считывается из буфера мотора в аккумулятор. Затем команда логического сложения ог1 выполняет операцию побитного «ИЛИ» кода команды с константой 11111100В. Такая операция установит в единицу все разряды, кроме двух младших. Именно два младших разряда будут записаны в регистр DD4, и будут влиять на работу двигателя. Неиспользуемые разряды порта всегда правильнее держать в единичном состоянии. Далее, полученный код помешается в порт рЗ. Следующая команда записывает в порт pi код 0FFH. Оба старших разряда в числе 0FFH равны единице, поэтому дешифратор DD3 перейдет в режим записи кода в регистр Э04. На выходе 12 дешифратора появится низкий логический уровень, который поступит на входы С обоих триггеров регистра 004. В следующий момент в порт р1 записывается код ЗРН. Уровень сигнала на обоих входах С микросхемы 004 становится равным единице. По переднему фронту происходит запись двух младших разрядов порта рЗ в этот микрорегистр. Закончив процедуру вывода сигнала управления мотором, программа приступает непосредственно к процедуре вывода старшего разряда. Эта процедура полностью аналогична процедуре вывода младшего разряда и повторять описание нет смысла. Итерация счетчика очистки от спецсимволов. После завершения обоих ветвей динамической индикации, программа переходит к процедуре организации счетчика задержки вывода спецсимволов. Дело в том, что в обычном режиме программа высвечивает на своем дисплее номер текущего выбранного канала в диапазоне от 00 до 99. Но для индикации различных дополнительных режимов работы на индикатор могут выводиться специальные не цифровые надписи (спецсимволы). Ниже приведен весь список спецсимволов, заложенных в программе: Р8 Работа. УС Установка. РУ Ручное управление. РУ Начальная установка. Конец процесса начальной установки. £г Ошибка процедуры чтения(записи) флэш-памяти. Каждый из спецсимволов, выведенный на дисплей, должен оставаться там несколько секунд и исчезать, уступая место номеру выбранного канала. Для этой цели разработана универсальная процедура, убирающая спецсимволы с дисплея. Она постоянно сравнивает содержимое буфера экрана (ЬиПц ЬиЯ) и содержимое регистра указателя номера текущего выбранного канала (пк). Если их содержимое не совпадает, то запускается специальный счетчик. Счетчик отсчитывает определенный период времени. По истечении этого периода программа переписывает содержимое указателя номера канала (пк) в буфер экрана. Спецсимвол «РУ» является исключением. Он высвечивается при нажатии на любую из кнопок ручного поворота антенны (в5 или Бб) и должен присутствовать на дисплее все время, пока нажата кнопка поворота. А поворот антенны на нужное направление может длиться достаточно долго. Поэтому в программе делается специальная проверка. Если в буфере экрана находятся коды надписи «РУ», то запуск счетчика очистки спецсимволов не производится. Начинается процедура счетчика очистки от спецсимволов сравнением старших разрядов буфера экрана и указателя номера канала. Старший разряд номера канала помещается в аккумулятор. Затем, при помоши команды cjne он сравнивается со старшим разрядом буфера экрана. Если коды не равны, управление передается по адресу zddl к процедуре запуска счетчика. Если старшие разряды оказались одинаковые, то таким же образом сравниваются младшие разряды. В случае различия младших разрядов управление также передается по адресу zddl. Если же и эти коды оказались равными, то на этом обработка счетчика удаления спецсимволов завершается. Значение счетчика сбрасывается в ноль. Нулевое значение счетчика означает для дальнейшей программы, что он еще не был запушен. Команда безусловного перехода jmp flh2 обходит все остальные операции, связанные с данным счетчиком, и переходят к последующим операциям. Если программа обнаружила спецсимвол и запустила счетчик, программа продолжается с адреса zddl. По этому адресу расположены команды проверки: не содержит ли буфер экрана надпись «РУ». Процедура эта полностью аналогична сравнению буфера экрана и указателя номера канала. Если в результате сравнения окажется, что в буфере экрана находится «РУ», то программа обходит дальнейшие операторы сравнения. Если в буфере экрана другой спецсимвол, то программа переходит непосредственно к процедуре итерации счетчика. Сначала производится проверка содержимого регистра счетчика (coudd) на равенство нулю. Если содержимое счетчика оказалось равно нулю, значит счетчик еше не запушен. Программа запускает счетчик, записывая в регистр coudd коэффициент пересчета tzdd, и заканчивает на этом процедуру обработки счетчика. Если содержимое счетчика не равно нулю, то это означает, что счетчик находится в режиме счета. Поэтому программа выполняет уменьшение его содержимого на единицу (команда dec). Новое значение содержимого счетчика записывается в coudd. Сразу после этого производится проверка на ноль. Если после очередного уменьшения содержимое счетчика стало равно нулю, то происходит завершение периода индикации спецсимвола. На индикатор выводится номер канала. Итерации счетчика задержки режима стирания гораздо проще. Все операции по запуску, сбросу и оценке окончания счета выполняет основная программа. На процедуру динамической индикации возложена лишь функция счета. Кроме того, в процедуру счета добавлена проверка двух дополнительных условий. При невыполнении любого из них счет приостанавливается. Первое условие: флаг flks должен быть равен единице. Если вы еще не забыли, флаг устанавливается в единицу сразу после нажатия кнопки «запись/стирание» (S4), а сбрасывается в том случае, если процедура стирания памяти уже произошла, даже если кнопка S4 еще не отпущена. Это условие останавливает счет, если режим стирания уже включился, а кнопка еще не отпущена. Второе условие — сама кнопка S4 должна быть нажата. Если она не нажата, счет тоже будет остановлен. Проверка этого условия производится путем сравнения содержимого буфера клавиатуры bufkl с кодом клавиши S4 (kkss). На этом процедура обработки прерывания заканчивается. В заключение процедуры происходит восстановление всех регистров, сохраненных в ее начале. Восстановление регистров производится при помощи команды pop. Команда pop служит для извлечения информации из стека. Восстановление регистров происходит в порядке, обратном тому, в каком производилось их сохранение. При восстановлении регистра PSW одновременно восстанавливается тот банк РОН, который был включен до начала процедуры обработки прерывания. И, наконец, выход из процедуры обработки прерывания происходит по команде reti. Команда reti по своему действию равнозначна команде ret. Она извлекает из стека адрес, на котором было прервано выполнение основной программы, и передает управление по этому адресу. Однако процедуры обработки прерывания всегда должны заканчиваться именно командой reti. Команда reti вызывает правильное срабатывание системы приоритетов. Процессор должен всегда точно знать, обработка каких прерываний в данный момент еще не закончилась. Используются технологии uCoz
|