РАЗРАБОТКА ИНТЕЛЛЕКТУАЛЬНОГО ДАТЧИКА УГЛОВОЙ СКОРОСТИ
2
СОДЕРЖАНИЕ ВВЕДЕНИЕ ...
361 downloads
289 Views
5MB Size
Report
This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Report copyright / DMCA form
РАЗРАБОТКА ИНТЕЛЛЕКТУАЛЬНОГО ДАТЧИКА УГЛОВОЙ СКОРОСТИ
2
СОДЕРЖАНИЕ ВВЕДЕНИЕ ........................................................................................................................................ 3 1. ОБЩАЯ СТРУКТУРА СИСТЕМЫ ............................................................................................. 4 2. УСТРОЙСТВО ДАТЧИКА И ПРИНЦИП ИЗМЕРЕНИЯ СКОРОСТИ ................................... 5 3. ВЫБОР ЭЛЕМЕНТОВ СИСТЕМЫ, ИХ ЭЛЕКТРИЧЕСКИЕ ПАРАМЕТРЫ И СХЕМЫ ВКЛЮЧЕНИЯ ................................................................................................................................... 6 3.1. Микроконтроллер ................................................................................................................... 6 3.2. Индикатор ............................................................................................................................... 7 3.3. Клавиатура ............................................................................................................................ 12 5.4. Интерфейс с компьютером .................................................................................................. 12 4. РАЗРАБОТКА СТРУКТУРНОЙ СХЕМЫ ................................................................................ 15 5. РАЗРАБОТКА ПРИНЦИПИАЛЬНОЙ СХЕМЫ ...................................................................... 17 6. РАЗРАБОТКА ПРОГРАММЫ ДЛЯ МИКРОКОНТРОЛЛЕРА ............................................. 18 6.1. Библиотека операций с вещественными числами ............................................................. 18 6.2. Библиотека операций с неупакованными двоично-десятичными числами.................... 20 6.3. Драйвер знакосинтезирующего ЖКИ ................................................................................ 21 6.4. Библиотека подпрограмм для работы с клавиатурой и меню .......................................... 21 6.5. Основная программа ............................................................................................................ 22 7. ОТЛАДКА ПРОГРАММЫ ......................................................................................................... 27 8. РАЗРАБОТКА ПРИЛОЖЕНИЯ ДЛЯ ПЕРСОНАЛЬНОГО КОМПЬЮТЕРА ...................... 29 9. ТЕСТИРОВАНИЕ ....................................................................................................................... 31 ЗАКЛЮЧЕНИЕ................................................................................................................................ 34 СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ ...................................................................... 35 Приложение А. Схема структурная ............................................................................................... 37 Приложение Б. Схема электрическая принципиальная ............................................................... 38 Приложение В. Схема алгоритма программы .............................................................................. 40 Приложение Г. Схема расположения компонентов на печатной плате ..................................... 41 Приложение Д. Печатная плата устройства.................................................................................. 42 Приложение Е. Листинги программ .............................................................................................. 45 Приложение Ж. Свидетельство участника Всероссийской научной конференции студентов и аспирантов «МОЛОДЫЕ ИССЛЕДОВАТЕЛИ - РЕГИОНАМ»............................................... 111 Приложение З. Диплом Всероссийской научной конференции студентов и аспирантов «МОЛОДЫЕ ИССЛЕДОВАТЕЛИ - РЕГИОНАМ» ................................................................... 112 Приложение И. Свидетельство участника Всероссийской студенческой оллимпиады «КОНКУРС КОМПЬЮТЕРНЫХ ПРОГРАММ» ....................................................................... 113
3
ВВЕДЕНИЕ В современных прецизионных электроприводах для оценки истинного значения угловой скорости или углового положения вала рабочего органа используются оптоэлектронные импульсные датчики перемещения (энкодеры). В настоящее время наибольшее распространение получили два вида оптических датчиков поворота: инкрементные шифраторы и абсолютные шифраторы [1]. Абсолютные шифраторы, как правило, имеют на выходе число, пропорциональное углу поворота вала датчика, которое закодировано либо в бинарном коде, либо в коде Грея. Шифраторы такого типа имеют относительно более сложный принцип действия и являются более дорогостоящими. Абсолютные шифраторы применяются в тех случаях, когда устройство бездействует в течение продолжительных интервалов времени или перемещается с небольшой скоростью. Примерами таких устройств могут быть задвижки управления подъёмом воды, телескопы, грузовые краны и т. д. В большинстве случаев в устройствах систем контроля и управления угловой скоростью и перемещением используются более простые шифраторы инкрементного типа (шифраторы приращений). Информация с такого датчика, как правило, снимается в виде последовательности импульсов с одного или нескольких каналов шифратора. Производители предлагают разработчикам большое количество трехканальных импульсных датчиков с различными параметрами. Для получения информации с такого датчика в цифровом виде необходима микропроцессорная система сбора, преобразования и отображения данных. Цель данного проекта – разработка интеллектуального датчика скорости, способного представить результаты в цифровом виде с удобным интерфейсом для настройки и отображения информации, программируемым с компьютера и адаптивного к свойствам первичного преобразователя. Такой интеллектуальный датчик является универсальным средством измерения скорости. Устройство может применяться в области прецизионных цифровых электроприводов, например, в качестве датчика обратной связи. Также при помощи предлагаемого датчика может быть произведен компьютерный анализ переходных процессов, контроль регулируемой величины. В простейшем случае универсальный интеллектуальный датчик найдет свое применение в качестве тахометра.
4
1. ОБЩАЯ СТРУКТУРА СИСТЕМЫ Объектом разработки является микропроцессорная система измерения скорости вращения механического или электромеханического объекта, снабженного импульсным датчиком скорости. На рис. 1.1 изображена общая структура такой системы.
Рис. 1.1. Структура измерителя скорости вращения
В системе сигналы с первичного датчика скорости поступают на микроконтроллер. Микроконтроллер обрабатывает эти сигналы, вычисляет скорость вращения и результаты вычислений выводит на индикатор. Единицы измерения скорости и другие настройки устройства задаются с клавиатуры. Система снабжена стандартным для современных персональных компьютеров интерфейсом – RS232 (COM-порт). Это позволяет непрерывно получать данные с измерителя скорости, а также перепрограммировать устройство без аппаратного программатора. Преобразователь интерфейса служит для согласования уровней напряжения портов ввода/вывода микроконтроллера и COM-порта компьютера. Главным элементом измерителя скорости является AVR-микроконтроллер фирмы Atmel. На данный момент AVR-контроллеры по совокупному интегральному параметру «энергопотребление – производительность - цена» считаются лучшими в мире среди 8разрядных RISC-микроконтроллеров. Для отображения информации в схему включен двухстрочный знакосинтезирующий жидкокристаллический индикатор фирмы Мэлт. Такие индикаторы имеют в своем составе контроллер, облегчающий реализацию интерфейса ЖКИ и микропроцессора. Интеллектуальный датчик поддерживает работу в двух режимах: • Режим передачи данных. В этом режиме текущее значение скорости на валу энкодера отображается на индикаторе и транслируется через сетевой интерфейс RS232 на устройство сбора информации в формате чисел с плавающей децимальной точкой (см. п. 6.1). Устройство доступно для настройки через собственное меню. • Flash режим. В этом режиме устройство доступно для перепрограммирования и конфигурации собственных параметров через персональный компьютер по интерфейсу RS232.
5
2. УСТРОЙСТВО ДАТЧИКА И ПРИНЦИП ИЗМЕРЕНИЯ СКОРОСТИ В схеме используется оптоэлектронный датчик угловой скорости, называемый шифратором приращений или энкодером (encoder). В таком шифраторе в корпусе на валу крепится прозрачный стеклянный или пластиковый кодирующий диск, на котором, в зависимости от типа датчика, нанесены одна, две или три дорожки непрозрачных меток. На рис. 2.1 изображено устройство трехканального шифратора приращений. На три концентрические окружности нанесены метки. Число меток на внешних окружностях A и B равно. Это число k называется разрешающей способностью датчика. На третьей окружности I нанесена только одна индексная метка, фиксирующая точку отсчета. При вращении диска датчик формирует две сдвинутые по фазе на 90° периодические импульсные последовательности, соответствующие рядам меток A и B, и так называемый нулевой импульс, соответРис. 2.1. Шифратор приращений ствующий индексной метке I. Сдвиг импульсных последовательностей A и B зависит от направления вращения. При движении по часовой стрелке сигнал A отстает от сигнала B, а при движении против часовой стрелки сигнал A опережает сигнал B (рис. 2.2). Частота f и период T следования импульсов на выходе датчика однозначно связана со скоростью вращения вала:
f =
1 n⋅k = , T 60
где n – скорость вращения вала (об/мин). Знак скорости можно определить по фаРис. 2.2. Диаграммы сигналов на выходе импульсзовому сдвигу последовательностей A и B: ного датчика скорости - если сигнал A опережает сигнал B, то скорость считается положительной; - если сигнал A отстает от сигнала B, то скорость считается отрицательной. Для определения знака скорости можно, например, фиксировать состояние сигнала B в момент появления переднего фронта сигнала A. Тогда при B = 0 (см. рис. 2.2) перемещение положительно, а при B = 1 – отрицательно. На рис. 2.3 изображены поворотные шифраторы в различных конструктивных исполнениях. Для проектируемого устройства могут быть применены трехканальные шифраторы приращений с ТТЛ-выходами (A, B, I) и разрешающей способностью не более 10000 меток/оборот. Например, подойдет шифратор приращений с полым валом фирмы Pepperl+Fuchs GmbH типа Serles 88 c разрешением 2500 мет/об и максимальной скоростью вращения вала 6000 об/мин. Подробную информацию о различных типах поворотных шифраторов и их применении можно найти в [3, 4]. Рис. 2.3. Поворотные шифраторы
6
3. ВЫБОР ЭЛЕМЕНТОВ СИСТЕМЫ, ИХ ЭЛЕКТРИЧЕСКИЕ ПАРАМЕТРЫ И СХЕМЫ ВКЛЮЧЕНИЯ 3.1. Микроконтроллер Однокристальные микро–ЭВМ – микроконтроллеры (МК) широко применяются для построения радиоэлектронных устройств самого разнообразного назначения. Одними из наиболее популярных семейств являются 8-ми разрядные RISC–микроконтроллеры: AVR производства компании Atmel [12], и PIC-micro, выпускаемые Microchip LTD [14]. Превосходные характеристики, аппаратная поддержка распространенных протоколов связи (параллельной шины, интерфейсов RS232/485/422, I2C, USB, CAN и других), широкий модельный ряд, надежность и доступность в сочетании со сравнительно низкой стоимостью, наличием доступных средств разработки и отладки программ, массой справочной литературы, позволяют использовать эти микроконтроллеры не только в промышленной аппаратуре, но и в радиолюбительских конструкциях. Появление недорогих и несложных для освоения МК семейства PIC с FLASH–памятью программ, со встроенным UART и возможностью внутрисхемного программирования, позволило резко удешевить и упростить разработку периферийных устройств. Сокращенный набор высокоэффективных команд (всего 35 инструкций для МК среднего подсемейства) и простота архитектуры, позволяют в короткие сроки освоить эти микроконтроллеры. Микроконтроллеры AVR широко применяются для построения различных приборов, систем управления аппаратурой и оборудованием. МК этого семейства отличаются высоким быстродействием, надежностью, возможностью работы в многозадачных средах и в режиме реального времени. Достоинства AVR: быстродействующий RISC-процессор, FLASH-память с низковольтным напряжением программирования, внутреннее перезаписываемое ЭСПЗУ, мощные выходные порты, широкий диапазон питающего напряжения. И все это при малом потреблении тока, высокой скорости, а главное, при низкой цене. По совокупному интегральному параметру "энергопотребление – производительность – цена" AVR-контроллеры оказались лучшими в мире. Несколько расширенный набор команд позволяет эффективно использовать компиляторы языков высокого уровня (Си, Паскаль и Бейсик), незаменимые при разработке сложных проектов. Существует также средство алгоритмической разработки микропрограмм – Algorithm Builder [15], значительно упрощающее освоение программирования этих МК. Для выбора микроконтроллера зададимся следующими требованиями к его архитектуре и прочим показателям: • не менее 8 килобайт flash-памяти программ; • наличие EEPROM; • тактовая частота более 10 МГц; • не менее 23 контактов портов ввода/вывода; • наличие 16-битного таймера/счетчика; • 2 контакта для внешних прерываний; • наличие интерфейсов UART и SPI; • доступность среды проектирования и отладки; • доступность технической документации; • минимальная цена. Исходя из этих условий, а также согласно рекомендациям в [1] выбираем микроконтроллер ATmega8 фирмы Atmel. Основные технические параметры этого микроконтроллера сведены в таблицу 3.1. На рис. 3.1 представлена цоколевка микросхемы ATmega8 для различных типов корпусов (PDIP, TQFP, MLF).
7 Таблица 3.1 Основные параметры микроконтроллера ATmega8
Flash ROM, Кбайт EEPROM, байт RAM, байт ISP (I), Self prog (S) Количество контактов ввода/вывода Интерфейсы 8/16-битные таймеры N-канальный ШИМ Аналоговый компаратор N-канальный АЦП (10 бит) Внутренний RC-генератор Сторожевой таймер Аппаратный умножитель Количество инструкций Питание VCC, В Тактовая частота, МГц Тип корпуса
8 512 1024 I, S 23 USART, SPI, I2C 2/1 3 есть 6/8 есть есть есть 130 2.7-5.5, 4.0-5.5 0-8, 0-16 DIP28, TQFP32, MLF32
Рис. 3.1. Расположение выводов микроконтроллера ATmega8
3.2. Индикатор Многие фирмы (Optrex Corporation, Powertip, Seiko Instruments, Data Vision, Batron, Bolymin, МЭЛТ и др.) выпускают жидкокристаллические индикаторы со встроенными контроллерами, облегчающими реализацию интерфейса ЖКИ и микропроцессора. В данном проекте используется жидкокристаллический знакосинтезирующий индикатор MT-16S2H фирмы МЭЛТ на основе контроллера HD44780 (Hitachi). Этот ЖКИ имеет 2 строки по 16 символов в каждой. Рассматриваемый ЖКИ при помощи стандартного 14-контактного разъема (табл. 3.2) обменивается информацией с управляющим микроконтроллером (в нашем случае с AVR). AVR-микроконтроллер посылает в ЖКИ команды (табл. 3.3), управляющие режимами его работы, и коды выводимых символов. В свою очередь, ЖКИ может посылать AVRмикроконтроллеру по его запросу информацию о своем состоянии и данные из своих внутренних блоков памяти.
8 Таблица 3.2 Описание выводов стандартного разъема ЖКИ на базе HD44780
№ вывода 1 2 3 4 5 6 7 8 9 10 11 12 13 14
Название вывода VSS VDD V0 RS R/W E DB0 DB1 DB2 DB3 DB4 DB5 DB6 DB7
Описание Общий (GND) Напряжение питания Напряжение смещения, управляющее контрастностью Вход. Высокий уровень – данные; низкий – команды Вход. Высокий уровень – чтение; низкий – запись Вход. Строб, сопровождающий сигналы на шине данных Линия данных 0 Линия данных 1 Линия данных 2 Линия данных 3 Линия данных 4 Линия данных 5 Линия данных 6 Линия данных 7
Три вывода 14-контактного разъема предназначены для подачи питающего напряжения и напряжения смещения, которое управляет контрастностью дисплея. На рис. 3.2 показана рекомендуемая схема подключения этих выводов. Из оставшихся 11 выводов 8 (DB0 – DB7) используются для организации мультиплексированной шины "команды/данные", и на 3 вывода (RS, R/W, E) AVR-микроконтроллер выставляет управляющие Рис. 3.2. Возможная схема питания ЖКИ сигналы. На рис. 3.3 изображены временные диаграммы этих сигналов при записи команд/данных в контроллер ЖКИ. При помощи сигнала на линии RS микропроцессор сообщает контроллеру индикатора о том, что именно передается по шине: команда или данные. Сигнал на линии Е является стробом, сопровождающим сигналы на шине "команды/данные". Запись информации в ЖКИ происходит по спаду этого сигнала. Потенциал на управляющем выводе R / W задает направление передачи данных: запись в RAM индикатора ( R / W = 0) или считывание оттуда ( R / W = 1). Рис. 3.3. Запись данных в ЖКИ Для случая, когда микроконтроллер имеет ограниченное количество линий ввода/вывода, предусмотрен второй вариант подключения ЖКИ с использованием 4-х разрядной шины "команды/данные". При этом каждый байт данных передается по линиям DB4 – DB7 последовательно двумя тетрадами, начиная со старшей. Контроллер ЖКИ после приема байта команды или байта данных требует некоторого времени (табл. 3.3) для обработки полученной информации, в течение которого AVRмикроконтроллер не должен выполнять новых передач. Для того, чтобы определить, когда контроллер ЖКИ закончит свои внутренние операции, AVR может опрашивать BUSY-флаг индикатора (команда "чтение busy-флага"), который сбросится только тогда, когда контроллер ЖКИ освободится. Второй, более простой способ заключается в том, что управляющий микроконтроллер, зная, сколько времени требу-
9 ется ЖКИ на обработку той или иной команды, просто выполняет временную задержку после каждой передачи информации. Если во время цикла записи AVR-микроконтроллер передает в контроллер индикатора код команды, то этот код записывается в регистр команд контроллера ЖКИ, и команда сразу же начинает выполняться. Если AVR-микроконтроллер передает в контроллер ЖКИ данные, которые представляют собой коды отображаемых символов, то они записываются в буфер данных (DDRAM), который обычно содержит 80 ячеек (рис. 3.4). При записи или считывании буфера данных обращение осуществляется к ячейке, на которую в данный момент указывает курсор.
а)
б)
Рис. 3.4. Отображение на дисплее символов, коды которых записаны в DDRAM (а – однострочный ЖКИ, б – двухстрочный ЖКИ)
Буфер данных имеет больше ячеек, чем число знакомест дисплея. Смещая окно индикатора относительно буфера данных (см. систему команд), можно отображать на дисплее различные области буфера. У двухстрочных индикаторов первые 40 ячеек буфера данных, обычно, отображаются на верхней строке дисплея, а вторые 40 ячеек - на нижней строке. Сдвиг окна дисплея относительно буфера данных для верхней и нижней строк происходит синхронно. Курсор будет виден на индикаторе только в том случае, если он попал в зону видимости дисплея (и если предварительно была подана команда отображать курсор).
10 Таблица 3.3 Система команд контроллера HD44780
RS
R/W
DB7
DB6
DB5
DB4
DB3
DB2
DB1
DB0
Код
0
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
*
0
0
0
0
0
0
0
1
1/D
S
0
0
0
0
0
0
1
D
C
B
0
0
0
0
0
1
*
*
0
0
0
0
1
DL
*
*
0
0
0
1
0
0
1
ADD
0
1
BF
AC
1
0
Данные
1
1
Данные
S/C R/L
N
F
ACG
Описание Очистить дисплей и установить курсор в нулевую позицию (адрес 0). Установить курсор в нулевую позицию (адрес 0). Установить дисплей относительно буфера DDRAM в начальную позицию. Содержимое DDRAM при этом не меняется. Установить направление сдвига курсора вправо (I/D=1) или влево (I/D=0) при записи/чтении очередного кода в DDRAM. Разрешить (S=1) сдвиг дисплея вместе со сдвигом курсора. Включить(D=1)/выключить(D=0) дисплей. Зажечь(C=1) / погасить(C=0) курсор. Изображение курсора сделать мигающим (B=1). Переместить курсор (S/C=0) или сдвинуть дисплей (S/C=1) вправо (R/L=1) или влево(R/L=0). Установить разрядность шины данных 4 бита (DL=0) или 8 бит (DL=1), количество строк дисплея - одна (N=0) или две (N=1), шрифт - 5х7 точек (F=0) или 5х10 точек (F=1). Установка адреса CGRAM. После этой команды данные будут записываться/считываться в/из CGRAM. Установка адреса DDRAM. После этой команды данные будут записываться/считываться в/из DDRAM. Чтение состояния busy-флага (BF) и счетчика адреса. Запись данных в DDRAM или CGRAM. Чтение данных из DDRAM или CGRAM.
Время исполнения команды (fosc= 250 кГц) 82 мкс до 1,6 мс
40 мкс до 1,6 мс
40 мкс
40 мкс
40 мкс
40 мкс
40 мкс
40 мкс 1 мкс 40 мкс 40 мкс
11 Кроме DDRAM (display data RAM), контроллер ЖКИ содержит еще один блок памяти - знакогенератор CGRAM (character generator 0x0F RAM). Его "прошивка", то есть соответствие кодов символов их на0x11 чертанию, обычно имеется в описании индикатора. Знакогенератор 0x11 состоит из двух частей. Основная его часть представляет собой ПЗУ 0x0F (CGROM) и ее, следовательно, нельзя изменить. Вторая часть, в ко0x05 торой задаются начертания символов для первых 16-ти кодов табли0x09 цы знакогенератора, представляет собой перепрограммируемое ОЗУ 0x11 (CGRAM). Имеется возможность задать начертание 8 символов, со0x00 ответствующих кодам 0(8), 1(9), 2(10) ... 7(15). Для каждого из восьми перепрограммируемых символов в CGRAM отводится по 8 ячеек Рис. 3.5. Пример кодиропамяти, каждая из которых соответствует одной строке точек в изования символа бражении символа. Таким образом, перепрограммируемая часть знакогенератора содержит 64 байта памяти (8х8). Пример кодирования CGRAM для одной буквы приведен на рис. 3.5. Большинство алфавитно-цифровых индикаторов, продающихся на отечественном рынке, уже «прошиты» русифицированным CGROM. В табл. 3.4 приведены англо-русские коды символов таких ЖКИ. Таблица 3.4 Англо-русские коды символов индикаторов МЭЛТ
12 На рис. 3.6 изображена типовая схема подключения ЖКИ, которую можно использовать для AVRмикроконтроллеров, не имеющих возможности подключения внешней памяти данных. В этой схеме управляющие сигналы E и RS формируются программно на обычных линиях ввода/вывода AVR. В приведенном примере шина данных состоит из 4 разрядов. Каждый байт данных при этом, как упоминалось выше, передается за две последовательные посылки, начиная со старшей тетрады. Если передача данных между микроконтроллером и индикатором Рис. 3.6. Типовая схема подключения ЖКИ идет только в одном направлении, то контакт R / W ЖКИ можно замкнуть на общий провод (GND). При этом исчезнет возможность считывать данные с индикатора, однако будет сэкономлен один контакт порта ввода/вывода микроконтроллера. 3.3. Клавиатура Для управления измерителем скорости используется 6кнопочная клавиатура. На рис. 3.7 показано расположение клавиш Esc OK на панели управления. Принципиальная схема подключения клавиатуры матричного типа к микроконтроллеру изображена на рис. 3.8. В данном примере столбцы клавиатуры подключены к старшей тетраде порта B микроконтроллера. Строки клавиатуры подключены к младшей тетраде. Резисторы R1 – R12 предназначены для определения Рис. 3.7. Панель управления уровней логических сигналов на входах МК при нажатии клавиш. В стационарном состоянии старшая тетрада порта B настроена на вывод и находится на низком логическом уровне. Младшая тетрада настроена на ввод с подключенными внутренними «подтягивающими» резисторами. При нажатии на одну из кнопок клавиатуры один из диодов VD1 – VD4 «опускает» на низкий логический уровень линию внешнего прерывания INT0, у которой также подключен внутренний подтягивающий резистор. В момент поступления внешнего прерывания подпрограмма обслуживания этого прерывания должна считывать скан-код клавиши с порта B.
Рис. 3.8. Схема подключения матричной клавиатуры
5.4. Интерфейс с компьютером Обмен информацией между микропроцессорными системами и персональным компьютером (ПК), как правило, производится через последовательный (COM) порт компьютера и
13 УАПП (UART) микроконтроллера по интерфейсу RS232, что позволяет размещать устройство на значительном удалении от компьютера. Интерфейс RS232 использует двунаправленную последовательную асинхронную передачу данных по однонаправленным несимметричным линиям. Интерфейс использует разнополярные сигналы, причем логической единице соответствует уровень – 3…12В, а логическому нулю + 3…12В. Преобразование уровней сигналов RS232 в ТТЛ зачастую реализуется с помощью специализированной микросхемы - приемопередатчика RS232. Большинство таких микросхем имеют 2 и более каналов приема-передачи, из них используется только один, а остальные каналы, а также свободные линии интерфейсного кабеля, остаются незадействованными. При налаживании схемы микропроцессорного устройства и отладки микропрограммы может возникнуть необходимость неоднократной перезаписи программы в память микроконтроллера. Для записи микропрограммы («прошивки») в контроллер, может применяться как параллельный, так и последовательный способ программирования. Параллельный способ предполагает использование сложных аппаратных программаторов, не позволяет программировать МК внутрисхемно, и используется редко. Последовательный способ предполагает использование последовательных способов передачи данных. К достоинствам способа можно отнести простоту аппаратных средств, чаще всего представляющих собой простой преобразователь уровней, возможность программирования в составе изделия, простоту использования аппаратных и программных средств. Память программ многих современных МК выполнена на основе Flash-технологии и позволяет производить многократную перезапись при отладке. Однако в том случае, когда устройство физически удалено от компьютера, либо у компьютера отсутствуют свободные порты, программирование усложняется. Практически все AVR-контроллеры имеют функцию внутрисистемного программирования ISP (In-System Programming) через 3-х проводную шину SPI. Все линии однонаправленные: MOSI – вход данных, MISO – выход данных, SCK - вход тактового сигнала. В некоторых МК этот порт может использоваться и для обмена данными с внешними устройствами. Схема сопряжения, изображенная на рис. 3.9, адаптирована для микроконтроллеров AVR. Она позволяет перепрограммировать микроконтроллер и передавать данные, используя только один COM порт ПК и один интерфейсный кабель. Микросхема DD1 [9] используется для преобразования уровней ТТЛ в RS232 при передаче и RS232 в ТТЛ при приеме информации от ПК. UART микроконтроллера использует для асинхронного обмена данными Рис. 3.9. Схема сопряжения МК и ПК линии RXD и TXD. Остальные линии используются для программирования МК. Схема адаптирована для использования совместно со свободно распространяемой программой PonyProg [16] (автор Claudio Lanconelli, Италия). Переключатель-перемычка SA1 служит для перевода устройства в режим программирования либо в режим обмена данных. Она же защищает контроллер от случайного перепрограммирования. Так, при программировании, сигнал на шине ТХD интерфейса, переводит МК в режим программирования путем подачи низкого уровня на вход RESET. В режиме обмена, по этой линии микроконтроллер принимает данные из ПК. Сигналы ввода и вывода данных при программировании МК MOSI и MISO передаются по линиям CTS и DTR интерфейса. Для согласования их уровней используются свободные буферы DD1. Преобразование уровня сигнала тактирования МК SCK происходит при помощи ограничителя на R1 VD1.
14 Конструктивно схема сопряжения объединяется на одной плате с микроконтроллером. Разъем ХS1 должен быть надежно закреплен к плате или на корпусе устройства для обеспечения механической прочности. Налаживания схема не требует. Микросхемы приемопередатчиков интерфейса RS232 выпускаются многими фирмами, в качестве DD1 могут быть применены MAX202, MAX203, ADM 202, ADM231,ADM232, HIN202, HIN232, ICL232 и многие другие. Однако необходимо уточнить по справочной документации на микросхему расположение выводов и величину емкостей конденсаторов С1…С4. Соединение устройства с ПК выполняют при помощи интерфейсного кабеля с параллельной распайкой контактов. Длина интерфейсного кабеля может достигать 10 метров. Использование нуль-модемного кабеля недопустимо. При настройке программы PonyProg необходимо установить инверсию D-in и D-out в меню Interface Setup (рис. 3.10), поскольку эти сигналы инвертируются DD1, а также указать СОМ-порт, к которому подключено устройство.
Рис. 3.10. Настройки порта в PonyProg
15
4. РАЗРАБОТКА СТРУКТУРНОЙ СХЕМЫ ATmega8 – это 8-битный CMOS-микроконтроллер, основанный на архитектуре AVR RISC. В справочной литературе от Atmel [7] приводится блок-диаграмма его работы.
Рис. 4.1. Блок-диаграмма микроконтроллера ATmega8
На основе блок-диаграммы микроконтроллера и с учетом архитектуры остальных элементов системы разрабатывается структурная схема устройства. Структурная схема определяет основные функциональные части изделия, их назначение и связи. Разработка такой схемы подразумевает определение оптимального состава аппаратных и программных средств для решения поставленной задачи. Структурная схема интеллектуального датчика угловой скорости приведена в приложении А. Оценка скорости производится путем подсчета импульсов с выхода датчика за фиксированный интервал времени t1 . Время t1 необходимо отсчитывать с помощью таймера.
16 При известной частоте тактового генератра микроконтроллера ( CLK = 16МГц ) и разрадности таймера/счетчика 1 ( BitR = 16бит ) найдем интервал времени счета таймера/счетчика 1: t1 =
2 BitR 216 = = 0,004096с. CLK 16 ⋅10 6
Отсюда получим частоту возникновения прерываний от таймера/счетчика 1:
f1 =
1 1 = = 244,140625 Гц. t1 0,004096
Очевидно, что для вычисления угловой скорости можно воспользоваться следующими формулами: V=
mark ⎡ об ⎤ mark ⎡ об ⎤ mark ⎡ рад ⎤ ⋅ f1 ⎢ ⎥ = ⋅ f1 ⋅ 60⎢ = ⋅ f1 ⋅ 2π ⎢ , ⎥ res res res ⎣с ⎦ ⎣ мин ⎦ ⎣ с ⎥⎦
где mark – количество подсчитанных меток за интервал времени t1 ; res – разрешающая способность датчика [мет/об]. Таким образом, в системе задействован всего один таймер – 16-битный таймер/счетчик 1 (timer/counter 1). Этот таймер осуществляет подсчет тактовых импульсов CLK (Clock) частотой 16 МГц от генератора процессорного ядра и через интервалы времени t1 = 0,004096с генерирует запросы на прерывание по переполнению. Так как канал A энкодера подключен к входу внешнего прерывания INT1, а канал B – подключен к информационной линии ввода, то за время t1 в 16-битной регистровой переменной “MarkH:MarkL” накопится количество пройденных меток mark (с учетом знака скорости). Обработчик прерывания от таймера/счетчика 1 вызывает процедуры вычисления скорости. Результат вычислений хранится в регистрах “Float2” (число с плавающей точкой – см. п. 6.1). Переменная “Float2” идет на два канала передачи данных – индикатор и интерфейс УСАПП. Перед выводом на индикатор число с плавающей точкой “Float2” необходимо преобразовать в двоично-десятичный вид и привести в соответствие с ASCIIстандартом (см. п. 6.2). С помощью клавиатуры вводится вся необходимая информация для работы устройства – единицы измерения, настройки интерфейса передачи данных и др. Здесь предусмотрена удобная система меню и «горячих» клавиш. Результаты настройки устройства записываются в регистры “Tunes” (настройки), “ResH:ResL” (разрешающая способность датчика). На время выключения устрйства эти регистры сохраняются в энергонезависимой памяти.
17
5. РАЗРАБОТКА ПРИНЦИПИАЛЬНОЙ СХЕМЫ Схема электрическая принципиальная проектируемого устройства приведена в приложении Б. Главной частью схемы является микроконтроллер DD2 (ATmega8). В него должна быть «зашита» микропрограмма, разработанная в п. 6 проекта. Микроконтроллер DD2 тактируется от внешнего кварцевого генератора на 16 МГц (C6 – ZQ1 – C7). Сброс программы осуществляется с помощью нажатия на кнопку «Сброс» (SA2). При этом на входе RESET контроллера появляется лог. 0 и происходит перезагрузка. Каналы датчика скорости A, B и Index подключены к линиям портов ввода/вывода DD2, соответственно INT1, PB0 и PD4. Данные на знакосинтезирующий жидкокристаллический индикатор, подключенный к разъему XS3, поступают по четырехбитной шине PC0 – PC3. Вход выбора режима «команды/данные» индикатора RS подключен к контакту PC4 микроконтроллера. Стробирующий сигнал E на ЖКИ поступает от PC5. Чтение данных с индикатора в данном случае не используется, поэтому вход R/W индикатора заземлен. Регулирование яркости ЖКИ осуществляется вращением рукоятки переменного резистора R10. При желании R10 можно заменить на малогабаритный подстроечный резистор. Клавиатура состоит из шести кнопок. Столбцы клавиатуры матричного типа (см. п. 3.3) подключаются к линиям PD5 – PD7, строки – к PB1, PB2. При нажатии на одну из клавиш микроконтроллеру поступает запрос на внешнее прерывание по линии INT0. Микросхема преобразования уровней сигналов DD1 (MAX232ACPE) обеспечивает связь с компьютером по двум стандартным интерфейсам (UART и SPI) через COM-порт. Переключение между UART и SPI осуществляется при помощи переключателя SA1. Таким образом, происходит выбор режима устройства – программирование (SPI) или обмен данными (UART). Все элементы схемы питаются от общего сетевого адаптера 5 В, 500 мА. Измеритель скорости включается переключателем SA9 (положение «Вкл.»). При этом зажигается светодиодный индикатор красного свечения HL1.
18
6. РАЗРАБОТКА ПРОГРАММЫ ДЛЯ МИКРОКОНТРОЛЛЕРА Проектирование программы для микроконтроллера ведется в специализированной интегрированной среде разработчика программ для AVR микроконтроллеров – AVR Studio 4.12 Service Pack 4 build 498. Корректная компиляция программы в AVR Studio предыдущих версий не гарантируется. Последнюю версию AVR Studio и Service pack для нее можно загрузить бесплатно на официальном сайте фирмы Atmel [12]. 6.1. Библиотека операций с вещественными числами Библиотека операций над числами с плавающей точкой (вещественными числами) представлена в листинге 1 (приложение Е). В ней используются классические алгоритмы, изложенные в [6]. В целях экономии процессорного времени в данном случае вещественные числа имеют короткий формат (рис. 6.1).
Рис. 6.1. Формат числа с плавающей точкой
Из рис. 6.1 видно, что для представления вещественного числа в памяти микроконтроллера используется 3 байта (24 бита): 16-битная мантисса, 6-битный порядок и 2 знаковых бита. В общем случае для представления вещественного числа используется формула (6.1): A = (± M ) ⋅ N ( ± p ) ,
(6.1)
где M – мантисса числа A. Мантисса должна удовлетворять условию M ≤ 1 ; N – основание системы счисления, представленное целым положительным числом; p – порядок числа, показывающий истинное положение точки в разрядах мантиссы (по этой причине вещественные числа имеют второе название чисел с плавающей точкой, так как ее положение в разрядах мантиссы зависит от значения порядка). Для удобства обработки в ЭВМ чисел с плавающей точкой, на компоненты формулы (6.1) накладываются некоторые ограничения. В данном случае эти условия и ограничения заключаются в следующем: • Основание системы счисления N = 2 . • Мантисса M должна быть представлена в нормализованном виде. То есть, мантисса нормализованного числа должна удовлетворять условию: 1 / N ≤ M < 1 . Это означает, что старший бит представления мантиссы должен быть единичным. Для случая, когда N = 2 это соответствует отношению 1 / 2 ≤ M < 1 или в двоичном виде 0,10...00 ≤ M < 0,11...11 . Для выполнения операций над числами с плавающей точкой необходимо разобраться с наиболее часто используемыми на практике способами перевода дробных чисел. Для этого воспользуемся следующей формулой представления вещественного числа A в системе счисления p [5, (6.3)]:
19 A( p ) = a n−1 ⋅ p n−1 + a n−2 ⋅ p n−2 + ... + a1 ⋅ p1 + a0 ⋅ p 0 + a −1 ⋅ p −1 + a− 2 ⋅ p −2 + ... + a −m ⋅ p − m
(6.2)
Рассмотрим операции перевода чисел на примерах. Пример 1. Перевести в десятичное представление дробь в двоичной системе счисления 110100,010010112 . Для перевода используем формулу (6.2): 110100,010010112 = 1 ⋅ 2 5 + 1 ⋅ 2 4 + 0 ⋅ 2 3 + 1 ⋅ 2 2 + 0 ⋅ 21 + 0 ⋅ 2 0 + 0 ⋅ 2 −1 + 1 ⋅ 2 −2 + 0 ⋅ 2 −3 + 0 ⋅ 2 −4 + + 1 ⋅ 2 −5 + 0 ⋅ 2 −6 + 1⋅ 2 −7 + 1 ⋅ 2 −8. Вычислить целую часть десятичной дроби 1 ⋅ 2 5 + 1 ⋅ 2 4 + 0 ⋅ 2 3 + 1⋅ 2 2 + 0 ⋅ 21 + 0 ⋅ 2 0 = 48 труда не составляет. Для вычисления остальной части выражения удобно использовать табл. 6.1. Таблица 6.1 Значения отрицательных степеней по основанию числа 2
m
2−m
1
0.5
2
0.25
3
0.125
4
0.0625
5
0.03125
6
0.015625
7
0.0078125 и т. д.
Пользуясь табл. 6.1 получим дробную часть числа: 0 ⋅ 2 −1 + 1⋅ 2 −2 + 0 ⋅ 2 −3 + 0 ⋅ 2 −4 + 1 ⋅ 2 −5 + 0 ⋅ 2 −6 + 1⋅ 2 −7 + 1⋅ 2 −8 = 0.29296875. Таким образом, 110100,010010112 = 48,2929687510 . Пример 2. Перевести в двоичную систему счисления десятичную дробь 244,1410 . 1. Переведем целую часть десятичной дроби 244,1410 в двоичную систему счисления (рис. 6.2).
Рис. 6.2
20 2. Переведем дробную часть десятичного числа 244,1410 по алгоритму, показанному на рис. 6.3
Рис. 6.3
Результат перевода следующий: 244,1410 = 11110100,001000112 . Теперь это число несложно преобразовать в шестнадцатеричный вид, разбив его на тетрады. 6.2. Библиотека операций с неупакованными двоично-десятичными числами Арифметико-логическое устройство AVR-микроконтроллеров (как и других микропроцессоров) выполняет элементарные арифметические и логические операции над числами, представленными в двоичном коде. В двоичном коде считываются результаты преобразования АЦП, в двоичном коде (в формате целых чисел или чисел с плавающей точкой) удобно выполнять обработку результатов измерения. Однако, когда окончательный результат отображается на индикаторе, он должен быть преобразован в десятичный формат, удобный для восприятия человеком. В настоящее время распространены два формата представления десятичных чисел в микропроцессорах – упакованный двоично-десятичный код (BCD – Binary-Coded Decimal) и неупакованный десятичный код [6]. Неупакованный десятичный код является подмножеством международной таблицы кодирования символов ASCII (табл. 6.2).
Таблица 6.2 Таблица кодировок десятичных цифр
Десятичная цифра 0 1 2 3 4
Неупакованный BCD-код 0b00000000 0b00000001 0b00000010 0b00000011 0b00000100
ASCII-код 0x30 0x31 0x32 0x33 0x34
Десятичная цифра 5 6 7 8 9
Неупакованный BCD-код 0b00000101 0b00000110 0b00000111 0b00001000 0b00001001
ASCII-код 0x35 0x36 0x37 0x38 0x39
Библиотека операций над неупакованными двоично-десятичными числами представлена в листинге 2 (приложение Е). Эта библиотека содержит всего две подпрограммы. Подпро-
21 грамма"bin2ASCII16" служит для преобразования 16-битного двоичного значения в неупакованный BCD формат и использует алгоритм, изложенный в [6]. Алгоритм программы "bin2ASCII16" заключается в следующем. Предположим, что имеется целое беззнаковое 16-битное число (диапазон от 0 до 65535). Очевидно, что необходимо найти 5 десятичных цифр. Способ преобразования заключается в том, чтобы, вычитая из исходного числа число 10000, сначала определить десятичную цифру десятков тысяч. Затем находится цифра тысяч последовательным вычитанием числа 1000 и т. д. Вычитание каждый раз производится до получения отрицательной разности с подсчетом числа вычитаний. При переходе к определению каждого следующего десятичного разряда в регистрах исходного числа восстанавливается последняя положительная разность. После того, как будет найдена десятичная цифра десятков, в регистрах исходного числа останется десятичная цифра единиц. Процедура "ASCII2Float" предназначена для преобразования дробного неупакованного BCD-числа в формате [XXXX.XXXX] в 24-битный float-формат (см. п. 6.2). В основной программе эта функция вызывается сразу после введения пользователем числовых значений уставок. 6.3. Драйвер знакосинтезирующего ЖКИ Драйвером какого-либо аппаратного узла называют набор подпрограмм, которые учитывают все аппаратные особенности схемы включения этого узла и максимально облегчают работу с ним головной программе. Простейшими составными "кирпичиками" драйвера ЖКИ являются подпрограммы, приведенные в листинге 3 (приложение Е). Первые две из них ("LCDCommand" и "LCDData") для вывода в контроллер индикатора байта команды и байта данных реализуют рассмотренные ранее (п. 3.2) временные диаграммы обмена сигналами между контроллером индикатора и AVR-микроконтроллером. Построение этих подпрограмм целиком зависит от схемы включения индикатора. Подпрограмма инициализации контроллера ЖКИ "InitLCD", посылая в индикатор последовательность команд при помощи подпрограммы "LCDCommand", задает режим работы ЖКИ. Процедура "OutText" выводит в DDRAM индикатора текстовую строку заданной длины по определенному адресу DDRAM. Следует обратить внимание на то, что выводимый текст хранится во flash-памяти программ в виде таблицы. При извлечении данных из этой таблицы указатель адреса приходится умножать на 2. Это происходит из-за того, что память программ, в которой размещается таблица выводимых символов, имеет 16-разрядные ячейки, в каждой из которых хранится по два ASCII-кода данных. Задавая начальный адрес таблицы при помощи директивы .org, мы задаем адрес 16-разрядной ячейки. Но для команды LPM извлечения байта данных из памяти программ требуется задать адрес байта, который, очевидно, в два раза больше адреса слова. Процедура "OutChar" предназначена для вывода одного символа в указанную позицию DDRAM. Подпрограммы "OutBCD" и "OutFBCD" служат для вывода на дисплей чисел в BCD-формате. Процедура "OutFBCD" отличается от "OutBCD" тем, что при ее использовании перед младшей цифрой BCD-числа ставится децимальная точка, а также при необходимости перед числом выводится знак минуса. В данной библиотеке также имеется подпрограмма вывода на индикатор вещественных чисел "OutFloat" и некоторые другие служебные процедуры, в сумме составляющие полный функциональный набор для управления ЖКИ на основе контроллера HD44780. 6.4. Библиотека подпрограмм для работы с клавиатурой и меню Листинг 4 (приложение Е) представляет собой набор подпрограмм для работы с клавиатурой и меню. Подпрограмма “ReadKey” осуществляет сканирование матричной клавиатуры (см. п. 3.3) и работает следующим образом. Сначала осуществляется поиск строки нажатой клави-
22 ши (строки 40 – 43 листинга 4). Из рис. 3.8 следует, что при начальных установках портов на линии искомой строки появится лог. 0. Затем следует перенастройка портов, подключенных к клавиатуре. Теперь строки запрограммированы на выход, а столбцы на вход. Таким образом, в строках 55 – 60 листинга 4 по уже известной технике определяется номер столбца нажатой клавиши. Результат сканирования помещается в регистр “Key” (строка 61). После этого необходимо вернуть порты ввода/вывода в исходное состояние. Подпрограмма “OnAction” (строки 72 – 170) распределяет команды с клавиатуры между обработчиками событий “StateX” в зависимости от текущего состояния устройства. Обработчики событий решают, какие действия необходимо выполнить в ответ на нажатие определенной клавиши. Таким образом, реакция на нажатие клавиш зависит от контекста состояния устройства. В заключение листинга 4 приводятся подпрограммы для смены кадров интерфеса меню, выводимого на индикатор. В табл. 9.1 показаны все возможные варианты кадров меню, отображаемых на дисплее. 6.5. Основная программа В листинге 5 (приложение Е) приведена программа управления интеллектуальным датчиком угловой скорости. Основная программа включает в себя все библиотеки, описанные в п. 6.1 – 6.4, посредством директив препроцессора “.include”. Блок-схема алгоритма микропрограммы приведена в приложении В. В табл. 6.3 приводится описание инициализации устройств системы в соответствии с блок-схемой алгоритма.
Таблица 6.3 Описание инициализации устройств системы
Наименование на блок-схме Настройка стека на вершину RAM Программирование сторожевого таймера Инициализация портов ввода/вывода
Строки кода
Описание
115 – 118
В регистр указателя стека загружается указатель (“RAMEND”) на последнюю ячейку памяти данных
119 – 120
Включение и настройка сторожевого таймера на 2.2 мс
119 – 126
Иницализация ЖКИ
127
Чтение EEPROM
130
Инициализация USART Обновление интерфеса ЖКИ Настройка таймера/счетчика 1 и системы прерываний Сброс сторожевого таймера и ожидание прерываний
131 – 132 133 134 – 160 162 – 165
Установка направлений передачи данных и начальных значений портов ввода/вывода Вызов подпрограммы инициализации ЖКИ “InitLCD” (см. строки 41 – 65 листинга 3) Вызов подпрограммы загрузки из EEPROM регистров датчика – “EEPROM_Read” (см. строки 754 – 862) Если 3-й бит в “Tunes” установлен, то вызывается подпрограмма инициализации USART – “USART_Init” Вывести на дисплей интерфейс измерения скорости – подпрограмма “MeasureInterface” (см. листинг 4) INT1 по переднему фронту, INT0 – по заднему. Установка таймера/счетчика 1 на частоту CLK. Обнуление таймера/счетчика 1. Разрешение прерываний. Бесконечный цикл, в котором программа проводит большую часть времени. Сторожевой таймер используется как защита от «зависания» программы.
Примечание: Строки кода в таблице соответствуют листингу 5
В табл. 6.4 приводится описание обработки прерывания INT1 (канал A датчика) в соответствии с блок-схемой алгоритма.
23 Таблица 6.4 Описание обработки прерывания INT1 (канал A датчика)
Наименование на Строки блок-схме кода Помещение Mark в 190 – 191 стек Определение направ192 ления вращения Скорость положи194 тельна? Декремент/инкремент 195, 200 числа в стке Извлечение из стека 196 – 197, Mark – количества 201 – 202 подсчитанных меток
Описание Помещение “MarkH:MarkL” в стек Проверка состояния канала B энкодера Организация условного оперетора ветвления по состоянию канала B энкодера Вызов одной из подпрограмм “DecSigned16” или “IncSigned16” (см. строки 295 – 351) Модифицированная переменная “MarkH:MarkL” извлекается из стека
Примечание: Строки кода в таблице соответствуют листингу 5
В табл. 6.5 приводится описание обработки прерывания INT0 (клавиатура) в соответствии с блок-схемой алгоритма. Таблица 6.5 Описание обработки прерывания INT0 (клавиатура)
Наименование на блок-схме Получение скан-кода клавиши Реагирование на нажатую клавишу
Строки кода 173 174
Описание Вызов подпрограммы сканирования клавиатуры “ReadKey” (см. строки 34 – 70 листинга 4) Вызов подпрограммы распределения команд с клавиатуры “OnAction” (см. строки 72 – 170 листинга 4)
Примечание: Строки кода в таблице соответствуют листингу 5
В табл. 6.6 приводится описание обработки прерывания по переполнению таймера/счетчика 1 в соответствии с блок-схемой алгоритма. Таблица 6.6 Описание обработки прерывания по переполнению таймера/счетчика 1
Наименование на блок-схме Расчет скорости в Float2 Передача Float2 через USART Обнуление Mark
Строки кода 219 220 221 – 222
Преобразование скорости в BCD-формат
223 – 262
Вывод BCD-числа на ЖКИ
263 – 273
Описание Вызов подпрограммы вычисления скорости в необходимой размерности “GetVelocity” (см. строки 469 – 492) Вызов подпрограммы передачи “Float2” через USART “USART_Transmit” (см. строки 578 – 631) Обнуление регистров “MarkH:MarkL” Домножение скорости на 10, так как на идикаторе перед последней цифрой ставится децимальная точка. Вызов подпрограммы “bin2ASCII16” (см. листинг 2) Вызов подпрограммы вывода BCD на дисплей “OutFBCD” (см. строки 141– 192 листинга 3)
Примечание: Строки кода в таблице соответствуют листингу 5
24 Отдельно рассмотрим основные моменты управления некоторыми устройствами микроконттроллера Atmega8. ¾ Таймер/счетчик 1 Работа таймера/счетчика 1 в программе обеспечивается регистрами (рис. 6.4): • управления таймера/счетчика 1 tccr1a, tccr1b (control registers); • данных tcnt1h:tcnt1l; • маски прерываний timsk (mask register).
Рис. 6.4. Регистры таймера/счетчика 1
В регистре управления tccr1b находятся биты для подключения входа таймера/счетчика 1: биты 2..0 – cs12, cs11, cs10 (clock select). В табл. 6.7 приведены возможные варианты тактирования таймера/счетчика 1. Таблица 6.7 Управление входом таймера/счетчика 1
cs12 cs11 cs10 0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1 1 1
Описание Останов таймера/счетчика 1 CLK CLK/8 CLK/64 CLK/256 CLK/1024 Внешний контакт T1. Задний фронт импульса. Внешний контакт T1. Передний фронт импульса.
Как видно из табл. 6.7, для подключения входа таймера/счетчика 1 к тактовому генератору процессорного ядра необходимо установить биты cs12, cs11, cs10 в состояние 0b001, а для останова счета – в 0b000. Регистры данных tcnt1h:tcnt1l образуют 16-разрядный регистр, содержащий текущее значение 16-разрядного таймера/счетчика 1. Для сброса счетчика нужно записать в оба регистра значение 0. Для разрешения прерывания при переполнении счетчика необходимо установить бит TOIE1 в регистре маски прерываний timsk.
25 ¾ Энергонезависимая память EEPROM Работа с EEPROM в программе обеспечивается регистрами (рис. 6.5): • адреса EEPROM eearh:eearl (address registers); • данных eedr (data register); • управления eecr (control register).
Рис. 6.5. Регистры EEPROM
Регистры адреса eearh:eearl позволяют адресовать до 512 байт памяти EEPROM. Регистр данных eedr хранит данные для записи в EEPROM при выполнении операции записи или данные, считанные из EEPROM, при выполнении операции чтения. Бит eemwe регистра управления EEPROM eecr определяет, будет ли установленный в состояние 1 бит eewe разрешать запись в EEPROM. При установленном в состояние 1 бите eemwe установка бита eewe приведет к записи в EEPROM по заданному адресу. ¾ Интерфейс USART Работа с USART в программе обеспечивается регистрами (рис. 6.6): • данных udr (data register); • управления и статуса ucsra, ucsrb, ucsrc (control and status registers); • скорости передачи ubrrh:ubrrl (baud rate registers).
26
Рис. 6.6. Регистры USART
Регистр данных udr хранит данные для передачи или принятые данные в зависимости от режима работы USART. Регистры ubrrh:ubrrl определяют скорость обмена данными. Рекомендуемые значения для записи в ubrrh:ubrrl приведены в [7]. Бит udre регистра управления и статуса ucsra определяет готовность буфера USART для приема/передачи и по сути является стробом. Для включения передачи данных необходимо установить бит txen регистра управления и статуса ucsrb. Бит usbs регистра управления и статуса ucsrc определяет количество стоп-битов («0» - 1 стоп-бит; «1» - 2 стоп-бита). Биты ucsz1 и ucsz0 необходимо установить для 8битной передачи.
27
7. ОТЛАДКА ПРОГРАММЫ После написания программы ее необходимо откомпилировать. В результате компиляции будут сформированы несколько файлов: 1. Файл прошивки flash-памяти (Encoder.hex); 2. Файл прошивки EEPROM-памяти (Encoder.eep); 3. Файл листинга программы (Encoder.lst) и др. Файл листинга содержит информацию о ходе компиляции, а также статистику по использованию средств микроконтроллера. Из листинга программы видно, что использовано: 1. 91.4 % регистров; 2. 59.3 % инструкций микроконтроллера; 3. 92.7 % flash-памяти; 4. 2.0 % EEPROM-памяти Эта статистика является хорошим показателем по использованию основных ресурсов микроконтроллера. Таким образом, делаем вывод, что микроконтроллер для проекта выбран правильно. Используя интегрированную отладочную среду AVR Studio 4 смоделируем работу спроектированной системы и докажем ее работоспособность. На рис. 7.1 изображены регистры и порты ввода/вывода микроконтроллера сразу после инициализации всех устройств (строки 1 – 160 листинга 5).
Рис. 7.1. Регистры и порты ввода/вывода микроконтроллера после инициализации устройств
На рис. 7.2 показано состояние регистров общего назначения перед выводом скорости на дисплей (при отображении в об/с).
28
Рис. 7.2. Регистры общего назначения перед выводом скорости на дисплей (при отображении в об/с)
Абсолютное значение скорости храниться в регитрах tASCIIX: R15 R14 R13 R16 . R11. Децимальная точка ставится перед последней цифрой – R11. Из рис. 6.8 видно, что скорость, выводимая на индикатор составляет 49.9 об/с. Знак скорости хранится в памяти RAM с адресом 0x60 (на рисунке не показан, так как равен 0). На рис. 7.3 показано состояние регистров общего назначения перед выводом скорости на дисплей (при отображении в об/мин).
Рис. 7.3. Регистры общего назначения перед выводом скорости на дисплей (при отображении в об/мин)
Из рис. 7.3 видно, что скорость, выводимая на индикатор составляет 2999.8 об/мин. На рис. 7.4 показано состояние регистров общего назначения перед выводом скорости на дисплей (при отображении в рад/с).
Рис. 7.4. Регистры общего назначения перед выводом скорости на дисплей (при отображении в рад/с)
Из рис. 7.4 видно, что скорость, выводимая на индикатор составляет 314.0 рад/с.
29
8. РАЗРАБОТКА ПРИЛОЖЕНИЯ ДЛЯ ПЕРСОНАЛЬНОГО КОМПЬЮТЕРА Одним из основных достоинств предлагаемого датчика скорости является возможность его сопряжения с персональным компьютером (ПК). Это позволяет непрерывно получать данные с устройства и в режиме реального времени представлять эти данные в цифровом и графическом виде. Таким образом, основной задачей данного раздела проекта является разработка Windows-приложения, предназначенного для приёма, регистрации и анализа информации о скорости механизма, принимаемой с последовательного порта по интерфейсу RS232. Приложение для ПК проектируется в интегрированной среде разработки Borland Delphi 7 – одной из самых популярных RAD-систем (Rapid Application Development System). При написании исходного кода программы будем использовать язык Object Pascal и встроенный в него интерпретатор языка ассемблера. Полный текст программы и откомпилированный исполняемый файл Вы можете найти на прилагаемом компакт-диске. Здесь же мы лишь остановимся на наиболее принципиальных моментах, связанных с использованием функций Windows API для реализации приёмо-передачи по COM-порту. На рис. 8.1 показан внешний вид работающей программы для связи с контроллером интеллектуального датчика скорости.
Рис. 8.1. Внешний вид работающей программы
Как можно заметить на рис. 8.1, в рабочем поле программы помещён стандартный компонент VCL (Visual Component Library) класса TChart, предназначенный, в данном случае, для отображения и анализа переходных процессов по скорости. Главное меню приложения содержит команды управления приёмо-передачей, настройки интерфейса и отображения данных, команды сохранения графика скорости в форматах изображения Windows Bitmap и
30 электронной таблицы MS Excel. Также предусмотрена подробная справочная система, включающая в себя Tutorial (быстрое обучение). Рассмотрим асинхронный режим чтения и записи COM-порта на примерах из исходного кода нашей программы. Первая проблема, которую предстоит решить, – это преобразование 24-битного числового формата, принятого в п. 6.1 для микроконтроллера, в стандартный PC-совместимый 64-битный формат числа с плавающей точкой (тип “Real” в Object Pascal). Функция “ FloatConvert”, решающая эту задачу, приведена в листинге 6. Её алгоритм основан на побитном выделении из 24-битного поля исходного числа мантииссы, знака мантиссы, порядка и знака порядка. Итак, порядок запуска и работы "службы" (назовем все описываемое ниже так) COMпортов состоит из нескольких достаточно хорошо известных шагов: 1) Инициализация COM-порта посредством вызова функции CreateFile; 2) Установка параметров COM-порта посредством последовательного вызова функций GetCommState и SetCommState, а также SetupComm; 3) Установка параметров тайм-аутов для чтения и записи - GetCommTimeouts и SetCommTimeouts; 4) Собственно записи в COM-порт – WriteFile и чтения из него - ReadFile; 5) Закрытие порта по окончанию работ CloseHandle. Очень большой сложности описанные выше шаги не представляют, однако реализация чтения данных из порта в асинхронном (неблокирующем) режиме заставляет задуматься. Об этом и пойдёт речь далее. Судя по контексту справки, касающейся функции CreateFile, для "отлова" момента поступления данных в COM-порт следует использовать функцию WaitCommEvent. Предварительно установив маску SetCommMask на то событие, которое хотелось бы отследить. Нужное событие наступает - вызываем функцию ReadFile для чтения поступающих данных. Казалось бы все в порядке, но... Вызов функции WaitCommEvent «наглухо» тормозит приложение, пока какие-либо данные не поступят в COM-порт. Как выход из ситуации многие специалисты предлагают использовать потоки (thread), забывая при этом описать как это делать. В модуле Classes для потоков определен специальный класс TThread. Для создания потоков специалисты рекомендуют использовать именно его, а не создавать потоки используя BeginThread и EndThread, так как библиотека VCL не является защищенной для потоков в такой реализации. Следуя советам экспертов, для организации контроля поступающих данных в COM-порт и будем использовать готовый класс TThread (листинг 7). В разделе interface определим тип переменных этого класса, переопределив только один метод класса - Execute, и дополнительно объявим свой метод, который и займется опросом COM-порта. Далее в разделе глобальных переменных определим поток-переменную полученного типа TComThread. Опишем порядок использования получившегося класса TComThread: 1) Инициализируем поток, используя метод Create запуском процедуры StartComThread; 2) Запускаем процедуру опроса порта в нашем потоке (TCommThread.Execute); 3) Реализуем асинхронные опрос порта и чтение из него данных (TCommThread.QueryPort).
31
9. ТЕСТИРОВАНИЕ После сборки интеллектуального датчика скорости и «прошивания» микроконтроллера необходимо проверить правильность работы всего устройства в целом. Вал приводящего двигателя и вал энкодера необходимо совместить, обеспечив точное центрирование. Если два вала не могут быть точно сопряжены или ось вращения вала не совпадает с его геометрической осью, то в этих случаях вал поворотного шифратора должен соединяться с ведущим валом посредством гибких соединительных муфт [3]. Для измерения линейной скорости объекта на вал энкодера необходимо насадить специальное мерное колесо [3] (рис. 9.3). В этом случае необходимо в контроллере датчика выбрать единицы измерения «см/с» и ввести коэффициент передачи механизма по скорости. Этот коэффициент вычисляется следующим образом: для измерения линейной скорости: К ЛИН = радиус _ мерного _ колеса, [см]; для измерения угловой скорости: радиус _ мерного _ колеса, [см] К УГЛ = . радиус _ поверхности _ объекта, [см] Для тестирования интеллектуальный датчик угловой скорости в качестве анализатора переходных процессов был встроен в лабораторный стенд по исследованию студентами характеристик электропривода постоянного тока ЭШИР-1А (рис. 9.1). На рис. 8.1 изображены переходные процессы, снятые с этого электропривода.
Рис. 9.1. Лабораторный стенд ЭШИР-1А с анализатором переходных процессов
32
Рис. 9.2. Упрощённая схема иерархии встроенного меню контроллера датчика
Рис. 9.3. Применение мерный колёс для измерения линейной и угловой скорости
Таблица 9.1 иллюстрирует работу интеллектуального датчика скорости при угловой частоте вращения приводящего вала ω = 15об / с . Для навигации по меню контроллера датчика можно воспользоваться упрощённой схемой иерархии встроенного меню, изображённой на рис. 9.2.
33 Таблица 9.1 Тестирование интеллектуального датчика скорости
Шаг
Нажатая клавиша
Действие
1
Вкл. (SA9)
2
Вправо
3
Вправо
4
Вправо
5
OK
Вызов меню
6
ОК
Выбор пункта меню «Размерность»
7 8 9 10
11
12 13 14 15
16
Включение устройства Быстрое переключение единиц измерения Быстрое переключение единиц измерения Быстрое переключение единиц измерения
Прокрутка меню до пункта «Коэф. передачи» Ввод коэффициента передачи между Введите число 1.0 валом двигателя и энкодером (если в поле ввода на одном валу, то 1.0) Выход из подменю «Размерность», Esc, вниз прокрутка меню вниз Выбор пункта меню «Точность», OK, вниз, вниз прокрутка вниз до подпункта «Автокалибровка» Автокалибровка датчика. Система сама подбирает оптимальное соотношение между частотой обновлеOK ния данных и их допустимой погрешностью Выход из подменю «Точность», Esc, вниз прокрутка меню вниз Выбор пункта меню «Интерфейс», OK, вниз прокрутка меню вниз Выбор подменю «Скорость обмена», OK, 7 раз вниз прокрутка меню вниз до упора Выбор скорости обмена по интерOK, OK, 3 раза фейсу. Вызов меню, прокрутка до вниз упора вниз. Выбор пункта меню «Самодиагностика». Определение разрешающей способности энкодера, вывод ее на дисплей, временная задержка и возOK вращение к измерению скорости. Применяется при замене первичного преобразователя (энкодера). 4 раза вниз
Содержимое индикатора
Скорость: ◄► ₣▓ 0902.0 об/мин i Скорость: ◄► ₣▓ 0015.0 об/с i Скорость: ◄► ₣▓ 0015.0 см/с i Скорость: ◄► ₣▓ 0094.5 рад/с i █ Меню █ ▼▲ ₣ * ►Размерность ↓ █ Меню █ ▼▲ ₣ * ►об/мин ↓ см/с ↑ ►Коэф. передачи↓ 1.0000 ██₣0123456789.←↓ Размерность ►Точность
↑ ↓
Погрешность ↑ ►Автокалибровка Погрешность ↑ ►Автокалибровка Точность ↑ ►Интерфейс ↓ Включить ↑ ►Скорость обмена 57600 бод ↑ ►115200 бод Интерфейс ↑ ►Самодиагностика
Энкодер: 01000 мет/об
Примечание: клавиши «Вправо» и «Влево» при измерении скорости позволяют быстро переключать единицы измерения (об/с; об/мин; рад/с; см/с).
34
ЗАКЛЮЧЕНИЕ В представленной работе содержится вся ключевая информация по практически завершенному инновационному проекту: разработаны все схемы, программы, конструкторская документация, необходимые для внедрения разработки в производство. В результате проектирования собран макетный образец устройства, который был испытан в реальных условиях при электромагнитных помехах от двигателей и вентильного преобразователя. Себестоимость готового устройства оказалась довольно низкой, следовательно, разработка легко может найти свою нишу на рынке интеллектуальных измерительных устройств. Этому также будет способствовать универсальность и адаптивность датчика. Предполагается реализация представленной идеи на уровне коммерческой разработки с финансированием по венчурным схемам. Результаты разработки неоднократно докладывались на научно-технических конференциях и семинарах, представлялись на конкурсы инновационных проектов, где были отмечены дипломами и свидетельствами участника, копии которых приведены в приложениях Ж, З и И.
35
СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
Микропроцессоры в электроприводе: Методические указания к курсовому проектированию / сост. А. М. Водовозов – Вологда: ВоГТУ, 2006. – 20 с. Водовозов, А. М. Микроконтроллеры для систем автоматики: Учебное пособие / А. М. Водовозов. – Вологда: ВоГТУ, 2002. – 128 с. Жданкин, В. К. Поворотные шифраторы: основные типы и некоторые особенности применения / В. К. Жданкин // Современные технологии автоматизации. – 2001. - №2. – с. 68 – 79. Жданкин, В. К. Поворотные шифраторы фирмы Pepperl+Fuchs / В. К. Жданкин // Современные технологии автоматизации. – 2001. – №3. – с. 6 – 24. Юров, В. Assembler / В. Юров. – СПб.: Питер, 2000. – 624 с: ил. Злобин В. К., Григорьев В. П. Программирование арифметических операций в микропроцессорах., М.: Высш. шк., 1991. - 303с. 8-bit AVR with 8K bytes In-System Programmable Flash ATmega8(L). – Режим доступа: http://www.atmel.com AVR240: 4 x 4 Keypad – Wake-up on Keypress, 8-bit AVR microcontroller. Application note. – Режим доступа: http://www.atmel.com MAX220-MAX249. +5V – Powered, Multichannel RS232 Drivers/Receivers. Datasheet. – Режим доступа: http://www.maxim-ic.com Русскоязычный сайт фирмы Bourns. – Режим доступа: http://www.bourns.ru Платан, интернет-магазин. – Режим доступа: http://www.platan.ru Официальный сайт фирмы Atmel. – Режим доступа: http://www.atmel.com Русскоязычный сайт фирмы Atmel. – Режим доступа: http://www.atmel.ru Официальный сайт компании Microchip LTD. – Режим доступа: http://www.microchip.com Algorithm Builder for AVR. – Режим доступа: http://www.algrom.net PonyProg Programmer. – Режим доступа: http://www.lancos.com
36
ПРИЛОЖЕНИЯ
Запись
DDRAM ЖКИ
Линии столбцов и строк клавиатуры
Компьютер
+30H Запись
Преобразование Float2 в BCD-формат (регистры tASCII)
Обработка прерывания от клавиатуры. Определение сканкода и выбор действия
INT0 Клав-ра
Интерфейс RS232 Регистр данных USART - UDR Запись
Запись Чтение
Регистр настройки устройства Tunes
Расчет скорости в необходимой размерности (регистры Float2) Чтение
Разрешающая способность энкодера Чтение (регистры ResH:ResL)
Вызов Канал B Обнуление INT1 Канал A
Обработка внешнего прерывания. Распознание знака скорости.
±1
Регистры количества меток (регистры MarkH:MarkL)
Чтение
Обработка прерывания от Т/С 1 CLK
Таймер/счетчик 1
Переполнение
КП. 140604. 1019. 22. Э1 Лит. Изм. Лист
№ докум.
Разраб.
Шатков А. П.
Пров.
Водовозов А. М.
Т. контр. Н. контр. Утв.
Подп.
Дата
Измеритель скорости. Схема структурная
Масса
1:1
у
Лист
Масштаб
Листов 1
ВоГТУ ЭП-41
Обработка прерывания от таймера Основная программа
Начало
Начало Расчет скорости в Float2 Настройка стека на вершину RAM
Передача Float2 через USART
Программирование сторожевого таймера
Обработка прерывания INT1
Инициализация портов ввода/вывода
Начало
Инициализация ЖКИ
Помещение Mark в стек
Чтение EEPROM
Определение направления вращения Скорость положительна ?
Инициализация USART
Обнуление Mark
Преобразование скорости в BCD-формат Вывод BCD-числа на ЖКИ
Выход из прерывания да
нет
Обновление интерфейса дисплея ЖКИ
Декремент числа в стеке
Настройка таймера/ счетчика 1 и системы прерываний
Извлечение из стека Mark - количества подсчитанных меток
Сброс сторожевого таймера и ожидание прерываний
Инкремент числа в стеке
Обработка прерывания INT0
Выход из прерывания
Конец
Начало
Получение скан-кода клавиши Реагирование на нажатую клавишу
Выход из прерывания
КП. 140604. 1019. 22. Э1 Изм. Лист
№ докум.
Разраб.
Шатков А. П.
Пров.
Водовозов А. М.
Т. контр. Н. контр. Утв.
Подп.
Дата
Измеритель скорости. Схема алгоритма программы.
Лит.
Масса
1:1
у
Лист 1
Масштаб
Листов 1
ВоГТУ ЭП-41
45
Приложение Е. Листинги программ Листинг 1. Библиотека операций над числами с плавающей точкой <1> <2> <3> <4> <5> <6> <7> <8> <9> <10> <11> <12> <13> <14> <15> <16> <17> <18> <19> <20> <21> <22> <23> <24> <25> <26> <27> <28> <29> <30> <31> <32> <33> <34> <35> <36> <37> <38> <39> <40> <41> <42> <43> <44> <45> <46> <47> <48> <49> <50> <51> <52> <53> <54> <55> <56> <57> <58> <59> <60> <61> <62> <63> <64> <65> <66> <67> <68> <69> <70> <71> <72> <73> <74> <75> <76>
;=============================================================================== ; Файл: Float.inc ; Библиотека подпрограмм для операций над числами с плавающей точкой ;=============================================================================== ; ; ; ; ; ;
Формат числа с плавающей точкой: 3 байта 1ый - порядок : бит 7 - знак числа (1 - отрицательное число) 6 - знак порядка (1 - положительное число) 0..5 - значение порядка 2ой - младший байт мантиссы 3ий - старший байт мантиссы
; !!! Эти переменные должны быть определены в основной программе !!! ;.def ;.def ;.def ; ;.def ;.def ;.def
Float1O = r16 Float1L = r17 Float1H = r18
;.def ;.def ;.def ;.def
FTempO FTempL FTempH FCnt
Float2O = r19 Float2L = r20 Float2H = r21 = = = =
r22 r23 r24 r25
;******************************************************************************* ; Fix2Float - перевод целого числа в число с плавающей точкой ; Float2Fix - перевод числа с плавающей точкой в целое число ; FNeg - смена знака числа с плавающей точкой: Float2 = -Float2 ; SwapFl - обмен Float1 и Float2 ; FAdd - сложение чисел с плавающей точкой: Float2 = Float2 + Float1 ; FSub - вычитание чисел с плавающей точкой: Float2 = Float2 - Float1 ; FMult - умножение чисел с плавающей точкой: Float2 = Float2 * Float1 ; FDiv - деление чисел с плавающей точкой: Float2 = Float1 / Float2 ;******************************************************************************* ;------------------------------------------------------------------------------; Перевод целого числа в число с плавающей точкой ; Вход - 2-байтное число в Float2L, Float2H ; Выход - 3-байтное число с плавающей точкой в Float2 ; Используемые регистры - Float2O,Float2L,Float2H ;------------------------------------------------------------------------------Fix2Float: clc ; Обнуление переноса tst Float2L ; Проверка число на 0 brne Fx2Fl_A tst Float2H brne Fx2Fl_A ldi Float2O, 0x40 ; Если Float2L = Float2H = 0 установить число в 0 ret Fx2Fl_A: ldi Float2O, 0x50 ; Если целое число # 0 установить поядок в 50H Fx2Fl_B: sbrc Float2H, 7 ; Пропустить, если бит 7#0 ret ; Иначе - возврат rol FLoat2L ; Сдвиг числа влево rol Float2H dec Float2O ; Декремент порядка rjmp Fx2Fl_B ; Продолжать, пока бит 7#1 ;------------------------------------------------------------------------------; Перевод числа с плавающей точкой в целое число ; Вход - Float2 ; Выход - Float2L, Float2H ; carry = 1, если есть переполнение ; Используемые регистры - Float2O, Float2L, Float2H ;------------------------------------------------------------------------------Float2Fix: sbrc Float2O, 7 ; Проверка знака числа rjmp SetOverflow ; Для отрицательного числа установить переполнение sbrs Float2O, 6 ; Проверка знака порядка rjmp Float2eq0 ; Для отрицательного порядка установить число в 0 andi Float2O, 0x3f ; Маскирование знаковых битов
46 <77> <78> <79> <80> <81> <82> <83> <84> <85> <86> <87> <88> <89> <90> <91> <92> <93> <94> <95> <96> <97> <98> <99> <100> <101> <102> <103> <104> <105> <106> <107> <108> <109> <110> <111> <112> <113> <114> <115> <116> <117> <118> <119> <120> <121> <122> <123> <124> <125> <126> <127> <128> <129> <130> <131> <132> <133> <134> <135> <136> <137> <138> <139> <140> <141> <142> <143> <144> <145> <146> <147> <148> <149> <150> <151> <152> <153> <154> <155> <156>
cpi brlo rjmp Fl2Fx_A: subi neg Fl2Fx_C: clc tst brne ret Fl2Fx_B: ror ror dec rjmp
Float2O, 0x11 Fl2Fx_A SetOverflow
; Проверка максимального порядка ; Перейти, если порядок < 11H ; Иначе, установить переполнение
Float2O, 0x10 Float2O
; Float2O = 10H - Float2O
Float2O Fl2Fx_B
; Обнулить перенос ; Проверка порядка ; Возврат, если порядок = 0
Float2H Float2L Float2O Fl2Fx_C
; Сдвиг вправо ; Декремент порядка ; Повторять, пока порядок # 0
Float2eq0: clr Float2L clr Float2H ret ;------------------------------------------------------------------------------; Смена знака числа с плавающей точкой: Float2 = -Float2 ; Вход - Float2 ; Выход - Float2 ; Используемые регистры - Float2O, Float2L, Float2H ;------------------------------------------------------------------------------FNeg: neg Float2O subi Float2O, 0x80 neg Float2O clc ret ;------------------------------------------------------------------------------; Обмен Float1 и Float2 ;------------------------------------------------------------------------------SwapFl: eor Float1O, Float2O eor Float2O, Float1O eor Float1O, Float2O eor Float1L, Float2L eor Float2L, Float1L eor Float1L, Float2L eor Float1H, Float2H eor Float2H, Float1H eor Float1H, Float2H ret ;------------------------------------------------------------------------------; Сложение чисел с плавающей точкой: Float2 = Float2 + Float1 ; Вход - Float1, Float2 ; Выход - Float2 ; Используемые регистры - Float1O, Float1L, Float1H, Float2O, Float2L, Float2H ;------------------------------------------------------------------------------FAdd: sbrc Float1O, 7 ; Пропустить, если Float1 > 0 rjmp FAdd_A ; Перейти, если Float1 < 0 sbrs Float2O, 7 ; Пропустить, если Float2 < 0 rjmp FAdd_B ; Перейти, если FLoat1 и Float2 < 0 ; Если знаки чисел не равны (Float1 > 0, Float2 < 0 или Float1 < 0, Float2 > 0) ; Если Float1 > 0, Float2 < 0, результат = Float1 - Float2 FAdd_C: rcall FNeg ; Смена знака Float2 rcall SwapFl rjmp FSub ; Вызов подпрограммы вычитания ; Если Float1 < 0, Float2 > 0, результат = Float2 - Float1 FAdd_X: rcall SwapFl ; Смена знака Float1 rcall FNeg rcall SwapFl rjmp FSub FAdd_A: sbrs Float2O, 7 ; Пропустить, если Float1 < 0 и Float2 < 0 rjmp FAdd_X ; Если знаки чисел равны FAdd_B: tst Float1H ; Проверка Float1 на 0 brne FAdd_D
47 <157> <158> <159> <160> <161> <162> <163> <164> <165> <166> <167> <168> <169> <170> <171> <172> <173> <174> <175> <176> <177> <178> <179> <180> <181> <182> <183> <184> <185> <186> <187> <188> <189> <190> <191> <192> <193> <194> <195> <196> <197> <198> <199> <200> <201> <202> <203> <204> <205> <206> <207> <208> <209> <210> <211> <212> <213> <214> <215> <216> <217> <218> <219> <220> <221> <222> <223> <224> <225> <226> <227> <228> <229> <230> <231> <232> <233> <234> <235> <236>
tst Float1L brne FAdd_D ret FAdd_D: tst Float2H brne FAdd_E tst Float2L brne FAdd_E rjmp Fl1toFl2 FAdd_E: cp Float2O, Float1O breq FAdd_G brlo FAdd_F rcall SwapFl FAdd_F: sub Float2O, Float1O neg Float2O cpi Float2O, 0x10 brlo FAdd_H rjmp Fl1toFl2 FAdd_H: clc ror Float2H ror Float2L dec Float2O brne FAdd_H ; Если порядки равны FAdd_G: add Float2L, Float1L adc Float2H, Float1H brcs FAdd_I FAdd_J: mov Float2O, Float1O ret FAdd_I: ror FLoat2H ror Float2L inc Float1O rjmp FAdd_J
; Если Float1 = 0, результат = Float2 ; Проверка Float2 на 0
; Если Float2 = 0, копировать Float1 как результат ; ; ; ;
Сравнение порядков Если порядки равны Если Float2O < Float1O Иначе поменять числа
; Float2O = Float1O - Float2O ; Если Float1O - Float2O < 16 ; Иначе copy Float1 копировать Float1 как результат ; Обнуление переноса ; Сдвиг Float2 вправо ; Декремент порядка ; Повторять, пока порядок > 0 ; Сложение чисел ; Перейти, если установлен перенос ; Копирование значения порядка ; и возврат ; Сдвиг Float2 вправо ; Инкремент порядка
;------------------------------------------------------------------------------; Вычитание чисел с плавающей точкой: Float2 = Float2 - Float1 ; Вход - Float1, Float2 ; Выход - Float2 ; Используемые регистры - Float1O, Float1L, Float1H, Float2O, Float2L, Float2H ;------------------------------------------------------------------------------FSub: sbrc Float1O, 7 ; Пропустить, если Float1 > 0 rjmp FSub_A ; Перейти, если Float1 < 0 sbrs Float2O, 7 ; Пропустить, если Float2 < 0 rjmp FSub_B ; Перейти, если Float1 > 0 и Float2 > 0 ; Если знаки чисел не равны FSub_C: rcall SwapFl rcall FNeg ; Смена знака 2го числа rcall SwapFl rjmp FAdd ; Вызов подпрограммы вычитания FSub_A: sbrs Float2O, 7 ; Пропустить, если Float2 < 0 и Float1 < 0 rjmp FSub_C ; Перейти, если Float2 > 0 (Float1 < 0) ; Если знаки чисел равны FSub_B: tst Float1H ; Проверка Float1 на 0 brne FSub_D tst Float1L brne FSub_D ret ; Если Float1 = 0, результат = Float2 FSub_D: tst Float2H ; Проверка Float2 на 0 brne FSub_E tst Float2L brne FSub_E rcall Fl1toFl2 ; Если FLoat2 = 0, результат = -Float1 rjmp FNeg ; Смена знака и возврат FSub_E: clt cp Float1O, Float2O ; Сравнение порядков breq FSub_G ; Если порядки равны brlo FSub_F ; Если Float1O < Float2O set ; Установить флаг
48 <237> <238> <239> <240> <241> <242> <243> <244> <245> <246> <247> <248> <249> <250> <251> <252> <253> <254> <255> <256> <257> <258> <259> <260> <261> <262> <263> <264> <265> <266> <267> <268> <269> <270> <271> <272> <273> <274> <275> <276> <277> <278> <279> <280> <281> <282> <283> <284> <285> <286> <287> <288> <289> <290> <291> <292> <293> <294> <295> <296> <297> <298> <299> <300> <301> <302> <303> <304> <305> <306> <307> <308> <309> <310> <311> <312> <313> <314> <315> <316>
rcall SwapFl FSub_F: sub Float1O, Float2O neg Float1O cpi Float1O, 0x10 brlo FSub_H ret ; Уравнение порядков FSub_H: clc ror Float1H ror Float1L dec Float1O brne FSub_H brtc FSub_G rcall SwapFl clt FSub_G: cp Float2L, Float1L cpc Float2H, Float1H brlo FSub_I FSub_J: sub Float2L, Float1L sbc Float2H, Float1H sbrc Float2H, 7 ret rjmp Fx2Fl_B FSub_I: rcall SwapFl rcall FNeg rjmp FSub_J ror FLoat2H ror Float2L inc Float2O rcall FNeg ret
; Смена чисел, если Float1O > Float2O ; Float1O = Float2O - Float1O ; Если Float2O - Float1O < 16 ; Иначе результат = Float2
; Сдвиг Float1 вправо ; Повторять, пока порядки не равны ; ; Снова поменять числа
; Сложение чисел ; Пропустить, если MSB = 0 ; Иначе - выход ; Нормализация резльтата ; Поменять числа ; Смена знака результата ; Сдвиг Float2 вправо ; Инкремент порядка ; и смена знака ; Иначе - выход
;------------------------------------------------------------------------------; Умножение чисел с плавающей точкой: Float2 = Float2 * Float1 ; Вход - Float1, Float2 ; Выход - Float2 ; Используемые регистры - Float1O, Float1L, Float1H, Float2O, Float2L, Float2H ; FTempO, FTempL, FCnt ;------------------------------------------------------------------------------FMult: tst Float1H ; Проверка Float1 на 0 brne FMul_A tst Float1L brne FMul_A rjmp SetRes0 ; Если Float1 = 0, установить Float2 = 0 и возврат FMul_A: tst Float2H ; Проверка Float2 на 0 brne FMul_B tst Float2L brne FMul_B ret ; Если Float2 = 0 - возврат FMul_B: mov FTempO, Float1O ; Поиск знака результата eor FTempO, Float2O ; FTempO бит 7 равен знаку результата cbr Float1O, 0x80 ; Сброс знаков чисел cbr Float2O, 0x80 bst FTempO, 7 ; Сохранение знака результата в T add Float2O, Float1O ; Сложение порядков ldi Float1O, 0x40 ; add Float2O, Float1O bld Float2O, 7 ; 16x16 bits unsigned multiplication from ****AVR200**** application note FMul_D: clr FTempO ; Обнуление двух старших байт результата clr FTempL ldi FCnt,16 ; Инициализация счетчика цикла lsr Float2H ror Float2L FMul_E: brcc FMul_F ; Если бит 0 множителя установлен add FTempO, Float1L ; Сл-е мл-го байта множимого с байтом 2 результата adc FTempL, Float1H ; Сл-е ст-го байта множимого с байтом 3 результата FMul_F: ror FTempL ; Сдвиг вправо байта 3 результата ror FTempO ; Сдвиг вправо байта 2 результата
49 <317> <318> <319> <320> <321> <322> <323> <324> <325> <326> <327> <328> <329> <330> <331> <332> <333> <334> <335> <336> <337> <338> <339> <340> <341> <342> <343> <344> <345> <346> <347> <348> <349> <350> <351> <352> <353> <354> <355> <356> <357> <358> <359> <360> <361> <362> <363> <364> <365> <366> <367> <368> <369> <370> <371> <372> <373> <374> <375> <376> <377> <378> <379> <380> <381> <382> <383> <384> <385> <386> <387> <388> <389> <390> <391> <392> <393> <394> <395> <396>
ror Float2H ; Сдвиг вправо байта 1 результата и множителя High ror Float2L ; Сдвиг вправо байта 0 результата и множителя Low dec FCnt ; Декремент счетчика цикла brne FMul_E ; Если не закончен, следующая итерация цикла ; После умножения - нормализация результата FMul_H: sbrc FTempL, 7 rjmp FMul_G ; Перейти, если результат нормализован rol Float2L ; Сдвиг числа влево rol Float2H rol FTempO rol FTempL dec Float2O ; Декремент порядка результата rjmp FMul_H FMul_G: bld Float2O, 7 ; Загрузить знак результата из T mov Float2L, FTempO ; Копирование мантиссы в результат mov Float2H, FTempL ret ;------------------------------------------------------------------------------; Деление чисел с плавающей точкой: Float2 = Float1 / Float2 ; Вход - Float1, Float2 ; Выход - Float2 ; Используемые регистры - Float1O, Float1L, Float1H, Float2O, Float2L, Float2H ; FTempO, FTempL, FTempH, FCnt ;------------------------------------------------------------------------------FDiv: mov FTempO, Float1L ; Проверка Float1 на 0 or FTempO, Float1H tst FTempO brne FDiv_A rjmp SetRes0 ; Если Float1 = 0 - результат = 0 FDiv_A: sbrs Float2H, 7 rjmp SetOverflow ; Если Float2 не нормализован или 0 - переполнение ldi FCnt, 0x10 ; Счетчик бит mov FTempO, Float1O andi FTempO, 0x80 ; Выбрать знаковый бит add FTempO, Float2O bst FTempO, 7 ; Загрузить знак результата из T mov FTempO, Float1O ; Подготовка 1го числа порядка sub FTempO, Float2O ; Вычитание порядков subi FTempO, -0x41 ; Прибавить 41H bld FTempO, 7 ; Загрузить знак результата clr Float1O ; Обнуление порядков clr Float2O clr FTempH ldi FTempL, 1 ; Основной цикл деления FDiv_C: sbrs FTempL, 0 rjmp FDiv_D sub Float1L, Float2L sbc Float1H, Float2H sbc Float1O, Float2O ; Установка переноса rjmp FDiv_E FDiv_D: add Float1L, Float2L adc Float1H, Float2H adc Float1O, Float2O FDiv_E: andi Float1O, 0x01 push Float1O ; Сохранение порядка clc eor Float1O, Float2O brne FDiv_F sec FDiv_F: pop Float1O ; Загрузка порядка rol FTempL rol FTempH clc ; Обнуление переноса rol Float1L rol Float1H mov Float1O, FTempH rol Float1O dec FCnt ; Декремент счетчика brne FDiv_C ; Повторять, пока FCnt#0 mov Float2L, FTempL ; Копирование результата
50 <397> <398> <399> <400> <401> <402> <403> <404> <405> <406> <407> <408> <409> <410> <411> <412> <413> <414> <415> <416> <417> <418> <419> <420>
mov mov rjmp
Float2H, FTempH Float2O, FTempO Fx2Fl_B
; Нормализация результата
; Вспомогательные подпрограммы ; Установка флага переполнения SetOverflow: sec ret ; Копирование из Float1 в Float2 Fl1toFl2: mov Float2O, Float1O mov Float2H, Float1H mov Float2L, Float1L ret ; Установка результата в 0 (Float2 = 0) SetRes0: clr Float2L clr Float2H ldi Float2O, 0x40 ret
51 Листинг 2. Библиотека операций с неупакованными двоично-десятичными числами <1> <2> <3> <4> <5> <6> <7> <8> <9> <10> <11> <12> <13> <14> <15> <16> <17> <18> <19> <20> <21> <22> <23> <24> <25> <26> <27> <28> <29> <30> <31> <32> <33> <34> <35> <36> <37> <38> <39> <40> <41> <42> <43> <44> <45> <46> <47> <48> <49> <50> <51> <52> <53> <54> <55> <56> <57> <58> <59> <60> <61> <62> <63> <64> <65> <66> <67> <68> <69> <70> <71> <72> <73> <74> <75> <76> <77> <78> <79>
;=============================================================================== ; Файл: BCD.inc ; Библиотека подпрограмм для работы с неупакованными двоично-десятичными числами ;=============================================================================== ;------------------------------------------------------------------------------; Подпрограмма преобразования 16-битного двоичного значения в ; неупакованный BCD формат ; Вход - исходное 16-битное число в fASCIIL и fASCIIH ; Выход - неупакованное BCD-число в tASCIIX ;------------------------------------------------------------------------------;******************************************************************************* ;* Количество слов кода : 22 + возврат ;* Количество циклов : 60/220 (Мин/Макс) + возврат ;* Использованные младшие регистры : 5 (fASCIIL/tASCII0, fASCIIH, tASCII2, ;* tASCII3, tASCII4) ;* Использованные старшие регистры : 3 (cnt16a/tASCII1, tmp16a, tmp16b) ;******************************************************************************* ;***** Регистровые переменные подпрограммы должны быть определены ; в основной программе ***** ;* Примечания: 1. Переменные fASCIIL и tASCII0 должны размещаться в ;* одном регистре. ;* 2. Переменные cnt16a и tASCII1 должны размещаться в одном ;* регистре. ;* 3. Переменные, определгнные в младших регистрах могут быть ;* также определены и в старших регистрах. ;.def ;.def ;.def ;.def ;.def ;.def ;.def ;.def ;.def ;.def
fASCIIL tASCII0 fASCIIH tASCII2 tASCII3 tASCII4 tASCII1 cnt16a tmp16a tmp16b
= = = = = = = = = =
r11 r11 r12 r13 r14 r15 r16 r16 r17 r18
;***** Код ********************************************************************* bin2ASCII16: ldi tmp16a, low(10000) ldi tmp16b, high(10000) rcall bin2ASCII_digit mov tASCII4, cnt16a ldi tmp16a, low(1000) ldi tmp16b, high(1000) rcall bin2ASCII_digit mov tASCII3, cnt16a ldi tmp16a, low(100) ldi tmp16b, high(100) rcall bin2ASCII_digit mov tASCII2, cnt16a ldi tmp16a, low(10) ldi tmp16b, high(10) bin2ASCII_digit: ldi cnt16a, -1 bin2ASCII_digit_loop: inc cnt16a sub fASCIIL, tmp16a sbc fASCIIH, tmp16b brsh bin2ASCII_digit_loop add fASCIIL, tmp16a adc fASCIIH, tmp16b ret ;------------------------------------------------------------------------------; Подпрограмма преобразования дробного ASCII-числа в 24-х битный float-формат ; Вход - дробное ASCII-число в SRAM [0x70:0x78] ; Выход - число с плавающей точкой в Float2 ; код ошибки в RAM [0x69] ;------------------------------------------------------------------------------ASCII2Float: ldi xh, 0 ; Загрузка указателя на число ldi xl, 0x70 FindPoint: ; Поиск конца целой части числа ld tASCII3, x+
52 <80> <81> <82> <83> <84> <85> <86> <87> <88> <89> <90> <91> <92> <93> <94> <95> <96> <97> <98> <99> <100> <101> <102> <103> <104> <105> <106> <107> <108> <109> <110> <111> <112> <113> <114> <115> <116> <117> <118> <119> <120> <121> <122> <123> <124> <125> <126> <127> <128> <129> <130> <131> <132> <133> <134> <135> <136> <137> <138> <139> <140> <141> <142> <143> <144> <145> <146> <147> <148> <149> <150> <151> <152> <153> <154> <155> <156> <157> <158> <159>
ldi r25, 0x2e cpse tASCII3, r25 rjmp FindPoint dec xl mov r4, xl ldi Float2H, 0 ldi Float2L, 0 rcall Fix2Float cpi xl, 0x70 breq IntConvEnd1 ld Float2L, -x ldi Float2H, 0 subi Float2L, 0x30 rcall Fix2Float push Float2L push Float2H push Float2O cpi xl, 0x70 breq IntConvEnd ldi Float2L, 10 ldi Float2H, 0 rcall Fix2Float rcall SwapFl ld Float2L, -x ldi Float2H, 0 subi Float2L, 0x30 rcall Fix2Float rcall FMult pop Float1O pop Float1H pop Float1L rcall FAdd push Float2L push Float2H push Float2O cpi xl, 0x70 breq IntConvEnd ldi Float2L, 100 ldi Float2H, 0 rcall Fix2Float rcall SwapFl ld Float2L, -x ldi Float2H, 0 subi Float2L, 0x30 rcall Fix2Float rcall FMult pop Float1O pop Float1H pop Float1L rcall FAdd push Float2L push Float2H push Float2O cpi xl, 0x70 breq IntConvEnd ldi Float2L, 0xe8 ldi Float2H, 0x3 rcall Fix2Float rcall SwapFl ld Float2L, -x ldi Float2H, 0 subi Float2L, 0x30 rcall Fix2Float rcall FMult pop Float1O pop Float1H pop Float1L rcall FAdd rjmp IntConvEnd1 IntConvEnd: pop Float2O pop Float2H pop Float2L IntConvEnd1: ldi xh, 0 mov xl, r4 inc xl Find2Point: ld tASCII3, x+ cpi xl, 0x7b
; Сохранение указателя на точку в r4 ; Загрузка нулевого начального значения в Float2 ; Конвертирование целой части числа
; Загрузка указателя на символ после точки ; Поиск конца дробной части числа
53 <160> <161> <162> <163> <164> <165> <166> <167> <168> <169> <170> <171> <172> <173> <174> <175> <176> <177> <178> <179> <180> <181> <182> <183> <184> <185> <186> <187> <188> <189> <190> <191> <192> <193> <194> <195> <196> <197> <198> <199> <200> <201> <202> <203> <204> <205> <206> <207> <208> <209> <210> <211> <212> <213> <214> <215> <216> <217> <218> <219> <220> <221> <222> <223> <224> <225> <226> <227> <228> <229> <230> <231> <232> <233> <234> <235> <236> <237> <238> <239>
brne rjmp FloatExist: ldi cpse rjmp dec push mov pop inc push push push cpse rjmp rjmp FE_1: ldi ldi rcall rcall ld ldi subi rcall rcall rcall pop pop pop rcall push push push cpse rjmp rjmp FE_2: ldi ldi rcall rcall ld ldi subi rcall rcall rcall pop pop pop rcall push push push cpse rjmp rjmp FE_3: ldi ldi rcall rcall ld ldi subi rcall rcall rcall pop pop pop rcall push push push cpse rjmp rjmp
FloatExist FloatConvEnd1 r25, 0x2e tASCII3, r25 Find2Point xl xl xl, r4 r4 xl Float2L Float2H Float2O xl, r4 FE_1 FloatConvEnd Float2L, 10 Float2H, 0 Fix2Float SwapFl Float2L, x+ Float2H, 0 Float2L, 0x30 Fix2Float SwapFl FDiv Float1O Float1H Float1L FAdd Float2L Float2H Float2O xl, r4 FE_2 FloatConvEnd Float2L, 100 Float2H, 0 Fix2Float SwapFl Float2L, x+ Float2H, 0 Float2L, 0x30 Fix2Float SwapFl FDiv Float1O Float1H Float1L FAdd Float2L Float2H Float2O xl, r4 FE_3 FloatConvEnd Float2L, 0xe8 Float2H, 0x03 Fix2Float SwapFl Float2L, x+ Float2H, 0 Float2L, 0x30 Fix2Float SwapFl FDiv Float1O Float1H Float1L FAdd Float2L Float2H Float2O xl, r4 FE_4 FloatConvEnd
; Конвертирование дробной части числа
54 <240> <241> <242> <243> <244> <245> <246> <247> <248> <249> <250> <251> <252> <253> <254> <255> <256> <257> <258> <259> <260> <261> <262> <263>
FE_4: ldi Float2L, 0x10 ldi Float2H, 0x27 rcall Fix2Float rcall SwapFl ld Float2L, x+ ldi Float2H, 0 subi Float2L, 0x30 rcall Fix2Float rcall SwapFl rcall FDiv pop Float1O pop Float1H pop Float1L rcall FAdd push Float2L push Float2H push Float2O FloatConvEnd: pop Float2O pop Float2H pop Float2L FloatConvEnd1: ret
55 Листинг 3. Библиотека подпрограмм для работы со знакосинтезирующим ЖКИ <1> <2> <3> <4> <5> <6> <7> <8> <9> <10> <11> <12> <13> <14> <15> <16> <17> <18> <19> <20> <21> <22> <23> <24> <25> <26> <27> <28> <29> <30> <31> <32> <33> <34> <35> <36> <37> <38> <39> <40> <41> <42> <43> <44> <45> <46> <47> <48> <49> <50> <51> <52> <53> <54> <55> <56> <57> <58> <59> <60> <61> <62> <63> <64> <65> <66> <67> <68> <69> <70> <71> <72> <73> <74> <75> <76> <77> <78> <79>
;=============================================================================== ; Файл: LCD.inc ; Библиотека подпрограмм для работы со знакосинтезирующим ЖКИ с драйвером на ; основе микроконтроллера HD44780 или его аналога ;=============================================================================== ;------------------------------------------------------------------------------; Вывод байта-команды в контролер ЖКИ ;------------------------------------------------------------------------------LCDCommand: swap r25 ; Подготовить старшую тетраду для передачи mov r26, r25 andi r26, $ef ; Очистка бита 4 порта C (сигнал RS = 0) ori r26, $e0 ; Установка бита 5 порта C (сигнал E = 1) out portc, r26 cbi portc, 5 ; Стробирующий сброс бита 5 порта C (сигнал E = 0) swap r25 ; Подготовить младшую тетраду для передачи mov r26, r25 andi r26, $ef ; Очистка бита 4 порта C (сигнал RS = 0) ori r26, $e0 ; Установка бита 5 порта C (сигнал E = 1) out portc, r26 cbi portc, 5 ; Стробирующий сброс бита 5 порта C (сигнал E = 0) ret ;------------------------------------------------------------------------------; Вывод байта данных в контроллер ЖКИ ;------------------------------------------------------------------------------LCDData: swap r25 ; Подготовить старшую тетраду для передачи mov r26, r25 ori r26, $f0 ; Установка бита 4 порта C (сигнал RS = 1) и out portc, r26 ; бита 5 порта C (сигнал E = 1) cbi portc, 5 ; Стробирующий сброс бита 5 порта C (сигнал E = 0) swap r25 ; Подготовить младшую тетраду для передачи mov r26, r25 ori r26, $f0 ; Установка бита 4 порта C (сигнал RS = 1) и out portc, r26 ; бита 5 порта C (сигнал E = 1) cbi portc, 5 ; Стробирующий сброс бита 5 порта C (сигнал E = 0) ret ;------------------------------------------------------------------------------; Инициализация ЖКИ ;------------------------------------------------------------------------------InitLCD: ldi r26, 0xff ; Задержка ~12.29 мс при кварце 16 МГц ldi r27, 0xff rcall Delay ldi r25, $20 ; 4-битный интерфейс, 1 строка, шрифт - 5х7 точек rcall LCDCommand ldi r26, 214 ; Задержка ~40 мкс при кварце 16 МГц ldi r27, 0 rcall Delay ldi r25, $28 ; 4-битный интерфейс, 2 строки, шрифт - 5х7 точек rcall LCDCommand ldi r26, 214 ; Задержка ~40 мкс при кварце 16 МГц ldi r27, 0 rcall Delay ldi r25, $0C ; Включить дисплей, выключить курсор rcall LCDCommand ldi r25, $1 ; Очистить дисплей и установить курсор в rcall LCDCommand ; начальную позицию ldi r26, 0x80 ; Задержка ~1.8 мс при кварце 16 МГц ldi r27, 0x25 rcall Delay ret ;------------------------------------------------------------------------------; Подпрограмма вывода в DDRAM строки символов ; Вход - адрес начала строки в указателе Z ; число символов в r24 ; начальный адрес DDRAM в r25 ;------------------------------------------------------------------------------OutText: ldi var, 0x80 add r25, var ; После этой команды данные записываются в DDRAM rcall LCDCommand ; начиная с адреса в r25 ldi r26, 214 ; Задержка ~40 мкс при кварце 16 МГц ldi r27, 0 rcall Delay
56 <80> <81> <82> <83> <84> <85> <86> <87> <88> <89> <90> <91> <92> <93> <94> <95> <96> <97> <98> <99> <100> <101> <102> <103> <104> <105> <106> <107> <108> <109> <110> <111> <112> <113> <114> <115> <116> <117> <118> <119> <120> <121> <122> <123> <124> <125> <126> <127> <128> <129> <130> <131> <132> <133> <134> <135> <136> <137> <138> <139> <140> <141> <142> <143> <144> <145> <146> <147> <148> <149> <150> <151> <152> <153> <154> <155> <156> <157> <158> <159>
NextByte: lpm mov rcall ldi ldi rcall ld dec brne ret
; Извлечь из flash-памяти байт данных r25, r0 LCDData r26, 214 r27, 0 Delay r1, z+ r24 NextByte
; Записать его в DDRAM ; Задержка ~40 мкс при кварце 16 МГц ; Увеличить на 1 указатель Z адреса flash-памяти ; Если еще не все ячейки запрограммированы, ; то вернуться назад
;------------------------------------------------------------------------------; Подпрограмма вывода в DDRAM символа ; Вход - код символа в r24 ; начальный адрес DDRAM в r25 ;------------------------------------------------------------------------------OutChar: ldi var, 0x80 add r25, var ; После этой команды данные записываются в DDRAM rcall LCDCommand ; начиная с адреса в r25 ldi r26, 214 ; Задержка ~40 мкс при кварце 16 МГц ldi r27, 0 rcall Delay mov r25, r24 rcall LCDData ; Записать символ в DDRAM ldi r26, 214 ; Задержка ~40 мкс при кварце 16 МГц ldi r27, 0 rcall Delay ret ;------------------------------------------------------------------------------; Подпрограмма вывода в DDRAM BCD-числа ; Вход - BCD-число в tASCIIX ; начальный адрес DDRAM в r25 ;------------------------------------------------------------------------------OutBCD: ldi var, 0x80 add r25, var ; После этой команды данные записываются в DDRAM rcall LCDCommand ; начиная с адреса в r25 ldi r26, 214 ; Задержка ~40 мкс при кварце 16 МГц ldi r27, 0 rcall Delay ldi r24, 5 ; Количество байтов в BCD-числе push tASCII0 ; Помещение в стек BCD-числа push tASCII1 push tASCII2 push tASCII3 push tASCII4 NextNum: pop r25 ; Извлечение из стека очередного байта числа ldi var, 0x30 ; Приведение к соответствию с ASCII-стандартом add r25, var rcall LCDData ; Записать его в DDRAM ldi r26, 214 ; Задержка ~40 мкс при кварце 16 МГц ldi r27, 0 rcall Delay dec r24 ; Если еще не все ячейки запрограммированы, brne NextNum ; то вернуться назад ret ;------------------------------------------------------------------------------; Подпрограмма вывода в DDRAM BCD-числа в формате A4A3A2A1.A0 ; Вход - BCD-число в tASCIIX ; начальный адрес DDRAM в r25 ;------------------------------------------------------------------------------OutFBCD: ldi var, 0x80 add r25, var ; После этой команды данные записываются в DDRAM rcall LCDCommand ; начиная с адреса в r25 ldi r26, 214 ; Задержка ~40 мкс при кварце 16 МГц ldi r27, 0 rcall Delay ldi r24, 5 ; Количество байтов в BCD-числе push tASCII0 ; Помещение в стек BCD-числа push tASCII1 push tASCII2 push tASCII3 push tASCII4 lds var, 0x60 ; Загрузка знака числа из памяти
57 <160> <161> <162> <163> <164> <165> <166> <167> <168> <169> <170> <171> <172> <173> <174> <175> <176> <177> <178> <179> <180> <181> <182> <183> <184> <185> <186> <187> <188> <189> <190> <191> <192> <193> <194> <195> <196> <197> <198> <199> <200> <201> <202> <203> <204> <205> <206> <207> <208> <209> <210> <211> <212> <213> <214> <215> <216> <217> <218> <219> <220> <221> <222> <223> <224> <225> <226> <227> <228> <229> <230> <231> <232> <233> <234> <235> <236> <237> <238> <239>
tst breq ldi rcall ldi ldi rcall rjmp PutSpace: ldi rcall ldi ldi rcall NextFNum: pop ldi add rcall ldi ldi rcall cpi brne ldi rcall ldi ldi rcall NotDot: dec brne ret
var PutSpace r25, 0x2d LCDData r26, 214 r27, 0 Delay NextFNum
; Знак минуса ; Записать его в DDRAM ; Задержка ~40 мкс при кварце 16 МГц
r25, 0x20 LCDData r26, 214 r27, 0 Delay
; Пробел ; Записать его в DDRAM ; Задержка ~40 мкс при кварце 16 МГц
r25 var, 0x30 r25, var LCDData r26, 214 r27, 0 Delay r24, 2 NotDot r25, 0x2e LCDData r26, 214 r27, 0 Delay
; Извлечение из стека очередного байта числа ; Приведение к соответствию с ASCII-стандартом
r24 NextFNum
; Записать его в DDRAM ; Задержка ~40 мкс при кварце 16 МГц ; ; ; ; ;
Если был записан предпоследний символ, то записать после него точку Символ децимальной точки Запись ее в DDRAM Задержка ~40 мкс при кварце 16 МГц
; Если еще не все ячейки запрограммированы, ; то вернуться назад
;------------------------------------------------------------------------------; Подпрограмма очистки дисплея и установки адреса DDRAM в 0 ;------------------------------------------------------------------------------ClrScr: ldi r25, 1 rcall LCDCommand ldi r26, 0x55 ; Задержка ~1.6 мс при кварце 16 МГц ldi r27, 0x21 rcall Delay ret ;------------------------------------------------------------------------------; Подпрограмма установки курсора в позицию r25 ;------------------------------------------------------------------------------SetCursorPos: ldi r24, 0x80 add r25, r24 rcall LCDCommand ldi r26, 214 ; Задержка ~40 мкс при кварце 16 МГц ldi r27, 0 rcall Delay ret ;------------------------------------------------------------------------------; Подпрограмма вывода в DDRAM float-числа ; Вход - float-число Float2 ; начальный адрес DDRAM в r25 ;------------------------------------------------------------------------------OutFloat: push Float2O ; Сохранение параметров в стеке push Float2H push Float2L push r25 mov Float1O, Float2O ; Float1 = Float2 mov Float1H, Float2H mov Float1L, Float2L rcall Float2Fix ; Выделение целой части числа push Float1O ; Сохранение в стеке оригинала числа push Float1H push Float1L mov fASCIIL, Float2L ; Вывод целой части числа на дисплей mov fASCIIH, Float2H rcall bin2ASCII16 rcall OutBCDEx pop Float1L ; Извлечение из стека оригинала числа
58 <240> <241> <242> <243> <244> <245> <246> <247> <248> <249> <250> <251> <252> <253> <254> <255> <256> <257> <258> <259> <260> <261> <262> <263> <264> <265> <266> <267> <268> <269> <270> <271> <272> <273> <274> <275> <276> <277> <278> <279> <280> <281> <282> <283> <284> <285> <286> <287> <288> <289> <290> <291> <292> <293> <294> <295> <296> <297> <298> <299> <300> <301> <302> <303> <304> <305> <306> <307> <308> <309> <310> <311> <312> <313> <314> <315> <316> <317> <318> <319>
pop pop rcall rcall cp brne cp brne cp brne ldi ldi rcall rjmp NeedSub: rcall SubOK: pop add push ldi rcall rcall ldi ldi rcall rcall pop inc rcall mov mov rcall rcall pop pop pop ret
Float1H Float1O Fix2Float SwapFl Float1O, Float2O NeedSub Float1H, Float2H NeedSub Float1L, Float2L NeedSub Float2H, 0 Float2L, 0 Fix2Float SubOK FSub r25 r25, r7 r25 r24, 0x2e OutChar SwapFl Float2H, 0x27 Float2L, 0x10 Fix2Float FMult r25 r25 Float2Fix fASCIIL, Float2L fASCIIH, Float2H bin2ASCII16 OutBCD4 Float2L Float2H Float2O
; Загрузка в Float2 целой части числа ; Проверка необходимости вычитания
; Выделение дробной части числа
; Вывод децимальной точки ; Домножение на 10000
; Вывод дробной части на дисплей
; Освобождение стека и восстановление Float2
;------------------------------------------------------------------------------; Подпрограмма вывода в DDRAM BCD-числа без лишних нулей ; Вход - BCD-число в tASCIIX ; начальный адрес DDRAM в r25 ;------------------------------------------------------------------------------OutBCDEx: ldi var, 0x80 add r25, var ; После этой команды данные записываются в DDRAM rcall LCDCommand ; начиная с адреса в r25 ldi r26, 214 ; Задержка ~40 мкс при кварце 16 МГц ldi r27, 0 rcall Delay ldi r24, 5 ; Помещение числа в стек без первых нулей ldi var, 0 cpse tASCII4, var rjmp ReadyToPush dec r24 cpse tASCII3, var rjmp ReadyToPush dec r24 cpse tASCII2, var rjmp ReadyToPush dec r24 cpse tASCII1, var rjmp ReadyToPush dec r24 ReadyToPush: mov r7, r24 push tASCII0 cpi r24, 2 brlo NextNumEx push tASCII1 cpi r24, 3 brlo NextNumEx push tASCII2 cpi r24, 4 brlo NextNumEx push tASCII3 cpi r24, 5 brlo NextNumEx push tASCII4
59 <320> <321> <322> <323> <324> <325> <326> <327> <328> <329> <330> <331> <332> <333> <334> <335> <336> <337> <338> <339> <340> <341> <342> <343> <344> <345> <346> <347> <348> <349> <350> <351> <352> <353> <354> <355> <356> <357> <358> <359>
NextNumEx: pop ldi add rcall ldi ldi rcall dec brne ret
r25 var, 0x30 r25, var LCDData r26, 214 r27, 0 Delay r24 NextNumEx
; Извлечение из стека очередного байта числа ; Приведение к соответствию с ASCII-стандартом ; Записать его в DDRAM ; Задержка ~40 мкс при кварце 16 МГц ; Если еще не все ячейки запрограммированы, ; то вернуться назад
;------------------------------------------------------------------------------; Подпрограмма вывода в DDRAM 4-х значного BCD-числа ; Вход - BCD-число в tASCIIX ; начальный адрес DDRAM в r25 ;------------------------------------------------------------------------------OutBCD4: ldi var, 0x80 add r25, var ; После этой команды данные записываются в DDRAM rcall LCDCommand ; начиная с адреса в r25 ldi r26, 214 ; Задержка ~40 мкс при кварце 16 МГц ldi r27, 0 rcall Delay ldi r24, 4 ; Количество байтов в BCD-числе push tASCII0 ; Помещение в стек BCD-числа push tASCII1 push tASCII2 push tASCII3 NextNum4: pop r25 ; Извлечение из стека очередного байта числа ldi var, 0x30 ; Приведение к соответствию с ASCII-стандартом add r25, var rcall LCDData ; Записать его в DDRAM ldi r26, 214 ; Задержка ~40 мкс при кварце 16 МГц ldi r27, 0 rcall Delay dec r24 ; Если еще не все ячейки запрограммированы, brne NextNum4 ; то вернуться назад ret
60 Листинг 4. Библиотека подпрограмм для работы с клавиатурой и меню <1> <2> <3> <4> <5> <6> <7> <8> <9> <10> <11> <12> <13> <14> <15> <16> <17> <18> <19> <20> <21> <22> <23> <24> <25> <26> <27> <28> <29> <30> <31> <32> <33> <34> <35> <36> <37> <38> <39> <40> <41> <42> <43> <44> <45> <46> <47> <48> <49> <50> <51> <52> <53> <54> <55> <56> <57> <58> <59> <60> <61> <62> <63> <64> <65> <66> <67> <68> <69> <70> <71> <72> <73> <74> <75> <76> <77> <78> <79>
;=============================================================================== ; Файл: Keypad.inc ; Библиотека подпрограмм для работы с клавиатурой и меню ;=============================================================================== ;------------------------------------------------------------------------------; Определение имен состояния устройства ;------------------------------------------------------------------------------.equ Measure = 0 ; Измерение скорости .equ Menu1 = 1 ; Меню (пункт "Размерность" выделен) .equ Menu2 = 2 ; Меню (пункт "Точность" выделен) .equ Menu3 = 3 ; Меню (пункт "Интерфейс" выделен) .equ Menu4 = 4 ; Меню (пункт "Самодиагностика" выделен) .equ Menu1_1 = 5 ; Меню (Размерность->об/мин) .equ Menu1_2 = 6 ; Меню (Размерность->об/с) .equ Menu1_3 = 7 ; Меню (Размерность->рад/с) .equ Menu1_4 = 8 ; Меню (Размерность->см/с) .equ Menu1_5 = 9 ; Меню (Размерность->Коэф. передачи) .equ Menu2_1 = 10 ; Меню (Точность->Интервал счёта) .equ Menu2_2 = 11 ; Меню (Точность->Погрешность) .equ Menu2_3 = 12 ; Меню (Точность->Автокалибровка) .equ Menu3_1 = 13 ; Меню (Интерфейс->Включить) .equ Menu3_2 = 14 ; Меню (Интерфейс->Скорость обмена) .equ Menu3_2_1 = 15 ; Меню (2400 бод) .equ Menu3_2_2 = 16 ; Меню (4800 бод) .equ Menu3_2_3 = 17 ; Меню (9600 бод) .equ Menu3_2_4 = 18 ; Меню (14400 бод) .equ Menu3_2_5 = 19 ; Меню (19200 бод) .equ Menu3_2_6 = 20 ; Меню (38400 бод) .equ Menu3_2_7 = 21 ; Меню (57600 бод) .equ Menu3_2_8 = 22 ; Меню (115200 бод) .equ Menu4_1 = 23 ; Меню (Самодиагностика->...) ;------------------------------------------------------------------------------; Подпрограмма сканирования клавиатуры ; Выход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------ReadKey: ldi Key, 0xff ; Возвращает 0xff в случае помехи или дребез. конт. sbis pinb, 1 ; Поиск строки нажатой клавиши ldi Key, 0 sbis pinb, 2 ldi Key, 3 ldi var, 0b110 ; Перенастройка портов: out ddrb, var ; строки - выходы (0); столбцы - входы (1) ldi var, 0b000 out portb, var ldi var, 0b00000010 out ddrd, var ldi var, 0b11100000 out portd, var ldi r26, 100 ; Задержка для установки портов ldi r27, 0 rcall Delay sbis pind, 5 ; Поиск столбца нажатой клавиши ldi var, 0 sbis pind, 6 ldi var, 1 sbis pind, 7 ldi var, 2 add Key, var ; Получение скан-кода в Key ldi var, 0b000 ; Перенастройка портов в исходное состояние: out ddrb, var ; строки - входы (1); столбцы - выходы (0) ldi var, 0b110 out portb, var ldi var, 0b11100010 out ddrd, var ldi var, 0b00000000 out portd, var ret ; Выход из подпрограммы ;------------------------------------------------------------------------------; Подпрограмма распределения команд с клавиатуры ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------OnAction: lds State, mState ; Загрузка текущего состояния устройства из памяти cpi State, Measure ; Измерение скорости? brne st2
61 <80> <81> <82> <83> <84> <85> <86> <87> <88> <89> <90> <91> <92> <93> <94> <95> <96> <97> <98> <99> <100> <101> <102> <103> <104> <105> <106> <107> <108> <109> <110> <111> <112> <113> <114> <115> <116> <117> <118> <119> <120> <121> <122> <123> <124> <125> <126> <127> <128> <129> <130> <131> <132> <133> <134> <135> <136> <137> <138> <139> <140> <141> <142> <143> <144> <145> <146> <147> <148> <149> <150> <151> <152> <153> <154> <155> <156> <157> <158> <159>
rjmp
State1
cpi brne rjmp
State, Menu1 st3 State2
; Menu1?
cpi brne rjmp
State, Menu2 st4 State3
; Menu2?
cpi brne rjmp
State, Menu3 st5 State4
; Menu3?
cpi brne rjmp
State, Menu4 st6 State5
; Menu4?
cpi brne rjmp
State, Menu1_1 st7 State6
; Menu1_1?
cpi brne rjmp
State, Menu1_2 st8 State7
; Menu1_2?
cpi brne rjmp
State, Menu1_3 st9 State8
; Menu1_3?
cpi brne rjmp st10: cpi brne rjmp st11: cpi brne rjmp st12: cpi brne rjmp st13: cpi brne rjmp st14: cpi brne rjmp st15: cpi brne rjmp st16: cpi brne rjmp st17: cpi brne rjmp st18: cpi brne rjmp st19: cpi brne rjmp st20: cpi brne rjmp st21: cpi brne
State, Menu1_4 st10 State9
; Menu1_4?
State, Menu1_5 st11 State10
; Menu1_5?
State, Menu2_1 st12 State11
; Menu2_1?
State, Menu2_2 st13 State12
; Menu2_2?
State, Menu2_3 st14 State13
; Menu2_3?
State, Menu3_1 st15 State14
; Menu3_1?
State, Menu3_2 st16 State15
; Menu3_2?
State, Menu3_2_1 st17 State16
; Menu3_2_1?
State, Menu3_2_2 st18 State17
; Menu3_2_2?
State, Menu3_2_3 st19 State18
; Menu3_2_3?
State, Menu3_2_4 st20 State19
; Menu3_2_4?
State, Menu3_2_5 st21 State20
; Menu3_2_5?
State, Menu3_2_6 st22
; Menu3_2_6?
st2:
st3:
st4:
st5:
st6:
st7:
st8:
st9:
62 <160> <161> <162> <163> <164> <165> <166> <167> <168> <169> <170> <171> <172> <173> <174> <175> <176> <177> <178> <179> <180> <181> <182> <183> <184> <185> <186> <187> <188> <189> <190> <191> <192> <193> <194> <195> <196> <197> <198> <199> <200> <201> <202> <203> <204> <205> <206> <207> <208> <209> <210> <211> <212> <213> <214> <215> <216> <217> <218> <219> <220> <221> <222> <223> <224> <225> <226> <227> <228> <229> <230> <231> <232> <233> <234> <235> <236> <237> <238> <239>
rjmp st22: cpi brne rjmp st23: cpi brne rjmp st24: ret
State21 State, Menu3_2_7 st23 State22
; Menu3_2_7?
State, Menu3_2_8 st24 State23
; Menu3_2_8?
; Выход из подпрограммы
;------------------------------------------------------------------------------; Измерение скорости (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State1: cpi Key, 3 ; Нажата клавиша "Вправо" ? brne State1_4 lds Tunes, mTunes ; Загрузка настроек из памяти sbrs Tunes, 0 ; Настройка на следующую размерность rjmp State1_1 ori Tunes, 0b10000 andi Tunes, 0b11111000 sts mTunes, Tunes ; Сохранение настроек в SRAM rcall EEPROM_Write ; Сохранение настроек в EEPROM rcall MeasureInterface ; Вывести на дисплей интерфейс измерения скорости rjmp State1_9 State1_1: sbrs Tunes, 1 ; Настройка на следующую размерность rjmp State1_2 ori Tunes, 0b1 andi Tunes, 0b11101001 sts mTunes, Tunes ; Сохранение настроек в SRAM rcall EEPROM_Write ; Сохранение настроек в EEPROM rcall MeasureInterface ; Вывести на дисплей интерфейс измерения скорости rjmp State1_9 State1_2: sbrs Tunes, 2 ; Настройка на следующую размерность rjmp State1_3 ori Tunes, 0b10 andi Tunes, 0b11101010 sts mTunes, Tunes ; Сохранение настроек в SRAM rcall EEPROM_Write ; Сохранение настроек в EEPROM rcall MeasureInterface ; Вывести на дисплей интерфейс измерения скорости rjmp State1_9 State1_3: ori Tunes, 0b100 ; Настройка на следующую размерность andi Tunes, 0b11101100 sts mTunes, Tunes ; Сохранение настроек в SRAM rcall EEPROM_Write ; Сохранение настроек в EEPROM rcall MeasureInterface ; Вывести на дисплей интерфейс измерения скорости rjmp State1_9 State1_4: cpi Key, 5 ; Нажата клавиша "Влево" ? brne State1_8 lds Tunes, mTunes ; Загрузка настроек из памяти sbrs Tunes, 0 ; Настройка на предыдущую размерность rjmp State1_5 ori Tunes, 0b010 andi Tunes, 0b11101010 sts mTunes, Tunes ; Сохранение настроек в SRAM rcall EEPROM_Write ; Сохранение настроек в EEPROM rcall MeasureInterface ; Вывести на дисплей интерфейс измерения скорости rjmp State1_9 State1_5: sbrs Tunes, 1 ; Настройка на предыдущую размерность rjmp State1_6 ori Tunes, 0b100 andi Tunes, 0b11101100 sts mTunes, Tunes ; Сохранение настроек в SRAM rcall EEPROM_Write ; Сохранение настроек в EEPROM rcall MeasureInterface ; Вывести на дисплей интерфейс измерения скорости rjmp State1_9 State1_6: sbrs Tunes, 2 ; Настройка на предыдущую размерность rjmp State1_7 ori Tunes, 0b10000 andi Tunes, 0b11111000 sts mTunes, Tunes ; Сохранение настроек в SRAM
63 <240> <241> <242> <243> <244> <245> <246> <247> <248> <249> <250> <251> <252> <253> <254> <255> <256> <257> <258> <259> <260> <261> <262> <263> <264> <265> <266> <267> <268> <269> <270> <271> <272> <273> <274> <275> <276> <277> <278> <279> <280> <281> <282> <283> <284> <285> <286> <287> <288> <289> <290> <291> <292> <293> <294> <295> <296> <297> <298> <299> <300> <301> <302> <303> <304> <305> <306> <307> <308> <309> <310> <311> <312> <313> <314> <315> <316> <317> <318> <319>
rcall rcall rjmp State1_7: ori andi sts rcall rcall rjmp State1_8: cpi brne ldi sts rcall ldi out ldi out State1_9: ret
EEPROM_Write MeasureInterface State1_9
; Сохранение настроек в EEPROM ; Вывести на дисплей интерфейс измерения скорости
Tunes, 0b1 Tunes, 0b11101001 mTunes, Tunes EEPROM_Write MeasureInterface State1_9
; Настройка на предыдущую размерность
Key, 0 State1_9 State, Menu1 mState, State Menu1Interface var, 0 timsk, var var, 0b01000000 gicr, var
; Нажата клавиша "OK" ?
; Сохранение настроек в SRAM ; Сохранение настроек в EEPROM ; Вывести на дисплей интерфейс измерения скорости
; Изменение состояния на Menu1 ; Вывести на дисплей интерфейс Menu1 ; Запрет вычисления скорости
;------------------------------------------------------------------------------; Меню (пункт "Размерность" выделен): реакция на нажатие клавиши ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State2: cpi Key, 2 ; Нажата клавиша Esc - возвращение к измерению brne State2_1 rcall MeasureInterface ; Вывести на дисплей интерфейс измерения скорости ldi State, Measure ; Изменить состояние устройства: sts mState, State ; измерение скорости ldi var, 0b10001 ; Разрешение вычисления скорости out timsk, var ldi var, 0b11000000 out gicr, var rjmp State2_3 State2_1: cpi Key, 4 ; Нажата клавиша "вниз" - переход на Menu2 brne State2_2 ldi State, Menu2 ; Изменение состояния на Menu2 sts mState, State rcall Menu2Interface ; Вывести на дисплей интерфейс Menu2 rjmp State2_3 State2_2: cpi Key, 0 ; Нажата клавиша "OK" - переход на Menu1_1 brne State2_3 ldi State, Menu1_1 ; Изменение состояния на Menu1_1 sts mState, State rcall Menu1_1Interface ; Вывести на дисплей интерфейс Menu1_1 State2_3: ret ;------------------------------------------------------------------------------; Меню (пункт "Точность" выделен): реакция на нажатие клавиши ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State3: cpi Key, 2 ; Нажата клавиша Esc - возвращение к измерению brne State3_1 rcall MeasureInterface ; Вывести на дисплей интерфейс измерения скорости ldi State, Measure ; Изменить состояние устройства: sts mState, State ; измерение скорости ldi var, 0b10001 ; Разрешение вычисления скорости out timsk, var ldi var, 0b11000000 out gicr, var rjmp State3_4 State3_1: cpi Key, 4 ; Нажата клавиша "вниз" - переход на Menu3 brne State3_2 ldi State, Menu3 ; Изменение состояния на Menu3 sts mState, State rcall Menu3Interface ; Вывести на дисплей интерфейс Menu3 rjmp State3_4 State3_2: cpi Key, 1 ; Нажата клавиша "вверх" - переход на Menu1 brne State3_3 ldi State, Menu1 ; Изменение состояния на Menu1
64 <320> <321> <322> <323> <324> <325> <326> <327> <328> <329> <330> <331> <332> <333> <334> <335> <336> <337> <338> <339> <340> <341> <342> <343> <344> <345> <346> <347> <348> <349> <350> <351> <352> <353> <354> <355> <356> <357> <358> <359> <360> <361> <362> <363> <364> <365> <366> <367> <368> <369> <370> <371> <372> <373> <374> <375> <376> <377> <378> <379> <380> <381> <382> <383> <384> <385> <386> <387> <388> <389> <390> <391> <392> <393> <394> <395> <396> <397> <398> <399>
sts rcall rjmp State3_3: cpi brne ldi sts rcall State3_4: ret
mState, State Menu1Interface State3_4 Key, 0 State3_4 State, Menu2_1 mState, State Menu2_1Interface
; Вывести на дисплей интерфейс Menu1 ; Нажата клавиша "OK" - переход на Menu2_1 ; Изменение состояния на Menu2_1 ; Вывести на дисплей интерфейс Menu2_1
;------------------------------------------------------------------------------; Меню (пункт "Интерфейс" выделен): реакция на нажатие клавиши ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State4: cpi Key, 2 ; Нажата клавиша Esc - возвращение к измерению brne State4_1 rcall MeasureInterface ; Вывести на дисплей интерфейс измерения скорости ldi State, Measure ; Изменить состояние устройства: sts mState, State ; измерение скорости ldi var, 0b10001 ; Разрешение вычисления скорости out timsk, var ldi var, 0b11000000 out gicr, var rjmp State4_4 State4_1: cpi Key, 4 ; Нажата клавиша "вниз" - переход на Menu4 brne State4_2 ldi State, Menu4 ; Изменение состояния на Menu4 sts mState, State rcall Menu4Interface ; Вывести на дисплей интерфейс Menu4 rjmp State4_4 State4_2: cpi Key, 1 ; Нажата клавиша "вверх" - переход на Menu2 brne State4_3 ldi State, Menu2 ; Изменение состояния на Menu2 sts mState, State rcall Menu2Interface ; Вывести на дисплей интерфейс Menu2 rjmp State4_4 State4_3: cpi Key, 0 ; Нажата клавиша "OK" - переход на Menu3_1 brne State4_4 ldi State, Menu3_1 ; Изменение состояния на Menu3_1 sts mState, State rcall Menu3_1Interface ; Вывести на дисплей интерфейс Menu3_1 State4_4: ret ;------------------------------------------------------------------------------; Меню (пункт "Самодиагностика" выделен): реакция на нажатие клавиши ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State5: cpi Key, 2 ; Нажата клавиша Esc - возвращение к измерению brne State5_1 ; скорости rcall MeasureInterface ; Вывести на дисплей интерфейс измерения скорости ldi State, Measure ; Изменить состояние устройства: sts mState, State ; измерение скорости ldi var, 0b10001 ; Разрешение вычисления скорости out timsk, var ldi var, 0b11000000 out gicr, var rjmp State5_3 State5_1: cpi Key, 1 ; Нажата клавиша "вверх" - переход на Menu3 brne State5_2 ldi State, Menu3 ; Изменение состояния на Menu3 sts mState, State rcall Menu3Interface ; Вывести на дисплей интерфейс Menu3 rjmp State5_3 State5_2: cpi Key, 0 ; Нажата клавиша "OK" - переход на Menu4_1 brne State5_3 ldi State, Menu4_1 ; Изменение состояния на Menu4_1 sts mState, State rcall Menu4_1Interface ; Вывести на дисплей интерфейс Menu4_1 rcall GetResolution ; Получить количество меток энкодера в Res rcall MeasureInterface ; Вывести на дисплей интерфейс измерения скорости
65 <400> <401> <402> <403> <404> <405> <406> <407> <408> <409> <410> <411> <412> <413> <414> <415> <416> <417> <418> <419> <420> <421> <422> <423> <424> <425> <426> <427> <428> <429> <430> <431> <432> <433> <434> <435> <436> <437> <438> <439> <440> <441> <442> <443> <444> <445> <446> <447> <448> <449> <450> <451> <452> <453> <454> <455> <456> <457> <458> <459> <460> <461> <462> <463> <464> <465> <466> <467> <468> <469> <470> <471> <472> <473> <474> <475> <476> <477> <478> <479>
ldi sts ldi out ldi out State5_3: ret
State, Measure mState, State var, 0b10001 timsk, var var, 0b11000000 gicr, var
; Изменить состояние устройства: ; измерение скорости ; Разрешение вычисления скорости
;------------------------------------------------------------------------------; Пункт меню "об/мин" (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State6: cpi Key, 2 ; Нажата клавиша Esc - возвращение к Menu1 brne State6_1 ldi State, Menu1 ; Изменение состояния на Menu1 sts mState, State rcall Menu1Interface ; Вывести на дисплей интерфейс Menu1 rjmp State6_3 State6_1: cpi Key, 4 ; Нажата клавиша "вниз" - переход на Menu1_2 brne State6_2 ldi State, Menu1_2 ; Изменение состояния на Menu1_2 sts mState, State rcall Menu1_2Interface ; Вывести на дисплей интерфейс Menu1_2 rjmp State6_3 State6_2: cpi Key, 0 ; Нажата клавиша "OK" - переход к измерению brne State6_3 ; с новыми настройками lds Tunes, mTunes ; Изменение настроек на "об/мин" andi Tunes, 0b11101000 ori Tunes, 0b00000010 sts mTunes, Tunes ; Сохранение настроек в SRAM rcall EEPROM_Write ; Сохранение настроек в EEPROM rcall MeasureInterface ; Вывести на дисплей интерфейс измерения скорости ldi State, Measure ; Изменить состояние устройства: sts mState, State ; измерение скорости ldi var, 0b10001 ; Разрешение вычисления скорости out timsk, var ldi var, 0b11000000 out gicr, var State6_3: ret ;------------------------------------------------------------------------------; Пункт меню "об/с" (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State7: cpi Key, 2 ; Нажата клавиша Esc - возвращение к Menu1 brne State7_1 ldi State, Menu1 ; Изменение состояния на Menu1 sts mState, State rcall Menu1Interface ; Вывести на дисплей интерфейс Menu1 rjmp State7_4 State7_1: cpi Key, 4 ; Нажата клавиша "вниз" - переход на Menu1_3 brne State7_2 ldi State, Menu1_3 ; Изменение состояния на Menu1_3 sts mState, State rcall Menu1_3Interface ; Вывести на дисплей интерфейс Menu1_3 rjmp State7_4 State7_2: cpi Key, 1 ; Нажата клавиша "вверх" - переход на Menu1_1 brne State7_3 ldi State, Menu1_1 ; Изменение состояния на Menu1_1 sts mState, State rcall Menu1_1Interface ; Вывести на дисплей интерфейс Menu1_1 rjmp State7_4 State7_3: cpi Key, 0 ; Нажата клавиша "OK" - переход к измерению brne State7_4 ; с новыми настройками lds Tunes, mTunes ; Изменение настроек на "об/с" andi Tunes, 0b11101000 ori Tunes, 0b00000001 sts mTunes, Tunes ; Сохранение настроек в SRAM rcall EEPROM_Write ; Сохранение настроек в EEPROM rcall MeasureInterface ; Вывести на дисплей интерфейс измерения скорости ldi State, Measure ; Изменить состояние устройства:
66 <480> <481> <482> <483> <484> <485> <486> <487> <488> <489> <490> <491> <492> <493> <494> <495> <496> <497> <498> <499> <500> <501> <502> <503> <504> <505> <506> <507> <508> <509> <510> <511> <512> <513> <514> <515> <516> <517> <518> <519> <520> <521> <522> <523> <524> <525> <526> <527> <528> <529> <530> <531> <532> <533> <534> <535> <536> <537> <538> <539> <540> <541> <542> <543> <544> <545> <546> <547> <548> <549> <550> <551> <552> <553> <554> <555> <556> <557> <558> <559>
sts ldi out ldi out State7_4: ret
mState, State var, 0b10001 timsk, var var, 0b11000000 gicr, var
; измерение скорости ; Разрешение вычисления скорости
;------------------------------------------------------------------------------; Пункт меню "рад/с" (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State8: cpi Key, 2 ; Нажата клавиша Esc - возвращение к Menu1 brne State8_1 ldi State, Menu1 ; Изменение состояния на Menu1 sts mState, State rcall Menu1Interface ; Вывести на дисплей интерфейс Menu1 rjmp State8_3 State8_1: cpi Key, 4 ; Нажата клавиша "вниз" - переход на Menu1_4 brne State8_2 ldi State, Menu1_4 ; Изменение состояния на Menu1_4 sts mState, State rcall Menu1_4Interface ; Вывести на дисплей интерфейс Menu1_4 rjmp State8_4 State8_2: cpi Key, 1 ; Нажата клавиша "вверх" - переход на Menu1_2 brne State8_3 ldi State, Menu1_2 ; Изменение состояния на Menu1_2 sts mState, State rcall Menu1_2Interface ; Вывести на дисплей интерфейс Menu1_2 rjmp State8_4 State8_3: cpi Key, 0 ; Нажата клавиша "OK" - переход к измерению brne State8_4 ; с новыми настройками lds Tunes, mTunes ; Изменение настроек на "рад/с" andi Tunes, 0b11101000 ori Tunes, 0b00000100 sts mTunes, Tunes ; Сохранение настроек в SRAM rcall EEPROM_Write ; Сохранение настроек в EEPROM rcall MeasureInterface ; Вывести на дисплей интерфейс измерения скорости ldi State, Measure ; Изменить состояние устройства: sts mState, State ; измерение скорости ldi var, 0b10001 ; Разрешение вычисления скорости out timsk, var ldi var, 0b11000000 out gicr, var State8_4: ret ;------------------------------------------------------------------------------; Пункт меню "см/с" (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State9: cpi Key, 2 ; Нажата клавиша Esc - возвращение к Menu1 brne State9_1 ldi State, Menu1 ; Изменение состояния на Menu1 sts mState, State rcall Menu1Interface ; Вывести на дисплей интерфейс Menu1 rjmp State9_4 State9_1: cpi Key, 4 ; Нажата клавиша "вниз" - переход на Menu1_5 brne State9_2 ldi State, Menu1_5 ; Изменение состояния на Menu1_5 sts mState, State rcall Menu1_5Interface ; Вывести на дисплей интерфейс Menu1_5 rjmp State9_4 State9_2: cpi Key, 1 ; Нажата клавиша "вверх" - переход на Menu1_3 brne State9_3 ldi State, Menu1_3 ; Изменение состояния на Menu1_3 sts mState, State rcall Menu1_3Interface ; Вывести на дисплей интерфейс Menu1_3 rjmp State9_4 State9_3: cpi Key, 0 ; Нажата клавиша "OK" - переход к измерению brne State9_4 ; с новыми настройками lds Tunes, mTunes ; Изменение настроек на "см/с"
67 <560> <561> <562> <563> <564> <565> <566> <567> <568> <569> <570> <571> <572> <573> <574> <575> <576> <577> <578> <579> <580> <581> <582> <583> <584> <585> <586> <587> <588> <589> <590> <591> <592> <593> <594> <595> <596> <597> <598> <599> <600> <601> <602> <603> <604> <605> <606> <607> <608> <609> <610> <611> <612> <613> <614> <615> <616> <617> <618> <619> <620> <621> <622> <623> <624> <625> <626> <627> <628> <629> <630> <631> <632> <633> <634> <635> <636> <637> <638> <639>
andi ori sts rcall rcall ldi sts ldi out ldi out State9_4: ret
Tunes, 0b11101000 Tunes, 0b00010000 mTunes, Tunes EEPROM_Write MeasureInterface State, Measure mState, State var, 0b10001 timsk, var var, 0b11000000 gicr, var
; ; ; ; ; ;
Сохранение настроек в SRAM Сохранение настроек в EEPROM Вывести на дисплей интерфейс измерения скорости Изменить состояние устройства: измерение скорости Разрешение вычисления скорости
;------------------------------------------------------------------------------; Пункт меню "Коэф. передачи" (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State10: cpi Key, 2 ; Нажата клавиша Esc - возвращение к Menu1 brne State10_1 ldi State, Menu1 ; Изменение состояния на Menu1 sts mState, State rcall Menu1Interface ; Вывести на дисплей интерфейс Menu1 rjmp State10_3 State10_1: cpi Key, 1 ; Нажата клавиша "вверх" - переход на Menu1_4 brne State10_2 ldi State, Menu1_4 ; Изменение состояния на Menu1_4 sts mState, State rcall Menu1_4Interface ; Вывести на дисплей интерфейс Menu1_4 rjmp State10_3 State10_2: cpi Key, 0 ; Нажата клавиша "OK" - ввод коэффициента передачи brne State10_3 rcall EEPROM_Read lds Float2O, KO ; Загрузка в Float2 коэффициента передачи K lds Float2L, KL lds Float2H, KH ldi var, 0b10000000 ; Безразмерная величина в EditBox mov r9, var rcall EditBox ; Вызов поля ввода EditBox sts KO, Float2O ; Сохранение коэффициента передачи K sts KL, Float2L sts KH, Float2H rcall EEPROM_Write ; Сохранение параметров в EEPROM ldi State, Menu1_5 ; Изменение состояния на Menu1_5 sts mState, State rcall Menu1_5Interface ; Вывести на дисплей интерфейс Menu1_5 State10_3: ret ;------------------------------------------------------------------------------; Пункт меню "Интервал счёта" (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State11: cpi Key, 2 ; Нажата клавиша Esc - возвращение к Menu2 brne State11_1 ldi State, Menu2 ; Изменение состояния на Menu2 sts mState, State rcall Menu2Interface ; Вывести на дисплей интерфейс Menu2 rjmp State11_3 State11_1: cpi Key, 4 ; Нажата клавиша "вниз" - переход на Menu2_2 brne State11_2 ldi State, Menu2_2 ; Изменение состояния на Menu2_2 sts mState, State rcall Menu2_2Interface ; Вывести на дисплей интерфейс Menu2_2 rjmp State11_3 State11_2: cpi Key, 0 ; Нажата клавиша "OK" - ввод интевала счета brne State11_3 rcall EEPROM_Read ; Чтение параметров из EEPROM lds Float1O, TO ; Загрузка в Float1 интервала счета T lds Float1L, TL lds Float1H, TH ldi Float2H, 0x03 ; Перевод T в [мс] ldi Float2L, 0xe8 rcall Fix2Float
68 <640> <641> <642> <643> <644> <645> <646> <647> <648> <649> <650> <651> <652> <653> <654> <655> <656> <657> <658> <659> <660> <661> <662> <663> <664> <665> <666> <667> <668> <669> <670> <671> <672> <673> <674> <675> <676> <677> <678> <679> <680> <681> <682> <683> <684> <685> <686> <687> <688> <689> <690> <691> <692> <693> <694> <695> <696> <697> <698> <699> <700> <701> <702> <703> <704> <705> <706> <707> <708> <709> <710> <711> <712> <713> <714> <715> <716> <717> <718> <719>
rcall ldi mov rcall rcall ldi ldi rcall rcall sts sts sts rcall rcall ldi sts rcall State11_3: ret
FMult var, 0b10000 r9, var EditBox SwapFl Float2H, 0x03 Float2L, 0xe8 Fix2Float FDiv TO, Float2O TL, Float2L TH, Float2H SetTimerInterval EEPROM_Write State, Menu2_1 mState, State Menu2_1Interface
; Размерность в EditBox [мс] ; Вызов поля ввода EditBox ; Перевод T в [с]
; Сохранение интервала счета T ; Установка интервала счета ; Сохранение параметров в EEPROM ; Изменение состояния на Menu2_1 ; Вывести на дисплей интерфейс Menu2_1
;------------------------------------------------------------------------------; Пункт меню "Погрешность" (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State12: cpi Key, 2 ; Нажата клавиша Esc - возвращение к Menu2 brne State12_1 ldi State, Menu2 ; Изменение состояния на Menu2 sts mState, State rcall Menu2Interface ; Вывести на дисплей интерфейс Menu2 rjmp State12_4 State12_1: cpi Key, 4 ; Нажата клавиша "вниз" - переход на Menu2_3 brne State12_2 ldi State, Menu2_3 ; Изменение состояния на Menu2_3 sts mState, State rcall Menu2_3Interface ; Вывести на дисплей интерфейс Menu2_3 rjmp State12_4 State12_2: cpi Key, 1 ; Нажата клавиша "вверх" - переход на Menu2_1 brne State12_3 ldi State, Menu2_1 ; Изменение состояния на Menu2_1 sts mState, State rcall Menu2_1Interface ; Вывести на дисплей интерфейс Menu2_1 rjmp State12_4 State12_3: cpi Key, 0 ; Нажата клавиша "OK" - ввод допустимой погрешности brne State12_4 rcall GetMistake ; Вычисление абсолютной погрешности lds Float2O, MistakeO ; Загрузка в Float2 допустимой погрешности Mistake lds Float2L, MistakeL lds Float2H, MistakeH lds Tunes, mTunes ; Установка в EditBox текущей размерности sbrc Tunes, 0 ldi var, 0b1 sbrc Tunes, 1 ldi var, 0b10 sbrc Tunes, 2 ldi var, 0b100 sbrc Tunes, 4 ldi var, 0b1000 mov r9, var rcall EditBox ; Вызов поля ввода EditBox sts MistakeO, Float2O ; Сохранение допустимой погрешности sts MistakeL, Float2L sts MistakeH, Float2H rcall GetTimerInterval ; Вычисление интервала счета rcall SetTimerInterval ; Установка интервала счета rcall EEPROM_Write ; Сохранение параметров в EEPROM ldi State, Menu2_2 ; Изменение состояния на Menu2_2 sts mState, State rcall Menu2_2Interface ; Вывести на дисплей интерфейс Menu2_2 State12_4: ret ;------------------------------------------------------------------------------; Пункт меню "Автокалибровка" (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State13:
69 <720> <721> <722> <723> <724> <725> <726> <727> <728> <729> <730> <731> <732> <733> <734> <735> <736> <737> <738> <739> <740> <741> <742> <743> <744> <745> <746> <747> <748> <749> <750> <751> <752> <753> <754> <755> <756> <757> <758> <759> <760> <761> <762> <763> <764> <765> <766> <767> <768> <769> <770> <771> <772> <773> <774> <775> <776> <777> <778> <779> <780> <781> <782> <783> <784> <785> <786> <787> <788> <789> <790> <791> <792> <793> <794> <795> <796> <797> <798> <799>
cpi Key, 2 brne State13_1 ldi State, Menu2 sts mState, State rcall Menu2Interface rjmp State13_3 State13_1: cpi Key, 1 brne State13_2 ldi State, Menu2_2 sts mState, State rcall Menu2_2Interface rjmp State13_3 State13_2: cpi Key, 0 brne State13_3 lds Tunes, mTunes sbrs Tunes, 1 rjmp State13_RadPS ldi Float2O, 0x43 ldi Float2L, 0x00 ldi Float2H, 0xc0 rjmp State13_OK State13_RadPS: sbrs Tunes, 2 rjmp State13_Other ldi Float2O, 0x40 ldi Float2L, 0xd8 ldi Float2H, 0xa0 rjmp State13_OK State13_Other: ldi var, 0b1000 ldi Float2O, 0x3d ldi Float2L, 0xcc ldi Float2H, 0xcc State13_OK: sts MistakeO, Float2O sts MistakeL, Float2L sts MistakeH, Float2H rcall GetTimerInterval rcall SetTimerInterval rcall EEPROM_Write ldi State, Menu2_3 sts mState, State rcall Menu2_3Interface State13_3: ret
; Нажата клавиша Esc - возвращение к Menu2 ; Изменение состояния на Menu2 ; Вывести на дисплей интерфейс Menu2 ; Нажата клавиша "вверх" - переход на Menu2_2 ; Изменение состояния на Menu2_2 ; Вывести на дисплей интерфейс Menu2_2 ; Нажата клавиша "OK" - выполнение автокалибровки ; Выбор допустимой погрешности в звисимости от ; текущих единиц измерения ; 6 [об/мин]
; 0.6283 [рад/с]
; 0.1 [об/с]
; Сохранение допустимой погрешности ; ; ; ;
Вычисление интервала счета Установка интервала счета Сохранение параметров в EEPROM Изменение состояния на Menu2_3
; Вывести на дисплей интерфейс Menu2_3
;------------------------------------------------------------------------------; Пункт меню "Включить" (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State14: cpi Key, 2 ; Нажата клавиша Esc - возвращение к Menu3 brne State14_1 ldi State, Menu3 ; Изменение состояния на Menu3 sts mState, State rcall Menu3Interface ; Вывести на дисплей интерфейс Menu3 rjmp State14_3 State14_1: cpi Key, 4 ; Нажата клавиша "вниз" - переход на Menu3_2 brne State14_2 ldi State, Menu3_2 ; Изменение состояния на Menu3_2 sts mState, State rcall Menu3_2Interface ; Вывести на дисплей интерфейс Menu3_2 rjmp State14_3 State14_2: cpi Key, 0 ; Нажата клавиша "OK" - переход к измерению brne State14_3 ; с новыми настройками lds Tunes, mTunes ; Изменение состояния интерфейса на противоположное sbrc Tunes, 3 ; rjmp State14_I1 ori Tunes, 0b00001000 rcall USART_Init ; Инициализация USART rjmp State14_I2 State14_I1: andi Tunes, 0b11110111 rcall USART_ShutDown ; Деактивация USART State14_I2: sts mTunes, Tunes ; Сохранение настроек в SRAM
70 <800> <801> <802> <803> <804> <805> <806> <807> <808> <809> <810> <811> <812> <813> <814> <815> <816> <817> <818> <819> <820> <821> <822> <823> <824> <825> <826> <827> <828> <829> <830> <831> <832> <833> <834> <835> <836> <837> <838> <839> <840> <841> <842> <843> <844> <845> <846> <847> <848> <849> <850> <851> <852> <853> <854> <855> <856> <857> <858> <859> <860> <861> <862> <863> <864> <865> <866> <867> <868> <869> <870> <871> <872> <873> <874> <875> <876> <877> <878> <879>
rcall rcall ldi sts ldi out ldi out State14_3: ret
EEPROM_Write MeasureInterface State, Measure mState, State var, 0b10001 timsk, var var, 0b11000000 gicr, var
; ; ; ; ;
Сохранение настроек в EEPROM Вывести на дисплей интерфейс измерения скорости Изменить состояние устройства: измерение скорости Разрешение вычисления скорости
;------------------------------------------------------------------------------; Пункт меню "Скорость обмена" (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State15: cpi Key, 2 ; Нажата клавиша Esc - возвращение к Menu3 brne State15_1 ldi State, Menu3 ; Изменение состояния на Menu3 sts mState, State rcall Menu3Interface ; Вывести на дисплей интерфейс Menu3 rjmp State15_3 State15_1: cpi Key, 1 ; Нажата клавиша "вверх" - переход на Menu3_1 brne State15_2 ldi State, Menu3_1 ; Изменение состояния на Menu3_1 sts mState, State rcall Menu3_1Interface ; Вывести на дисплей интерфейс Menu3_1 rjmp State15_3 State15_2: cpi Key, 0 ; Нажата клавиша "OK" - переход на Menu3_2_1 brne State15_3 ldi State, Menu3_2_1 ; Изменение состояния на Menu3_2_1 sts mState, State rcall Menu3_2_1Interface ; Вывести на дисплей интерфейс Menu3_2_1 State15_3: ret ;------------------------------------------------------------------------------; Пункт меню "2400 бод" (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State16: cpi Key, 2 ; Нажата клавиша Esc - возвращение к Menu3_2 brne State16_1 ldi State, Menu3_2 ; Изменение состояния на Menu3_2 sts mState, State rcall Menu3_2Interface ; Вывести на дисплей интерфейс Menu3_2 rjmp State16_3 State16_1: cpi Key, 4 ; Нажата клавиша "вниз" - переход на Menu3_2_2 brne State16_2 ldi State, Menu3_2_2 ; Изменение состояния на Menu3_2_2 sts mState, State rcall Menu3_2_2Interface ; Вывести на дисплей интерфейс Menu3_2_2 rjmp State16_3 State16_2: cpi Key, 0 ; Нажата клавиша "OK" - переход к измерению brne State16_3 ; с новыми настройками ldi BitRateFlags, 0 sts mBitRate, BitRateFlags ; Сохранение битрейта в SRAM rcall EEPROM_Write ; Сохранение настроек в EEPROM rcall USART_SetBitRate ; Установка скоростти обмена rcall MeasureInterface ; Вывести на дисплей интерфейс изм-я скорости ldi State, Measure ; Изменить состояние устройства: sts mState, State ; измерение скорости ldi var, 0b10001 ; Разрешение вычисления скорости out timsk, var ldi var, 0b11000000 out gicr, var State16_3: ret ;------------------------------------------------------------------------------; Пункт меню "4800 бод" (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State17: cpi Key, 2 ; Нажата клавиша Esc - возвращение к Menu3_2 brne State17_1
71 <880> <881> <882> <883> <884> <885> <886> <887> <888> <889> <890> <891> <892> <893> <894> <895> <896> <897> <898> <899> <900> <901> <902> <903> <904> <905> <906> <907> <908> <909> <910> <911> <912> <913> <914> <915> <916> <917> <918> <919> <920> <921> <922> <923> <924> <925> <926> <927> <928> <929> <930> <931> <932> <933> <934> <935> <936> <937> <938> <939> <940> <941> <942> <943> <944> <945> <946> <947> <948> <949> <950> <951> <952> <953> <954> <955> <956> <957> <958> <959>
ldi sts rcall rjmp State17_1: cpi brne ldi sts rcall rjmp State17_2: cpi brne ldi sts rcall rjmp State17_3: cpi brne ldi sts rcall rcall rcall ldi sts ldi out ldi out State17_4: ret
State, Menu3_2 mState, State Menu3_2Interface State17_4
; Изменение состояния на Menu3_2
Key, 4 State17_2 State, Menu3_2_3 mState, State Menu3_2_3Interface State17_4
; Нажата клавиша "вниз" - переход на Menu3_2_3
; Вывести на дисплей интерфейс Menu3_2
; Изменение состояния на Menu3_2_3 ; Вывести на дисплей интерфейс Menu3_2_3
Key, 1 State17_3 State, Menu3_2_1 mState, State Menu3_2_1Interface State17_4
; Нажата клавиша "вверх"- переход на Menu3_2_1
Key, 0 State17_4 BitRateFlags, 1 mBitRate, BitRateFlags EEPROM_Write USART_SetBitRate MeasureInterface State, Measure mState, State var, 0b10001 timsk, var var, 0b11000000 gicr, var
; Нажата клавиша "OK" - переход к измерению ; с новыми настройками
; Изменение состояния на Menu3_2_1 ; Вывести на дисплей интерфейс Menu3_2_1
; ; ; ; ; ; ;
Сохранение битрейта в SRAM Сохранение настроек в EEPROM Установка скоростти обмена Вывести на дисплей интерфейс изм-я скорости Изменить состояние устройства: измерение скорости Разрешение вычисления скорости
;------------------------------------------------------------------------------; Пункт меню "9600 бод" (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State18: cpi Key, 2 ; Нажата клавиша Esc - возвращение к Menu3_2 brne State18_1 ldi State, Menu3_2 ; Изменение состояния на Menu3_2 sts mState, State rcall Menu3_2Interface ; Вывести на дисплей интерфейс Menu3_2 rjmp State18_4 State18_1: cpi Key, 4 ; Нажата клавиша "вниз" - переход на Menu3_2_4 brne State18_2 ldi State, Menu3_2_4 ; Изменение состояния на Menu3_2_4 sts mState, State rcall Menu3_2_4Interface ; Вывести на дисплей интерфейс Menu3_2_4 rjmp State18_4 State18_2: cpi Key, 1 ; Нажата клавиша "вверх"- переход на Menu3_2_2 brne State18_3 ldi State, Menu3_2_2 ; Изменение состояния на Menu3_2_2 sts mState, State rcall Menu3_2_2Interface ; Вывести на дисплей интерфейс Menu3_2_2 rjmp State18_4 State18_3: cpi Key, 0 ; Нажата клавиша "OK" - переход к измерению brne State18_4 ; с новыми настройками ldi BitRateFlags, 2 sts mBitRate, BitRateFlags ; Сохранение битрейта в SRAM rcall EEPROM_Write ; Сохранение настроек в EEPROM rcall USART_SetBitRate ; Установка скоростти обмена rcall MeasureInterface ; Вывести на дисплей интерфейс изм-я скорости ldi State, Measure ; Изменить состояние устройства: sts mState, State ; измерение скорости ldi var, 0b10001 ; Разрешение вычисления скорости out timsk, var ldi var, 0b11000000 out gicr, var State18_4: ret ;------------------------------------------------------------------------------; Пункт меню "14400 бод" (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key
72 <960> <961> <962> <963> <964> <965> <966> <967> <968> <969> <970> <971> <972> <973> <974> <975> <976> <977> <978> <979> <980> <981> <982> <983> <984> <985> <986> <987> <988> <989> <990> <991> <992> <993> <994> <995> <996> <997> <998> <999> <1000> <1001> <1002> <1003> <1004> <1005> <1006> <1007> <1008> <1009> <1010> <1011> <1012> <1013> <1014> <1015> <1016> <1017> <1018> <1019> <1020> <1021> <1022> <1023> <1024> <1025> <1026> <1027> <1028> <1029> <1030> <1031> <1032> <1033> <1034> <1035> <1036> <1037> <1038> <1039>
;------------------------------------------------------------------------------State19: cpi Key, 2 ; Нажата клавиша Esc - возвращение к Menu3_2 brne State19_1 ldi State, Menu3_2 ; Изменение состояния на Menu3_2 sts mState, State rcall Menu3_2Interface ; Вывести на дисплей интерфейс Menu3_2 rjmp State19_4 State19_1: cpi Key, 4 ; Нажата клавиша "вниз" - переход на Menu3_2_5 brne State19_2 ldi State, Menu3_2_5 ; Изменение состояния на Menu3_2_5 sts mState, State rcall Menu3_2_5Interface ; Вывести на дисплей интерфейс Menu3_2_5 rjmp State19_4 State19_2: cpi Key, 1 ; Нажата клавиша "вверх"- переход на Menu3_2_3 brne State19_3 ldi State, Menu3_2_3 ; Изменение состояния на Menu3_2_3 sts mState, State rcall Menu3_2_3Interface ; Вывести на дисплей интерфейс Menu3_2_3 rjmp State19_4 State19_3: cpi Key, 0 ; Нажата клавиша "OK" - переход к измерению brne State19_4 ; с новыми настройками ldi BitRateFlags, 3 sts mBitRate, BitRateFlags ; Сохранение битрейта в SRAM rcall EEPROM_Write ; Сохранение настроек в EEPROM rcall USART_SetBitRate ; Установка скоростти обмена rcall MeasureInterface ; Вывести на дисплей интерфейс изм-я скорости ldi State, Measure ; Изменить состояние устройства: sts mState, State ; измерение скорости ldi var, 0b10001 ; Разрешение вычисления скорости out timsk, var ldi var, 0b11000000 out gicr, var State19_4: ret ;------------------------------------------------------------------------------; Пункт меню "19200 бод" (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State20: cpi Key, 2 ; Нажата клавиша Esc - возвращение к Menu3_2 brne State20_1 ldi State, Menu3_2 ; Изменение состояния на Menu3_2 sts mState, State rcall Menu3_2Interface ; Вывести на дисплей интерфейс Menu3_2 rjmp State20_4 State20_1: cpi Key, 4 ; Нажата клавиша "вниз" - переход на Menu3_2_6 brne State20_2 ldi State, Menu3_2_6 ; Изменение состояния на Menu3_2_6 sts mState, State rcall Menu3_2_6Interface ; Вывести на дисплей интерфейс Menu3_2_6 rjmp State20_4 State20_2: cpi Key, 1 ; Нажата клавиша "вверх"- переход на Menu3_2_4 brne State20_3 ldi State, Menu3_2_4 ; Изменение состояния на Menu3_2_4 sts mState, State rcall Menu3_2_4Interface ; Вывести на дисплей интерфейс Menu3_2_4 rjmp State20_4 State20_3: cpi Key, 0 ; Нажата клавиша "OK" - переход к измерению brne State20_4 ; с новыми настройками ldi BitRateFlags, 4 sts mBitRate, BitRateFlags ; Сохранение битрейта в SRAM rcall EEPROM_Write ; Сохранение настроек в EEPROM rcall USART_SetBitRate ; Установка скоростти обмена rcall MeasureInterface ; Вывести на дисплей интерфейс изм-я скорости ldi State, Measure ; Изменить состояние устройства: sts mState, State ; измерение скорости ldi var, 0b10001 ; Разрешение вычисления скорости out timsk, var ldi var, 0b11000000 out gicr, var State20_4: ret
73 <1040> <1041> <1042> <1043> <1044> <1045> <1046> <1047> <1048> <1049> <1050> <1051> <1052> <1053> <1054> <1055> <1056> <1057> <1058> <1059> <1060> <1061> <1062> <1063> <1064> <1065> <1066> <1067> <1068> <1069> <1070> <1071> <1072> <1073> <1074> <1075> <1076> <1077> <1078> <1079> <1080> <1081> <1082> <1083> <1084> <1085> <1086> <1087> <1088> <1089> <1090> <1091> <1092> <1093> <1094> <1095> <1096> <1097> <1098> <1099> <1100> <1101> <1102> <1103> <1104> <1105> <1106> <1107> <1108> <1109> <1110> <1111> <1112> <1113> <1114> <1115> <1116> <1117> <1118> <1119>
;------------------------------------------------------------------------------; Пункт меню "38400 бод" (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State21: cpi Key, 2 ; Нажата клавиша Esc - возвращение к Menu3_2 brne State21_1 ldi State, Menu3_2 ; Изменение состояния на Menu3_2 sts mState, State rcall Menu3_2Interface ; Вывести на дисплей интерфейс Menu3_2 rjmp State21_4 State21_1: cpi Key, 4 ; Нажата клавиша "вниз" - переход на Menu3_2_7 brne State21_2 ldi State, Menu3_2_7 ; Изменение состояния на Menu3_2_7 sts mState, State rcall Menu3_2_7Interface ; Вывести на дисплей интерфейс Menu3_2_7 rjmp State21_4 State21_2: cpi Key, 1 ; Нажата клавиша "вверх"- переход на Menu3_2_5 brne State21_3 ldi State, Menu3_2_5 ; Изменение состояния на Menu3_2_5 sts mState, State rcall Menu3_2_5Interface ; Вывести на дисплей интерфейс Menu3_2_5 rjmp State21_4 State21_3: cpi Key, 0 ; Нажата клавиша "OK" - переход к измерению brne State21_4 ; с новыми настройками ldi BitRateFlags, 5 sts mBitRate, BitRateFlags ; Сохранение битрейта в SRAM rcall EEPROM_Write ; Сохранение настроек в EEPROM rcall USART_SetBitRate ; Установка скоростти обмена rcall MeasureInterface ; Вывести на дисплей интерфейс изм-я скорости ldi State, Measure ; Изменить состояние устройства: sts mState, State ; измерение скорости ldi var, 0b10001 ; Разрешение вычисления скорости out timsk, var ldi var, 0b11000000 out gicr, var State21_4: ret ;------------------------------------------------------------------------------; Пункт меню "57600 бод" (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State22: cpi Key, 2 ; Нажата клавиша Esc - возвращение к Menu3_2 brne State22_1 ldi State, Menu3_2 ; Изменение состояния на Menu3_2 sts mState, State rcall Menu3_2Interface ; Вывести на дисплей интерфейс Menu3_2 rjmp State22_4 State22_1: cpi Key, 4 ; Нажата клавиша "вниз" - переход на Menu3_2_8 brne State22_2 ldi State, Menu3_2_8 ; Изменение состояния на Menu3_2_8 sts mState, State rcall Menu3_2_8Interface ; Вывести на дисплей интерфейс Menu3_2_8 rjmp State22_4 State22_2: cpi Key, 1 ; Нажата клавиша "вверх"- переход на Menu3_2_6 brne State22_3 ldi State, Menu3_2_6 ; Изменение состояния на Menu3_2_6 sts mState, State rcall Menu3_2_6Interface ; Вывести на дисплей интерфейс Menu3_2_6 rjmp State22_4 State22_3: cpi Key, 0 ; Нажата клавиша "OK" - переход к измерению brne State22_4 ; с новыми настройками ldi BitRateFlags, 6 sts mBitRate, BitRateFlags ; Сохранение битрейта в SRAM rcall EEPROM_Write ; Сохранение настроек в EEPROM rcall USART_SetBitRate ; Установка скоростти обмена rcall MeasureInterface ; Вывести на дисплей интерфейс изм-я скорости ldi State, Measure ; Изменить состояние устройства: sts mState, State ; измерение скорости ldi var, 0b10001 ; Разрешение вычисления скорости out timsk, var
74 <1120> <1121> <1122> <1123> <1124> <1125> <1126> <1127> <1128> <1129> <1130> <1131> <1132> <1133> <1134> <1135> <1136> <1137> <1138> <1139> <1140> <1141> <1142> <1143> <1144> <1145> <1146> <1147> <1148> <1149> <1150> <1151> <1152> <1153> <1154> <1155> <1156> <1157> <1158> <1159> <1160> <1161> <1162> <1163> <1164> <1165> <1166> <1167> <1168> <1169> <1170> <1171> <1172> <1173> <1174> <1175> <1176> <1177> <1178> <1179> <1180> <1181> <1182> <1183> <1184> <1185> <1186> <1187> <1188> <1189> <1190> <1191> <1192> <1193> <1194> <1195> <1196> <1197> <1198> <1199>
ldi var, 0b11000000 out gicr, var State22_4: ret ;------------------------------------------------------------------------------; Пункт меню "115200 бод" (реакция на нажатие клавиши) ; Вход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------State23: cpi Key, 2 ; Нажата клавиша Esc - возвращение к Menu3_2 brne State23_1 ldi State, Menu3_2 ; Изменение состояния на Menu3_2 sts mState, State rcall Menu3_2Interface ; Вывести на дисплей интерфейс Menu3_2 rjmp State23_3 State23_1: cpi Key, 1 ; Нажата клавиша "вверх"- переход на Menu3_2_7 brne State23_2 ldi State, Menu3_2_7 ; Изменение состояния на Menu3_2_7 sts mState, State rcall Menu3_2_7Interface ; Вывести на дисплей интерфейс Menu3_2_7 rjmp State23_3 State23_2: cpi Key, 0 ; Нажата клавиша "OK" - переход к измерению brne State23_3 ; с новыми настройками ldi BitRateFlags, 7 sts mBitRate, BitRateFlags ; Сохранение битрейта в SRAM rcall EEPROM_Write ; Сохранение настроек в EEPROM rcall USART_SetBitRate ; Установка скоростти обмена rcall MeasureInterface ; Вывести на дисплей интерфейс изм-я скорости ldi State, Measure ; Изменить состояние устройства: sts mState, State ; измерение скорости ldi var, 0b10001 ; Разрешение вычисления скорости out timsk, var ldi var, 0b11000000 out gicr, var State23_3: ret ;------------------------------------------------------------------------------; Интерфейс для режима Measure ;------------------------------------------------------------------------------MeasureInterface: rcall ClrScr ; Очистка дисплея ldi r25, 10 ; Начальный адрес DDRAM ldi r24, 6 ; Количество символов ldi r30, low(TextIcons*2) ; Установить указатель Z на ldi r31, high(TextIcons*2) ; начало буфера TextMenu rcall OutText ; Вывод строки на дисплей ldi r25, 0 ; Начальный адрес DDRAM ldi r24, 9 ; Количество символов ldi r30, low(TextVel*2) ; Установить указатель Z на ldi r31, high(TextVel*2) ; начало буфера TextVel rcall OutText ; Вывод строки на дисплей rcall OutDimension ; Вывод размерности на дисплей rcall OutI ; Вывод состояния интерфейса на дисплей rcall USART_Transmit ; Вывод данных на интерфейс rcall USART_Transmit ret ;------------------------------------------------------------------------------; Подпрограмма вывода размерности на дисплей ; Вход - Tunes (извлекается из памяти RAM) ;------------------------------------------------------------------------------OutDimension: lds Tunes, mTunes ; Загрузка текущих настроек устройства sbrs Tunes, 0 ; об/с ? rjmp OD2 ldi r24, 4 ; Количество символов ldi r30, low(TextRPS*2) ; Установить указатель Z на ldi r31, high(TextRPS*2) ; начало буфера TextRPS rjmp OutDim OD2: sbrs Tunes, 1 ; об/мин ? rjmp OD3 ldi r24, 6 ; Количество символов ldi r30, low(TextRPM*2) ; Установить указатель Z на ldi r31, high(TextRPM*2) ; начало буфера TextRPM rjmp OutDim
75 <1200> <1201> <1202> <1203> <1204> <1205> <1206> <1207> <1208> <1209> <1210> <1211> <1212> <1213> <1214> <1215> <1216> <1217> <1218> <1219> <1220> <1221> <1222> <1223> <1224> <1225> <1226> <1227> <1228> <1229> <1230> <1231> <1232> <1233> <1234> <1235> <1236> <1237> <1238> <1239> <1240> <1241> <1242> <1243> <1244> <1245> <1246> <1247> <1248> <1249> <1250> <1251> <1252> <1253> <1254> <1255> <1256> <1257> <1258> <1259> <1260> <1261> <1262> <1263> <1264> <1265> <1266> <1267> <1268> <1269> <1270> <1271> <1272> <1273> <1274> <1275> <1276> <1277> <1278> <1279>
OD3: sbrs rjmp ldi ldi ldi rjmp OD4: ldi ldi ldi OutDim: ldi rcall ret
Tunes, 4 OD4 r24, 4 r30, low(TextSMS*2) r31, high(TextSMS*2) OutDim
; см/с ? ; Количество символов ; Установить указатель Z на ; начало буфера TextSMS
; рад/с ? r24, 5 ; Количество символов r30, low(TextRadPS*2) ; Установить указатель Z на r31, high(TextRadPS*2) ; начало буфера TextRadPS r25, 72 OutText
; Начальный адрес DDRAM ; Вывод строки на дисплей ; Выход из подпрограммы
;------------------------------------------------------------------------------; Подпрограмма вывода состояния интерфейса на дисплей ; Вход - Tunes (извлекается из памяти RAM) ;------------------------------------------------------------------------------OutI: lds Tunes, mTunes ; Загрузка текущих настроек устройства sbrs Tunes, 3 ; Если включен интерфейс, вывести символ "i" rjmp OutIret ldi r24, 0x95 ; Символ "i" ldi r25, 79 ; Адрес DDRAM rcall OutChar OutIret: ret ; Выход из подпрограммы ;------------------------------------------------------------------------------; Интерфейс для режима Menu1 ;------------------------------------------------------------------------------Menu1Interface: rcall ClrScr ; Очистка дисплея ldi r24, 16 ; Количество символов ldi r30, low(TextMenu*2) ; Установить указатель Z на ldi r31, high(TextMenu*2) ; начало буфера TextMenu ldi r25, 0 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xdc ; Символ выделения пункта меню ldi r25, 64 ; Адрес DDRAM rcall OutChar ldi r24, 11 ; Количество символов ldi r30, low(TextDim*2) ; Установить указатель Z на ldi r31, high(TextDim*2) ; начало буфера TextDim ldi r25, 65 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xda ; Символ стрелки вниз ldi r25, 79 ; Адрес DDRAM rcall OutChar rcall USART_Transmit ; Вывод данных на интерфейс rcall USART_Transmit ret ;------------------------------------------------------------------------------; Интерфейс для режима Menu2 ;------------------------------------------------------------------------------Menu2Interface: rcall ClrScr ; Очистка дисплея ldi r24, 11 ; Количество символов ldi r30, low(TextDim*2) ; Установить указатель Z на ldi r31, high(TextDim*2) ; начало буфера TextDim ldi r25, 1 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 8 ; Количество символов ldi r30, low(TextPrecision*2) ; Установить указатель Z на ldi r31, high(TextPrecision*2) ; начало буфера TextPrecision ldi r25, 65 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xdc ; Символ выделения пункта меню ldi r25, 64 ; Адрес DDRAM rcall OutChar ldi r24, 0xda ; Символ стрелки вниз ldi r25, 79 ; Адрес DDRAM rcall OutChar ldi r24, 0xd9 ; Символ стрелки вверх ldi r25, 15 ; Адрес DDRAM rcall OutChar rcall USART_Transmit ; Вывод данных на интерфейс
76 <1280> <1281> <1282> <1283> <1284> <1285> <1286> <1287> <1288> <1289> <1290> <1291> <1292> <1293> <1294> <1295> <1296> <1297> <1298> <1299> <1300> <1301> <1302> <1303> <1304> <1305> <1306> <1307> <1308> <1309> <1310> <1311> <1312> <1313> <1314> <1315> <1316> <1317> <1318> <1319> <1320> <1321> <1322> <1323> <1324> <1325> <1326> <1327> <1328> <1329> <1330> <1331> <1332> <1333> <1334> <1335> <1336> <1337> <1338> <1339> <1340> <1341> <1342> <1343> <1344> <1345> <1346> <1347> <1348> <1349> <1350> <1351> <1352> <1353> <1354> <1355> <1356> <1357> <1358> <1359>
rcall ret
USART_Transmit
;------------------------------------------------------------------------------; Интерфейс для режима Menu3 ;------------------------------------------------------------------------------Menu3Interface: rcall ClrScr ; Очистка дисплея ldi r24, 8 ; Количество символов ldi r30, low(TextPrecision*2) ; Установить указатель Z на ldi r31, high(TextPrecision*2) ; начало буфера TextPrecision ldi r25, 1 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 9 ; Количество символов ldi r30, low(TextInt*2) ; Установить указатель Z на ldi r31, high(TextInt*2) ; начало буфера TextInt ldi r25, 65 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xdc ; Символ выделения пункта меню ldi r25, 64 ; Адрес DDRAM rcall OutChar ldi r24, 0xda ; Символ стрелки вниз ldi r25, 79 ; Адрес DDRAM rcall OutChar ldi r24, 0xd9 ; Символ стрелки вверх ldi r25, 15 ; Адрес DDRAM rcall OutChar rcall USART_Transmit ; Вывод данных на интерфейс rcall USART_Transmit ret ;------------------------------------------------------------------------------; Интерфейс для режима Menu4 ;------------------------------------------------------------------------------Menu4Interface: rcall ClrScr ; Очистка дисплея ldi r24, 9 ; Количество символов ldi r30, low(TextInt*2) ; Установить указатель Z на ldi r31, high(TextInt*2) ; начало буфера TextInt ldi r25, 1 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 15 ; Количество символов ldi r30, low(TextDiag*2) ; Установить указатель Z на ldi r31, high(TextDiag*2) ; начало буфера TextDiag ldi r25, 65 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xdc ; Символ выделения пункта меню ldi r25, 64 ; Адрес DDRAM rcall OutChar ldi r24, 0xd9 ; Символ стрелки вверх ldi r25, 15 ; Адрес DDRAM rcall OutChar rcall USART_Transmit ; Вывод данных на интерфейс rcall USART_Transmit ret ;------------------------------------------------------------------------------; Интерфейс для режима Menu1_1 ;------------------------------------------------------------------------------Menu1_1Interface: rcall ClrScr ; Очистка дисплея ldi r24, 16 ; Количество символов ldi r30, low(TextMenu*2) ; Установить указатель Z на ldi r31, high(TextMenu*2) ; начало буфера TextEsc ldi r25, 0 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xdc ; Символ выделения пункта меню ldi r25, 64 ; Адрес DDRAM rcall OutChar ldi r24, 6 ; Количество символов ldi r30, low(TextRPM*2) ; Установить указатель Z на ldi r31, high(TextRPM*2) ; начало буфера TextRPM ldi r25, 65 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xda ; Символ стрелки вниз ldi r25, 79 ; Адрес DDRAM rcall OutChar lds Tunes, mTunes ; Если необходимо вывести флажок установки sbrs Tunes, 1 ; rjmp M1_1_1
77 <1360> <1361> <1362> <1363> <1364> <1365> <1366> <1367> <1368> <1369> <1370> <1371> <1372> <1373> <1374> <1375> <1376> <1377> <1378> <1379> <1380> <1381> <1382> <1383> <1384> <1385> <1386> <1387> <1388> <1389> <1390> <1391> <1392> <1393> <1394> <1395> <1396> <1397> <1398> <1399> <1400> <1401> <1402> <1403> <1404> <1405> <1406> <1407> <1408> <1409> <1410> <1411> <1412> <1413> <1414> <1415> <1416> <1417> <1418> <1419> <1420> <1421> <1422> <1423> <1424> <1425> <1426> <1427> <1428> <1429> <1430> <1431> <1432> <1433> <1434> <1435> <1436> <1437> <1438> <1439>
ldi ldi rcall M1_1_1: rcall rcall ret
r24, 0x94 r25, 71 OutChar
; Символ Флажка установки ; Адрес DDRAM
USART_Transmit USART_Transmit
; Вывод данных на интерфейс
;------------------------------------------------------------------------------; Интерфейс для режима Menu1_2 ;------------------------------------------------------------------------------Menu1_2Interface: rcall ClrScr ; Очистка дисплея ldi r24, 6 ; Количество символов ldi r30, low(TextRPM*2) ; Установить указатель Z на ldi r31, high(TextRPM*2) ; начало буфера TextRPM ldi r25, 1 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 4 ; Количество символов ldi r30, low(TextRPS*2) ; Установить указатель Z на ldi r31, high(TextRPS*2) ; начало буфера TextRPS ldi r25, 65 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xdc ; Символ выделения пункта меню ldi r25, 64 ; Адрес DDRAM rcall OutChar ldi r24, 0xda ; Символ стрелки вниз ldi r25, 79 ; Адрес DDRAM rcall OutChar ldi r24, 0xd9 ; Символ стрелки вверх ldi r25, 15 ; Адрес DDRAM rcall OutChar lds Tunes, mTunes ; Если необходимо вывести флажок установки sbrs Tunes, 1 ; rjmp M1_2_1 ldi r24, 0x94 ; Символ Флажка установки ldi r25, 7 ; Адрес DDRAM rcall OutChar M1_2_1: lds Tunes, mTunes ; Если необходимо вывести флажок установки sbrs Tunes, 0 ; rjmp M1_2_2 ldi r24, 0x94 ; Символ Флажка установки ldi r25, 69 ; Адрес DDRAM rcall OutChar M1_2_2: rcall USART_Transmit ; Вывод данных на интерфейс rcall USART_Transmit ret ;------------------------------------------------------------------------------; Интерфейс для режима Menu1_3 ;------------------------------------------------------------------------------Menu1_3Interface: rcall ClrScr ; Очистка дисплея ldi r24, 4 ; Количество символов ldi r30, low(TextRPS*2) ; Установить указатель Z на ldi r31, high(TextRPS*2) ; начало буфера TextRPS ldi r25, 1 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 5 ; Количество символов ldi r30, low(TextRadPS*2) ; Установить указатель Z на ldi r31, high(TextRadPS*2) ; начало буфера TextRadPS ldi r25, 65 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xdc ; Символ выделения пункта меню ldi r25, 64 ; Адрес DDRAM rcall OutChar ldi r24, 0xda ; Символ стрелки вниз ldi r25, 79 ; Адрес DDRAM rcall OutChar ldi r24, 0xd9 ; Символ стрелки вверх ldi r25, 15 ; Адрес DDRAM rcall OutChar lds Tunes, mTunes ; Если необходимо вывести флажок установки sbrs Tunes, 0 ; rjmp M1_3_1 ldi r24, 0x94 ; Символ Флажка установки ldi r25, 5 ; Адрес DDRAM rcall OutChar
78 <1440> <1441> <1442> <1443> <1444> <1445> <1446> <1447> <1448> <1449> <1450> <1451> <1452> <1453> <1454> <1455> <1456> <1457> <1458> <1459> <1460> <1461> <1462> <1463> <1464> <1465> <1466> <1467> <1468> <1469> <1470> <1471> <1472> <1473> <1474> <1475> <1476> <1477> <1478> <1479> <1480> <1481> <1482> <1483> <1484> <1485> <1486> <1487> <1488> <1489> <1490> <1491> <1492> <1493> <1494> <1495> <1496> <1497> <1498> <1499> <1500> <1501> <1502> <1503> <1504> <1505> <1506> <1507> <1508> <1509> <1510> <1511> <1512> <1513> <1514> <1515> <1516> <1517> <1518> <1519>
M1_3_1: lds sbrs rjmp ldi ldi rcall M1_3_2: rcall rcall ret
Tunes, mTunes Tunes, 2 M1_3_2 r24, 0x94 r25, 70 OutChar
; Если необходимо вывести флажок установки ;
USART_Transmit USART_Transmit
; Вывод данных на интерфейс
; Символ Флажка установки ; Адрес DDRAM
;------------------------------------------------------------------------------; Интерфейс для режима Menu1_4 ;------------------------------------------------------------------------------Menu1_4Interface: rcall ClrScr ; Очистка дисплея ldi r24, 5 ; Количество символов ldi r30, low(TextRadPS*2) ; Установить указатель Z на ldi r31, high(TextRadPS*2) ; начало буфера TextRadPS ldi r25, 1 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 4 ; Количество символов ldi r30, low(TextSMS*2) ; Установить указатель Z на ldi r31, high(TextSMS*2) ; начало буфера TextSMS ldi r25, 65 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xdc ; Символ выделения пункта меню ldi r25, 64 ; Адрес DDRAM rcall OutChar ldi r24, 0xda ; Символ стрелки вниз ldi r25, 79 ; Адрес DDRAM rcall OutChar ldi r24, 0xd9 ; Символ стрелки вверх ldi r25, 15 ; Адрес DDRAM rcall OutChar lds Tunes, mTunes ; Если необходимо вывести флажок установки sbrs Tunes, 2 ; rjmp M1_4_1 ldi r24, 0x94 ; Символ Флажка установки ldi r25, 6 ; Адрес DDRAM rcall OutChar M1_4_1: lds Tunes, mTunes ; Если необходимо вывести флажок установки sbrs Tunes, 4 ; rjmp M1_4_2 ldi r24, 0x94 ; Символ Флажка установки ldi r25, 69 ; Адрес DDRAM rcall OutChar M1_4_2: rcall USART_Transmit ; Вывод данных на интерфейс rcall USART_Transmit ret ;------------------------------------------------------------------------------; Интерфейс для режима Menu1_5 ;------------------------------------------------------------------------------Menu1_5Interface: rcall ClrScr ; Очистка дисплея ldi r24, 4 ; Количество символов ldi r30, low(TextSMS*2) ; Установить указатель Z на ldi r31, high(TextSMS*2) ; начало буфера TextSMS ldi r25, 1 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 14 ; Количество символов ldi r30, low(TextCoef*2) ; Установить указатель Z на ldi r31, high(TextCoef*2) ; начало буфера TextCoef ldi r25, 65 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xdc ; Символ выделения пункта меню ldi r25, 64 ; Адрес DDRAM rcall OutChar ldi r24, 0xd9 ; Символ стрелки вверх ldi r25, 15 ; Адрес DDRAM rcall OutChar lds Tunes, mTunes ; Если необходимо вывести флажок установки sbrs Tunes, 4 ; rjmp M1_5_1 ldi r24, 0x94 ; Символ Флажка установки ldi r25, 5 ; Адрес DDRAM
79 <1520> <1521> <1522> <1523> <1524> <1525> <1526> <1527> <1528> <1529> <1530> <1531> <1532> <1533> <1534> <1535> <1536> <1537> <1538> <1539> <1540> <1541> <1542> <1543> <1544> <1545> <1546> <1547> <1548> <1549> <1550> <1551> <1552> <1553> <1554> <1555> <1556> <1557> <1558> <1559> <1560> <1561> <1562> <1563> <1564> <1565> <1566> <1567> <1568> <1569> <1570> <1571> <1572> <1573> <1574> <1575> <1576> <1577> <1578> <1579> <1580> <1581> <1582> <1583> <1584> <1585>
rcall M1_5_1: rcall rcall ret
OutChar USART_Transmit USART_Transmit
; Вывод данных на интерфейс
;------------------------------------------------------------------------------; Интерфейс для режима Menu2_1 ;------------------------------------------------------------------------------Menu2_1Interface: rcall ClrScr ; Очистка дисплея ldi r24, 16 ; Количество символов ldi r30, low(TextMenu*2) ; Установить указатель Z на ldi r31, high(TextMenu*2) ; начало буфера TextEsc ldi r25, 0 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xdc ; Символ выделения пункта меню ldi r25, 64 ; Адрес DDRAM rcall OutChar ldi r24, 14 ; Количество символов ldi r30, low(TextCountInterval*2) ; Установить указатель Z на ldi r31, high(TextCountInterval*2) ; начало буфера TextCountInterval ldi r25, 65 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xda ; Символ стрелки вниз ldi r25, 79 ; Адрес DDRAM rcall OutChar rcall USART_Transmit ; Вывод данных на интерфейс rcall USART_Transmit ret ;------------------------------------------------------------------------------; Интерфейс для режима Menu2_2 ;------------------------------------------------------------------------------Menu2_2Interface: rcall ClrScr ; Очистка дисплея ldi r24, 14 ; Количество символов ldi r30, low(TextCountInterval*2) ; Установить указатель Z на ldi r31, high(TextCountInterval*2) ; начало буфера TextCountInterval ldi r25, 1 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 11 ; Количество символов ldi r30, low(TextMistake*2) ; Установить указатель Z на ldi r31, high(TextMistake*2) ; начало буфера TextMistake ldi r25, 65 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xdc ; Символ выделения пункта меню ldi r25, 64 ; Адрес DDRAM rcall OutChar ldi r24, 0xda ; Символ стрелки вниз ldi r25, 79 ; Адрес DDRAM rcall OutChar ldi r24, 0xd9 ; Символ стрелки вверх ldi r25, 15 ; Адрес DDRAM rcall OutChar rcall USART_Transmit ; Вывод данных на интерфейс rcall USART_Transmit ret ;------------------------------------------------------------------------------; Интерфейс для режима Menu2_3 ;------------------------------------------------------------------------------Menu2_3Interface: rcall ClrScr ; Очистка дисплея ldi r24, 11 ; Количество символов ldi r30, low(TextMistake*2) ; Установить указатель Z на
<1586> <1587> <1588> <1589> <1590>
ldi ldi rcall ldi ldi
r31, high(TextMistake*2) r25, 1 OutText r24, 14 r30, low(TextAutocalibration*2)
; ; ; ; ;
начало буфера TextMistake Начальный адрес DDRAM Вывод строки на дисплей Количество символов Установить указатель Z на
<1591> <1592> <1593> <1594> <1595> <1596> <1597>
ldi ldi rcall ldi ldi rcall ldi
r31, high(TextAutocalibration*2) r25, 65 OutText r24, 0xdc r25, 64 OutChar r24, 0xd9
; ; ; ; ;
начало буфера TextAutocalibration Начальный адрес DDRAM Вывод строки на дисплей Символ выделения пункта меню Адрес DDRAM
; Символ стрелки вверх
80 <1598> <1599> <1600> <1601> <1602> <1603> <1604> <1605> <1606> <1607> <1608> <1609> <1610> <1611> <1612> <1613> <1614> <1615> <1616> <1617> <1618> <1619> <1620> <1621> <1622> <1623> <1624> <1625> <1626> <1627> <1628> <1629> <1630> <1631> <1632> <1633> <1634> <1635> <1636> <1637> <1638> <1639> <1640> <1641> <1642> <1643> <1644> <1645> <1646> <1647> <1648> <1649> <1650> <1651> <1652> <1653> <1654> <1655> <1656> <1657> <1658> <1659> <1660> <1661> <1662> <1663> <1664> <1665> <1666> <1667> <1668> <1669> <1670> <1671> <1672> <1673> <1674> <1675> <1676> <1677>
ldi rcall rcall rcall ret
r25, 15 OutChar USART_Transmit USART_Transmit
; Адрес DDRAM ; Вывод данных на интерфейс
;------------------------------------------------------------------------------; Интерфейс для режима Menu3_1 ;------------------------------------------------------------------------------Menu3_1Interface: rcall ClrScr ; Очистка дисплея ldi r24, 16 ; Количество символов ldi r30, low(TextMenu*2) ; Установить указатель Z на ldi r31, high(TextMenu*2) ; начало буфера TextMenu ldi r25, 0 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xdc ; Символ выделения пункта меню ldi r25, 64 ; Адрес DDRAM rcall OutChar ldi r24, 8 ; Количество символов ldi r30, low(TextOn*2) ; Установить указатель Z на ldi r31, high(TextOn*2) ; начало буфера TextOn ldi r25, 65 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей lds Tunes, 0x62 ; Если интерфейс включен, sbrs Tunes, 3 ; вывести флажок установки rjmp M3_1NoCheckI ldi r24, 0x94 ; Символ Флажка установки ldi r25, 73 ; Адрес DDRAM rcall OutChar M3_1NoCheckI: ldi r24, 0xda ; Символ стрелки вниз ldi r25, 79 ; Адрес DDRAM rcall OutChar rcall USART_Transmit ; Вывод данных на интерфейс rcall USART_Transmit ret ;------------------------------------------------------------------------------; Интерфейс для режима Menu3_2 ;------------------------------------------------------------------------------Menu3_2Interface: rcall ClrScr ; Очистка дисплея ldi r24, 8 ; Количество символов ldi r30, low(TextOn*2) ; Установить указатель Z на ldi r31, high(TextOn*2) ; начало буфера TextOn ldi r25, 1 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 15 ; Количество символов ldi r30, low(TextBitRate*2) ; Установить указатель Z на ldi r31, high(TextBitRate*2) ; начало буфера TextBitRate ldi r25, 65 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xdc ; Символ выделения пункта меню ldi r25, 64 ; Адрес DDRAM rcall OutChar ldi r24, 0xd9 ; Символ стрелки вверх ldi r25, 15 ; Адрес DDRAM rcall OutChar lds Tunes, 0x62 ; Если интерфейс включен, sbrs Tunes, 3 ; вывести флажок установки rjmp M3_2NoCheckI ldi r24, 0x94 ; Символ Флажка установки ldi r25, 9 ; Адрес DDRAM rcall OutChar M3_2NoCheckI: rcall USART_Transmit ; Вывод данных на интерфейс rcall USART_Transmit ret ;------------------------------------------------------------------------------; Интерфейс для режима Menu3_2_1 ;------------------------------------------------------------------------------Menu3_2_1Interface: rcall ClrScr ; Очистка дисплея ldi r24, 16 ; Количество символов ldi r30, low(TextMenu*2) ; Установить указатель Z на ldi r31, high(TextMenu*2) ; начало буфера TextEsc ldi r25, 0 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей
81 <1678> <1679> <1680> <1681> <1682> <1683> <1684> <1685> <1686> <1687> <1688> <1689> <1690> <1691> <1692> <1693> <1694> <1695> <1696> <1697> <1698> <1699> <1700> <1701> <1702> <1703> <1704> <1705> <1706> <1707> <1708> <1709> <1710> <1711> <1712> <1713> <1714> <1715> <1716> <1717> <1718> <1719> <1720> <1721> <1722> <1723> <1724> <1725> <1726> <1727> <1728> <1729> <1730> <1731> <1732> <1733> <1734> <1735> <1736> <1737> <1738> <1739> <1740> <1741> <1742> <1743> <1744> <1745> <1746> <1747> <1748> <1749> <1750> <1751> <1752> <1753> <1754> <1755> <1756> <1757>
ldi ldi rcall ldi ldi ldi ldi rcall ldi ldi rcall lds cpi brne ldi ldi rcall M3_2_1_1: rcall rcall ret
r24, 0xdc r25, 64 OutChar r24, 8 r30, low(TextBR2400*2) r31, high(TextBR2400*2) r25, 65 OutText r24, 0xda r25, 79 OutChar
; Символ выделения пункта меню ; Адрес DDRAM
BitRateFlags, mBitRate BitRateFlags, 0 M3_2_1_1 r24, 0x94 r25, 73 OutChar
; Если необходимо вывести флажок установки
USART_Transmit USART_Transmit
; Вывод данных на интерфейс
; ; ; ; ; ; ;
Количество символов Установить указатель Z на начало буфера TextBR2400 Начальный адрес DDRAM Вывод строки на дисплей Символ стрелки вниз Адрес DDRAM
; Символ Флажка установки ; Адрес DDRAM
;------------------------------------------------------------------------------; Интерфейс для режима Menu3_2_2 ;------------------------------------------------------------------------------Menu3_2_2Interface: rcall ClrScr ; Очистка дисплея ldi r24, 8 ; Количество символов ldi r30, low(TextBR2400*2) ; Установить указатель Z на ldi r31, high(TextBR2400*2) ; начало буфера TextBR2400 ldi r25, 1 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 8 ; Количество символов ldi r30, low(TextBR4800*2) ; Установить указатель Z на ldi r31, high(TextBR4800*2) ; начало буфера TextBR4800 ldi r25, 65 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xdc ; Символ выделения пункта меню ldi r25, 64 ; Адрес DDRAM rcall OutChar ldi r24, 0xda ; Символ стрелки вниз ldi r25, 79 ; Адрес DDRAM rcall OutChar ldi r24, 0xd9 ; Символ стрелки вверх ldi r25, 15 ; Адрес DDRAM rcall OutChar lds BitRateFlags, mBitRate ; Если ..., вывести флажок установки cpi BitRateFlags, 0 brne M3_2_2_1 ldi r24, 0x94 ; Символ Флажка установки ldi r25, 9 ; Адрес DDRAM rcall OutChar M3_2_2_1: lds BitRateFlags, mBitRate ; Если необходимо вывести флажок установки cpi BitRateFlags, 1 brne M3_2_2_2 ldi r24, 0x94 ; Символ Флажка установки ldi r25, 73 ; Адрес DDRAM rcall OutChar M3_2_2_2: rcall USART_Transmit ; Вывод данных на интерфейс rcall USART_Transmit ret ;------------------------------------------------------------------------------; Интерфейс для режима Menu3_2_3 ;------------------------------------------------------------------------------Menu3_2_3Interface: rcall ClrScr ; Очистка дисплея ldi r24, 8 ; Количество символов ldi r30, low(TextBR4800*2) ; Установить указатель Z на ldi r31, high(TextBR4800*2) ; начало буфера TextBR4800 ldi r25, 1 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 8 ; Количество символов ldi r30, low(TextBR9600*2) ; Установить указатель Z на ldi r31, high(TextBR9600*2) ; начало буфера TextBR9600 ldi r25, 65 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей
82 <1758> <1759> <1760> <1761> <1762> <1763> <1764> <1765> <1766> <1767> <1768> <1769> <1770> <1771> <1772> <1773> <1774> <1775> <1776> <1777> <1778> <1779> <1780> <1781> <1782> <1783> <1784> <1785> <1786> <1787> <1788> <1789> <1790> <1791> <1792> <1793> <1794> <1795> <1796> <1797> <1798> <1799> <1800> <1801> <1802> <1803> <1804> <1805> <1806> <1807> <1808> <1809> <1810> <1811> <1812> <1813> <1814> <1815> <1816> <1817> <1818> <1819> <1820> <1821> <1822> <1823> <1824> <1825> <1826> <1827> <1828> <1829> <1830> <1831> <1832> <1833> <1834> <1835> <1836> <1837>
ldi ldi rcall ldi ldi rcall ldi ldi rcall lds cpi brne ldi ldi rcall M3_2_3_1: lds cpi brne ldi ldi rcall M3_2_3_2: rcall rcall ret
r24, 0xdc r25, 64 OutChar r24, 0xda r25, 79 OutChar r24, 0xd9 r25, 15 OutChar BitRateFlags, mBitRate BitRateFlags, 1 M3_2_3_1 r24, 0x94 r25, 9 OutChar
; Символ выделения пункта меню ; Адрес DDRAM
BitRateFlags, mBitRate BitRateFlags, 2 M3_2_3_2 r24, 0x94 r25, 73 OutChar
; Если необходимо вывести флажок установки
USART_Transmit USART_Transmit
; Вывод данных на интерфейс
; Символ стрелки вниз ; Адрес DDRAM ; Символ стрелки вверх ; Адрес DDRAM ; Если необходимо вывести флажок установки ; Символ Флажка установки ; Адрес DDRAM
; Символ Флажка установки ; Адрес DDRAM
;------------------------------------------------------------------------------; Интерфейс для режима Menu3_2_4 ;------------------------------------------------------------------------------Menu3_2_4Interface: rcall ClrScr ; Очистка дисплея ldi r24, 8 ; Количество символов ldi r30, low(TextBR9600*2) ; Установить указатель Z на ldi r31, high(TextBR9600*2) ; начало буфера TextBR9600 ldi r25, 1 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 9 ; Количество символов ldi r30, low(TextBR14400*2) ; Установить указатель Z на ldi r31, high(TextBR14400*2) ; начало буфера TextBR14400 ldi r25, 65 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xdc ; Символ выделения пункта меню ldi r25, 64 ; Адрес DDRAM rcall OutChar ldi r24, 0xda ; Символ стрелки вниз ldi r25, 79 ; Адрес DDRAM rcall OutChar ldi r24, 0xd9 ; Символ стрелки вверх ldi r25, 15 ; Адрес DDRAM rcall OutChar lds BitRateFlags, mBitRate ; Если необходимо вывести флажок установки cpi BitRateFlags, 2 brne M3_2_4_1 ldi r24, 0x94 ; Символ Флажка установки ldi r25, 9 ; Адрес DDRAM rcall OutChar M3_2_4_1: lds BitRateFlags, mBitRate ; Если необходимо вывести флажок установки cpi BitRateFlags, 3 brne M3_2_4_2 ldi r24, 0x94 ; Символ Флажка установки ldi r25, 74 ; Адрес DDRAM rcall OutChar M3_2_4_2: rcall USART_Transmit ; Вывод данных на интерфейс rcall USART_Transmit ret ;------------------------------------------------------------------------------; Интерфейс для режима Menu3_2_5 ;------------------------------------------------------------------------------Menu3_2_5Interface: rcall ClrScr ; Очистка дисплея ldi r24, 9 ; Количество символов ldi r30, low(TextBR14400*2) ; Установить указатель Z на ldi r31, high(TextBR14400*2) ; начало буфера TextBR14400 ldi r25, 1 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 9 ; Количество символов
83 <1838> <1839> <1840> <1841> <1842> <1843> <1844> <1845> <1846> <1847> <1848> <1849> <1850> <1851> <1852> <1853> <1854> <1855> <1856> <1857> <1858> <1859> <1860> <1861> <1862> <1863> <1864> <1865> <1866> <1867> <1868> <1869> <1870> <1871> <1872> <1873> <1874> <1875> <1876> <1877> <1878> <1879> <1880> <1881> <1882> <1883> <1884> <1885> <1886> <1887> <1888> <1889> <1890> <1891> <1892> <1893> <1894> <1895> <1896> <1897> <1898> <1899> <1900> <1901> <1902> <1903> <1904> <1905> <1906> <1907> <1908> <1909> <1910> <1911> <1912> <1913> <1914> <1915> <1916> <1917>
ldi ldi ldi rcall ldi ldi rcall ldi ldi rcall ldi ldi rcall lds cpi brne ldi ldi rcall M3_2_5_1: lds cpi brne ldi ldi rcall M3_2_5_2: rcall rcall ret
r30, low(TextBR19200*2) r31, high(TextBR19200*2) r25, 65 OutText r24, 0xdc r25, 64 OutChar r24, 0xda r25, 79 OutChar r24, 0xd9 r25, 15 OutChar BitRateFlags, mBitRate BitRateFlags, 3 M3_2_5_1 r24, 0x94 r25, 10 OutChar
; ; ; ; ; ;
Установить указатель Z на начало буфера TextBR19200 Начальный адрес DDRAM Вывод строки на дисплей Символ выделения пункта меню Адрес DDRAM
BitRateFlags, mBitRate BitRateFlags, 4 M3_2_5_2 r24, 0x94 r25, 74 OutChar
; Если необходимо вывести флажок установки
USART_Transmit USART_Transmit
; Вывод данных на интерфейс
; Символ стрелки вниз ; Адрес DDRAM ; Символ стрелки вверх ; Адрес DDRAM ; Если необходимо вывести флажок установки ; Символ Флажка установки ; Адрес DDRAM
; Символ Флажка установки ; Адрес DDRAM
;------------------------------------------------------------------------------; Интерфейс для режима Menu3_2_6 ;------------------------------------------------------------------------------Menu3_2_6Interface: rcall ClrScr ; Очистка дисплея ldi r24, 9 ; Количество символов ldi r30, low(TextBR19200*2) ; Установить указатель Z на ldi r31, high(TextBR19200*2) ; начало буфера TextBR19200 ldi r25, 1 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 9 ; Количество символов ldi r30, low(TextBR38400*2) ; Установить указатель Z на ldi r31, high(TextBR38400*2) ; начало буфера TextBR38400 ldi r25, 65 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xdc ; Символ выделения пункта меню ldi r25, 64 ; Адрес DDRAM rcall OutChar ldi r24, 0xda ; Символ стрелки вниз ldi r25, 79 ; Адрес DDRAM rcall OutChar ldi r24, 0xd9 ; Символ стрелки вверх ldi r25, 15 ; Адрес DDRAM rcall OutChar lds BitRateFlags, mBitRate ; Если необходимо вывести флажок установки cpi BitRateFlags, 4 brne M3_2_6_1 ldi r24, 0x94 ; Символ Флажка установки ldi r25, 10 ; Адрес DDRAM rcall OutChar M3_2_6_1: lds BitRateFlags, mBitRate ; Если необходимо вывести флажок установки cpi BitRateFlags, 5 brne M3_2_6_2 ldi r24, 0x94 ; Символ Флажка установки ldi r25, 74 ; Адрес DDRAM rcall OutChar M3_2_6_2: rcall USART_Transmit ; Вывод данных на интерфейс rcall USART_Transmit ret ;------------------------------------------------------------------------------; Интерфейс для режима Menu3_2_7 ;------------------------------------------------------------------------------Menu3_2_7Interface: rcall ClrScr ; Очистка дисплея ldi r24, 9 ; Количество символов ldi r30, low(TextBR38400*2) ; Установить указатель Z на
84 <1918> <1919> <1920> <1921> <1922> <1923> <1924> <1925> <1926> <1927> <1928> <1929> <1930> <1931> <1932> <1933> <1934> <1935> <1936> <1937> <1938> <1939> <1940> <1941> <1942> <1943> <1944> <1945> <1946> <1947> <1948> <1949> <1950> <1951> <1952> <1953> <1954> <1955> <1956> <1957> <1958> <1959> <1960> <1961> <1962> <1963> <1964> <1965> <1966> <1967> <1968> <1969> <1970> <1971> <1972> <1973> <1974> <1975> <1976> <1977> <1978> <1979> <1980> <1981> <1982> <1983> <1984> <1985> <1986> <1987> <1988> <1989> <1990> <1991> <1992> <1993> <1994> <1995> <1996> <1997>
ldi ldi rcall ldi ldi ldi ldi rcall ldi ldi rcall ldi ldi rcall ldi ldi rcall lds cpi brne ldi ldi rcall M3_2_7_1: lds cpi brne ldi ldi rcall M3_2_7_2: rcall rcall ret
r31, high(TextBR38400*2) r25, 1 OutText r24, 9 r30, low(TextBR57600*2) r31, high(TextBR57600*2) r25, 65 OutText r24, 0xdc r25, 64 OutChar r24, 0xda r25, 79 OutChar r24, 0xd9 r25, 15 OutChar BitRateFlags, mBitRate BitRateFlags, 5 M3_2_7_1 r24, 0x94 r25, 10 OutChar
; ; ; ; ; ; ; ; ; ;
начало буфера TextBR38400 Начальный адрес DDRAM Вывод строки на дисплей Количество символов Установить указатель Z на начало буфера TextBR57600 Начальный адрес DDRAM Вывод строки на дисплей Символ выделения пункта меню Адрес DDRAM
BitRateFlags, mBitRate BitRateFlags, 6 M3_2_7_2 r24, 0x94 r25, 74 OutChar
; Если необходимо вывести флажок установки
USART_Transmit USART_Transmit
; Вывод данных на интерфейс
; Символ стрелки вниз ; Адрес DDRAM ; Символ стрелки вверх ; Адрес DDRAM ; Если необходимо вывести флажок установки ; Символ Флажка установки ; Адрес DDRAM
; Символ Флажка установки ; Адрес DDRAM
;------------------------------------------------------------------------------; Интерфейс для режима Menu3_2_8 ;------------------------------------------------------------------------------Menu3_2_8Interface: rcall ClrScr ; Очистка дисплея ldi r24, 9 ; Количество символов ldi r30, low(TextBR57600*2) ; Установить указатель Z на ldi r31, high(TextBR57600*2) ; начало буфера TextBR57600 ldi r25, 1 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 10 ; Количество символов ldi r30, low(TextBR115200*2) ; Установить указатель Z на ldi r31, high(TextBR115200*2) ; начало буфера TextBR115200 ldi r25, 65 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r24, 0xdc ; Символ выделения пункта меню ldi r25, 64 ; Адрес DDRAM rcall OutChar ldi r24, 0xd9 ; Символ стрелки вверх ldi r25, 15 ; Адрес DDRAM rcall OutChar lds BitRateFlags, mBitRate ; Если необходимо вывести флажок установки cpi BitRateFlags, 6 brne M3_2_8_1 ldi r24, 0x94 ; Символ Флажка установки ldi r25, 10 ; Адрес DDRAM rcall OutChar M3_2_8_1: lds BitRateFlags, mBitRate ; Если необходимо вывести флажок установки cpi BitRateFlags, 7 brne M3_2_8_2 ldi r24, 0x94 ; Символ Флажка установки ldi r25, 75 ; Адрес DDRAM rcall OutChar M3_2_8_2: rcall USART_Transmit ; Вывод данных на интерфейс rcall USART_Transmit ret ;------------------------------------------------------------------------------; Интерфейс для режима Menu4_1 ;------------------------------------------------------------------------------Menu4_1Interface: rcall ClrScr ; Очистка дисплея ldi r24, 15 ; Количество символов
85 <1998> <1999> <2000> <2001> <2002> <2003> <2004> <2005> <2006> <2007> <2008> <2009> <2010> <2011> <2012> <2013> <2014> <2015> <2016> <2017> <2018> <2019> <2020> <2021> <2022> <2023> <2024> <2025> <2026> <2027> <2028> <2029> <2030> <2031> <2032> <2033> <2034> <2035> <2036> <2037> <2038> <2039> <2040> <2041> <2042> <2043> <2044> <2045> <2046> <2047> <2048> <2049> <2050> <2051> <2052> <2053> <2054> <2055> <2056> <2057> <2058> <2059> <2060> <2061> <2062> <2063> <2064> <2065> <2066> <2067> <2068> <2069> <2070> <2071> <2072> <2073> <2074> <2075> <2076> <2077>
ldi ldi ldi rcall ldi ldi ldi ldi rcall ldi ldi rcall rcall rcall ret
r30, low(TextDiag*2) r31, high(TextDiag*2) r25, 0 OutText r24, 12 r30, low(TextWait*2) r31, high(TextWait*2) r25, 65 OutText r24, 0x3a r25, 15 OutChar USART_Transmit USART_Transmit
; ; ; ; ; ; ; ; ; ; ;
Установить указатель Z на начало буфера TextDiag Начальный адрес DDRAM Вывод строки на дисплей Количество символов Установить указатель Z на начало буфера TextWait Начальный адрес DDRAM Вывод строки на дисплей Символ двоеточия Адрес DDRAM
; Вывод данных на интерфейс
;------------------------------------------------------------------------------; Поле ввода числа ; Вход - число, выводимое в EditBox в Float2 ; флаг размерности числа в r9 ; (бит 0 - об/с; 1 - об/мин; 2 - рад/с; 3 - см/с; 4 - мс; 5 - мет/об; ; 6 - см; 7 - безразмерная величина) ; Выход - введенное число в Float2 ;------------------------------------------------------------------------------EditBox: rcall ClrScr ; Очистка дисплея ldi r25, 0 ; Начальный адрес DDRAM rcall OutFloat ; Вывод числа в поле ввода rcall EditBoxOutDim ldi r24, 16 ; Количество символов ldi r30, low(TextEdit*2) ; Установить указатель Z на ldi r31, high(TextEdit*2) ; начало буфера TextEdit ldi r25, 64 ; Начальный адрес DDRAM rcall OutText ; Вывод строки на дисплей ldi r25, $0D ; Включить курсор rcall LCDCommand ldi r26, 214 ; Задержка ~40 мкс при кварце 16 МГц ldi r27, 0 rcall Delay ldi r25, 66 ; Установка позиции курсора rcall SetCursorPos rcall KeyPressed ; Ожидание нажатой клавиши cpi Key, 0 ; OK или Esc - выход breq EditQuit cpi Key, 2 breq EditQuit ldi r24, 9 ; Количество символов ldi r30, low(TextEmpty*2) ; Установить указатель Z на ldi r31, high(TextEmpty*2) ; начало буфера TextEmpty ldi r25, 0 ; Начальный адрес DDRAM rcall OutText ; Очистка поля ввода ldi r25, 66 ; Установка позиции курсора rcall SetCursorPos ldi EditPos, 0 ; Установка позиции символа ldi xh, 0 ; Указатель на число в памяти ldi xl, 0x70 StoreNext: ; Цикл ввода числа st x+, EditPos ; Увеличение позиции символа cpi xl, 0x7a brne StoreNext ldi CursorPos, 66 EditWait: rcall KeyPressed cpi Key, 2 ; Реакция на нажатие клавиши breq EditQuit cpi Key, 0 brne EB_0 ldi r17, 0 rcall OnKeyDown ; Обработка нажатия клавиши tst r17 brne EditConvert EB_0: cpi Key, 3 brne EB_1 cpi CursorPos, 78 breq SkipInc inc CursorPos SkipInc: mov r25, CursorPos rcall SetCursorPos
86 <2078> <2079> <2080> <2081> <2082> <2083> <2084> <2085> <2086> <2087> <2088> <2089> <2090> <2091> <2092> <2093> <2094> <2095> <2096> <2097> <2098> <2099> <2100> <2101> <2102> <2103> <2104> <2105> <2106> <2107> <2108> <2109> <2110> <2111> <2112> <2113> <2114> <2115> <2116> <2117> <2118> <2119> <2120> <2121> <2122> <2123> <2124> <2125> <2126> <2127> <2128> <2129> <2130> <2131> <2132> <2133> <2134> <2135> <2136> <2137> <2138> <2139> <2140> <2141> <2142> <2143> <2144> <2145> <2146> <2147> <2148> <2149> <2150> <2151> <2152> <2153> <2154> <2155> <2156> <2157>
EB_1: cpi Key, 5 brne EB_2 cpi CursorPos, 66 breq SkipDec dec CursorPos SkipDec: mov r25, CursorPos rcall SetCursorPos EB_2: rjmp EditWait EditConvert: rcall ASCII2Float EditQuit: ldi r25, $0C rcall LCDCommand ldi r26, 214 ldi r27, 0 rcall Delay EditKeyUp: sbis pind, 2 rjmp EditKeyUp ret
; Преобразование числа в float-формат ; Выключить курсор ; Задержка ~40 мкс при кварце 16 МГц
;------------------------------------------------------------------------------; Ожидание события от клавиатуры и ее сканирование ; Выход - скан-код клавиатуры в Key ;------------------------------------------------------------------------------KeyPressed: sbis pind, 2 rjmp KeyPressed KP_1: sbic pind, 2 rjmp KP_1 rcall ReadKey ret ;------------------------------------------------------------------------------; Обработка нажатия клавиши OK в EditBox ; Вход - позиция курсора на панельке ввода CursorPos ; позиция курсора в поле ввода EditPos ;------------------------------------------------------------------------------OnKeyDown: cpi CursorPos, 66 brne Key_0 ldi r24, 0x2e ldi xl, 0x70 ldi xh, 0 add xl, EditPos st x, r24 ldi r17, 1 rjmp KeyRet Key_0: cpi CursorPos, 67 brne Key_1 cpi EditPos, 9 breq Key_1 ldi r24, 0x30 ; Символ цифры "0" mov r25, EditPos ; Адрес DDRAM ldi xl, 0x70 ldi xh, 0 add xl, EditPos st x, r24 rcall OutChar inc EditPos mov r25, CursorPos rcall SetCursorPos Key_1: cpi CursorPos, 68 brne Key_2 cpi EditPos, 9 breq Key_2 ldi r24, 0x31 ; Символ цифры "1" mov r25, EditPos ; Адрес DDRAM ldi xl, 0x70 ldi xh, 0 add xl, EditPos st x, r24 rcall OutChar inc EditPos
87 <2158> <2159> <2160> <2161> <2162> <2163> <2164> <2165> <2166> <2167> <2168> <2169> <2170> <2171> <2172> <2173> <2174> <2175> <2176> <2177> <2178> <2179> <2180> <2181> <2182> <2183> <2184> <2185> <2186> <2187> <2188> <2189> <2190> <2191> <2192> <2193> <2194> <2195> <2196> <2197> <2198> <2199> <2200> <2201> <2202> <2203> <2204> <2205> <2206> <2207> <2208> <2209> <2210> <2211> <2212> <2213> <2214> <2215> <2216> <2217> <2218> <2219> <2220> <2221> <2222> <2223> <2224> <2225> <2226> <2227> <2228> <2229> <2230> <2231> <2232> <2233> <2234> <2235> <2236> <2237>
mov rcall Key_2: cpi brne cpi breq ldi mov ldi ldi add st rcall inc mov rcall Key_3: cpi brne cpi breq ldi mov ldi ldi add st rcall inc mov rcall Key_4: cpi brne cpi breq ldi mov ldi ldi add st rcall inc mov rcall Key_5: cpi brne cpi breq ldi mov ldi ldi add st rcall inc mov rcall Key_6: cpi brne cpi breq ldi mov ldi ldi add st rcall inc mov rcall Key_7: cpi brne
r25, CursorPos SetCursorPos CursorPos, 69 Key_3 EditPos, 9 Key_3 r24, 0x32 r25, EditPos xl, 0x70 xh, 0 xl, EditPos x, r24 OutChar EditPos r25, CursorPos SetCursorPos CursorPos, 70 Key_4 EditPos, 9 Key_4 r24, 0x33 r25, EditPos xl, 0x70 xh, 0 xl, EditPos x, r24 OutChar EditPos r25, CursorPos SetCursorPos CursorPos, 71 Key_5 EditPos, 9 Key_5 r24, 0x34 r25, EditPos xl, 0x70 xh, 0 xl, EditPos x, r24 OutChar EditPos r25, CursorPos SetCursorPos CursorPos, 72 Key_6 EditPos, 9 Key_6 r24, 0x35 r25, EditPos xl, 0x70 xh, 0 xl, EditPos x, r24 OutChar EditPos r25, CursorPos SetCursorPos CursorPos, 73 Key_7 EditPos, 9 Key_7 r24, 0x36 r25, EditPos xl, 0x70 xh, 0 xl, EditPos x, r24 OutChar EditPos r25, CursorPos SetCursorPos CursorPos, 74 Key_8
; Символ цифры "2" ; Адрес DDRAM
; Символ цифры "3" ; Адрес DDRAM
; Символ цифры "4" ; Адрес DDRAM
; Символ цифры "5" ; Адрес DDRAM
; Символ цифры "6" ; Адрес DDRAM
88 <2238> <2239> <2240> <2241> <2242> <2243> <2244> <2245> <2246> <2247> <2248> <2249> <2250> <2251> <2252> <2253> <2254> <2255> <2256> <2257> <2258> <2259> <2260> <2261> <2262> <2263> <2264> <2265> <2266> <2267> <2268> <2269> <2270> <2271> <2272> <2273> <2274> <2275> <2276> <2277> <2278> <2279> <2280> <2281> <2282> <2283> <2284> <2285> <2286> <2287> <2288> <2289> <2290> <2291> <2292> <2293> <2294> <2295> <2296> <2297> <2298> <2299> <2300> <2301> <2302> <2303> <2304> <2305> <2306> <2307> <2308> <2309> <2310> <2311> <2312> <2313> <2314> <2315> <2316> <2317>
cpi breq ldi mov ldi ldi add st rcall inc mov rcall Key_8: cpi brne cpi breq ldi mov ldi ldi add st rcall inc mov rcall Key_9: cpi brne cpi breq ldi mov ldi ldi add st rcall inc mov rcall Key_Point: cpi brne cpi breq ldi mov ldi ldi add st rcall inc mov rcall Key_Del: cpi brne cpi breq dec ldi mov ldi ldi add st rcall mov rcall KeyRet: ret
EditPos, 9 Key_8 r24, 0x37 r25, EditPos xl, 0x70 xh, 0 xl, EditPos x, r24 OutChar EditPos r25, CursorPos SetCursorPos CursorPos, 75 Key_9 EditPos, 9 Key_9 r24, 0x38 r25, EditPos xl, 0x70 xh, 0 xl, EditPos x, r24 OutChar EditPos r25, CursorPos SetCursorPos CursorPos, 76 Key_Point EditPos, 9 Key_Point r24, 0x39 r25, EditPos xl, 0x70 xh, 0 xl, EditPos x, r24 OutChar EditPos r25, CursorPos SetCursorPos CursorPos, 77 Key_Del EditPos, 9 Key_Del r24, 0x2e r25, EditPos xl, 0x70 xh, 0 xl, EditPos x, r24 OutChar EditPos r25, CursorPos SetCursorPos CursorPos, 78 KeyRet EditPos, 0 KeyRet EditPos r24, 0x20 r25, EditPos xl, 0x70 xh, 0 xl, EditPos x, r24 OutChar r25, CursorPos SetCursorPos
; Символ цифры "7" ; Адрес DDRAM
; Символ цифры "8" ; Адрес DDRAM
; Символ цифры "9" ; Адрес DDRAM
; Символ точки ; Адрес DDRAM
; Символ пробела ; Адрес DDRAM
;------------------------------------------------------------------------------; Подпрограмма вывода размерности в EditBox ; Вход - флаг размерности числа в r9 ;------------------------------------------------------------------------------EditBoxOutDim:
89 <2318> <2319> <2320> <2321> <2322> <2323> <2324> <2325> <2326> <2327> <2328> <2329> <2330> <2331> <2332> <2333> <2334> <2335> <2336> <2337> <2338> <2339> <2340> <2341> <2342> <2343> <2344> <2345> <2346> <2347> <2348> <2349> <2350> <2351> <2352> <2353> <2354> <2355> <2356> <2357> <2358> <2359> <2360> <2361> <2362> <2363> <2364> <2365> <2366> <2367> <2368> <2369> <2370> <2371> <2372> <2373> <2374>
sbrs rjmp ldi ldi ldi ldi rcall EOD_1: sbrs rjmp ldi ldi ldi ldi rcall EOD_2: sbrs rjmp ldi ldi ldi ldi rcall EOD_3: sbrs rjmp ldi ldi ldi ldi rcall EOD_4: sbrs rjmp ldi ldi ldi ldi rcall EOD_5: sbrs rjmp ldi ldi ldi ldi rcall EOD_6: sbrs rjmp ldi ldi ldi ldi rcall EOD_7: ret
r9, 0 EOD_1 r24, 4 r30, low(TextRPS*2) r31, high(TextRPS*2) r25, 12 OutText
; ; ; ; ;
Количество символов Установить указатель Z на начало буфера TextRPS Начальный адрес DDRAM Вывод строки на дисплей
r9, 1 EOD_2 r24, 6 r30, low(TextRPM*2) r31, high(TextRPM*2) r25, 10 OutText
; ; ; ; ;
Количество символов Установить указатель Z на начало буфера TextRPM Начальный адрес DDRAM Вывод строки на дисплей
r9, 2 EOD_3 r24, 5 r30, low(TextRadPS*2) r31, high(TextRadPS*2) r25, 11 OutText
; ; ; ; ;
Количество символов Установить указатель Z на начало буфера TextRadPS Начальный адрес DDRAM Вывод строки на дисплей
r9, 3 EOD_4 r24, 4 r30, low(TextSMS*2) r31, high(TextSMS*2) r25, 12 OutText
; ; ; ; ;
Количество символов Установить указатель Z на начало буфера TextSMS Начальный адрес DDRAM Вывод строки на дисплей
r9, 4 EOD_5 r24, 2 r30, low(TextMS*2) r31, high(TextMS*2) r25, 14 OutText
; ; ; ; ;
Количество символов Установить указатель Z на начало буфера TextMS Начальный адрес DDRAM Вывод строки на дисплей
r9, 5 EOD_6 r24, 6 r30, low(TextLPR*2) r31, high(TextLPR*2) r25, 10 OutText
; ; ; ; ;
Количество символов Установить указатель Z на начало буфера TextLPR Начальный адрес DDRAM Вывод строки на дисплей
r9, 6 EOD_7 r24, 2 r30, low(TextSMS*2) r31, high(TextSMS*2) r25, 14 OutText
; ; ; ; ;
Количество символов Установить указатель Z на начало буфера TextSMS Начальный адрес DDRAM Вывод строки на дисплей
90 Листинг 5. Основная программа <1> <2> <3> <4> <5> <6> <7> <8> <9> <10> <11> <12> <13> <14> <15> <16> <17> <18> <19> <20> <21> <22> <23> <24> <25> <26> <27> <28> <29> <30> <31> <32> <33> <34> <35> <36> <37> <38> <39> <40> <41> <42> <43> <44> <45> <46> <47> <48> <49> <50> <51> <52> <53> <54> <55> <56> <57> <58> <59> <60> <61> <62> <63> <64> <65> <66> <67> <68> <69> <70> <71> <72> <73> <74> <75> <76> <77> <78> <79>
;=============================================================================== ; Файл: Encoder.asm ; Программа управления интеллектуальным датчиком скорости ;=============================================================================== ;------------------------------------------------------------------------------; Включение заголовочного файла микроконтроллера ATmega8 ;------------------------------------------------------------------------------.include "m8def.inc" ;------------------------------------------------------------------------------; Определение имен регистров ;------------------------------------------------------------------------------.def Float1O = r16 ; Число 1 вещественного типа .def Float1L = r17 .def Float1H = r18 .def Float2O = r19 ; Число 2 вещественного типа .def Float2L = r20 .def Float2H = r21 .def FTempO = r22 ; Временные переменные для вещественных вычислений .def FTempL = r23 .def FTempH = r24 .def FCnt = r25 .def var = r22 ; Переменная общего назначения .def MarkL = r26 ; Количество подсчитанных меток энкодера (16 бит) .def MarkH = r27 .def ResL = r28 ; Разрешающая способность энкодера (16 бит) .def ResH = r29 .def fASCIIL = r11 ; Переменные для BIN2BCD-преобразования .def tASCII0 = r11 .def fASCIIH = r12 .def tASCII2 = r13 .def tASCII3 = r14 .def tASCII4 = r15 .def tASCII1 = r16 .def cnt16a = r16 .def tmp16a = r17 .def tmp16b = r18 .def LCDPrescaler = r5 ; Счетчик вывода значения скорости на LCD .def Key = r16 ; Скан-код клавиатуры .def State = r17 ; Байт состояния .def BitRateFlags = r22 ; Байт флагов скорости обмена по интерфейсу .def EditPos = r18 ; Позиция редактируемой цифры в EditBox .def CursorPos = r23 ; Позиция курсора ввода в EditBox .def Tunes = r18 ; Байт флагов настройки устройства ;***Флаги настройки*** ;* 0 - об/с ;* 1 - об/мин ;* 2 - рад/с ;* 3 - интерфейс ;* 4 - см/с ;********************* ;------------------------------------------------------------------------------; Определение переменных в памяти SRAM ;------------------------------------------------------------------------------.equ mSign = 0x60 ; Копия знака скорости .equ mState = 0x61 ; Байт состояния .equ mTunes = 0x62 ; Байт флагов настройки устройства .equ mBitRate = 0x63 ; Байт флагов скорости обмена по интерфейсу .equ KO = 0x64 ; Коэффициент передачи K .equ KL = 0x65 .equ KH = 0x66 .equ TO = 0x88 ; Интервал счета T .equ TL = 0x89 .equ TH = 0x8a .equ mtccr1b = 0x8b ; Копия регистра tccr1b .equ SumO = 0x8c ; Сумма значений считанных данных .equ SumL = 0x8d .equ SumH = 0x8e .equ LCDState = 0x8f ; Состояние дисплея .equ CountO = 0x91 ; Количество считанных данных .equ CountL = 0x92 .equ CountH = 0x93 .equ MistakeO = 0x94 ; Допустимая погрешность измерений .equ MistakeL = 0x95 .equ MistakeH = 0x96 ;-------------------------------------------------------------------------------
91 <80> <81> <82> <83> <84> <85> <86> <87> <88> <89> <90> <91> <92> <93> <94> <95> <96> <97> <98> <99> <100> <101> <102> <103> <104> <105> <106> <107> <108> <109> <110> <111> <112> <113> <114> <115> <116> <117> <118> <119> <120> <121> <122> <123> <124> <125> <126> <127> <128> <129> <130> <131> <132> <133> <134> <135> <136> <137> <138> <139> <140> <141> <142> <143> <144> <145> <146> <147> <148> <149> <150> <151> <152> <153> <154> <155> <156> <157> <158> <159>
; Начальные настройки и параметры датчика в EEPROM ;------------------------------------------------------------------------------.eseg // Интерфейс включен; ед. изм. - об/с; разрешение энкодера - 1000 мет/об. // BitRate = 115200 baud // Коэффициент передачи K = 1 // Период счета T = 0.01 с .org 0 .db 0b1001, 0x03, 0xe8, 0x07, 0x41, 0x00, 0x80, 0x3a, 0xd6, 0xa3 ;------------------------------------------------------------------------------; Таблица векторов прерываний ;------------------------------------------------------------------------------.cseg ; RESET .org 0 rjmp main ; Запрос на внешнее прерывание int0 (клавиатура) .org 0x1 rjmp int0Request ; Запрос на внешнее прерывание int1 (канал A энкодера) .org 0x2 rjmp int1Request ; Сравнение таймера/счетчика 1 с регистром сравнения A .org 0x6 rjmp intTimer1COMPA ; Переполнение таймера/счетчика 0 .org 0x9 rjmp intTimer0OVF .org 0x20 ;------------------------------------------------------------------------------; Основная программа ;------------------------------------------------------------------------------main: ldi var, high(RAMEND) ; Настройка указателя стека на вершину RAM out sph, var ldi var, low(RAMEND) out spl, var ldi var, 0b110 ; Настройка порта B out portb, var ldi var, 0b11100010 ; Настройка порта D out ddrd, var ldi var, 0b00000000 out portd, var ldi var, 0b111111 ; Настройка линий pc0..pc5 на вывод данных out ddrc, var rcall InitLCD ; Инициализация ЖКИ ldi State, 0 ; Загрузка начального состояния в память sts mState, State rcall EEPROM_Read ; Чтение настроек из EEPROM sbrc Tunes, 3 ; Если необходим интерфейс, то включить его rcall USART_Init ; Инициализация USART rcall MeasureInterface ; Вывести на дисплей интерфейс измерения скорости ldi var, 0b1110 ; Настройка запроса на прерывание int1 out mcucr, var ; по переднему фронту, а int0 - по заднему ldi var, 0b11000000 ; Разрешение внешних прерываний out gicr, var ldi var, 0b101 ; Настройка таймера/счетчика 0 на частоту CLK/1024 out tccr0, var rcall SetTimerInterval ; Установка интервала счета in var, tccr1b ; Сохранение tccr1b в SRAM sts mtccr1b, var ldi var, 0 ; Обнуление таймера/счетчика 1 out tcnt1h, var out tcnt1l, var out tcnt0, var ldi var, 0b10001 ; Разрешение прерывания по сравнению out timsk, var ; таймера/счетчика 1 ldi var, 0 ; Обнуление счетчика вывода на ЖКИ mov LCDPrescaler, var ldi Float2H, 0 ; Обнуление суммы значений считанных данных ldi Float2L, 0 rcall Fix2Float sts SumO, Float2O sts SumL, Float2L sts SumH, Float2H sts CountO, Float2O ; Обнуление количества считанных данных sts CountL, Float2L sts CountH, Float2H
92 <160> <161> <162> <163> <164> <165> <166> <167> <168> <169> <170> <171> <172> <173> <174> <175> <176> <177> <178> <179> <180> <181> <182> <183> <184> <185> <186> <187> <188> <189> <190> <191> <192> <193> <194> <195> <196> <197> <198> <199> <200> <201> <202> <203> <204> <205> <206> <207> <208> <209> <210> <211> <212> <213> <214> <215> <216> <217> <218> <219> <220> <221> <222> <223> <224> <225> <226> <227> <228> <229> <230> <231> <232> <233> <234> <235> <236> <237> <238> <239>
sei
; Глобальное разрешение прерываний
/***** Основной цикл программы ************************************************/ loop: nop ; Ожидание прерываний rjmp loop ;------------------------------------------------------------------------------; Подпрограмма обработки запроса на внешнее прерывание int0 (клавиатура) ;------------------------------------------------------------------------------int0Request: ldi var, 0b0 ; Выключение таймера/счетчика 1 out tccr1b, var rcall ReadKey ; Получить скан-код в Key rcall OnAction ; Отреагировать на нажатую клавишу lds State, mState ; Загрузка состояния устройства tst State ; Если State = Measure, brne NoTimer ; то включить таймер 1 lds var, mtccr1b ; Восстановление частоты таймера/счетчика 1 out tccr1b, var ldi var, 0 ; Обнуление таймера/счетчика 1 out tcnt1h, var out tcnt1l, var NoTimer: reti ; Выход из прерывания ;------------------------------------------------------------------------------; Подпрограмма обработки запроса на внешнее прерывание int1 (канал A энкодера) ;------------------------------------------------------------------------------int1Request: push MarkH ; Помещение переменной Mark в стек push MarkL in var, pinb ; Проверка состояния канала B энкодера bst var, 0 ; Ниже идет вычисление: Mark = Mark (+/-) 1 brtc Positive rcall DecSigned16 ; Уменьшить на 1 количество подсчитанных меток pop MarkH pop MarkL rjmp CountOK Positive: rcall IncSigned16 ; Увеличить на 1 количество подсчитанных меток pop MarkH pop MarkL CountOK: reti ; Выход из прерывания ;------------------------------------------------------------------------------; Подпрограмма обработки прерывания сравнения таймера/счетчика 1 ;------------------------------------------------------------------------------intTimer1COMPA: ldi var, 0b0 ; Выключение таймера/счетчика 1 out tccr1b, var ldi var, 0 ; Распознание знака скорости tst MarkH brpl SavePos ldi var, 1 ; var = 1, если скорость отрицательна, иначе 0 subi MarkH, 0x80 ; Приведение Mark к модулю: Mark = abs(Mark) SavePos: sts 0x60, var ; Сохранение знака скорости в памяти rcall GetVelocity ; Получение текущей скорости в Float2 rcall USART_Transmit ; Передача скорости через USART clr MarkH ; Обнуление Mark clr MarkL rcall SwapFl ; Умножение скорости на 10 (12345=10*1234.5) ldi Float2L, 10 ldi Float2H, 0 rcall Fix2Float rcall SwapFl rcall FMult lds Float1O, SumO ; Загрузка суммы значений из памяти lds Float1L, SumL lds Float1H, SumH rcall FAdd ; Добавление текущего значеня к сумме sts SumO, Float2O ; Сохранение суммы в памяти sts SumL, Float2L sts SumH, Float2H lds Float1O, CountO ; Загрузка количества значений из памяти lds Float1L, CountL lds Float1H, CountH ldi Float2O, 0x41 ; Добавление единицы к количеству значений
93 <240> <241> <242> <243> <244> <245> <246> <247> <248> <249> <250> <251> <252> <253> <254> <255> <256> <257> <258> <259> <260> <261> <262> <263> <264> <265> <266> <267> <268> <269> <270> <271> <272> <273> <274> <275> <276> <277> <278> <279> <280> <281> <282> <283> <284> <285> <286> <287> <288> <289> <290> <291> <292> <293> <294> <295> <296> <297> <298> <299> <300> <301> <302> <303> <304> <305> <306> <307> <308> <309> <310> <311> <312> <313> <314> <315> <316> <317> <318> <319>
ldi ldi rcall sts sts sts lds tst breq ldi sts clr lds lds lds lds lds lds rcall rcall mov mov rcall ldi rcall ldi ldi rcall sts sts sts sts sts sts SkipLCDOut: lds out ldi out out reti
Float2L, 0x00 Float2H, 0x80 FAdd CountO, Float2O CountL, Float2L CountH, Float2H var, LCDState var SkipLCDOut var, 0 LCDState, var LCDPrescaler Float1O, SumO Float1L, SumL Float1H, SumH Float2O, CountO Float2L, CountL Float2H, CountH FDiv Float2Fix fASCIIL, Float2L fASCIIH, Float2H bin2ASCII16 r25, 64 OutFBCD Float2H, 0 Float2L, 0 Fix2Float SumO, Float2O SumL, Float2L SumH, Float2H CountO, Float2O CountL, Float2L CountH, Float2H var, 0x8b tccr1b, var var, 0 tcnt1h, var tcnt1l, var
; Сохранение количества значений в памяти ; Если разрешен вывод скорости на ЖКИ, то вывести
; Преобразование скорости в целое число ; Преобразование скорости BCD-формат ; Начальный адрес DDRAM ; Вывод скорости на дисплей
; Восстановление частоты таймера/счетчика 1 ; Обнуление таймера/счетчика 1 ; Выход из прерывания
;------------------------------------------------------------------------------; Подпрограмма обработки прерывания переполнения таймера/счетчика 0 ;------------------------------------------------------------------------------intTimer0OVF: inc LCDPrescaler ; Увеличение счетчика вывода на ЖКИ ldi var, 31 ; Если прошло 0.5 с, то обновить данные на ЖКИ cp LCDPrescaler, var ; (установкой флага LCDState) brne NoLCDFlag ldi var, 1 sts LCDState, var NoLCDFlag: reti ; Выход из прерывания ;------------------------------------------------------------------------------; Подпрограмма инкремента 16-битного числа со знаком ;------------------------------------------------------------------------------IncSigned16: pop r1 ; Сохранение адреса возврата в R1:R0 pop r0 pop r26 ; Извлечение из стека аргумента pop r27 tst r27 brmi NegArg ; Проверка знака аргумента adiw r27:r26, 1 ; Аргумент положителен rjmp IncOK NegArg: ; Аргумент отрицателен tst r26 ; Учет смены знака при инкременте (-0 = 0) brne NoNegZero cpi r27, 0b10000000 brne NoNegZero ldi r27, 0 adiw r27:r26, 1 rjmp IncOK NoNegZero: sbiw r27:r26, 1 IncOK: push r26 ; Возвращение результата в стек push r27
94 <320> <321> <322> <323> <324> <325> <326> <327> <328> <329> <330> <331> <332> <333> <334> <335> <336> <337> <338> <339> <340> <341> <342> <343> <344> <345> <346> <347> <348> <349> <350> <351> <352> <353> <354> <355> <356> <357> <358> <359> <360> <361> <362> <363> <364> <365> <366> <367> <368> <369> <370> <371> <372> <373> <374> <375> <376> <377> <378> <379> <380> <381> <382> <383> <384> <385> <386> <387> <388> <389> <390> <391> <392> <393> <394> <395> <396> <397> <398> <399>
push push ret
r0 r1
; Помещение адреса возврата в стек ; Выход из подпрограммы
;------------------------------------------------------------------------------; Подпрограмма декремента 16-битного числа со знаком ;------------------------------------------------------------------------------DecSigned16: pop r1 ; Сохранение адреса возврата в R1:R0 pop r0 pop r26 ; Извлечение из стека аргумента pop r27 tst r27 brpl PosArg ; Проверка знака аргумента adiw r27:r26, 1 ; Аргумент отрицателен rjmp IncOK PosArg: ; Аргумент положителен tst r26 ; Учет смены знака при декременте (0 = -0) brne NoPosZero cpi r27, 0 brne NoPosZero ldi r27, 0b10000000 adiw r27:r26, 1 rjmp DecOK NoPosZero: sbiw r27:r26, 1 DecOK: push r26 ; Возвращение результата в стек push r27 push r0 ; Помещение адреса возврата в стек push r1 ret ; Выход из подпрограммы ;------------------------------------------------------------------------------; Подпрограмма вычисления скорости в об/с ; Вход - Mark ; Выход - Float2 (скорость в об/с) ;------------------------------------------------------------------------------GetVelRevPerSec: mov Float2L, MarkL ; Преобразование Mark в вещественный тип mov Float2H, MarkH rcall Fix2Float mov Float1O, Float2O ; Загрузка Mark в Float1 mov Float1L, Float2L mov Float1H, Float2H mov Float2L, ResL ; Преобразование Res в вещественный тип mov Float2H, ResH rcall Fix2Float rcall FDiv ; Float2 = Mark / Res lds Float1O, TO ; Загрузка в Float1 периода опроса энкодера T[с] lds Float1L, TL lds Float1H, TH rcall SwapFl rcall FDiv ; Float2 = Mark / (Res * T) lds Float1O, KO ; Загрузка в Float1 коэффициента передачи K lds Float1L, KL lds Float1H, KH rcall FMult ; Float2 = Mark * K / (Res * T) (результат) ret ; Выход из подпрограммы ;------------------------------------------------------------------------------; Подпрограмма вычисления скорости в об/мин ; Вход - Mark ; Выход - Float2 (скорость в об/мин) ;------------------------------------------------------------------------------GetVelRevPerMin: mov Float2L, MarkL ; Преобразование Mark в вещественный тип mov Float2H, MarkH rcall Fix2Float mov Float1O, Float2O ; Загрузка Mark в Float1 mov Float1L, Float2L mov Float1H, Float2H mov Float2L, ResL ; Преобразование Res в вещественный тип mov Float2H, ResH rcall Fix2Float rcall FDiv ; Float2 = Mark / Res lds Float1O, TO ; Загрузка в Float1 периода опроса энкодера T[с] lds Float1L, TL lds Float1H, TH rcall SwapFl
95 <400> <401> <402> <403> <404> <405> <406> <407> <408> <409> <410> <411> <412> <413> <414> <415> <416> <417> <418> <419> <420> <421> <422> <423> <424> <425> <426> <427> <428> <429> <430> <431> <432> <433> <434> <435> <436> <437> <438> <439> <440> <441> <442> <443> <444> <445> <446> <447> <448> <449> <450> <451> <452> <453> <454> <455> <456> <457> <458> <459> <460> <461> <462> <463> <464> <465> <466> <467> <468> <469> <470> <471> <472> <473> <474> <475> <476> <477> <478> <479>
rcall ldi ldi ldi rcall lds lds lds rcall ret
FDiv Float1O, Float1L, Float1H, FMult Float1O, Float1L, Float1H, FMult
0x48 0x00 0x3c KO KL KH
; Float2 = Mark / (Res * T) ; Загрузка в Float1 числа 60 ; Float2 = Mark * 60 / (Res * T) ; Загрузка в Float1 коэффициента передачи K ; Float2 = Mark * 60 * K / (Res * T) (результат) ; Выход из подпрограммы
;------------------------------------------------------------------------------; Подпрограмма вычисления скорости в рад/с ; Вход - Mark ; Выход - Float2 (скорость в рад/с) ;------------------------------------------------------------------------------GetVelRadPerSec: mov Float2L, MarkL ; Преобразование Mark в вещественный тип mov Float2H, MarkH rcall Fix2Float mov Float1O, Float2O ; Загрузка Mark в Float1 mov Float1L, Float2L mov Float1H, Float2H mov Float2L, ResL ; Преобразование Res в вещественный тип mov Float2H, ResH rcall Fix2Float rcall FDiv ; Float2 = Mark / Res lds Float1O, TO ; Загрузка в Float1 периода опроса энкодера T[с] lds Float1L, TL lds Float1H, TH rcall SwapFl rcall FDiv ; Float2 = Mark / (Res * T) ldi Float1O, 0x48 ; Загрузка в Float1 числа 2*pi = 6.283 ldi Float1L, 0x48 ldi Float1H, 0x06 rcall FMult ; Float2 = Mark * 2 * pi / (Res * T) lds Float1O, KO ; Загрузка в Float1 коэффициента передачи K lds Float1L, KL lds Float1H, KH rcall FMult ; Float2 = Mark * 2*pi * K / (Res * T) (результат) ret ; Выход из подпрограммы ;------------------------------------------------------------------------------; Подпрограмма вычисления скорости в см/с ; Вход - Mark ; Выход - Float2 (скорость в см/с) ;------------------------------------------------------------------------------GetVelSMPerSec: mov Float2L, MarkL ; Преобразование Mark в вещественный тип mov Float2H, MarkH rcall Fix2Float mov Float1O, Float2O ; Загрузка Mark в Float1 mov Float1L, Float2L mov Float1H, Float2H mov Float2L, ResL ; Преобразование Res в вещественный тип mov Float2H, ResH rcall Fix2Float rcall FDiv ; Float2 = Mark / Res lds Float1O, TO ; Загрузка в Float1 периода опроса энкодера T[с] lds Float1L, TL lds Float1H, TH rcall SwapFl rcall FDiv ; Float2 = Mark / (Res * T) lds Float1O, KO ; Загрузка в Float1 коэффициента передачи K lds Float1L, KL lds Float1H, KH rcall FMult ; Float2 = Mark * K / (Res * T) (результат) ret ; Выход из подпрограммы ;------------------------------------------------------------------------------; Подпрограмма получения скорости в нужной размерности ; Выход - значение скорости в Float2 ;------------------------------------------------------------------------------GetVelocity: lds Tunes, mTunes ; Загрузка настроек из памяти sbrs Tunes, 0 rjmp GV1 rcall GetVelRevPerSec ; Получение текущей скорости в Float2 (об/с) rjmp GV4 GV1:
96 <480> <481> <482> <483> <484> <485> <486> <487> <488> <489> <490> <491> <492> <493> <494> <495> <496> <497> <498> <499> <500> <501> <502> <503> <504> <505> <506> <507> <508> <509> <510> <511> <512> <513> <514> <515> <516> <517> <518> <519> <520> <521> <522> <523> <524> <525> <526> <527> <528> <529> <530> <531> <532> <533> <534> <535> <536> <537> <538> <539> <540> <541> <542> <543> <544> <545> <546> <547> <548> <549> <550> <551> <552> <553> <554> <555> <556> <557> <558> <559>
sbrs rjmp rcall rjmp
Tunes, 1 GV2 GetVelRevPerMin GV4
; Получение текущей скорости в Float2 (об/мин)
sbrs rjmp rcall rjmp
Tunes, 4 GV3 GetVelSMPerSec GV4
; Получение текущей скорости в Float2 (см/с)
rcall
GetVelRadPerSec
; Получение текущей скорости в Float2 (рад/с)
GV2:
GV3: GV4: ret
; Выход из подпрограммы
;------------------------------------------------------------------------------; Подпрограмма инициализации USART ;------------------------------------------------------------------------------USART_Init: rcall USART_SetBitRate ; Установка скоростти обмена ldi var, (1<
97 <560> <561> <562> <563> <564> <565> <566> <567> <568> <569> <570> <571> <572> <573> <574> <575> <576> <577> <578> <579> <580> <581> <582> <583> <584> <585> <586> <587> <588> <589> <590> <591> <592> <593> <594> <595> <596> <597> <598> <599> <600> <601> <602> <603> <604> <605> <606> <607> <608> <609> <610> <611> <612> <613> <614> <615> <616> <617> <618> <619> <620> <621> <622> <623> <624> <625> <626> <627> <628> <629> <630> <631> <632> <633> <634> <635> <636> <637> <638> <639>
out USBR_6: cpi brne ldi out ldi out USBR_7: cpi brne ldi out ldi out USBR_8: ret
ubrrl, var BitRateFlags, 6 USBR_7 var, 0 ubrrh, var var, 0x10 ubrrl, var
; Установка скоростти передачи 57600 bps
BitRateFlags, 7 USBR_8 var, 0 ubrrh, var var, 0x8 ubrrl, var
; Установка скоростти передачи 115200 bps
;------------------------------------------------------------------------------; Подпрограмма передачи текущего значения скорости и состояния через USART ; Вход - значение скорости в Float2 ;------------------------------------------------------------------------------USART_Transmit: lds Tunes, mTunes ; Загрузка текущих настроек устройства sbrs Tunes, 3 ; Если интерфейс включен, то передать rjmp UT3 ; данные; иначе - возврат lds var, mSign ; Загрузка знака числа из памяти tst var breq UT50 rcall FNeg ; Смена знака Float2 на противоположный UT50: ldi var, 0xff ; Передача стартовых байт пакета UT10: sbis ucsra, udre ; Ожидание освобождения буфера передачи rjmp UT10 out udr, var ; Передача 1-го стартового байта UT11: sbis ucsra, udre ; Ожидание освобождения буфера передачи rjmp UT11 out udr, var ; Передача 2-го стартового байта UT12: sbis ucsra, udre ; Ожидание освобождения буфера передачи rjmp UT12 out udr, var ; Передача 3-го стартового байта UT0: sbis ucsra, udre ; Ожидание освобождения буфера передачи rjmp UT0 out udr, Float2O ; Передача байта порядка скорости UT1: sbis ucsra, udre ; Ожидание освобождения буфера передачи rjmp UT1 out udr, Float2H ; Передача старшего байта мантиссы скорости UT2: sbis ucsra, udre ; Ожидание освобождения буфера передачи rjmp UT2 out udr, Float2L ; Передача младшего байта мантиссы скорости lds Tunes, mTunes UT15: sbis ucsra, udre ; Ожидание освобождения буфера передачи rjmp UT15 out udr, Tunes ; Передача байта настроек устройства lds State, mState UT16: sbis ucsra, udre ; Ожидание освобождения буфера передачи rjmp UT16 out udr, State ; Передача байта состояния меню lds var, mSign tst var ; Проверка знака скорости breq UT3 ; Если "-", то сменить знак rcall FNeg ; Смена знака Float2 на противоположный UT3: ret ; Выход из подпрограммы ;------------------------------------------------------------------------------; Подпрограмма сохранения текущих настроек устройства в EEPROM ; Вход - байт флагов настройки устройства в SRAM mTunes ; разрешающая способность энкодера в Res ; скорость обмена по USART в SRAM mBitRate ;------------------------------------------------------------------------------EEPROM_Write:
98 <640> <641> <642> <643> <644> <645> <646> <647> <648> <649> <650> <651> <652> <653> <654> <655> <656> <657> <658> <659> <660> <661> <662> <663> <664> <665> <666> <667> <668> <669> <670> <671> <672> <673> <674> <675> <676> <677> <678> <679> <680> <681> <682> <683> <684> <685> <686> <687> <688> <689> <690> <691> <692> <693> <694> <695> <696> <697> <698> <699> <700> <701> <702> <703> <704> <705> <706> <707> <708> <709> <710> <711> <712> <713> <714> <715> <716> <717> <718> <719>
// Сохранение настроек в EEPROM lds Tunes, mTunes ; Загрузка текущих настроек устройства EEPROMwait1: sbic eecr, eewe ; Ожидание готовности EEPROM rjmp EEPROMwait1 ldi var, 0 ; Установка адреса EEPROM out eearh, var out eearl, var out eedr, Tunes ; Запись настроек в регистр данных EEPROM sbi eecr, eemwe ; Запись лог. 1 в EEMWE sbi eecr, eewe ; Начало записи в EEPROM после установки EEWE // Сохранение разрешения энкодера в EEPROM EEPROMwait2: sbic eecr, eewe ; Ожидание готовности EEPROM rjmp EEPROMwait2 ldi var, 0 ; Установка адреса EEPROM out eearh, var ldi var, 1 out eearl, var out eedr, ResH ; Запись старшего байта в регистр данных EEPROM sbi eecr, eemwe ; Запись лог. 1 в EEMWE sbi eecr, eewe ; Начало записи в EEPROM после установки EEWE EEPROMwait3: sbic eecr, eewe ; Ожидание готовности EEPROM rjmp EEPROMwait3 ldi var, 0 ; Установка адреса EEPROM out eearh, var ldi var, 2 out eearl, var out eedr, ResL ; Запись младшего байта в регистр данных EEPROM sbi eecr, eemwe ; Запись лог. 1 в EEMWE sbi eecr, eewe ; Начало записи в EEPROM после установки EEWE // Сохранение скорости обмена по USART в EEPROM EEPROMwait4: sbic eecr, eewe ; Ожидание готовности EEPROM rjmp EEPROMwait4 ldi var, 0 ; Установка адреса EEPROM out eearh, var ldi var, 3 out eearl, var lds BitRateFlags, mBitRate ; Восстановление из памяти BitRateFlags out eedr, BitRateFlags ; Запись BitRateFlags в регистр данных EEPROM sbi eecr, eemwe ; Запись лог. 1 в EEMWE sbi eecr, eewe ; Начало записи в EEPROM после установки EEWE // Сохранение коэффициента передачи в EEPROM EEPROMwait5: sbic eecr, eewe ; Ожидание готовности EEPROM rjmp EEPROMwait5 ldi var, 0 ; Установка адреса EEPROM out eearh, var ldi var, 4 out eearl, var lds var, KO ; Восстановление из памяти KO out eedr, var ; Запись KO в регистр данных EEPROM sbi eecr, eemwe ; Запись лог. 1 в EEMWE sbi eecr, eewe ; Начало записи в EEPROM после установки EEWE EEPROMwait6: sbic eecr, eewe ; Ожидание готовности EEPROM rjmp EEPROMwait6 ldi var, 0 ; Установка адреса EEPROM out eearh, var ldi var, 5 out eearl, var lds var, KL ; Восстановление из памяти KL out eedr, var ; Запись KL в регистр данных EEPROM sbi eecr, eemwe ; Запись лог. 1 в EEMWE sbi eecr, eewe ; Начало записи в EEPROM после установки EEWE EEPROMwait7: sbic eecr, eewe ; Ожидание готовности EEPROM rjmp EEPROMwait7 ldi var, 0 ; Установка адреса EEPROM out eearh, var ldi var, 6 out eearl, var lds var, KH ; Восстановление из памяти KH out eedr, var ; Запись KH в регистр данных EEPROM sbi eecr, eemwe ; Запись лог. 1 в EEMWE sbi eecr, eewe ; Начало записи в EEPROM после установки EEWE // Сохранение периода счета в EEPROM EEPROMwait8:
99 <720> <721> <722> <723> <724> <725> <726> <727> <728> <729> <730> <731> <732> <733> <734> <735> <736> <737> <738> <739> <740> <741> <742> <743> <744> <745> <746> <747> <748> <749> <750> <751> <752> <753> <754> <755> <756> <757> <758> <759> <760> <761> <762> <763> <764> <765> <766> <767> <768> <769> <770> <771> <772> <773> <774> <775> <776> <777> <778> <779> <780> <781> <782> <783> <784> <785> <786> <787> <788> <789> <790> <791> <792> <793> <794> <795> <796> <797> <798> <799>
sbic eecr, eewe rjmp EEPROMwait8 ldi var, 0 out eearh, var ldi var, 7 out eearl, var lds var, TO out eedr, var sbi eecr, eemwe sbi eecr, eewe EEPROMwait9: sbic eecr, eewe rjmp EEPROMwait9 ldi var, 0 out eearh, var ldi var, 8 out eearl, var lds var, TL out eedr, var sbi eecr, eemwe sbi eecr, eewe EEPROMwait10: sbic eecr, eewe rjmp EEPROMwait10 ldi var, 0 out eearh, var ldi var, 9 out eearl, var lds var, TH out eedr, var sbi eecr, eemwe sbi eecr, eewe ret
; Ожидание готовности EEPROM ; Установка адреса EEPROM
; ; ; ;
Восстановление из памяти TO Запись TO в регистр данных EEPROM Запись лог. 1 в EEMWE Начало записи в EEPROM после установки EEWE
; Ожидание готовности EEPROM ; Установка адреса EEPROM
; ; ; ;
Восстановление из памяти TL Запись TL в регистр данных EEPROM Запись лог. 1 в EEMWE Начало записи в EEPROM после установки EEWE
; Ожидание готовности EEPROM ; Установка адреса EEPROM
; ; ; ; ;
Восстановление из памяти TH Запись TH в регистр данных EEPROM Запись лог. 1 в EEMWE Начало записи в EEPROM после установки EEWE Выход из подпрограммы
;------------------------------------------------------------------------------; Подпрограмма загрузки настроек устройства, сохраненных в EEPROM ; Выход - байт флагов настройки устройства в SRAM mTunes ; разрешающая способность энкодера в Res ; скорость обмена по USART в SRAM mBitRate ;------------------------------------------------------------------------------EEPROM_Read: // Загрузка настроек из EEPROM sbic eecr, eewe ; Ожидание готовности EEPROM rjmp EEPROM_Read ldi var, 0 ; Установка адреса EEPROM out eearh, var out eearl, var sbi eecr, eere ; Начало чтения из EEPROM после установки EERE in Tunes, eedr ; Чтение настроек из регистра данных EEPROM sts mTunes, Tunes ; Сохранение настроек в SRAM // Загрузка разрешения энкодера из EEPROM EEPROMwait11: sbic eecr, eewe ; Ожидание готовности EEPROM rjmp EEPROMwait11 ldi var, 0 ; Установка адреса EEPROM out eearh, var ldi var, 1 out eearl, var sbi eecr, eere ; Начало чтения из EEPROM после установки EERE in ResH, eedr ; Чтение стар-го байта из регистра данных EEPROM EEPROMwait12: sbic eecr, eewe ; Ожидание готовности EEPROM rjmp EEPROMwait12 ldi var, 0 ; Установка адреса EEPROM out eearh, var ldi var, 2 out eearl, var sbi eecr, eere ; Начало чтения из EEPROM после установки EERE in ResL, eedr ; Чтение млад-го байта из регистра данных EEPROM // Загрузка скорости обмена по USART из EEPROM EEPROMwait13: sbic eecr, eewe ; Ожидание готовности EEPROM rjmp EEPROMwait13 ldi var, 0 ; Установка адреса EEPROM out eearh, var ldi var, 3 out eearl, var sbi eecr, eere ; Начало чтения из EEPROM после установки EERE in BitRateFlags, eedr ; Чтение BitRateFlags из регистра данных EEPROM sts mBitRate, BitRateFlags ; Сохранение в памяти BitRateFlags
100 <800> <801> <802> <803> <804> <805> <806> <807> <808> <809> <810> <811> <812> <813> <814> <815> <816> <817> <818> <819> <820> <821> <822> <823> <824> <825> <826> <827> <828> <829> <830> <831> <832> <833> <834> <835> <836> <837> <838> <839> <840> <841> <842> <843> <844> <845> <846> <847> <848> <849> <850> <851> <852> <853> <854> <855> <856> <857> <858> <859> <860> <861> <862> <863> <864> <865> <866> <867> <868> <869> <870> <871> <872> <873> <874> <875> <876> <877> <878> <879>
// Загрузка коэффициента передачи из EEPROM EEPROMwait14: sbic eecr, eewe ; Ожидание готовности EEPROM rjmp EEPROMwait14 ldi var, 0 ; Установка адреса EEPROM out eearh, var ldi var, 4 out eearl, var sbi eecr, eere ; Начало чтения из EEPROM после установки in var, eedr ; Чтение KO из регистра данных EEPROM sts KO, var ; Сохранение в памяти KO EEPROMwait15: sbic eecr, eewe ; Ожидание готовности EEPROM rjmp EEPROMwait15 ldi var, 0 ; Установка адреса EEPROM out eearh, var ldi var, 5 out eearl, var sbi eecr, eere ; Начало чтения из EEPROM после установки in var, eedr ; Чтение KL из регистра данных EEPROM sts KL, var ; Сохранение в памяти KL EEPROMwait16: sbic eecr, eewe ; Ожидание готовности EEPROM rjmp EEPROMwait16 ldi var, 0 ; Установка адреса EEPROM out eearh, var ldi var, 6 out eearl, var sbi eecr, eere ; Начало чтения из EEPROM после установки in var, eedr ; Чтение KH из регистра данных EEPROM sts KH, var ; Сохранение в памяти KH // Загрузка периода счета из EEPROM EEPROMwait17: sbic eecr, eewe ; Ожидание готовности EEPROM rjmp EEPROMwait17 ldi var, 0 ; Установка адреса EEPROM out eearh, var ldi var, 7 out eearl, var sbi eecr, eere ; Начало чтения из EEPROM после установки in var, eedr ; Чтение TO из регистра данных EEPROM sts TO, var ; Сохранение в памяти TO EEPROMwait18: sbic eecr, eewe ; Ожидание готовности EEPROM rjmp EEPROMwait18 ldi var, 0 ; Установка адреса EEPROM out eearh, var ldi var, 8 out eearl, var sbi eecr, eere ; Начало чтения из EEPROM после установки in var, eedr ; Чтение TL из регистра данных EEPROM sts TL, var ; Сохранение в памяти TL EEPROMwait19: sbic eecr, eewe ; Ожидание готовности EEPROM rjmp EEPROMwait19 ldi var, 0 ; Установка адреса EEPROM out eearh, var ldi var, 9 out eearl, var sbi eecr, eere ; Начало чтения из EEPROM после установки in var, eedr ; Чтение TH из регистра данных EEPROM sts TH, var ; Сохранение в памяти TH ret ; Выход из подпрограммы
EERE
EERE
EERE
EERE
EERE
EERE
;------------------------------------------------------------------------------; Подпрограмма определения количества меток энкодера ; Выход - количество меток энкодера в Res ;------------------------------------------------------------------------------GetResolution: in var, sreg ; Сохранение регистра флагов в стеке push var ; Разрешение прерывания int1 ldi var, 0b10000000 out gicr, var IndexWait: ; Ожидание индексной метки in var, pind sbrs var, 4 rjmp IndexWait clr MarkH ; Обнуление количества меток clr MarkL NullWait: ; Ожидание прохода индексной метки
101 <880> <881> <882> <883> <884> <885> <886> <887> <888> <889> <890> <891> <892> <893> <894> <895> <896> <897> <898> <899> <900> <901> <902> <903> <904> <905> <906> <907> <908> <909> <910> <911> <912> <913> <914> <915> <916> <917> <918> <919> <920> <921> <922> <923> <924> <925> <926> <927> <928> <929> <930> <931> <932> <933> <934> <935> <936> <937> <938> <939> <940> <941> <942> <943> <944> <945> <946> <947> <948> <949> <950> <951> <952> <953> <954> <955> <956> <957> <958> <959>
in sbrc rjmp sei ResCount: in sbrs rjmp cli mov mov cbr push push rcall pop pop rcall rcall ldi rcall clr clr ldi out pop out ret
var, pind var, 4 NullWait r8, pind r8, 4 ResCount ResH, MarkH ResL, MarkL ResH, 0b10000000 ResH ResL IncSigned16 ResH ResL OutDiag EEPROM_Write r22, 0x54 LongDelay MarkH MarkL var, 0b01000000 gicr, var var sreg, var
; Глобальное разрешение прерываний ; Подсчет количества меток до следующей ; индексной метки (ожидание прерываний от int1) ; Глобальное запрещение прерываний ; Помещение количества меток в Res ; Приведение к модулю ; Помещение переменной Mark в стек ; Увеличить на 1 количество подсчитанных меток ; Вывод параметров датчика ; Сохранение параметров в EEPROM ; Временная задержка ~1 с прикварце 16 МГц ; Обнуление количества меток ; Запрещение прерывания int1 ; Восстановление регистра флагов из стека ; Выход из подпрограммы
;------------------------------------------------------------------------------; Подпрограмма вывода на дисплей количества меток энкодера ; Вход - количество меток энкодера в Res ;------------------------------------------------------------------------------OutDiag: rcall ClrScr ; Очистка дисплея ldi r25, 0 ; Начальный адрес DDRAM ldi r24, 8 ; Количество символов ldi r30, low(TextEncoder*2) ; Установить указатель Z на ldi r31, high(TextEncoder*2) ; начало буфера TextEncoder rcall OutText ; Вывод строки на дисплей ldi r25, 71 ; Начальный адрес DDRAM ldi r24, 6 ; Количество символов ldi r30, low(TextLPR*2) ; Установить указатель Z на ldi r31, high(TextLPR*2) ; начало буфера TextLPR rcall OutText ; Вывод строки на дисплей mov fASCIIL, ResL mov fASCIIH, ResH rcall bin2ASCII16 ; Преобразование разрешения в BCD-формат ldi r25, 65 ; Начальный адрес DDRAM rcall OutBCD ; Вывод разрешения датчика на дисплей ret ; Выход из подпрограммы ;------------------------------------------------------------------------------; Подпрограмма установки интервала счета ; Вход - интервал счета T в памяти RAM ;------------------------------------------------------------------------------SetTimerInterval: lds Float1O, TO ; Загрузка в Float1 интервала счета T из RAM lds Float1L, TL lds Float1H, TH ldi Float2O, 0x58 ; Загрузка в Float2 тактовой частоты 16000000 Гц ldi Float2L, 0x24 ldi Float2H, 0xf4 rcall FMult ; Получение в Float2 интервала счета в тактах (CNT) push Float2O ; Сохранение CNT в стеке push Float2H push Float2L ldi Float1O, 0x51 ; Загрузка в Float1 числа 65536 ldi Float1L, 0x00 ldi Float1H, 0x80 rcall SwapFl rcall FDiv ; Float2 = N = CNT / 65536 (минимальный множитель) rcall Float2Fix ; Отброс дробной части N и перевод в целый формат tst Float2L brne FindScaler8 ldi Float2L, 1 ; Float2 = P = 1 (предделитель таймера/счетчика 1) ldi var, 0b1 ; Установка предделителя таймера/счетчика 1 out tccr1b, var sts mtccr1b, var rjmp TM_OCR
102 <960> <961> <962> <963> <964> <965> <966> <967> <968> <969> <970> <971> <972> <973> <974> <975> <976> <977> <978> <979> <980> <981> <982> <983> <984> <985> <986> <987> <988> <989> <990> <991> <992> <993> <994> <995> <996> <997> <998> <999> <1000> <1001> <1002> <1003> <1004> <1005> <1006> <1007> <1008> <1009> <1010> <1011> <1012> <1013> <1014> <1015> <1016> <1017> <1018> <1019> <1020> <1021> <1022> <1023> <1024> <1025> <1026> <1027> <1028> <1029> <1030> <1031> <1032> <1033> <1034> <1035> <1036> <1037> <1038> <1039>
FindScaler8: sts 0x85, Float2L ldi var, 1 sts 0x86, var ldi var, 7 sts 0x87, var rcall TestInterval lds var, 0x85 tst var breq FindScaler64 ldi Float2L, 8 ldi var, 0b10 out tccr1b, var sts mtccr1b, var rjmp TM_OCR FindScaler64: ldi Float2L, 64 ldi var, 0b11 out tccr1b, var sts mtccr1b, var TM_OCR: rcall Fix2Float pop Float1L pop Float1H pop Float1O push Float1O push Float1H push Float1L rcall FDiv rcall Float2Fix out ocr1ah, Float2H out ocr1al, Float2L ldi Float2O, 0x58 ldi Float2L, 0x24 ldi Float2H, 0xf4 pop Float1L pop Float1H pop Float1O rcall FDiv sts TO, Float2O sts TL, Float2L sts TH, Float2H ret
; Float2 = P = 8 (предделитель таймера/счетчика 1) ; Установка предделителя таймера/счетчика 1
; Float2 = P = 64 (предделитель таймера/счетчика 1) ; Установка предделителя таймера/счетчика 1
; Извлечение CNT из стека ; Сохранение CNT в стеке ; OCR = CNT / P (коэффицент пересчета счетчика 1) ; Перевод OCR в целочисленный формат ; Установка регистра сравнения ; Загрузка в Float2 тактовой частоты 16000000 Гц ; Извлечение CNT из стека ; T[с] = CNT / 16M (интервал счета) ; Сохранение T[с] в SRAM
;------------------------------------------------------------------------------; Подпрограмма проверки принадлежновти числа интервалу ; Вход - проверяемое число в SRAM (0x85) ; начало интервала в SRAM (0x86) ; конец интервала в SRAM (0x87) ; Выход - логическое значение в SRAM (0x85) ;------------------------------------------------------------------------------TestInterval: lds r6, 0x85 ; Загрузка проверяемого числа lds r10, 0x86 ; Загрузка начала интервала cp r6, r10 ; Проверка принадлежности (>=) brsh TestHi TestSetFalse: ldi var, 0 ; Установка отрицательного результата sts 0x85, var rjmp TestQuit TestHi: lds r10, 0x87 ; Загрузка конца интервала cp r10, r6 ; Проверка принадлежности (<=) brsh TestSetTrue rjmp TestSetFalse TestSetTrue: ldi var, 1 ; Установка положительного результата sts 0x85, var TestQuit: ret ;------------------------------------------------------------------------------; Подпрограмма вычисления абсолютной пагрешности ; Вход - разрешение энкодера Res[мет] ; интервал счета Т[с] в SRAM ; коэффициент передачи K в SRAM ; Выход - абсолютная погрешность скорости в текущей размерности Mistake в SRAM ;------------------------------------------------------------------------------GetMistake: lds Float1O, TO ; Загрузка в Float1 интервала счета T[с]
103 <1040> <1041> <1042> <1043> <1044> <1045> <1046> <1047> <1048> <1049> <1050> <1051> <1052> <1053> <1054> <1055> <1056> <1057> <1058> <1059> <1060> <1061> <1062> <1063> <1064> <1065> <1066> <1067> <1068> <1069> <1070> <1071> <1072> <1073> <1074> <1075> <1076> <1077> <1078> <1079> <1080> <1081> <1082> <1083> <1084> <1085> <1086> <1087> <1088> <1089> <1090> <1091> <1092> <1093> <1094> <1095> <1096> <1097> <1098> <1099> <1100> <1101> <1102> <1103> <1104> <1105> <1106> <1107> <1108> <1109> <1110> <1111> <1112> <1113> <1114> <1115> <1116> <1117> <1118> <1119>
lds lds mov mov rcall rcall lds lds lds rcall lds sbrs rjmp ldi ldi ldi rcall rjmp GM_RadPS: sbrs rjmp ldi ldi ldi rcall GM_Store: sts sts sts ret
Float1L, TL Float1H, TH Float2L, ResL Float2H, ResH Fix2Float FMult Float1O, KO Float1L, KL Float1H, KH FDiv Tunes, mTunes Tunes, 1 GM_RadPS Float1O, 0x48 Float1L, 0x00 Float1H, 0x3c FMult GM_Store Tunes, 2 GM_Store Float1O, 0x48 Float1L, 0x48 Float1H, 0x06 FMult
; Загрузка в Float2 разрешения датчика Res[мет] ; Float2 = T[с] * Res[мет] ; Загрузка в Float1 коэффициента передачи K ; Float2 = K / (T[с] * Res[мет]) ; Загрузка настроек из памяти ; Загрузка в Float1 числа 60 ; Float2 = 60*K / (T[с] * Res[мет]) (результат)
; Загрузка в Float1 числа 2*pi = 6.283 ; Float2 = 2*pi*K / (T[с] * Res[мет]) (результат)
MistakeO, Float2O ; Сохранение Mistake в SRAM MistakeL, Float2L MistakeH, Float2H
;------------------------------------------------------------------------------; Подпрограмма вычисления интервала счета ; Вход - разрешение энкодера Res[мет] ; допустимая абсолютная погрешность Mistake в SRAM ; коэффициент передачи K в SRAM ; Выход - интервал счета T[с] в SRAM ;------------------------------------------------------------------------------GetTimerInterval: lds Float1O, MistakeO ; Загрузка в Float1 абсолютной погрешности Mistake lds Float1L, MistakeL lds Float1H, MistakeH mov Float2L, ResL ; Загрузка в Float2 разрешения датчика Res[мет] mov Float2H, ResH rcall Fix2Float rcall FMult ; Float2 = Mistake * Res[мет] lds Float1O, KO ; Загрузка в Float1 коэффициента передачи K lds Float1L, KL lds Float1H, KH rcall FDiv ; Float2 = K / (Mistake * Res[мет]) lds Tunes, mTunes ; Загрузка настроек из памяти sbrs Tunes, 1 rjmp GTI_RadPS ldi Float1O, 0x48 ; Загрузка в Float1 числа 60 ldi Float1L, 0x00 ldi Float1H, 0x3c rcall FMult ; Float2 = 60*K / (Mistake * Res[мет]) (результат) rjmp GTI_Store GTI_RadPS: sbrs Tunes, 2 rjmp GTI_Store ldi Float1O, 0x48 ; Загрузка в Float1 числа 2*pi = 6.283 ldi Float1L, 0x48 ldi Float1H, 0x06 rcall FMult ; Float2 = 2*pi*K / (Mistake*Res[мет]) (результат) GTI_Store: sts TO, Float2O ; Сохранение T[с] в SRAM sts TL, Float2L sts TH, Float2H ret ;------------------------------------------------------------------------------; Подпрограмма временной задержки ; Вход - количество 3-тактных итераций цикла задержки (16-битное число r27:r26) ;------------------------------------------------------------------------------Delay: sbiw r27:r26, 1 brne Delay ret
104 <1120> ;------------------------------------------------------------------------------<1121> ; Подпрограмма длительной временной задержки <1122> ; Вход - количество итераций цикла задержки по ~12.29 мс (число в r22) <1123> ;------------------------------------------------------------------------------<1124> LongDelay: <1125> ldi r26, 0xff ; Временная задержка ~12.29 мс <1126> ldi r27, 0xff <1127> rcall Delay <1128> subi r22, 1 <1129> brne LongDelay ; Повторить r22 раз <1130> ret <1131> <1132> ;------------------------------------------------------------------------------<1133> ; Библиотека операций с вещественными числами <1134> ;------------------------------------------------------------------------------<1135> .include "Float.inc" <1136> <1137> ;------------------------------------------------------------------------------<1138> ; Библиотека операций с BCD числами <1139> ;------------------------------------------------------------------------------<1140> .include "BCD.inc" <1141> <1142> ;------------------------------------------------------------------------------<1143> ; Библиотека подпрограмм для работы с клавиатурой и меню <1144> ;------------------------------------------------------------------------------<1145> .include "Keypad.inc" <1146> <1147> ;------------------------------------------------------------------------------<1148> ; Библиотека подпрограмм для работы с ЖКИ <1149> ;------------------------------------------------------------------------------<1150> .include "LCD.inc" <1151> <1152> ;------------------------------------------------------------------------------<1153> ; Строки для вывода на ЖКИ <1154> ;------------------------------------------------------------------------------<1155> .org 3800 <1156> ; Иконки <1157> TextIcons: .db 0x20, 0x85, 0x84, 0x20, 0x7e, 0x8f <1158> ; "Скорость:" <1159> TextVel: .db 0x43, 0xba, 0x6f, 0x70, 0x6f, 0x63, 0xbf, 0xc4, 0x3a <1160> ; "об/мин" <1161> TextRPM: .db 0x6f, 0xb2, 0x2f, 0xbc, 0xbd, 0xbd <1162> ; "об/с" <1163> TextRPS: .db 0x6f, 0xb2, 0x2f, 0x63 <1164> ; "рад/с" <1165> TextRadPS: .db 0x70, 0x61, 0xe3, 0x2f, 0x63 <1166> ; "см/с" <1167> TextSMS: .db 0x63, 0xbc, 0x2f, 0x63 <1168> ; "мет/об" <1169> TextLPR: .db 0xbc, 0x65, 0xbf, 0x2f, 0x6f, 0xb2 <1170> ; "мс" <1171> TextMS: .db 0xbc, 0x63 <1172> ; "Коэф. передачи" <1173> TextCoef: .db 0x4b, 0x6f, 0xc5, 0xe4, 0x2e, 0x20, 0xbe, 0x65, 0x70, 0x65, 0xe3, 0x61, 0xc0,0xb8 <1174> ; "Размерность" <1175> TextDim: .db 0x50, 0x61, 0xb7, 0xbc, 0x65, 0x70, 0xbd, 0x6f, 0x63, 0xbf, 0xc4 <1176> ; "Точность" <1177> TextPrecision: .db 0x54, 0x6f, 0xc0, 0xbd, 0x6f, 0x63, 0xbf, 0xc4 <1178> ; "Интервал счёта" <1179> TextCountInterval: .db 0xa5, 0xbd, 0xbf, 0x65, 0x70, 0xb3, 0x61, 0xbb, 0x20, 0x63, 0xc0, 0xb5,0xbf, 0x61 <1180> ; "Погрешность" <1181> TextMistake: .db 0xa8, 0x6f, 0xb4, 0x70, 0x65, 0xc1, 0xbd, 0x6f, 0x63, 0xbf, 0xc4 <1182> ; "Автокалибровка" <1183> TextAutocalibration: .db 0x41, 0xb3, 0xbf, 0x6f, 0xba, 0x61, 0xbb, 0xb8, 0xb2, 0x70, 0x6f, 0xb3, 0xba, 0x61 <1184> ; "Скорость обмена" <1185> TextBitRate: .db 0x43, 0xba, 0x6f, 0x70, 0x6f, 0x63, 0xbf, 0xc4, 0x20, 0x6f, 0xb2, 0xbc,0x65, 0xbd, 0x61 <1186> ; "Интерфейс" <1187> TextInt: .db 0xa5, 0xbd, 0xbf, 0x65, 0x70, 0xe4, 0x65, 0xb9, 0x63 <1188> ; "Включить" <1189> TextOn: .db 0x42, 0xba, 0xbb, 0xc6, 0xc0, 0xb8, 0xbf, 0xc4 <1190> ; "Выключить" <1191> TextOff: .db 0x42, 0xc3, 0xba, 0xbb, 0xc6, 0xc0, 0xb8, 0xbf, 0xc4 <1192> ; "Самодиагностика" <1193> TextDiag: .db 0x43, 0x61, 0xbc, 0x6f, 0xe3, 0xb8, 0x61, 0xb4, 0xbd, 0x6f, 0x63, 0xbf, 0xb8, 0xba, 0x61 <1194> ; "Подождите..."
105 <1195> TextWait: .db 0xa8, 0x6f, 0xe3, 0x6f, 0xb6, 0xe3, 0xb8, 0xbf, 0x65, 0x2e, 0x2e, 0x2e <1196> ; " # Меню #" + иконки <1197> TextMenu: .db 0x20, 0xff, 0x20, 0x4d, 0x65, 0xbd, 0xc6, 0x20, 0xff, 0x20, 0x86, 0x87, 0x20, 0x7e, 0x20, 0x2a <1198> ; "Энкодер:" <1199> TextEncoder: .db 0xaf, 0xbd, 0xba, 0x6f, 0xe3, 0x65, 0x70, 0x3a <1200> ; "2400 бод" <1201> TextBR2400: .db 0x32, 0x34, 0x30, 0x30, 0x20, 0xb2, 0x6f, 0xe3 <1202> ; "4800 бод" <1203> TextBR4800: .db 0x34, 0x38, 0x30, 0x30, 0x20, 0xb2, 0x6f, 0xe3 <1204> ; "9600 бод" <1205> TextBR9600: .db 0x39, 0x36, 0x30, 0x30, 0x20, 0xb2, 0x6f, 0xe3 <1206> ; "14400 бод" <1207> TextBR14400: .db 0x31, 0x34, 0x34, 0x30, 0x30, 0x20, 0xb2, 0x6f, 0xe3 <1208> ; "19200 бод" <1209> TextBR19200: .db 0x31, 0x39, 0x32, 0x30, 0x30, 0x20, 0xb2, 0x6f, 0xe3 <1210> ; "38400 бод" <1211> TextBR38400: .db 0x33, 0x38, 0x34, 0x30, 0x30, 0x20, 0xb2, 0x6f, 0xe3 <1212> ; "57600 бод" <1213> TextBR57600: .db 0x35, 0x37, 0x36, 0x30, 0x30, 0x20, 0xb2, 0x6f, 0xe3 <1214> ; "115200 бод" <1215> TextBR115200: .db 0x31, 0x31, 0x35, 0x32, 0x30, 0x30, 0x20, 0xb2, 0x6f, 0xe3 <1216> ; Строка для поля ввода <1217> TextEdit: .db 0xff, 0xff, 0x7e, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2e, 0x14, 0xff <1218> ; Пустая строка <1219> TextEmpty: .db 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 <1220> <1221> .exit
106 Листинг 6. Функция преобразования числовых форматов МК и ПК //-----------------------------------------------------------------------------// Функция, преобразующая вещественное число из 24-битного в 64-битный формат //-----------------------------------------------------------------------------function FloatConvert(var FloatXO, FloatXH, FloatXL: Byte): Real; var Order, i: Shortint; FXO, FXH, FXL, CF: Byte; FloatXM: Word; FloatX: Real; label Positive, NotCF1, NotCF2; begin // Резервирование аргументов FXO := FloatXO; FXH := FloatXH; FXL := FloatXL; Order := FXO; FloatX := 0; asm mov ah, FXH mov al, FXL mov FloatXM, ax // Получение 16-битной мантиссы mov al, Order mov Order, al and Order, 00111111b // Получение модуля порядка mov al, FXO bt ax, 6 jc Positive bts ax, 7 // Установка отрицательного знака xor al, 01111111b mov Order, al Positive: end; // Конвертирование for i := (Order-1) downto (Order-16) do begin asm mov CF, 0 shl FloatXM, 1 jnc NotCF1 mov CF, 1 NotCF1: end; if CF = 1 then FloatX := FloatX + Power(2, i); end; // Установка знака числа asm mov CF, 0 mov al, FXO bt ax, 7 jnc NotCF2 mov CF, 1 NotCF2: end; if CF = 1 then FloatX := -FloatX; Result := FloatX; // Возвращение результата end;
107 Листинг 7. Класс TComThread для работы с COM-портом unit uComPort; interface uses Windows, SysUtils, Classes, uControl, uRusErrorStr, Math, Graphics; type // Определим класс TComThread наследником класса TThread TCommThread = class(TThread) private { Private declarations } // Процедура, занимающаяся опросом порта procedure QueryPort; protected // Переопределим метод запуска потока procedure Execute; override; end; procedure StartService; procedure StopService; procedure WriteStrToPort(Str:String); var i: Integer; CommThread: TCommThread; hPort: Integer; SendBytes: Cardinal; ReciveBytes: Cardinal;
// // // //
Поток, в котором производится опрос порта Дескриптор порта Количество переданных в порт байт Количество считанных из порта байт
implementation uses uDislpay; //=================================StartComThread=============================== procedure StartComThread; // Инициализация нашего потока begin {StartComThread} // Пытаемся инициализировать поток CommThread := TCommThread.Create(False); // Проверяем получилось или нет if CommThread = nil then begin // Ошибка, все выключаем и выходим SysErrorMessage(GetLastError); MainForm.N13.Click; Exit; end; end; {StartComThread} //================================StartComThread================================ //****************************************************************************** //===================================Execute==================================== // Запустим процедуру опроса порта в нашем потоке procedure TCommThread.Execute; begin {Execute} repeat QueryPort; // Опрос порта будет производиться пока поток не будет прекращен until Terminated; end; {Execute} //===================================Execute==================================== //****************************************************************************** //==================================QueryPort=================================== // Процедура опроса порта procedure TCommThread.QueryPort; var PacketBuff: array[0..7] of Byte; // Буфер для чтения данных ByteReaded: Cardinal; // Количество считанных байт h, m, s, ms: Word; // Переменные времени ChartPage: Word; // Страница просмотра графика ChartColor: TColor; // Цвет графика begin {QueryPort} FillChar(PacketBuff, SizeOf(PacketBuff), #0); // Обнуление буфера и чтение if not ReadFile(hPort, PacketBuff, SizeOf(PacketBuff), ByteReaded, nil) then begin {ошибка при чтении данных} // Ошибка, все закрываем и уходим SysErrorMessage(GetLastError); MainForm.N13.Click; Exit; end; {ошибка при чтении данных} if ByteReaded = SizeOf(PacketBuff) then
108 begin if (PacketBuff[0] = 255) and (PacketBuff[1] = 255) and (PacketBuff[2] = 255) and (PacketBuff[3] <> 255) then begin // Проверка стартовых байт пакета DecodeTime(Time-BeginTime, h, m, s, ms); GlobalTime := h*3600000+m*60000+s*1000+ms; // Получение времени и скорости Velocity := FloatConvert(PacketBuff[3], PacketBuff[4], PacketBuff[5]); State := PacketBuff[7]; // Получение информации о состоянии датчика if InitData.Monochrome then ChartColor := clBlack else ChartColor := clRed; if State = 0 then MainForm.DataChart.SeriesList[0].AddXY(GlobalTime, Velocity, '', ChartColor); // Добавление точки на график if Dimention <> PacketBuff[6] then begin if PacketBuff[6] = 9 then MainForm.DataChart.LeftAxis.Title.Caption := 'Скорость, об/с' else if PacketBuff[6] = 10 then MainForm.DataChart.LeftAxis.Title.Caption := 'Скорость, об/мин' else if PacketBuff[6] = 12 then MainForm.DataChart.LeftAxis.Title.Caption := 'Скорость, рад/с' else if PacketBuff[6] = 24 then MainForm.DataChart.LeftAxis.Title.Caption := 'Скорость, см/с'; Dimention := PacketBuff[6]; end; DisplayRefresh; // Обновление виртульного дисплея датчика if (GlobalTime > TimePageSize) and InitData.AutoX then begin MainForm.DataChart.BottomAxis.Automatic := False; ChartPage := GlobalTime div TimePageSize; MainForm.DataChart.BottomAxis.Maximum := ChartPage*TimePageSize + TimePageSize; MainForm.DataChart.BottomAxis.Minimum := ChartPage*TimePageSize; end; end else begin // Поиск стартовых байт пакета и вход в синхронизм FillChar(PacketBuff, SizeOf(PacketBuff), #0); // Обнуление буфера и чтение i := 0; repeat PacketBuff[0] := 0; if not ReadFile(hPort, PacketBuff, 1, ByteReaded, nil) then begin {ошибка при чтении данных} // Ошибка, все закрываем и уходим SysErrorMessage(GetLastError); MainForm.N13.Click; Exit; end; {ошибка при чтении данных} if PacketBuff[0] = 255 then inc(i) else i := 0; until (i = 3); i := 0; repeat PacketBuff[0] := 0; if not ReadFile(hPort, PacketBuff, 1, ByteReaded, nil) then begin SysErrorMessage(GetLastError); MainForm.N13.Click; Exit; end; if PacketBuff[0] <> 255 then i := 1; until (i = 1); FillChar(PacketBuff, SizeOf(PacketBuff), #0); if not ReadFile(hPort, PacketBuff, 4, ByteReaded, nil) then begin {ошибка при чтении данных} //ошибка, все закрываем и уходим SysErrorMessage(GetLastError); MainForm.N13.Click; Exit; end; {ошибка при чтении данных} end; end; {ByteReaded = SizeOf(PacketBuff)} end; {QueryPort} //==================================QueryPort=================================== //****************************************************************************** //==================================InitPort====================================
109 // Инициализация порта procedure InitPort; var DCB: TDCB; // Структура для хранения настроек порта CT: TCommTimeouts; // Стркутура для хранения тайм-аутов begin {InitPort} hPort := CreateFile(PChar(InitData.PortName), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hPort < 0) // не удалось создать файл (инициализировать порт) or not SetupComm(hPort, 2048, 2048) // не удалось установить размерность // входящих - выходящих буферов or not GetCommState(hPort, DCB) then // не удалось получить данные порта begin {ошибка} SysErrorMessage(GetLastError); MainForm.N13.Click; Exit; end; {ошибка} // Параметры порта DCB.BaudRate := InitData.BitRate; // Скорость обмена DCB.StopBits := 0; // Стоповые биты (0 - 1, 1 - 1,5, 2 - 2) DCB.Parity := 0; // Проверка четности DCB.ByteSize := 8; // Биты данных if not SetCommState(hPort, DCB) then // не удалось установить парам-ры порта begin {ошибка} SysErrorMessage(GetLastError); MainForm.N13.Click; Exit; end; {ошибка} // Устанавливаем параметры тайм-аутов if not GetCommTimeouts(hPort, CT) then // не удалось получ. знач-я тайм-аутов begin {ошибка} SysErrorMessage(GetLastError); MainForm.N13.Click; Exit; end; {ошибка} //тайм-ауты CT.ReadTotalTimeoutConstant := 50; CT.ReadIntervalTimeout := 50; CT.ReadTotalTimeoutMultiplier := 1; CT.WriteTotalTimeoutMultiplier := 10; CT.WriteTotalTimeoutConstant := 10; if not SetCommTimeouts(hPort, CT) then // не удалось установить тайм-ауты begin {ошибка} SysErrorMessage(GetLastError); MainForm.N13.Click; Exit; end; {ошибка} end;{InitPort} //==================================InitPort==================================== //****************************************************************************** //================================WriteStrToPort================================ // Процедура записи данных в порт procedure WriteStrToPort(Str: String); var ByteWritten: Cardinal; MyBuff: array[0..1023] of Char; begin {WriteStrToPort} // Готовим буфер для передачи FillChar(MyBuff, SizeOf(MyBuff), #0); Str:=Str+#13#10; StrPCopy(MyBuff, Str); // Передаем данные if not WriteFile(hPort, MyBuff, Length(Str), ByteWritten, nil) then begin {ошибка} SysErrorMessage(GetLastError); MainForm.N13.Click; Exit; end; {ошибка} end; {WriteStrToPort} //================================WriteStrToPort================================ //****************************************************************************** //=====================================StopService============================== // Остановка "службы" опроса порта procedure StopService; begin {StopService} CommThread.Free; // "Отпускаем" поток CloseHandle(hPort); // Закрываем порт
110 MainForm.N12.Enabled := True; MainForm.N13.Enabled := False; end; {StopService} //=====================================StopService============================== //****************************************************************************** //====================================StartService============================== // Запуск "службы" опроса порта procedure StartService; begin {StartService} InitPort; // Инициализируем порт StartComThread; // Запускаем поток MainForm.N12.Enabled := False; MainForm.N13.Enabled := True; end; {StartService} //====================================StartService============================== end.
111
Приложение Ж. Свидетельство участника Всероссийской научной конференции студентов и аспирантов «МОЛОДЫЕ ИССЛЕДОВАТЕЛИ РЕГИОНАМ»
112
Приложение З. Диплом Всероссийской научной конференции студентов и аспирантов «МОЛОДЫЕ ИССЛЕДОВАТЕЛИ - РЕГИОНАМ»
113
Приложение И. Свидетельство участника Всероссийской студенческой оллимпиады «КОНКУРС КОМПЬЮТЕРНЫХ ПРОГРАММ»