Главная

Материал взят из книги


Скачать оригинал КНИГИ в хорошем качестве

Инициализация системы

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

1. Присвоение начальных значений всем переменным программы.

2. Настройка всех внутренних систем микроконтроллера.

3. Восстановление режимов работы системы, установленных в предыдущем сеансе работы путем считывания соответствующих параметров из внешней флэш-памяти.

4. Выполнение процедур, предназначенных для установки всех периферийных устройств схемы позиционера в исходное состояние (очистка индикаторов, подтверждение команды остановки двигателя и т.д.).

5. Выполнение процедуры запуска системных счетчиков-таймеров и механизма прерываний микроконтроллера.

Фрагмент №4 управляющей программы позиционера представляет собой процедуру' инициализации. Рассмотрим ее подробнее.


Начинается этот фрагмент с оператора СЖО. Он устанавливает указатель сегмента в положение ЗОН. Именно с этого адреса и начинается основной программный модуль. Метка шН, поставленная перед первым оператором программного модуля, автоматически принимает значение ЗОН. Конечно, можно было бы обойтись и без метки — применить прямую адресацию. При этом во фрагменте №3 вместо команды ]шр нШ, стояло бы ]шр ЗОН. Но так не принято.

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

Теперь рассмотрим по порядку назначение всех команд Фрагмента №4.

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

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

Следующая команда нашей программы («питание выключить») сбрасывает флаг flonoff в ноль. Здесь используется новая для нас команда процессора clr. Эта команда используется для сброса в ноль содержимого любой ячейки битового пространства микроконтроллера. Флаг flonoff используется программой для переключения режимов «основная рабо-та»/«дежурный режим». Нулевое состояние этого флага означает, что позиционер находится в дежурном режиме. Таким образом, сразу после включения питания позиционер переходит в дежурный режим.

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

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

Команда установки вершины стека сводится к записи в регистр SP требуемого начального значения. В качестве начального значения используется константа stack, значение которой задано в модуле описаний (см. Фрагмент №1). В процессе записи в стек, содержимое регистра SP увеличивается. При извлечении из стека, содержимое SP уменьшается. Особенность работы стека такова, что возможна ситуация, когда значение стека превысит свое начальное значение на единицу. Поэтому начальное значение регистра SP принято брать на единицу меньшим адреса вершины стека.

Инициализация переменных динамической индикации. Эта группа команд предназначена для присвоения начальных значений группе переменных, используемых в процедуре динамической индикации. На самом деле в данной процедуре используется гораздо больше переменных, но лишь две из них требуют начальной инициализации. Для хранения обеих этих переменных использованы регистры обшего назначения. Одна из них — это указатель текущего разряда индикации. Он обозначен как ibuf. Второй — это счетчик мерцаний (iflash). Процедура динамической индикации работает с банком 1 регистров общего назначения. Поэтому, прежде чем присваивать начальные значения переменным, нужно выбрать первый банк. Для этого в регистр PSW записывается соответствующая константа. Код 7FH, записанный в регистр ibuf соответствует младшему разряду индикатора. Подробнее об этом вы прочитаете в разделе, посвященном процедуре динамической индикации. Сейчас вам достаточно понять, что процесс индикации начнется с младшего разряда.

Что такое счетчик мерцаний (iflesh), нужно пояснить особо. Дело в том, что программа вывода на индикатор кроме обычного режима индикации должна обеспечивать режим мерцания. Этот способ индикации используется в режиме записи позиции антенны в память позиционера. Для организации мерцания используется этот счетчик. Принцип работы счетчика прост. Он отсчитывает определенное количество циклов динамической индикации и гасит индикатор. Затем опять отсчитывает такое же количество и зажигает изображение. Начальное значение счетчика мерцания — это коэффициент пересчета. От значения этого коэффициента зависит частота мерцания.

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

К переменным основного цикла отнесены: основной и дополнительный буферы команд управления мотором (bufmot и doprnot), а также два специальных счетчика (coukl и couddj. Переменная buftnot предназначена для временного хранения команд управления мотором. Переменная dopmot дублирует эти команды, но с учетом инерции двигателя. Все подробности вы также узнаете при описании соответствующей процедуры. В обе ячейки управления мотором записывается нулевое значение. Нулевой код — это команда остановки мотора.

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

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

Инициализация переменных ДУ. Здесь присваиваются начальные значения переменным процедуры приема сигналов ДУ. Специфическое назначение этих переменных будет рассмотрено при описании самой процедуры. Особенностью данного блока команд является необычный способ обнуления регистра г5 из банка 3. Для сокращения количества команд обращение к этому регистру происходит как к ячейке ОЗУ.

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

Инициализация 12С-шины. В качестве такой шины выступают две линии порта Р1, которым в программе присвоены символьные имена SDA и SCL. Обе эти линии переводятся в единичное состояние, что позволяет использовать линии, как входные (см. раздел «Назначение выводов»).

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

■ Текущее значение счетчика положения антенны.

■ Регистр флагов.

■ Константа ДУ.

■ Номер текущего выбранного канала.

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

Для чтения информации из внешней флэш-памяти разработана специальная подпрограмма. Она расположена в памяти программ по адресу гё_ЙЬ. Эта программа разработана на основе стандартной процедуры, взятой с сайта «А1те1». Мы не будем рассматривать алгоритм работы этой подпрограммы. Все желающие могут самостоятельно скачать эти примеры и разобраться в алгоритме их работы. Для того, чтобы пользоваться подпрограммой, не обязательно изучать все тонкости ее алгоритма. Достаточно представлять, для чего она предназначена, и знать правила ее использования. Правила использования подпрограммы чтения из внешней флэш-памяти:

■ При каждом обращении подпрограмма читает два байта данных, расположенных в двух соседних ячейках флэш-памяти.

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

Группа команд, озаглавленная как «Настройки из флэш-памяти», производит последовательное чтение каждого из перечисленных выше параметров, при помощи подпрограммы гс!_АЬ. Рассмотрим этот процесс на примере чтения текущего положения антенны. Сначала при помощи уже знакомой нам команды шоу в регистры а и Ь записываются соответствующие константы. Константа фа — это адрес во внешней флэш-памяти, где хранится это значение. Константа ра!ек — это адрес ячейки ОЗУ, используемой в качестве счетчика поворота антенны. После того, как параметры записаны, следует команда вызова подпрограммы (call). Подробное описание процесса перехода к подпрограмме и выхода из нее уже приводилось в главе 2. По команде call управление передается на начало подпрограммы, по адресу rd_flh. В конце подпрограммы обязательно стоит оператор ret, который осуществляет возврат из этой подпрограммы. Управление передается в то самое место, откуда она была вызвана.

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

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

Канал    №1    ООН,    03 И

Канал    №2    ООН,    С/Н

Канал    №23    02Н,    03Н

Канал    №48    04Н,    06Н

Такое представление номера облегчает работу с ним. Например, для вывода номера канала на индикатор, достаточно каждый байт вывести в свой разряд индикатора. Такой способ хранения номера канала предполагает, что каждый из двух байтов будет принимать значения в диапазоне от ООН до 09Н. Остальные значения недопустимы. Если в результате случайного сбоя во внешней флэш-памяти окажется недопустимое значение, то это можно легко обнаружить программным путем. Поэтому после команд чтения номера канала непосредственно идут команды проверки.

Сначала старший разряд номера канала записывается в накопитель. Следующие два оператора служат для оценки проверяемой величины. Оценка производится путем вычитания из проверяемого значения числа 10. Если результат получится отрицательный, то это значит, что проверяемое число было меньше десяти. Если результат положительный, то число либо равно, либо больше десяти. В системе команд микроконтроллера существует только одна команда вычитания. Это команда ьиЬЬ. Команда ьиЬЬ а,#10 производит вычитание константы, имеющей значение, равное десяти, из содержимого аккумулятора. Причем при вычитании учитывается значение признака переноса из предыдущего разряда (флаг с). Поэтому, для правильности вычислений перед началом вычитания команда с1г с сбрасывает значение признака переноса в ноль. Команда условного перехода фс вызывает передачу управления в том случае, если признак переноса равен нулю. В нашем случае управление передается по адресу тП. По этому адресу находятся команды, выполняемые в случае ошибочного кода. Они просто принудительно устанавливают значение параметра, переключая позиционер на первый канал.

Если значение первого разряда оказалось в допустимых пределах, то таким же образом проверяется второй разряд. Однако тут применяется другая команда условного перехода. Команда ф передает управление в случае единичного значения признака переноса. Переход на адрес т\2 — это обход команд принудительной установки первого канала. Он произойдет только в случае правильности обоих разрядов. В противном случае перехода не произойдет и программа все же выполнит операторы принудительной установки.

В завершении группы команд чтения из флэш-памяти из нее извлекается значение, называемое «требуемое положение антенны». Для того, чтобы понять, как происходит чтение этого значения, сначала нужно понять, как производилась его запись. Для каждого из возможных каналов (от 0 до 99) существует своя специальная пара ячеек во внешней флэш-памяти, где хранится значение связанной с ним позиции антенны. В самом начале во все эти пары ячеек записан код ОРРН, ОРЕН. Такое содержимое ячейки индицирует тот факт, что в данном канале позиция еше не записана.

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

Для того, чтобы прочитать «требуемое положение» антенны, нужно предварительно вычислить адрес пары ячеек во внешней флэш-памяти, соответствующих выбранному каналу. Адрес вычисляется простым способом. Сначала номер канала приводится к обычной форме записи — в виде двоичного числа. Затем номер ячейки вычисляется по формуле:

АагХ = ПК* 2,

где:Аб^ — это адрес ячейки внешней памяти, где записано искомое положение для текущего канала;

МК — номер текущего капала.

Описанное выше вычисление реализуется при помощи специальной подпрограммы пкаёг. Эта подпрограмма вычисляет адрес во флэш-иамя-ти и помещает его в аккумулятор. Затем она помещает в регистр Ь адрес буфера для хранения «требуемого положения» антенны. После завершения подпрограммы пкайг выполняется подпрограмма чтения гс1_Ш1.

Программирование таймеров. Эта группа команд производит запись управляющих кодов во все регистры специального назначения микроконтроллера, связанные с настройкой встроенных таймеров-счетчиков и системы прерываний. Код, записанный в регистр ТМОО, определяет режимы работы обоих таймеров. В регистры ТНО и ТЪО записывается коэффициент пересчета таймера ТО. Он определяет период динамической индикации. В регистры ТН1, ТЫ записывается коэффициент пересчета таймера Т1. Он определяет период опроса фотоприемника. Затем загружается значение маски прерываний и значения приоритетов. В заключение записывается управляющий код в регистр ТСОМ Это приводит к запуску обоих таймеров-счетчиков. Именно с этого момента начинают работать оба дополнительных процесса, связанных с прерываниями: процесс динамической индикации и процесс опроса фотоприемника.

Используются технологии uCoz