logo
Создание анализатора качества горюче-смазочных материалов

Заключение

Поставленная передо мной задача создания и разработки малогабаритного анализатора качества ГСМ выполнена на уровне пробной версии устройства. Выполнены все предъявляемые ПТС требования.Для решения этой задачи были проделаны следующие виды работ:

Изучены отладочная плата Seeeduino и язык программирования Arduino, C, Assembler.

Найден, изучен и проанализирован имеющийся аналог устройство измерения ЭПС и ёмкости конденсатора.

Составлено техническое задание.

Составлены требования к ПС и ПТС, функциональные требования и требования к качеству разрабатываемого устройства.

Разработан алгоритм управляющей части ПТС.

Проведён анализ проделанной работы.

Создаваемое устройство более простое в использовании, надёжное и относительно недорогое. Аппаратная компонента разработанного ПТС реализована на микроконтроллере фирмы AtmelAttiny2313 и графическом ЖК-дисплее. Программная компонента устройства написана на языке Assembler. Объём программы не более 2КБ.

Данное устройство может быть использовано для анализа качества ГСМ и любой другой жидкости при предварительной доработке.

В дальнейшем возможна разработка компьютерного интерфейса.

Благодарю за огромный вклад и помощь своего научного руководителя: Коняева Сергея Ивановича.

Список использованных источников

1. Измеритель емкости и ЭПС конденсаторов / В. Келехсашвили / Журнал «Радио».-2010г,- выпуск 6-7 - стр.19-21.

2. Мактас М.Я. «8 уроков по P-CAD 2001»М.: СОЛОН-Пресс,2003 - стр.1-110.

3. У. Титце, К. Шенк Полупроводниковая схемотехника: справочное руководство» М.: МИР,1982 - стр. 56-65.

4. Описание ЖК-дисплея wh1602J-datasheet.-4c.

Приложение 1

Аналог разрабатываемого устройства спектрометр-анализатор

Известен спектрометр - анализатор веществ фирмы Brimrose [Бюллетень "AOTFSPECTROSCOPY", - фирма Brimrose, March, 1993]. Схема, которая представлена на рисунке.

Рис. 4

Где:

1 - источник широкополосного излучения;

2 - оптическая система доставки широкополосного излучения;

3 - акустооптическая ячейка;

4 - генератор высокой частоты;

5 - светоделительная пластина;

6 - опорный канал узкополосного излучения;

7 - сигнальный канал узкополосного излучения;

8 - фотоприемник опорного канала узкополосного излучения;

9 - фотоприемник сигнального канала узкополосного излучения;

10- анализируемое вещество;

11 - световод;

12 - блок обработки и индикации;

13 - собирающие линзы;

14 - светоделительная пластина;

15 - дифференциальный усилитель.

Этот спектрометр-анализатор работает следующим образом. От источника широкополосного излучения (1) излучение посредством оптической системы доставки широкополосного излучения (2) поступает в акустооптическую ячейку (3), которая выделяет из всего спектра названного излучения узкополосное излучение (излучение в узком спектральном диапазоне). Названный узкий спектральный диапазон формируется с помощью генератора высокой частоты (4) и зависит от частоты подаваемого им сигнала на акустооптическую ячейку (3). Полученное узкополосное оптическое излучение, вышедшее из акустооптической ячейки далее разделяется посредством светоделительной пластинки (14), на два пучка, первый из которых (6), направляется по опорному каналу узкополосного излучения на фотоприемник опорного канала (8), а второй направляется по сигнальному каналу узкополосного излучения (7), через световод (11), на анализируемое вещество (10) и далее возвращается через световод (11) и поступает на фотоприемник сигнального канала узкополосного излучения (9). Фотоприемники (8) и (9) преобразуют оптические сигналы в электрические, которые поступают на входы дифференциального усилителя и сравниваются по величине. Разность этих сигналов интерпретируется как функция поглощения (пропускания) веществом оптического сигнала с заданной длиной волны, которая в свою очередь, жестко связана с частотой генератора поступающей на акустооптическую ячейку. Перестраивая с помощью генератора высокой частоты (4) длину волны выделяемого акустооптической ячейкой узкополосного излучения, получают соответствующую спектральную функцию пропускания, или поглощения, т.е. зависимость изменения амплитуды напряжения на выходе дифференциального усилителя пропорционального изменению оптического сигнала на входе фотоприемника (9) во всем спектральном диапазоне длин оптических волн, в котором проводится измерение спектра поглощения (пропускания) анализируемого вещества.Полученная спектрограмма обрабатывается в электронном блоке обработки и индикации (12) и сравнивается со спектрограммой эталонного образца исследуемого вещества, хранящейся в памяти этого блока.

Приложение 2

Листинг программы

.defsotye = R0;Число сотых долей (1)

.defdesyatye = R1;Число десятых долей (2)

.defedinicy = R2;Число единиц (3)

.defdesyatki = R3;Число десятков (4)

.defsotni = R4;Число сотен тысяч (5)

.deftyshi = R5;Число тысяч (6)

.defdes_tysh= R6;Число десятков тысяч (7)

.defa1 = R7;1-й байт переменной a (младший байт)

.defa2 = R8;2-й байт переменной a

.defa3 = R9;3-й байт переменной a

.defb1 = R10;1-й байт переменной b (младший байт)

.defb2 = R11;2-й байт переменной b

.defb3 = R12;3-й байт переменной b

.defc1 = R13;1-й байт переменной c (младший байт)

.defc2 = R14;2-й байт переменной c

.defc3 = R15;3-й байт переменной c

;--------------------------------------------------------

.defc4 = R16;4-й байт переменной c

.deftemp = R17;Определение главного рабочего регистра

.deftemp2 = R18;Определение второго рабочего регистра

.deflcd= R19;Определение регистра для обращения к LCD

.defz1 = R20;1-й байт переменной z (младший байт)

.defz2 = R21;2-й байт переменной z

.defz3 = R22;3-й байт переменной z

.defz4 = R23;4-й байт переменной z

.defk_del= R24;Регистр поправки коеффициента деления таймера

.deftok_zar= R25;Регистр величины тока заряда

.defautoff= R28;Регистр счётчика автовыключения (он же YL)

.defautoff2= R29;Регистр предела измерения в Фарадах (он же YH)

;--------------------------------------------------------

.equconst1b = 8548;Константа перевода результата в ёмкость для большего тока (32768)

.equconst1m = 9124;Константа перевода результата в ёмкость для малого тока (524288)

.equconst2 = 2051;Константа 100*U1/Ib

.equconst3 = 3967;Константа 100*U2/Ib

.equconst4 = 129;Константа для задания скорости USART (9600 бит/с)

.equESRmax=2001;Порог максимального значения ESR (20,00 Ом)

.equporog1 = 32700;Порог переключения на младший предел (по U2)

.equporog2 = 15001;Порог переключения на малый ток (150 мкФ)

.equporog3 = 2001;Порог переключения предела на малом токе (20 мкФ)

.equd20m = 65535;Значение длительности паузы (~20мс при 20МГц) (тактов-9)/6

.equd3m = 9999;Значение длительности паузы (~3мс при 20МГц) (тактов-9)/6

.equd40u = 235;Значение длительности паузы (~40мкс при 20МГц) (тактов-4)/3

.equd1u=6;Значение длительности паузы (~1мкс при 20МГц) (тактов-4)/3

.equRS = 2;

.equE = 3;

;------------------------Начало программного кода

.cseg

.org0;установка текущего адреса на ноль

;------------------------Переопределение векторов прерываний

start:rjmpinit;Переход на начало программы

rjmpcom_U1;Внешнее прерывание 0

rjmpcom_U2;Внешнее прерывание 1

reti;Таймер/счётчик 1, захват

reti;Таймер/счётчик 1, совпадение, канал А

rjmpovtim1;Таймер/счётчик 1, прерывание по переполнению

reti;Таймер/счётчик 0, прерывание по переполнению

reti;Прерывание USART приём завершён

reti;Прерывание USART регистр данных пуст

reti;Прерывание USART передача завершена

reti;Прерывание по компаратору

reti;Прерывание по изменению на любом контакте

reti;Таймер/счётчик 1, совпадение, канал В

reti;Таймер/счётчик 0, совпадение, канал В

reti;Таймер/счётчик 0, совпадение, канал А

reti;USI готовность к старту

reti;USI переполнение

reti;EEPROM готовность

reti;Переполнение охранного таймера

;-----------------------Модуль инициализации

init:

;-----------------------Инициализация стека

lditemp, RAMEND;Выбор адреса внешнего стека

outSPL, temp;Запись его в регистр стека

;-----------------------Инициализация портов ВВ

lditemp,0b00000100;PA2 на вывод, PA0, PA1 на ввод

outDDRA,temp;

lditemp,0b00000100;Устанавливаем PA2, отключаем резисторы на PA0, PA1

outPORTA,temp;

lditemp,0b11111101;PB0, PB2...PB7 навывод, PB1 наввод

outDDRB,temp;

lditemp,0b00000000;Обнуляем PB1...PB7, устанавливаем PB1 ивключаемрезисторна PB0

outPORTB,temp;

lditemp,0b00110011;PD0, PD1, PD4...PD5 навывод, PD2, PD3, PD6 наввод

outDDRD,temp;

lditemp,0b01111111;Устанавливаем PD0, PD1, PD4...PD5 ивключаемрезисторы PD2, PD3, PD6

outPORTD,temp;

;-----------------------Инициализация таймера Т1

lditemp,0b00000000;Останов таймера, нормальный режим

outTCCR1B,temp;

;-----------------------Инициализация компаратора

lditemp,0b01110000;Настройка компаратора

outACSR,temp;

;-----------------------Определение масок прерываний

lditemp,0b00000000;Выбор режима вызова внешних прерываний PD2 (U1) и PD3 (U2)

outMCUCR,temp;

lditemp,0b00000000;Запрет прерываний по таймеру 1

outTIMSK,temp

lditemp,0b00000000;Запрет внешних прерываний

outGIMSK,temp;

;-----------------------Инициализация LCD (WH1602J)

lcd_init:

rcalldel20m;Вызов подпрограммы задержки (~20мс)

rcalldel20m;Вызов подпрограммы задержки (~20мс)

rcalldel20m;Вызов подпрограммы задержки (~20мс)

;Команда 0010

sbiPORTB,E;Строб вверх

lditemp,0b00101000;Команда (строб вверх + команда)

outPORTB,temp;Запись команды в порт

rcalldel1u;Вызов подпрограммы задержки (~1мкс)

cbiPORTB,E;Строб вниз

rcalldel1u;Вызов подпрограммы задержки (~1мкс)

ldilcd,0b00101000;Команды 0010 и 1000

rcalllcd_com;Вызов подпрограммы отправки команды на LCD

ldilcd,0b00001000;Команды 0000 и 1000

rcalllcd_com;Вызов подпрограммы отправки команды на LCD

ldilcd,0b00000001;Команды 0000 и 0001

rcalllcd_com;Вызов подпрограммы отправки команды на LCD

rcalldel3m;Вызов подпрограммы задержки (~3мс)

ldilcd,0b00000110;Команды 0000 и 0110

rcalllcd_com;Вызов подпрограммы отправки команды на LCD

;-----------------------Начало основной программы

cli;Глобально запрещаем прерывания

clrk_del;Очистка k_del

clrtok_zar;Очистка tok_zar

clrautoff;Очистка autoff

clrautoff2;Очистка autoff2

ldilcd,0b00001100;Включение дисплея и выбор курсора

rcalllcd_com;

;-----------------------Выключение прибора

lditemp,0b01110000;Разрешение перехода в режим Power-Down

outMCUCR,temp;

sbiPORTB,0;Выключение питания

sleep;Переход в режим Power-Down

bat_check1:

clrz1;Очистка z1

clrz2;Очистка z2

lditemp,55;Запись 55 в temp

bat_check2:

dectemp;Уменьшение temp на 1

sbisACSR,ACO;Если на выходе компаратора 1, то пропуск след.команды, иначе далее

rjmpbat_check3;На bat_check3

incz1;Увеличение z1 на 1

rjmpbat_check4;На bat_check4

bat_check3:

incz2;Увеличение z2 на 1

bat_check4:

cpitemp,0;Сравнение temp с 0

brnebat_check2;Если temp<>0, то на bat_check2, иначе далее

cpz1,z2;Сравнение z1 с z2

brlopusk_0;Если z1<z2, то на pusk_0, иначе далее

ldiZL,low(Bat*2);Запись в ZL младшего байта адреса ячейки из таблицы Bat (альтернативная адресация)

ldiZH,high(Bat*2);Запись в ZH старшего байта адреса ячейки из таблицы Bat (альтернативная адресация)

rcalllcd_all;Вызов подпрограммы отображения двух строк на LCD по данным из таблиц

incautoff2;Увеличение autoff2 на 1

;-----------------------Измерение на большом токе заряда

b_tok:

lditemp,0b00000001;Пуск таймера (clk/1)

addtemp,k_del;с коррекцией коеффициента деления таймера

cbiPORTD,0;Включение заряда конденсатора

outTCCR1B,temp;

rjmpcikl;На cikl

;-----------------------Измерение на малом токе заряда

m_tok:

lditemp,0b00000001;Пуск таймера (clk/1)

addtemp,k_del;с коррекцией коеффициента деления таймера

cbiPORTD,4;Включение заряда конденсатора

outTCCR1B,temp;

cikl:

rjmpcikl;Зацикливаем

;-----------------------Умножение (c3+c2+c1)*(XH+XL)=(c4+c3+c2+c1) или (n2-n1)*const1b

ldiXL,low(const1m);Запись младшего байта const1m в XL

ldiXH,high(const1m);Запись старшего байта const1m в XH

rjmpstep6_2;На step6_2

step6_1:

ldiXL,low(const1b);Записьмладшегобайта const1b в XL

ldiXH,high(const1b);Записьстаршегобайта const1b в XH

step6_2:

rcall mul16x16;Вызов подпрограммы перемножения 16-ти битных чисел

;-----------------------Отображение первой строки LCD

rcalllcd_1str;Вызов подпрограммы отображения первой строки LCD

clrautoff;Очистка autoff

;-----------------------Умножение (c3+c2+c1)*(XH+XL)=(c4+c3+c2+c1) или (U2/I)*n1

ldiXL,low(const3);Запись младшего байта const3 в XL

ldiXH,high(const3);Запись старшего байта const3 в XH

rcall mul16x16;Вызов подпрограммы перемножения 16-ти битных чисел

movz1,c1;Копирование результата умножения из c1 в z1

movz2,c2;Копирование результата умножения из c2 в z2

movz3,c3;Копирование результата умножения из c3 в z3

movz4,c4;Копирование результата умножения из c4 в z4

movc1,b1;Копирование 1-го байта n2 из b1 в c1

movc2,b2;Копирование 2-го байта n2 из b2 в c2

movc3,b3;Копирование 3-го байта n2 из b3 в c3

;-----------------------Умножение (c3+c2+c1)*(XH+XL)=(c4+c3+c2+c1) или (U1/I)*n2

ldiXL,low(const2);Запись младшего байта const2 в XL

ldiXH,high(const2);Запись старшего байта const2 в XH

rcall mul16x16;Вызов подпрограммы перемножения 16-ти битных чисел

popa3;Извлечение из стека в a3 (извлечение n2-n1)

popa2;Извлечение из стека в a2

popa1;Извлечение из стека в a1

subc1,z1;Вычитание z1 из c1 ((U1/I)*n2)-((U2/I)*n1)

sbcc2,z2;Вычитание z2 из c2 с учётом переноса

sbcc3,z3;Вычитание z3 из c3 с учётом переноса

sbcc4,z4;Вычитание z4 из c4 с учётом переноса

brplstep8;Если результат положительный, то на step8, иначе далее

ldiZL,low(ESRmn*2);Запись в ZL младшего байта адреса ячейки из таблицы ESRmn (альтернативная адресация)

ldiZH,high(ESRmn*2);Запись в ZH старшего байта адреса ячейки из таблицы ESRmn (альтернативная адресация)

;-----------------------Отображение второй строки LCD

step10:

rcalllcd_2str;Вызов подпрограммы отображения второй строки LCD

;-----------------------Подпрограмма отображение первой строки LCD

lcd_1str:

;-----------------------Отображение ёмкости

ldilcd,0x80;Выбор знакоместа (начало 1й строки)

rcalllcd_com;Вызов подпрограммы отправки команды на LCD

;-----------------------Отображение "12345" или " 2345"

clrtemp;Очистка temp

cpdes_tysh,temp;Если значение десятков тысяч не равно нулю, то переход на lcd_1str_4

brnelcd_1str_4;иначе далее

cptyshi,temp;Если значение тысяч не равно нулю, то переход на lcd_1str_3

brnelcd_1str_3;иначе далее

cpsotni,temp;Если значение сотен не равно нулю, то переход на lcd_1str_2

brnelcd_1str_2;иначе далее

cpdesyatki,temp;Если значение десятков не равно нулю, то переход на lcd_1str_0

brnelcd_1str_0;иначе далее

;-----------------------Отображение " 5,67" или "45,67"

ldilcd,0x20;Отображение " " (ёмкость)

rcalllcd_dat;

rjmplcd_1str_1;На lcd_1str_1

lcd_1str_0:

cpik_del,4;Сравнение k_del с 4

brnelcd_1str_0_1;Если k_del<>4, тона lcd_1str_0_1

ldilcd,0x30;Отображение "0" (ёмкость)

rcalllcd_dat;

ldilcd,0x2C;Отображение "," (ёмкость)

rcalllcd_dat;

lcd_1str_0_1:

ldilcd,0x30;Определение кода для числа десятков (ёмкость)

addlcd,desyatki;

rcalllcd_dat;Отображение числа десятков (ёмкость)

lcd_1str_1:

ldilcd,0x30;Определение кода для числа единиц (ёмкость)

addlcd,edinicy;

rcalllcd_dat;Отображение числа единиц (ёмкость)

cpik_del,4;Сравнение k_del с 4

brnelcd_1str_1_1;Если k_del<>4, то на lcd_1str_1_1

ldilcd,0x30;Определение кода для числа десятых долей (ёмкость)

addlcd,desyatye;

rcalllcd_dat;Отображение числа десятых долей (ёмкость)

ldilcd,0x30;Определение кода для числа сотых долей (ёмкость)

addlcd,sotye;

rcalllcd_dat;Отображение числа сотых долей (ёмкость)

ldilcd,0x20;Отображение " " (ёмкость)

rcalllcd_dat;

rjmpF_lcd;На F_lcd

lcd_1str_1_1:

ldilcd,0x2C;Отображение "," (ёмкость)

rcalllcd_dat;

ldilcd,0x30;Определение кода для числа десятых долей (ёмкость)

addlcd,desyatye;

rcalllcd_dat;Отображение числа десятых долей (ёмкость)

ldilcd,0x30;Определение кода для числа сотых долей (ёмкость)

addlcd,sotye;

rcalllcd_dat;Отображение числа сотых долей (ёмкость)

rjmpuF_lcd;На uF_lcd

;-----------------------Отображение "345,6"

lcd_1str_2:

ldilcd,0x30;Определение кода для числа сотен (ёмкость)

addlcd,sotni;

rcalllcd_dat;Отображение числа сотен (ёмкость)

ldilcd,0x30;Определение кода для числа десятков (ёмкость)

addlcd,desyatki;

rcalllcd_dat;Отображение числа десятков (ёмкость)

ldilcd,0x30;Определение кода для числа единиц (ёмкость)

addlcd,edinicy;

rcalllcd_dat;Отображение числа единиц (ёмкость)

ldilcd,0x2C;Отображение "," (ёмкость)

rcalllcd_dat;

ldilcd,0x30;Определение кода для числа десятых долей (ёмкость)

addlcd,desyatye;

rcalllcd_dat;Отображение числа десятых долей (ёмкость)

rjmpuF_lcd;На uF_lcd

;-----------------------Отображение " 2345" или "12345"

lcd_1str_3:

ldilcd,0x20;Отображение " " (ёмкость)

rcalllcd_dat;

rjmplcd_1str_5;На lcd_1str_5

lcd_1str_4:

ldilcd,0x30;Определение кода для числа десятков тысяч (ёмкость)

addlcd,des_tysh;

rcalllcd_dat;Отображение числа десятков тысяч (ёмкость)

lcd_1str_5:

ldilcd,0x30;Определение кода для числа тысяч (ёмкость)

addlcd,tyshi;

rcalllcd_dat;Отображение числа тысяч (ёмкость)

ldilcd,0x30;Определение кода для числа сотен (ёмкость)

addlcd,sotni;

rcalllcd_dat;Отображение числа сотен (ёмкость)

ldilcd,0x30;Определение кода для числа десятков (ёмкость)

addlcd,desyatki;

rcalllcd_dat;Отображение числа десятков (ёмкость)

ldilcd,0x30;Определение кода для числа единиц (ёмкость)

addlcd,edinicy;

rcalllcd_dat;Отображение числа единиц (ёмкость)

uF_lcd:

ldilcd,0x20;Отображение " " (ёмкость)

rcalllcd_dat;

ldilcd,0x75;Отображение "u" (ёмкость)

rcalllcd_dat;

F_lcd:

ldilcd,0x46;Отображение "F" (ёмкость)

rcalllcd_dat;

ret;Выход из подпрограммы

;-----------------------Подпрограмма отображение второй строки LCD

lcd_2str:

;-----------------------Отображение ESR

ldilcd,0xC0;Выбор знакоместа (начало 2й строки)

rcalllcd_com;

clrtemp;Очистка temp

cpdesyatki,temp;Если значение десятков равно нулю, то переход на lcd_2str_0

breqlcd_2str_0;иначе далее

ldilcd,0x30;Определение кода для числа десятков (ESR)

addlcd,desyatki;

rcalllcd_dat;Отображение числа десятков (ESR)

rjmplcd_2str_1;Переход на lcd_2str_1

lcd_2str_0:

ldilcd,0x20;Отображение " " (ESR)

rcalllcd_dat;

lcd_2str_1:

ldilcd,0x30;Определение кода для числа единиц (ESR)

addlcd,edinicy;

rcalllcd_dat;Отображение числа единиц (ESR)

ldilcd,0x2C;Отображение "," (ESR)

rcalllcd_dat;

ldilcd,0x30;Определение кода для числа десятых долей (ESR)

addlcd,desyatye;

rcalllcd_dat;Отображение числа десятых долей (ESR)

ldilcd,0x30;Определение кода для числа сотых долей (ESR)

addlcd,sotye;

rcalllcd_dat;Отображение числа сотых долей (ESR)

ldilcd,0x20;Отображение " " (ESR)

rcalllcd_dat;

ldilcd,0x4F;Отображение "О" (ESR)

rcalllcd_dat;

ldilcd,0xBC;Отображение "м" (ESR)

rcalllcd_dat;

ret;Выход из подпрограммы

;-----------------------Подпрограмма отображение сообщений на LCD

lcd_mess:

ldiz4,8;Запись 8 в z4

cpitemp,1;Сравнение temp с 1

brnelcd_mess_2str;Если str не равен 1, то на lcd_mess_2str, иначе далее

lcd_mess_1str:

ldilcd,0x80;Выбор знакоместа (начало 1й строки)

rcalllcd_com;

rjmplcd_mess_0;На lcd_mess_0

lcd_mess_2str:

ldilcd,0xC0;Выбор знакоместа (начало 2й строки)

rcalllcd_com;

lcd_mess_0:

lpmlcd,Z+;Запись lcd байта состояния строк из ячейки с адресом из Z

rcalllcd_dat;

decz4;Уменьшение z4 на 1

cpiz4,0;Сравнение z4 с 0

brnelcd_mess_0;Если z4<>0, то на lcd_mess_0, иначе далее

ret;Выход из подпрограммы

;-----------------------Подпрограмма отображения двух строк подряд на LCD по данным из таблиц

lcd_all:

lditemp,1;Отображение 1-й строки

rcalllcd_mess;Вызов подпрограммы отображения сообщений

lditemp,2;Отображение 2-й строки

rcalllcd_mess;Вызов подпрограммы отображения сообщений

ret;Выход из подпрограммы

;-----------------------Подпрограмма вычитания (c3+c2+c1)-(z3+z2+z1)=(c3+c2+c1)

c_minus_z:

subc1,z1;

sbcc2,z2;

sbcc3,z3;

ret;Выход из подпрограммы

;-----------------------Подпрограмма сложения (c3+c2+c1)+(z3+z2+z1)=(c3+c2+c1)

c_plus_z:

addc1,z1;

adcc2,z2;

adcc3,z3;

ret;Выход из подпрограммы

;-----------------------Подпрограмма отправки команды на LCD

lcd_com:

cbiPORTB,RS;Команда

intemp,PORTB

anditemp,0b00000011;Маска 00000011 дляобнулениялишнего

oritemp,0b00001000;Логическое сложение temp с 00001000 (строб вверх + команда)

rcalllcd_out;Вызов подпрограммы lcd_out

ret;Выход из подпрограммы

;-----------------------Подпрограмма отправки данных на LCD

lcd_dat:

sbiPORTB,RS;Данные

intemp,PORTB

anditemp,0b00000011;Маска 00000011 для обнуления лишнего

oritemp,0b00001100;Логическое сложение temp с 00001100 (строб вверх + команда)

rcalllcd_out;Вызов подпрограммы lcd_out

ret;Выход из подпрограммы

;-----------------------Подпрограмма отправки на LCD

lcd_out:

sbiPORTB,E;Строб вверх

pushlcd;Сохранение lcd в стеке

andilcd,0b11110000;Маска 11110000 для обнуления младшего полубайта

orlcd,temp;Логическое сложение lcd с temp (строб вверх + команда)

outPORTB,lcd;Запись команды в порт

cbiPORTB,E;Строб вниз

sbiPORTB,E;Строб вверх

poplcd;Извлечение lcd из стека

swaplcd;Смена полубайт местами

andilcd,0b11110000;Маска 11110000 для обнуления младшего полубайта

orlcd,temp;Логическое сложение lcd с temp (строб вверх + команда)

outPORTB,lcd;Запись команды в порт

rcalldel1u;Вызов подпрограммы задержки (~1мкс)

cbiPORTB,E;Строб вниз

rcalldel40u;Вызов подпрограммы задержки (~40мкс)

rcalldel40u;Вызов подпрограммы задержки (~40мкс)

ret;Выход из подпрограммы

;-----------------------Подпрограмма отображения числовых строк (для отладки)

otlad:

sbicPIND,6;Если PD6=0, то пропуск след.команды

rjmpotlad_2;На otlad_2

rcalldel3m;Вызов подпрограммы задержки (~3мс)

sbicPIND,6;Если PD6=0, то пропуск след.команды

rjmpotlad_2;На otlad_2

rcall lcd_both_str;Вызов подпрограммы отображения двух числовых строк

otlad_1:

rcallknop_off;Вызов подпрограммы ожидания отпускания кнопки

poptemp;Очистка стека (поскольку выход не по ret)

poptemp;Очистка стека

rjmpmain;На main

otlad_2:

ret;Выход из подпрограммы

;-----------------------Подпрограмма ожидания отпускания кнопки

knop_off:

sbisPIND,6;Если PD6=1, то пропуск след.команды

rjmpknop_off;На knop_off

rcalldel3m;Вызов подпрограммы задержки (~3мс)

sbisPIND,6;Если PD6=1, то пропуск след.команды

rjmpknop_off;На knop_off

ret;Выход из подпрограммы

;-----------------------Подпрограмма передачи с 1-го по 7-й байт через USART

usart_1_7:

rcallUSART_ready;Вызов подпрограммы ожидания готовности буфера передачи

lditemp,0x10;Запись 0x10 в temp

ordes_tysh,temp;Логическое сложение des_tysh с temp, результат в des_tysh

outUDR,des_tysh;Передачаиз des_tysh в USART

lditemp,0x20;Запись 0x20 в temp

ortyshi,temp;Логическое сложение tyshi с temp, результат в tyshi

outUDR,tyshi;Передача из tyshi в USART

lditemp,0x30;Запись 0x30 в temp

orsotni,temp;Логическое сложение sotni с temp, результат в sotni

outUDR,sotni;Передача из sotni в USART

lditemp,0x40;Запись 0x40 в temp

ordesyatki,temp;Логическое сложение desyatki с temp, результат в desyatki

outUDR,desyatki;Передача из desyatki в USART

lditemp,0x50;Запись 0x50 в temp

oredinicy,temp;Логическое сложение edinicy с temp, результат в edinicy

outUDR,edinicy;Передачаиз edinicy в USART

lditemp,0x60;Запись 0x60 в temp

ordesyatye,temp;Логическое сложение desyatye с temp, результат в desyatye

outUDR,desyatye;Передача из desyatye в USART

lditemp,0x70;Запись 0x70 в temp

orsotye,temp;Логическое сложение sotye с temp, результат в sotye

outUDR,sotye;Передача из sotye в USART

ret;Выход из подпрограммы

;-----------------------Подпрограмма отображения одной числовой строки

lcd_one_str:

ldilcd,0x4E;Отображение "N"

rcalllcd_dat;

ldilcd,0x3A;Отображение ":"

rcalllcd_dat;

ldilcd,0x30;Определение кода для числа тысяч

addlcd,tyshi;

rcalllcd_dat;Отображение числа тысяч

ldilcd,0x30;Определение кода для числа сотен

addlcd,sotni;

rcalllcd_dat;Отображение числа сотен

ldilcd,0x30;Определение кода для числа десятков

addlcd,desyatki;

rcalllcd_dat;Отображение числа десятков

ldilcd,0x30;Определение кода для числа единиц

addlcd,edinicy;

rcalllcd_dat;Отображение числа единиц

ldilcd,0x30;Определение кода для числа десятых долей

addlcd,desyatye;

rcalllcd_dat;Отображение числа десятых долей

ldilcd,0x30;Определение кода для числа сотых долей

addlcd,sotye;

rcalllcd_dat;Отображение числа сотых долей

ret;Выход из подпрограммы

;-----------------------Подпрограмма отображения двух числовых строк по данным

lcd_both_str:

movc1,a1;Копирование из a1 в c1

movc2,a2;Копирование из a2 в c2

movc3,a3;Копирование из a3 в c3

;-----------------------Отображение смещения от нуля для U1 "1= "

ldilcd,0x80;Выбор знакоместа (начало 1й строки)

rcalllcd_com;

rcalllcd_one_str;Вызов подпрограммы отображения одной числовой строки

movc1,b1;Копирование из b1 в c1

movc2,b2;Копирование из b2 в c2

movc3,b3;Копирование из b3 в c3

;-----------------------Отображение смещения от нуля для U2 "2= "

ldilcd,0xC0;Выбор знакоместа (начало 2й строки)

rcalllcd_com;

rcalllcd_one_str;Вызов подпрограммы отображения одной числовой строки

ret;Выход из подпрограммы

;-----------------------Подпрограмма обработки прерывания по переполнению таймера 1

;Поскольку выход не по reti, то глобально запрещённые прерывания остаются запрещены

ovtim1:

cli;Глобально запрещаем прерывания

lditemp,3;Заносим 3 в temp

cpc3,temp;Сравнение c3 с temp

breqovtim1_0;Если с3=3, то на ovtim1_0, иначе далее

incc3;Увеличение c3 на 1

reti;Выход из подпрограммы обработки прерывания

ovtim1_0:

sbiPORTD,0;Выключение большого тока заряда конденсатора

sbiPORTD,4;Выключение малого тока заряда конденсатора

sbiPORTD,5;Включение разряда конденсатора

lditemp,0b00000000;Останов таймера

outTCCR1B,temp;

poptemp;Очистка стека (поскольку выход по clk_down, а не по reti)

poptemp;Очистка стека

rjmpclk_down;Переход на clk_down

;-----------------------Подпрограмма обработки внешнего прерывания по U1

;Поскольку выход не по reti, то глобально запрещённые прерывания остаются запрещены

com_U1:

ina1,TCNT1L;Сохраняем 1-йбайт n1

ina2,TCNT1H;Сохраняем 2-йбайт n1

mova3,c3;Копируем из c3 в a3 3-й байт n1

lditemp,0b10000000;Разрешение внешнего прерывания только по PD3 (U2)

outGIMSK,temp;

reti;Выход из подпрограммы обработки прерывания

;-----------------------Подпрограмма обработки внешнего прерывания по

U2

com_U2:

inc1,TCNT1L;Сохраняем 1-й байт n2

inc2,TCNT1H;Сохраняем 2-й байт n2

cli;Глобально запрещаем прерывания

sbiPORTD,0;Выключение большого тока заряда конденсатора

sbiPORTD,4;Выключение малого тока заряда конденсатора

sbiPORTD,5;Включение разряда конденсатора

lditemp,0b00000000;Останов таймера

outTCCR1B,temp;

poptemp;Очистка стека (поскольку выход не по reti)

poptemp;Очистка стека