Рис. 11.17.Передняя панель усреднителя сигналов.
Отсутствующие возможности. Полезно пояснить, что именно мы не включили в нашу разработку, и почему. Мы не поддались повальному увлечению экранными меню по следующим причинам. Во-первых, приборы с управлением от клавиатуры нас часто раздражают, так как все они работают по-разному, и вам приходится постоянно переучиваться. Во-вторых, они замедляют вашу работу - для того лишь, чтобы переключать шкалу, вам надо набирать команду на клавиатуре. Наконец, управление от клавиатуры с помощью экранных меню требует разработки программ анализа введенных строк и формирования на экране изображения меню - программ, не представляющих интереса с педагогической точки зрения. Поэтому мы решили считывать состояния органов управления на передней панели с помощью параллельного порта; это быстрая и простая операция, хотя она ограничивает возможности выбора режимов и уменьшает универсальность прибора.
Можно перечислить еще целый ряд дополнений, которые улучшили бы наш прибор, но мы от них отказались, чтобы не усложнять описываемую здесь программу. Можно было предусмотреть второй аналоговый вход (микросхема 670 содержит два АЦП), переменное число ячеек, несколько "банков" памяти для хранения данных, цифровые выходы для индикации номера текущей ячейки, а также аналоговые сигналы, пропорциональные номеру ячейки (для контроля аналоговых величин). Это все довольно очевидные, но не принципиальные усовершенствования; более важной является возможность пересылать накопленные данные в микроЭВМ, для чего лучше всего использовать один из последовательных портов.
Даже в рамках выбранной нами конструкции можно было ввести дополнительные режимы. В частности, микропроцессорная система с аналого-цифровыми и цифро-аналоговыми преобразователями значительно выиграет при включении в нее аналоговых мультиплексоров, позволяющих связать выходы ЦАП со входами АЦП. В этом случае вы сможете выполнять программное тестирование всех преобразователей в качестве элемента общей процедуры тестирования при включении питания (куда также входит проверка памяти, портов и т. д.). Можно даже проверять, с помощью АЦП, напряжение (я) источника питания.
Упражнение 11.11. Покажите, как это сделать, если ко входам АЦП подключены аналоговые мультиплексоры. Вам потребуется предусмотреть адрес порта, по которому из ЦП будут направляться команды выбора мультиплексора.
11.07. Программирование: детали
Обзор. Программы обычно сложны. Программы реального времени на языке ассемблера сложны всегда. Однако вместо того, чтобы рассматривать упрощенную программу, которая в действительности работать не сможет, мы собираемся привести реальную законченную программу, годную для использования в нашем приборе, во всем ее великолепии (и безобразии). Чтобы помочь вам в ней разобраться, мы будем рассматривать ее постепенно, слой за слоем. Лучше всего воспользоваться методом "нисходящего проектирования", когда сначала определяются основные функции программы, порядок их выполнения и протокол обмена информацией между основными модулями программы. После этого можно перейти к структурным схемам конкретных программных модулей. Наконец, пишутся реальные программные строки на языке ассемблера.
Замечание: дальнейшее описание насыщено деталями. Читатели, желающие получить лишь общее представление, могут опустить обсуждение вопросов программирования, перейдя сразу к разд. 11.08 или 11.09.
На рис. 11.18 изображена общая структура, сильно упрощенная.
Рис. 11.18.Программирование: общая структура.
В ОЗУ мы организовали три массива: массив DATA из 256 32-разрядных ("длинных") целых чисел для хранения текущих данных для каждого канала; массив NORM из 256 16-разрядных ("слова") целых чисел для хранения количества полных разверток для каждого канала, что нужно для нормализации данных в режиме автомасштабирования; и, наконец, массив DISPLAY из 256 байт для хранения данных, непрерывно поступающих на дисплей. Основные функции программы заключаются в следующем: добавление в массив DATA новых данных из АЦП при одновременной модификации массива NORM; масштабирование этих длинных чисел с преобразованием их в байты массива (в режиме автомасштабирования - с использованием массива NORM, а при ручном задании масштаба - путем сдвига); непрерывный вывод этих байтов на экран.
Общая последовательность работы программы выглядит следующим образом. При включении питания ЦП активизирует процедуру начальной загрузки и начинает выполнять программу, записанную в ПЗУ (причем временный образ ПЗУ в самом начале адресного пространства содержит вектор перехода на истинное расположение ПЗУ, как это было объяснено в разд. 11.05). Инициализируются, при необходимости, периферийные микросхемы (посылкой соответствующих байтов в их управляющие регистры); кроме того, программа должна инициализировать массивы, указатели, начальные значения переменных и проч. Приборы вроде нашего характеризуются несколькими возможными состояниями (ожидания сигнала ПУСК, накопления данных и т. д.); мы начинаем с состояния ожидания нажатия кем-нибудь кнопки ПУСК. Однако прибор и в этом состоянии живет, выводя на экран данные, которые мы инициализировали нулями.
При нажатии кнопки ПУСК программа начинает с того, что считывает состояние органов управления на управляющей панели, чтобы получить параметры для своей работы. Затем программа переходит в режим приема данных (в соответствии с параметрами, введенными с управляющей панели), выдавая одновременно на экран текущие значения усредненного сигнала. После завершения заданного числа разверток или обнаружив нажатие кнопки СТОП, программа опять входит в режим ожидания.
Синхронизация; программное управление и управление от прерываний.
Наиболее важная задача - обеспечить выполнение АЦП преобразований каждые 100 мкс и накопление получаемых данных в массиве DATA. Следующая по важности задача - регенерация дисплея с частотой по меньшей мере 40 Гц, чтобы избежать мерцания. Менее важной является задача обновления по мере изменения содержимого массива DATA также и массива DISPLAY.
Вы можете подумать, что наиболее важная задача должна решаться средствами основной (зацикленной) программы, задачи же менее важные могут время от времени отнимать время процессора с помощью прерываний. Однако это не так. Прерывания имеют приоритет по отношению к текущей программе, поэтому срочные задачи должны выполняться обработчиками прерываний, задачи же менее важные - наоборот, "главной" программой, которая получит лишь то время ЦП, которое останется от обработки прерываний. (При этом, конечно, предполагается, что процессор обрабатывает прерывания достаточно быстро. Как мы увидим, большое число регистров МП 68008 позволяет ему исключительно быстро обрабатывать прерывания; МП 68008 прямо создан для этой задачи.)
Как было показано на рис. 11.18, данные из АЦП поступают в массив DATA с помощью прерываний, создаваемых каждые 100 мкс программируемым таймером 8536. Главная программа занимается непрерывным обновлением массива DISPLAY, используя для этого подпрограмму update (обновление) (поскольку эта подпрограмма совсем не думает о том, что у нее под носом протекает интереснейший процесс сбора данных, она вынуждена проверять флаг, устанавливаемый программой обработки прерываний и свидетельствующий об окончании измерений).
Мы сначала хотели включить в главную программу также и регенерацию дисплея, но этому помешало любопытное обстоятельство. С каждой парой сигналов X, Y, посылаемых на ЦАП для вывода на экран точки, надо формировать также и сигнал "оси Z" (подсветки). В разд. 10.20 было показано, как можно сформировать "программный сигнал", посылая в бит порта сначала 1, а затем 0. Сигналы оси Z должны иметь одинаковую длительность, иначе одни точки на экране будут ярче других. Если, однако, программа время от времени прерывается, невозможно гарантировать равную длительность программных сигналов.
Упражнение 11.12. Но почему?
Можно, конечно, выключать прерывания, генерировать сигнал, а затем снова включать прерывания. Это безобразное решение, поскольку в самый важный процесс регулярных выборок вносятся нежелательные задержки. Потом мы нашли лучший способ: вывод на экран одной точки выполнять, как вспомогательную задачу обработчиком прерываний. Обработчик срабатывает каждые 100 мкс, так что полное 256-точечное изображение будет выводиться 40 раз в секунду. При этом, поскольку прерывания возникают и в том случае, когда главная программа находится в состоянии ожидания (сигнала ПУСК), изображение на экране не будет гаснуть. Наконец, такой способ содержит в себе чудесную глюковину: ведь запустив АЦП, приходится выжидать 10 мкс перед тем, как снимать с него результат преобразования; этого времени как раз хватит, чтобы послать в ЦАП пару X, Y. Другими словами, регенерация дисплея в обработчике прерываний абсолютно не требует процессорного времени!