Вы находитесь на странице: 1из 24

Приложение 1.

Расширение функциональности модуля для блоков питания, за


счет "доукомплектования" его функцией 8-разрядного частотомера
(практикум по расширению функциональности устройства).

Сие иллюстрирует наращивание функциональности "матери" (программа


BP_MOD_1.asm), а заодно и разрешает внутренний, личностный конфликт между тем,
"на что был направлен глобальный, орлиный взор", и получившимся результатом.
В том смысле, что я "холил и лелеял" свободный вывод RA4/TOCKI (счетный вход
TMR0), а он так и остался свободным (безобразие какое-то).
Такого издевательства, над сокровенными надеждами, моя психика не выдерживает.
Это и есть причина того, что я "укомплектовал текущую железяку" функцией
8-разрядного частотомера.
Ну и "учёботренировка" совсем не помешает.
"Чистому ассемблерщику" постоянно нужно быть в хорошей спортивной форме!
Бицепсы/трицепсы должны быть стальными, а реакция на удар мгновенной (к этому
нужно стремиться), а иначе фингалы замучают.
Это с одной стороны.
С другой стороны, почему бы и не "укомплектоваться", если препятствий этому нет?
От этого, при копеечных затратах и минимуме "геморроя" (к конструктору это не
относится), стоимость и возможности устройства довольно-таки существенно
повышаются.
К тому же, ЖК-модуль уже "заинициализирован" и имеется вся необходимая
"индикаторная инфраструктура/обслуга".
Хоть убейте, но мимо этого "счастья" я пройти не могу (ночью ворочаюсь. Сильнейший
дискомфорт. Подсознание выражает недовольство).
Если функция частотомера Вам не нужна, то не включайте ее или выключите, если
ранее она была включена (все настройки энергонезависимо запоминаются), и все дела.
Принципиальная схема "железяки" выглядит так:

Всего-навсего нужно заменить "прошивку" и дополнить устройство простейшим блочкОм,


принципиальная схема которого находится в прямоугольнике, выделенном
светло-желтым цветом.

1
В данном случае, это простейший, входной формирователь, с низким Rвх., но ничто не
мешает заменить его входным формирователем с более высоким Rвх.
Его принципиальную схему Вы можете найти: CD à папка Картинки à файл №86.gif.
При этом, нужно читать не к точке соединения 2-го и 3-го выводов PIC16F84A, а
к точке соединения 5-го и 6-го выводов PIC16F873A.
Рекомендации по настройке такого формирователя Вы найдете в 3-й части
"Самоучителя по программированию PIC контроллеров для начинающих".
Вот и вся доработка принципиальной схемы.
Если кто-то скажет, что это очень сложно, то напоминаю про монастырь и веру в
человечество.
А вот о "программной составляющей" такого сказать нельзя.
Это "иллюстрирует" тот факт, что "центр тяжести МК-дел явно смещен" в сторону этой
сАмой "программной составляющей".
А теперь, по-порядку.
Процедуру, которая реализует функцию частотомера, нужно куда-то "врЕзать".
В рабочий цикл режима ЗАЩИТА ВКЛЮЧЕНА "врезаться" не буду.
Мотивация.
1. Если запретить прерывания на время исполнения процедуры,
реализующей функцию частотомера, то это соответствует сильному
ухудшению инерционности срабатывания защиты.
2. Если разрешить прерывания на время исполнения процедуры,
реализующей функцию частотомера, то верхняя граница диапазона
измеряемых частот "срежется" до примерно 10 Кгц (округлено. Это те частоты,
которые будут замеряться с более-менее приемлемой погрешностью) и возникнут
проблемы, связанные со стабильностью интервала времени измерения (возможны
его "гуляния").
Напоминаю, что период ухода в прерывания составляет 90 мкс.
Значит нужно ориентироваться на наихудшую периодичность опроса состояния
флага T0IF порядка 100 мкс. Вот Вам и "потолок" в 10 Кгц.
Значит, буду "врезАться" в рабочий цикл режима ЗАЩИТА ВЫКЛЮЧЕНА, причем, с
запретом прерываний на время отработки процедуры, реализующей функцию
частотомера (это позволяет максимально реализовать "потенциал частотомера").
То, что это ухудшит инерционность срабатывания защиты от перегрева и защиты от
КЗ, однозначно.
Защита от перегрева достаточно инерционна и поэтому то, что она сработает,
например, на 0,5 сек. или даже на 1 сек. позднее, вполне терпимо.
С защитой от КЗ дела обстоят хуже, но куда деваться?
В данном случае, единственное, что можно сделать, так это только минимизировать
"провал защиты".
Его можно примерно приравнять интервалу времени измерения частоты.
Значит, нужно стремиться его уменьшить. Например, до 0,1 сек.
Это конечно сделать можно, но "шаг" измерения величиной 10 Гц. не вызывает у меня
положительных эмоций.
А вообще, это на любителя. В жизни всякое бывает нужным. Хаять не буду.
Если взять за основу интервал времени измерения 1 сек., то "точностные дела будут
выглядеть" гораздо лучше, но "провал" в 1 сек. это многовато.
Вот и "чеши репу"… Обкуришься думаючи.
В соответствии со своим понятием об оптимальном (на безгрешность не претендую), я
выбрал интервал времени измерения 0,5 сек., с последующим умножением на 2 (сдвиг
влево, на один бит, содержимого многобайтного регистра, в котором "лежит" двоичный
результат текущего измерения частоты).
Точка. Так тому и быть.
Следующий вопрос: "Куда выводить результаты измерения частоты и как это отразится
на том, что есть"?
Напряжение и ток должны контролироваться.
Защита от КЗ, хотя и с хренОвой (извиняюсь за непарламентское выражение)
инерционностью, но должна работать (лучше хоть какая-то защита, чем ее
отсутствие).

2
Температура должна контролироваться (если термодатчик электрически подключен
и включен в настройках).
"Резвость кручения пропеллера" должна зависеть от температуры, и
термозащита должна работать.
Короче, всё то же самое (с поправкой на инерционность срабатывания защит), плюс,
на индикацию должен выводиться результат текущего замера частоты.
Значит, нужно сохранить все упомянутое и "расчистить местечко" для результатов
замеров частоты.
Не нужно быть "гигантом мысли" для того чтобы понять, что их нужно выводить в 1-ю
строку дисплея, взамен информирующей надписи ЗАЩИТА ВЫКЛ. (если термодатчик
работает) или ЗАЩИТА ВЫКЛЮЧЕНА (если термодатчик не работает).
Для удобства пользователя, 8-разрядный результат измерения частоты сформирую не
в виде ХХХХХХХХгц, а в виде ХХ ХХХ ХХХгц, то есть, с "промежутками".
Так как нужно организовать и "промежуток" между показаниями частоты и температуры,
а знакомест всего 16, необходимо t=хх заменить на пробелtхх.
В общем виде, это будет выглядеть так:
ХХ ХХХ ХХХгц tхх
где ХХ ХХХ ХХХ - результат измерения частоты, а хх - результат измерения температуры.
Примечание: сначала, в результат измерения частоты, я хотел вставить
разделительные точки, но потом от этого отказался, так как, на мой взгляд, символы
"пусто" смотрятся симпатичнее. Особенно при нулевых показаниях (незначащие нули
будут гаситься).
Голос из-за кулис: "Ну ладно, шкуру не убитого медведя поделил (подтекст: на
выдумки все горазды), а как конкретно заполучить это счастье"?
Ответ: "заполучать это счастье" нужно строго поэтапно (напоминаю про план, здравый
смысл и их производные).
Для начала, нужно организовать "технологическую" процедуру включения/выключения
частотомера, ведь с этого и начинается "весь сыр-бор".
Пользователь должен сам решать, включить частотомер или его выключить.
Кроме этого, нужно организовать энергонезависимое запоминание соответствующей
настройки.
Под это дело, в меню установки порогов, организован
дополнительный пункт.
На картинке слева изображено, как он выглядит.
После отжатия кнопки Установка порогов, произведенного в
интервале времени "высвечивания" этой надписи, вдруг, откуда не возьмись, появится
тот символ маркера, к которому Вы уже должны привыкнуть.
Он установится в том положении, которое соответствует "старой" (последней) настройке
(она энергонезависимо запоминается).
После "прошивки" ПИКа, маркер установится перед надписью
ВЫКЛ (см. картинку слева).
То есть, частотомер будет выключен, и устройство будет работать
точно так же, как и до введения этого "наворота".
Для того чтобы изменить положение маркера, нужно нажать/отжать всё ту же кнопку
Установка порогов.
Для того чтобы включить частотомер, нужно установить маркер
перед надписью ВКЛ (см. картинку слева).
В дальнейшем, можно сколько угодно раз включать (если он
нужен) и выключать (если он не нужен) частотомер.
Это кому как захочется.
При любом изменении положения маркера, в EEPROM-память данных записывается
соответствующий признак, и вплоть до последующей смены положения маркера,
в 1-й строке дисплея, будет отображаться либо информирующая надпись (если
частотомер выключен), либо результат измерения частоты (если частотомер включен).
После того, как с помощью кнопки Установка порогов, маркер будет установлен перед
нужной надписью, необходимо нажать/отжать кнопку Переключение режимов.
Если частотомер выключен, то произойдет возврат в тот основной режим, из которого
вызывалось меню установки порогов, и устройство будет работать точно так же, как и
до организации этого "наворота".
3
Если частотомер включен, то вне зависимости от того, из какого основного режима
вызывалось меню установки порогов, произойдет возврат в режим ЗАЩИТА
ВЫКЛЮЧЕНА.
Он происходит без отработки сценария-подсказки режима ЗАЩИТА ВЫКЛЮЧЕНА (№2).
В режиме ЗАЩИТА ВЫКЛЮЧЕНА, при условии, что частотомер включен, этот
сценарий-подсказка (№2) игнорируется, а при условии, что частотомер выключен, не
игнорируется (по-моему, это выглядит логично).
Если частотомер включен и производится замер частоты, то Вы
увидите то, что изображено на картинке слева.
Естественно, что показания могут быть и другими.
Если источник сигнала к частотомеру не подключен, то будет "высвечиваться" 0гц., а
все остальные нули будут погашены.
Если необходимо перейти, из режима ЗАЩИТА ВЫКЛЮЧЕНА (с включенным
частотомером), в режим ЗАЩИТА ВКЛЮЧЕНА, то нужно "стандартно" нажать/отжать
кнопку Переключение режимов.
При этом, факт включения частотомера, на работе в режиме ЗАЩИТА ВКЛЮЧЕНА,
никак не отразится.
Нужно перейти "в обратную сторону"?
То же самое (кнопка Переключение режимов).
То есть, в части касающейся "механики" переключений основных режимов, никаких
изменений не произошло.
После смены режима ЗАЩИТА ВКЛЮЧЕНА на ЗАЩИТА ВЫКЛЮЧЕНА
(сценарий-подсказка отрабатываться не будет), опять, откуда не возьмись, "возникнет
визуальный скелет" того, что Вы видите на "вышележащей" картинке.
Давайте разберемся с тем, что Вы на ней видите.
Вы видите результат "комплексного" замера значений напряжения, тока,
температуры и частоты, причем, "всё в одном флаконе" и не "застывшее", а в
динамике. Это достаточно информативно, а заодно и удобно (на мой взгляд).
Частотомер (если он включен), работает автономно, и его работа не зависит
от того, запитывается ли что-то от блока питания или не запитывается.
То есть, можно одновременно и запитывать какое-то устройство, и измерять частоту
сигнала, формируемого другим устройством.
А можно и не запитывать, а только измерять частоту.
Можно и запитать источник сигнала, и измерить его частоту.
Последнее удобно в том случае, если в состав блока питания входит такая
"нужность", как генератор стандартных сигналов или генератор импульсов.
Если они высокочастотные, то можно "сваять" делитель на 10.
Ну и т.д. На мой взгляд, частотомер это "штуковина" нужная.
Лишь бы он был в наличии, а "прислонить его можно к разнообразным стенкам".
В данном случае, "шаг" измерения 2 герца, а "верхний потолок частоты" определяется
быстродействием ПИКа (как минимум, 30 Мгц.).
Немного отклонился от "генеральной линии".
Это для того, чтобы Вы представили себе, о чем ниже пойдет речь.
Теперь нужно разобраться с программной организацией соответствующего пункта меню
установки порогов.
Примечание: имейте в виду, что после возникновения дополнительных
функциональностей, название меню установки порогов стало слегка некорректным,
так как в нем "каждой твари по паре", но раз уж я изначально "привязался" к этому
названию, то пусть оно таким и останется.
Дополнительный пункт меню (под включение/выключение частотомера) я организовал так:
......................................
......................................

;22222222222222222222222222222222222222222222222222222222222222222222222222222222
; 2-я СТРАНИЦА ПАМЯТИ ПРОГРАММ.
;################################################################################
......................................
......................................
......................................
;TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
4
; ГРУППА КОМАНД ПРОГРАММНОГО ВКЛЮЧЕНИЯ/ВЫКЛЮЧЕНИЯ ТЕРМОДАТЧИКА.
;TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
; Анализ состояния флага блокировки 4-го пункта меню.
;--------------------------------------------------------------------------------
btfsc Flag_1,4 ; Каково состояние флага ?
goto CHASTOTA ; Если поднят, то 4-й пункт меню не выводится
; на индикацию. Если опущен, то выводится.
......................................
......................................
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
; ГРУППА КОМАНД ВКЛЮЧЕНИЯ/ВЫКЛЮЧЕНИЯ ЧАСТОТОМЕРА.
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
CHASTOTA movlw .36 ; Задание времени (количества циклов)
movwf Temp ; "высвечивания" надписи
; "ЧАСТОТОМЕР/ВКЛ ОТКЛ".
;================================================================================
; Вывод на индикацию, в 1-ю строку, фиксированной надписи " ЧАСТОТОМЕР ".
;================================================================================
SNOVA_9 movlw b'10000000' ; Установка курсора в крайнее
call ENTER_BF_1 ; левое знакоместо 1-й строки.
movlw .16 ;
movwf Count ;
bsf PCLATH,0 ; ПП TEXT_47 находится
; во 2-м блоке 2-й страницы.
movf Count,W ;
sublw .16 ; Аналогично, только
call TEXT_47 ; для TEXT_47.
call SIMVOL_T_1 ;
decfsz Count,F ;
goto $-5 ;
;================================================================================
; Вывод на индикацию, в 2-ю строку, фиксированной надписи " ВКЛ ОТКЛ ".
;================================================================================
bcf PCLATH,0 ; ПП TEXT_43 находится
; в 1-м блоке 2-й страницы.
movlw b'11000001' ; Выбор 2-го знакоместа.
call ENTER_BF_1 ;
movlw .14 ;
movwf Count ;
movf Count,W ;
sublw .14 ; Аналогично, только
call TEXT_43 ; для TEXT_43.
call SIMVOL_T_1 ;
decfsz Count,F ;
goto $-5 ;
;--------------------------------------------------------------------------------
; Пауза между циклами вывода на индикацию.
;--------------------------------------------------------------------------------
call PAUSE_UI_1 ; Переход в ПП PAUSE_UI_1.
;--------------------------------------------------------------------------------
; Счет циклов.
;--------------------------------------------------------------------------------
btfsc PortB,1 ; Кнопка "Установка порогов" нажата
; или отжата ?
goto FREG ; Если отжата, то переход в ПП
; включения/отключения частотомера.
decfsz Temp,F ; Если нажата, то цикл вывода надписи
; "ЧАСТОТОМЕР/ВКЛ. ОТКЛ." повторяется
goto SNOVA_9 ; до тех пор, пока счетчик не обнулится.
; После этого, программа исполняется далее.
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
; ГРУППА КОМАНД ВОЗВРАТА ИЗ РЕЖИМА.
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
......................................
......................................

5
Дополнительный пункт меню установки порогов "врезан в промежуток" между пунктом
включения/выключения термодатчика и пунктом возврата из режима.
Соответственно, с целью обхода 4-го пункта меню (если термодатчик электрически
отключен), команда goto VOZVRAT заменена на команду goto CHASTOTA.
Пункт меню ЧАСТОТОМЕР / ВКЛ ОТКЛ, по сути, повторяет пункт меню
Термодатчик / ВКЛ ОТКЛ, только в приложении к надписи ЧАСТОТОМЕР
(организована дополнительная таблица вычисляемого перехода TEXT_47).
В случае выбора этого пункта меню, осуществляется переход в подпрограмму FREG.
Казалось бы, надпись ВКЛ ОТКЛ на индикацию выводить не нужно, ведь в случае
активности 4-го пункта меню, она выводится на индикацию ранее (зачем
подтверждать?), но это ошибка.
Если не вывести эту надпись на индикацию, то в том случае, если термодатчик
электрически не подключен (4-й пункт меню обходится), в 1-й строке дисплея "заторчит
инородная надпись" предыдущего пункта меню, что формально, не есть "Гитлер капут",
но фактически, является форменным безобразием, терпеть которое нельзя.
Поэтому и есть то, что есть.
Ладушки.
Один "вражина ликвидирован" (можно один раз кратковременно подуть в фанфары).
Пункт меню организован.
Теперь нужно "сваять переключалку/запоминалку".
От такой перспективы, дрожи в коленках вообще нет, так как эта "штуковина"
придумана ранее (имеется в наличии).
То есть, нужно "адаптировать переключалку/запоминалку" пункта Термодатчик ВКЛ ОТКЛ
под пункт ЧАСТОТОМЕР / ВКЛ ОТКЛ, и все дела (второе колесо изобретать не нужно).
В результате этой простой "комбинации из двух пальцев", получилось такое "творение":
......................................
......................................
;22222222222222222222222222222222222222222222222222222222222222222222222222222222
; 2-я СТРАНИЦА ПАМЯТИ ПРОГРАММ.
;################################################################################
......................................
......................................
......................................
;FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
; Подпрограмма включения/отключения частотомера.
;FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
; Противодребезговая задержка.
;--------------------------------------------------------------------------------
FREG call PAUSE_UI_1 ; Переход в ПП PAUSE_UI_1.
;--------------------------------------------------------------------------------
; Чтение, из EEPROM, байта указателя включения/выключения частотомера.
;--------------------------------------------------------------------------------
call READ_F ; Реализация оного.
;--------------------------------------------------------------------------------
; Анализ содержимого указателя включения/выключения частотомера.
;--------------------------------------------------------------------------------
SNOVA_10 btfss Temp_F,0 ; Что в бите №0 ?
goto F_VIKL ; Если 0, то частотомер выключается.
; Если 1, то частотомер включается.
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
; Включение частотомера.
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
; Задание адреса знакоместа, с которого начнется вывод на индикацию.
;-------------------------------------------------------------------
movlw b'11000000' ; 2-я строка, 1-е знакоместо. Адрес 00h.
call ADRES_1 ; Установка адреса.
;-------------------------------------------------------------------
; Вывод на индикацию символа активности (маркера).
;-------------------------------------------------------------------
movlw 0DCh ; Символ ">|"
call SIMVOL_1 ; Вывод этого символа на индикацию.
;-------------------------------------------------------------------
6
; Задание адреса знакоместа, с которого начнется вывод на индикацию.
;-------------------------------------------------------------------
movlw b'11001010' ; 2-я строка, 11-е знакоместо. Адрес 0Ah.
call ADRES_1 ; Установка адреса.
;-------------------------------------------------------------------
; Вывод на индикацию символа "пусто".
;-------------------------------------------------------------------
movlw 20h ; Символ "пусто"
call SIMVOL_1 ; Вывод этого символа на индикацию.
;--------------------------------------------------------------------------------
goto OBHOD_6 ; Обход процедуры выключения частотомера.

;OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
; Выключение частотомера.
;OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
; Задание адреса знакоместа, с которого начнется вывод на индикацию.
;-------------------------------------------------------------------
F_VIKL movlw b'11001010' ; 2-я строка, 11-е знакоместо. Адрес 0Ah.
call ADRES_1 ; Установка адреса.
;-------------------------------------------------------------------
; Вывод на индикацию символа активности (маркера).
;-------------------------------------------------------------------
movlw 0DCh ; Символ ">|"
call SIMVOL_1 ; Вывод этого символа на индикацию.
;-------------------------------------------------------------------
; Задание адреса знакоместа, с которого начнется вывод на индикацию.
;-------------------------------------------------------------------
movlw b'11000000' ; 2-я строка, 1-е знакоместо. Адрес 00h.
call ADRES_1 ; Установка адреса.
;-------------------------------------------------------------------
; Вывод на индикацию символа "пусто".
;-------------------------------------------------------------------
movlw 20h ; Символ "пусто"
call SIMVOL_1 ; Вывод этого символа на индикацию.

;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
; Опрос клавиатуры.
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
; Опрос кнопки "Переключение режимов".
;================================================================================
OBHOD_6 btfsc PortB,0 ; Кнопка "Переключение режимов" нажата
; или отжата ?
goto $+8 ; Если отжата, то переход на опрос кнопки
; "Установка порогов".
; Если нажата, то программа исполняется далее.
;--------------------------------------------------------------------------------
; Вывод на индикацию фиксированной надписи " СЛУШАЮСЬ и / ПОВИНУЮСЬ! ".
;--------------------------------------------------------------------------------
bcf PCLATH,3 ; Выбор 1-й страницы.
call SL_I_POVIN ; Переход в ПП вывода на индикацию
; этой надписи.
bsf PCLATH,3 ; Выбор 2-й страницы.
;--------------------------------------------------------------------------------
; Ожидание отжатия кнопки.
;--------------------------------------------------------------------------------
btfss PortB,0 ; Кнопка "Переключение режимов"
; нажата или отжата ?
goto $-1 ; Если нажата, то ожидание отжатия.
;OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
; Рабочее действие после отжатия.
;OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
clrf PCLATH ; Выбор 1-го блока 1-й страницы.
goto INKEY ; После отжатия, выход из режима.
;================================================================================
; Опрос кнопки "Установка порогов".
;================================================================================
7
btfsc PortB,1 ; Кнопка "Установка порогов" нажата
; или отжата ?
goto SNOVA_10 ; Если отжата, то переход на следующий
; внутренний цикл.
; Если нажата, то программа исполняется далее.
;--------------------------------------------------------------------------------
; Противодребезговая задержка.
;--------------------------------------------------------------------------------
call PAUSE_UI_1 ; Переход в ПП PAUSE_UI_1.
;--------------------------------------------------------------------------------
; Ожидание отжатия кнопки.
;--------------------------------------------------------------------------------
btfss PortB,1 ; Кнопка "Установка порогов" нажата
; или отжата ?
goto $-1 ; Если нажата, то ожидание отжатия.
;OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
; Рабочее действие после отжатия.
;OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
incf Temp_F,F ; Смена состояния указателя
; включения/выключения частотомера
; (Temp_F + 1 = ...).
;================================================================================
; Запись, в EEPROM-память данных, признака включения/выключения частотомера.
;================================================================================
bsf Status,RP1 ; Переход
bcf Status,RP0 ; во 2-й банк.
movlw 7 ; Выбор ячейки EEPROM
movwf EEAdr ; с адресом 07h.
movf Temp_F,W ; Temp_F -> W.
call WRITE ; Переход в элемент ПП записи.
;----------------------------------------------------------------------
; Проверка текущего значения признака включения/выключения частотомера.
;----------------------------------------------------------------------
btfss Temp_F,0 ; Что в бите №0 ?
goto SNOVA_10 ; Если 0 (частотомер выключен), то смена
; режима не производится.
bcf Trig,0 ; Если 1 (частотомер включен),
; то установка режима ЗАЩИТА ВЫКЛЮЧЕНА
call WR_TRIG ; и запись признака этого режима (0) в EEPROM.

goto SNOVA_10 ; Переход на следующий внутренний цикл.

;################################################################################
; НИЖНЯЯ "ОБСЛУГА" 2-й СТРАНИЦЫ.
;################################################################################
......................................
......................................
Организован/"прописан" регистр общего назначения Temp_F.
В его бит №0 записывается признак включения (1) или выключения (0) частотомера.
Вопрос: "Почему нельзя организовать флаг (например, в регистре Flag_1)"?
Ответ: потому, что нужно энергонезависимо запомнить признак включения или
выключения частотомера.
Еще конкретнее: в ячейку EEPROM-памяти нельзя записать отдельный бит.
В нее можно записать только байт. Целиком. Без вариантов.
Это и есть мотивация.
Естественно, что с учетом сказанного, в ПП START, нужно считать, в регистр Temp_F,
байт признака включения/выключения частотомера, а иначе как понять, был ли (на
момент предыдущего выключения питания устройства) частотомер включен или
выключен?
Вот и получается:
......................................
......................................
START
......................................

8
......................................
;ОООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООО
; Идентификация электрического подключения термодатчика.
;ОООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООО
bsf PCLATH,3 ; Выбор текущего блока 2-й страницы.
call DQ_INIT ; Переход в ПП инициализации термодатчика.
;--------------------------------------------------------------------------------
; Чтение, из EEPROM, байта указателя программного
; включения/выключения термодатчика.
;--------------------------------------------------------------------------------
call READ_V_O ; Реализация оного (результат -> Temp_3).
;--------------------------------------------------------------------------------
; Чтение, из EEPROM, байта указателя включения/выключения частотомера.
;--------------------------------------------------------------------------------
call READ_F ; Реализация оного (результат -> Temp_F).
;================================================================================
; Вывод на индикацию, в 1-ю строку, фиксированной надписи " Термодатчик ".
;================================================================================
movlw high TEXT_19; Выбор
movwf PCLATH ; 2-го блока 1-й страницы.
......................................
......................................
;22222222222222222222222222222222222222222222222222222222222222222222222222222222
; 2-я СТРАНИЦА ПАМЯТИ ПРОГРАММ.
;################################################################################
......................................
......................................
;================================================================================
; ПП чтения, из EEPROM, байта указателя включения/выключения частотомера.
;================================================================================
READ_F bsf Status,RP1 ; Переход
bcf Status,RP0 ; во 2-й банк.
movlw 7 ; Выбор ячейки EEPROM с адресом 07h.
call READ ; Переход в элемент ПП чтения.
movwf Temp_F ; Считывание байта, из выбранной ячейки,
; в регистр Temp_F.
bcf Status,RP1 ; Переход в 0-й банк.
return ; Возврат по стеку.
;================================================================================
......................................
......................................
Итак, буду считать, что на момент начала исполнения программы, в бите №0 байта
регистра Temp_F, "лежит" признак включения/выключения частотомера.
В начале ПП FREG, производится чтение байта признака включения/выключения
частотомера (call READ_F).
В принципе, это не обязательно (команду call READ_F можно убрать), так как такое
чтение было произведено в ПП START (на 1-м "витке" полного цикла программы), а в
дальнейшем (от 2-го "витка" и далее), признак включения/выключения частотомера, в
любом случае, оперативно запоминается в регистре Temp_F.
Но я посчитал более надежным считать признак включения/выключения частотомера из
EEPROM-памяти, нежели "уповать" на оперативную память.
От этого на душе спокойнее (она у меня очень привередливая).
Далее, происходит ровным счетом то же самое, что и в случае отработки пункта меню
включения/выключения термодатчика, только работа происходит не с указателем
включения/выключения термодатчика, а с указателем включения/выключения
частотомера (Temp_F), и признак включения/выключения частотомера записывается в
"свою, персональную" ячейку EEPROM-памяти (адрес 07h).
Примечание: после "прошивки" ПИКа, в эту ячейку, по умолчанию, записывается ноль
(частотомер выключен).
В самом конце ПП FREG (после завершения записи, в EEPROM, признака
включения/выключения частотомера), производится анализ текущего состояния указателя
включения/выключения частотомера (btfss Temp_F,0).

9
Если обнаруживается включение частотомера (Temp_F=1), то устройство
"принудительно" подготавливается к переходу в режим ЗАЩИТА ВЫКЛЮЧЕНА
(bcf Trig,0) и признак этого режима записывается в EEPROM-память (call WR_TRIG).
В дальнейшем, после нажатия/отжатия кнопки Переключение режимов, а также и после
выключения/включения питания устройства, будет отрабатываться режим ЗАЩИТА
ВЫКЛЮЧЕНА (без отработки сценария-подсказки).
Если обнаруживается выключение частотомера, то текущий режим не изменяется и в
дальнейшем, после нажатия/отжатия кнопки Переключение режимов, будет
полномасштабно отрабатываться тот основной режим, из которого вызывалось меню
установки порогов.
Еще раз ладушки (можно еще раз дунуть в фанфары).
"Менюшные дела сделаны".
"В сухом осадке", имеют место быть 2 сценария: частотомер включен и
частотомер выключен.
"Рулилкой" этих сценариев является бит №0 регистра Temp_F.
Предположим, что процедура измерения частоты имеется, и она работает так, что не
нарадуешься.
Вопрос: "Куда ее "засунуть"?
Ответ: лучше всего ее "засунуть" на 2-ю страницу памяти программ.
"Места там полно" и "ефрейторский суперзазорище цветет и пахнет".
Авось в дальнейшем пригодится. "Голубые дали" никто не отменял.
Примечание: с точки зрения "человека-калькулятора", сказанное есть идиотизм/маразм.
Эта точка зрения является его архибедой. "Такой солдат никогда не станет хорошим
(а не абы каким) генералом". По той причине, что подсознание не "включено в работу".
Это не мой (надеюсь, что и не Ваш) путь. Он безумно скучен и неказист.
Немного отвлекся (всякие мысли в голову приходят. Иногда в самый неподходящий
момент. Прошу прощения, если ими "достал").
Продолжаю в соответствующем духе (это не для "калькуляторов", а для… Домыслите
сами).
"Матка" сценария ЗАЩИТА ВЫКЛЮЧЕНА, в которой нужно организовать будущую
"свистопляску", "дислоцируется" на 1-й странице памяти программ.
В ней, в зависимости от того, включен частотомер или выключен, нужно организовать
соответствующие обходы.
Я это сделал так:
......................................
......................................
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
; Сценарий "ЗАЩИТА ВЫКЛЮЧЕНА". VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
......................................
......................................
;--------------------------------------------------------------------------------
; Опрос флага наличия/отсутствия термодатчика.
;--------------------------------------------------------------------------------
btfss Flag,1 ; Флаг наличия/отсутствия термодатчика
; поднят или нет ?
goto RABOTA_D ; Если термодатчик подключен, то переход
; в ПП RABOTA_D.
; Если термодатчик отключен, то программа
; исполняется далее.
;--------------------------------------------------------------------------------
; Проверка включения/выключения частотомера.
;--------------------------------------------------------------------------------
btfss Temp_F,0 ; Частотомер включен или выключен ?
goto OBHOD_7 ; Если выключен, то частота не замеряется и
; сценарий-подсказка №2 исполняется.
bsf PCLATH,3 ; Если включен, то выбор 2-й страницы PC.
call ZAMER_F ; Переход в процедуру измерения частоты.
clrf PCLATH ; Установка 1-го блока 1-й страницы.

goto YES_VIKL ; Переход в рабочий цикл без отработки


; сценария-подсказки №2.
10
;--------------------------------------------------------------------------------
; Опрос флага факта нажатия кнопки.
;--------------------------------------------------------------------------------
OBHOD_7 btfsc Flag,2 ; Флаг факта нажатия кнопки поднят или опущен?
goto YES_VIKL ; Если поднят, то обход сценария-подсказки.
bcf PortA,2 ; Если опущен, то ТРАНЗИСТОР ЗАКРЫВАЕТСЯ и
; отрабатывается сценарий-подсказка №2.
;********************************************************************************
; Начало сценария-подсказки №2
;********************************************************************************
......................................
......................................
YES_VKL
......................................
......................................
;********************************************************************************
; Начало рабочего сценария выключенной защиты.
;********************************************************************************
YES_VIKL
......................................
......................................
;--------------------------------------------------------------------------------
; Опрос флага наличия/отсутствия термодатчика.
;--------------------------------------------------------------------------------
btfss Flag,1 ; Флаг наличия/отсутствия термодатчика
; поднят или нет ?
goto RABOTA_D ; Если термодатчик включен, то переход
; в ПП RABOTA_D.
; Если термодатчик выключен, то программа
; исполняется далее.
;--------------------------------------------------------------------------------
; Проверка включения/выключения частотомера.
;--------------------------------------------------------------------------------
btfss Temp_F,0 ; Частотомер включен или выключен ?
goto OBHOD_8 ; Если выключен, то вывод на индикацию
; надписи ЗАЩИТА ВЫКЛЮЧЕНА.
; Если включен, то уничтожение надписи t=..
; (вместо нее, "пробелы").
movlw b'10001100' ; Установка курсора в 13 знакоместо.
call ENTER_BF ;
movlw 20h ; Запись в W символа "пробел".
bsf PortC,RS ; RS=1
call ENTER_BF ; "Плавающая" задержка со стробом.
movlw 20h ; Запись в W символа "пробел".
bsf PortC,RS ; RS=1
call ENTER_BF ; "Плавающая" задержка со стробом.
movlw 20h ; Запись в W символа "пробел".
bsf PortC,RS ; RS=1
call ENTER_BF ; "Плавающая" задержка со стробом.

goto OBHOD_D ; Обход работы с датчиком.


;================================================================================
; Вывод на индикацию, в 1-ю строку, фиксированной надписи "ЗАЩИТА ВЫКЛЮЧЕНА".
;================================================================================
OBHOD_8 movlw b'10000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 1-й строки.
movlw .16 ; Запись числа .16 (количества выводимых в
movwf Count ; строку символов) в регистр Count.
movf Count,W ; Count -> W.
sublw .16 ; .16 - Count = ... (результат -> W).
call TEXT_1 ; Условный переход в ПП TEXT_1.
call SIMVOL_T ; Вывод символа на индикацию.
decfsz Count,F ; Подготовка к выводу на индикацию
; следующего символа таблицы.
goto $-5 ; Если результат декремента не=0, то
; вывод на индикацию следующего символа.
11
goto OBHOD_D ; Если результат декремента =0,
; то обход работы с датчиком.
;--------------------------------------------------------------------------------
; Проверка включения/выключения частотомера.
;--------------------------------------------------------------------------------
RABOTA_D btfss Temp_F,0 ; Частотомер включен или выключен ?
goto OBHOD_9 ; Если выключен, то вывод на индикацию надписи
; ЗАЩИТА ВЫКЛ.t=
;--------------------------------------------------------------------------------
; Вместо надписи "t=" на индикацию выводится " t"
;--------------------------------------------------------------------------------
movlw b'10001100' ; Установка курсора в 13 знакоместо.
call ENTER_BF ;
movlw 20h ; Запись в W символа "пробел".
bsf PortC,RS ; RS=1
call ENTER_BF ; "Плавающая" задержка со стробом.
movlw 74h ; Запись в W символа "t".
bsf PortC,RS ; RS=1
call ENTER_BF ; "Плавающая" задержка со стробом.
goto OBHOD_10 ; Обход вывода на индикацию надписи
; ЗАЩИТА ВЫКЛ.t=
;================================================================================
; Вывод на индикацию, в 1-ю строку, фиксированной надписи "ЗАЩИТА ВЫКЛ.t= ".
;================================================================================
OBHOD_9 movlw high TEXT_1_1; Выбор PCH 1-й команды ПП TEXT_1_1.
movwf PCLATH ; (находится в 3-м блоке 1-й страницы).
movlw b'10000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 1-й строки.
movlw .14 ;
movwf Count ;
movf Count,W ;
sublw .14 ; Аналогично, только
call TEXT_1_1 ; для TEXT_1_1.
call SIMVOL_T ; Вывод символа на индикацию.
decfsz Count,F ;
goto $-5 ;
;-------------------------------------
; Подготовка к 2/10 преобразованию.
;-------------------------------------
OBHOD_10
......................................
......................................
;********************************************************************************
; Начало сценария-подсказки №4.
;********************************************************************************
OBHOD_D
......................................
......................................
Дополнительные команды (по отношению к программе BP_MOD_1.asm) выделены
красным цветом.
Возможные сценарии:

1. Если частотомер выключен в настройках (в меню установки порогов), то работа


происходит так, как описано в подразделе 2/2/23 2-й части "Практикума…".

2. Если частотомер включен, то:


а) Если термодатчик подключен, то в соответствии со сказанным выше, вместо
надписи t=, на индикацию выводится надпись .t (точка это символ "пусто").
Правее .t на индикацию выводится значение текущей температуры.
Левее .t на индикацию выводится текущее значение частоты.
Получается
ХХ ХХХ ХХХгц tхх
ХХ ХХХ ХХХ - частота, хх - температура.

12
б) Если термодатчик отключен, то символы температуры "уничтожаются" посредством
вывода на индикацию символов "пусто".
Получается
ХХ ХХХ ХХХгц
ХХ ХХХ ХХХ - частота.

Итак, в надписях "порядок навел".


Перехожу к "сердцевине" (к процедуре измерения частоты).
Она выглядит так:
......................................
......................................
;********************************************************************************
; Процедура измерения частоты.
;********************************************************************************
; Подготовительные операции.
;--------------------------------------------------------------------------------
ZAMER_F movlw .38 ; Запись констант
movwf Reg_1 ; в счетчик,
movlw .120 ; который формирует
movwf Reg_2 ; интервал времени
movlw .4 ; измерения.
movwf Reg_3 ; -----"-----

clrf TimerH ; Сброс в 0 регистра TimerH.


clrf TimerHH ; Сброс в 0 регистра TimerHH.
clrf Tmr0 ; Сброс в 0 регистра TMR0.

bsf Status,RP0 ; Переход в 1-й банк.


movlw b'00100111' ; Предделитель с Кдел.=256 подключен к TMR0,
movwf OptionR ; выбор внешнего тактового сигнала с вывода
; RA4/TOCK1, приращение TMR0 по переднему
; фронту.
;--------------------------------------------------------------------------------
; Начало счета на метке "On".
;--------------------------------------------------------------------------------
On bsf TrisA,3 ; Разблокировка счетного входа, начало счета.
bcf Status,RP0 ; Переход в 0-й банк.
;--------------------------------------------------------------------------------
; Проверка TMR0 на переполнение №1 (заполнение старшего байта счетчика частоты
; TimerH, и в случае его переполнения, самого старшего байта счетчика частоты
; TimerHH).
; Сценарии проверки флага T0IF выровнены. Любой из них исполняется
; за 0,2мкс.х8=1,6мкс.
;--------------------------------------------------------------------------------
CYCLE btfss IntCon,2 ; TMR0 переполнен или нет?
goto DO_NOTHING ; Нет - переход на DO_NOTHING.

incfsz TimerH,F ; Да - инкремент TimerH, и, если TimerH не


goto RESET ; переполнен, то переход на метку RESET.

incf TimerHH,F ; Если TimerH переполнен,


; то инкремент TimerHH.
RESET bcf IntCon,2 ; Сброс флага переполнения TMR0.
goto O_K ; Переход в ПП O_K.

DO_NOTHING goto $+1 ; Выравнивающая задержка


goto $+1 ; величиной
nop ; 2х2+1=5 м.ц.
;--------------------------------------------------------------------------------
; Формирование значения интервала времени измерения.
;--------------------------------------------------------------------------------
O_K decfsz Reg_1,F ; --------"---------
goto CYCLE ; --------"---------
; Трехбайтный вычитающий
decfsz Reg_2,F ; счетчик.
13
goto CYCLE ; --------"---------
; --------"---------
decfsz Reg_3,F ; --------"---------
goto CYCLE ; --------"---------
goto $+1 ; "Доводка до
goto $+1 ; нормы" (4 м.ц.)
;--------------------------------------------------------------------------------
; Конец счета на метке Off
; (от метки On, до метки Off, 2500000м.ц. х 0,2мкс.=500000мкс.).
;--------------------------------------------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
Off bcf TrisA,3 ; Ноль на выходе защелки вывода RA3
; блокирует счетный вход (конец счета).
bcf Status,RP0 ; Переход в 0-й банк.
;--------------------------------------------------------------------------------
; Проверка TMR0 на переполнение №2.
;--------------------------------------------------------------------------------
btfss IntCon,2 ; TMR0 переполнен?
goto $+4 ; Если нет, то выход из проверки.
incfsz TimerH,F ; Если да, то TimerH + 1 = ...
; Результат =0 или не=0 ?
goto $+2 ; Если не=0, то выход из проверки.
incf TimerHH,F ; Если =0, то TimerHH + 1 = ...
;-------------------------------------------------
; Копирование содержимого регистра TMR0 в регистр
; TimerM и сброс в 0 содержимого регистра TimerL.
;-------------------------------------------------
movf Tmr0,W ;
movwf TimerM ; TMR0 -> TimerM
clrf TimerL ; TimerL=0
;================================================================================
; Подпрограмма досчета.
;================================================================================
; Формирование импульса на счетном входе.
;----------------------------------------
COUNT_IT bsf Status,RP0 ; Выбор 1-го банка.
bsf OptionR,T0SE; Смена уровня.
call PAUSE_1MKS1 ; Задержка 1 мкс.
bcf OptionR,T0SE; Смена уровня.
bcf Status,RP0 ; Выбор 0-го банка.
;-----------------------------------------
; Досчет.
;-----------------------------------------
decf TimerL,F ; TimerL - 1 = ... (результат в TimerL).
movf Tmr0,W ; TMR0 -> W
xorwf TimerM,W ; "Исключающее ИЛИ" (проверка на одинаковость)
; TimerM и TMR0 (результат в W).
btfsc Status,Z ; Результат =0 или не=0 ?
goto COUNT_IT ; Если =0, то всё по новой.
; Если не=0, то выход из процедуры досчета.
;--------------------------------------------------------------------------------
; Умножение результата измерения на 2.
;--------------------------------------------------------------------------------
bcf Status,C ; C=0
rlf TimerL,F ; Циклический сдвиг влево 4-байтного числа,
rlf TimerM,F ; записанного в группе регистров
rlf TimerH,F ; TimerL/TimerM/TimerH/TimerHH, на одну
rlf TimerHH,F ; позицию через бит С регистра Status.
;********************************************************************************
; Процедура двоично-десятичного преобразования.
;********************************************************************************
BIN2_10_F ;(просто метка для ориентации. Эта ПП не вызывается).
bcf Status,C ; Сброс флага переноса-заема.
movlw .32 ; "Закладка" в регистр Count числа проходов
movwf Count ; преобразования, равного суммарному
; количеству разрядов счетчика частоты.
14
clrf LED0_F ; Сброс регистра LED0_F.
clrf LED1_F ; ------"------ LED1_F.
clrf LED2_F ; ------"------ LED2_F.
clrf LED3_F ; ------"------ LED3_F.
;--------------------------------------------------------------------------------
; Циклический сдвиг влево через бит С регистра Status.
;--------------------------------------------------------------------------------
LOOP_16 rlf TimerL,F ; Циклический сдвиг влево 4-байтного числа,
rlf TimerM,F ; записанного в группе регистров
rlf TimerH,F ; TimerL/TimerM/TimerH/TimerHH, на одну
rlf TimerHH,F ; позицию через бит С регистра Status.

rlf LED0_F,F ; Циклический сдвиг влево 4-байтного числа,


rlf LED1_F,F ; записанного в группе регистров
rlf LED2_F,F ; LED0_F/LED1_F/LED2_F/LED3_F, на одну позицию
rlf LED3_F,F ; через бит С регистра Status.

decfsz Count,F ; Декремент содержимого регистра Count с


; сохранением результата в нем же.
goto adjDEC ; Если результат не = 0, то переход в ПП
; adjDEC, а если = 0, то программа исполняется
; далее.
;--------------------------------------------------------------------------------
; Порязрядное распределение полубайтов регистров LED0_F...3_F
; по младшим полубайтам регистров LED0_F...7_F.
;--------------------------------------------------------------------------------
swapf LED3_F,W ; Запись старшего полубайта LED3_F
andlw 0Fh ; в младший полубайт LED7_F
movwf LED7_F ; -------------------------------

movfw LED3_F ; Запись младшего полубайта LED3_F


andlw 0Fh ; в младший полубайт LED6_F
movwf LED6_F ; -------------------------------

swapf LED2_F,W ; Запись старшего полубайта LED2_F


andlw 0Fh ; в младший полубайт LED5_F
movwf LED5_F ; -------------------------------

movfw LED2_F ; Запись младшего полубайта LED2_F


andlw 0Fh ; в младший полубайт LED4_F
movwf LED4_F ; -------------------------------

swapf LED1_F,W ; Запись старшего полубайта LED1_F


andlw 0Fh ; в младший полубайт LED3_F
movwf LED3_F ; -------------------------------

movfw LED1_F ; Запись младшего полубайта LED1_F


andlw 0Fh ; в младший полубайт LED2_F
movwf LED2_F ; -------------------------------

swapf LED0_F,W ; Запись старшего полубайта LED0_F


andlw 0Fh ; в младший полубайт LED1_F
movwf LED1_F ; -------------------------------

movfw LED0_F ; Запись младшего полубайта LED0_F


andlw 0Fh ; в младший полубайт LED0_F
movwf LED0_F ; -------------------------------

goto PREOBR_K ; Переход на кодовое преобразование.


;--------------------------------------------------------------------------------
; Запись в регистр FSR адресов регистров LED0_F...3_F для дальнейшей косвенной
; адресации к ним в ПП adjBCD.
; Переход к обработке следующего LED - после возврата по стеку.
;--------------------------------------------------------------------------------
adjDEC movlw LED0_F ; Запись в регистр FSR адреса регистра LED0_F
movwf FSR ; с дальнейшим переходом в ПП adjBCD.
15
call adjBCD ;

movlw LED1_F ; То же самое для регистра LED1_F.


movwf FSR ;
call adjBCD ;

movlw LED2_F ; То же самое для регистра LED2_F.


movwf FSR ;
call adjBCD ;

movlw LED3_F ; То же самое для регистра LED3_F.


movwf FSR ;
call adjBCD ;

goto LOOP_16 ; Переход на следующее кольцо числовых


; преобразований.
;--------------------------------------------------------------------------------
; Основные операции преобразования двоичных чисел в двоично-десятичные.
;--------------------------------------------------------------------------------
adjBCD movlw 3 ; Суммирование содержимого текущего LED
addwf 0,W ; (LED0_F...3_F) с числом 03h, с записью
movwf Mem ; результата операции, через регистр W,
; в регистр Mem.
btfsc Mem,3 ; Анализ состояния бита №3 регистра Mem.
movwf 0 ; Если бит №3 = 1, то содержимое регистра Mem
; копируется в текущий LED.
movlw 30 ; Если бит №3 = 0, то содержимое текущего LED
addwf 0,W ; складывается с константой 30h, с записью
movwf Mem ; результата операции, через регистр W,
; в регистр Mem.
btfsc Mem,7 ; Анализ состояние бита №7 регистра Mem.
movwf 0 ; Если бит №7 = 1, то содержимое регистра Mem
; копируется в текущий LED.
retlw 0 ; Если бит №7 = 0, то регистр W очищается и
; происходит возврат по стеку в ПП adjDEC.
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
; Процедура преобразования кода.
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
PREOBR_K movlw 30h ; Запись в регистр W числа 30h.
iorwf LED0_F,F ; Логическое "ИЛИ" содержимого регистра W и
; регистра LED0_F, с сохранением результата
; в нем же.
iorwf LED1_F,F ; То же самое для LED1_F.
iorwf LED2_F,F ; -------"------- LED2_F.
iorwf LED3_F,F ; -------"------- LED3_F.
iorwf LED4_F,F ; -------"------- LED4_F.
iorwf LED5_F,F ; -------"------- LED5_F.
iorwf LED6_F,F ; -------"------- LED6_F.
iorwf LED7_F,F ; -------"------- LED7_F.
;GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
; Процедура гашения незначащих нулей во всех разрядах, кроме младшего.
;GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
movlw .7 ; Запись количества проверяемых разрядов
movwf Total ; (8-1=7)в указатель разрядов Total.
;----------------------------------------------------------
; Косвенная адресация к содержимому текущих LED .
;----------------------------------------------------------
movlw LED7_F ; Стандартная процедура косвенной адресации с
movwf FSR ; "переправкой" содержимого регистра, сначала,
; LED7_F, а затем и всех остальных текущих LED
; (6_F...0_F) в регистр W.
SNOVA_0 movlw 30h ; Запись числа 30h в регистр W.
subwf IndF,W ; Вычесть из данных регистра с адресом в FSR
; (из содержимого текущего LED) число 30h,
; с сохранением результата в W.
;-------------------------------------
16
; 1-я проверка на нулевой результат.
;-------------------------------------
btfss Status,Z ; Проверка состояния флага Z.
goto DISPLAY_F ; Если содержимое W не=0, то выход из
; процедуры (goto DISPLAY_F).
movlw 20h ; Если содержимое W =0, то запись символа
movwf IndF ; "пробел" в регистр с адресом в FSR
; (в текущий LED).
;-------------------------------------
; Переход на следующий, текущий LED.
;-------------------------------------
decf FSR,F ; Уменьшение адреса текущего LED на 1.
decf Total,F ; Уменьшение содержимого указателя
; разрядов на 1.
;-------------------------------------
; 2-я проверка на нулевой результат.
;-------------------------------------
btfss Status,Z ; Проверка состояния флага Z.
goto SNOVA_0 ; Если содержимое Total не=0, то переход на
; повторную проверку на незначащие нули.
;********************************************************************************
; Вывод результатов измерения частоты в 1-ю строку.
;********************************************************************************
DISPLAY_F movlw b'10000000' ; Вывод на индикацию начинается
; с крайнего левого знакоместа.
call ENTER_BF_1 ; "Плавающая" задержка со стробом.

movf LED7_F,W ; LED7_F -> W


bsf PortC,RS ; RS=1
call ENTER_BF_1 ; "Плавающая" задержка со стробом.

movf LED6_F,W ; LED6_F -> W


bsf PortC,RS ; -----"-----
call ENTER_BF_1 ; -----"-----

movlw 20h ; Запись в W символа "пусто".


bsf PortC,RS ; -----"-----
call ENTER_BF_1 ; -----"-----

movf LED5_F,W ; LED5_F -> W


bsf PortC,RS ; -----"-----
call ENTER_BF_1 ; -----"-----

movf LED4_F,W ; LED4_F -> W


bsf PortC,RS ; -----"-----
call ENTER_BF_1 ; -----"-----

movf LED3_F,W ; LED3_F -> W


bsf PortC,RS ; -----"-----
call ENTER_BF_1 ; -----"-----

movlw 20h ; Запись в W символа "пусто".


bsf PortC,RS ; -----"-----
call ENTER_BF_1 ; -----"-----

movf LED2_F,W ; LED2_F -> W


bsf PortC,RS ; -----"-----
call ENTER_BF_1 ; -----"-----

movf LED1_F,W ; LED1_F -> W


bsf PortC,RS ; -----"-----
call ENTER_BF_1 ; -----"-----

movf LED0_F,W ; LED0_F -> W


bsf PortC,RS ; -----"-----
17
call ENTER_BF_1 ; -----"-----

movlw 0B4h ; Запись в W символа "г".


bsf PortC,RS ; -----"-----
call ENTER_BF_1 ; -----"-----
movlw 0E5h ; Запись в W символа "ц".
bsf PortC,RS ; -----"-----
call ENTER_BF_1 ; -----"-----

return ; Возврат из процедуры измерения частоты.


;################################################################################
; КОНЕЦ НИЖНЕЙ "ОБСЛУГИ" 2-й СТРАНИЦЫ. ##########################################
;################################################################################
end ; Конец программы.

Подготовительные операции "урезаны" за счет того, что на "влёте" в процедуру, имеет


место быть такой "расклад", что часть подготовительных операций просто будет
подтверждать ранее установленные состояния.
Поэтому они просто не нужны.
Так как частотомер имеет достаточно большое количество разрядов, то применена
стандартная ПП 2/10 преобразования.
В этом случае, она наиболее выгодна.
ПП "плавающей" задержки на основе анализа состояния флага занятости BF
выдумывать не нужно, так как она есть (ПП ENTER_BF_1).
В ПП DISPLAY_F, я отказался от косвенной адресации по двум причинам:
- применение косвенной адресации замедляет вывод данных на индикацию
(в данном случае, скорость важна),
- в результат измерения "вклинено" два символа "пусто", что усложняет "конструкцию"
процедуры косвенной адресации.
А вообще, процедура измерения частоты просто банально "передрана из ранее
нарытого" (суть не изменилась).
После этого, мне стало как-то скучновато, и душа, как мустанг, захотела в прерии.
Потакая этой слабости, я "модернизировал" ПП досчета в соответствии со своим
представлением о прериях (см. CD à папка Статьи à папка Статья2 à файл
Статья2_1).
Работает нормально. "Мин нет".
Интервал времени измерения откалибровал ровно под 2500000 м.ц., что соответствует
500000 мкс.
А раз это так, то организована процедура умножения результата измерения частоты на
два:
;--------------------------------------------------------------------------------
; Умножение результата измерения на 2.
;--------------------------------------------------------------------------------
bcf Status,C ; C=0
rlf TimerL,F ; Циклический сдвиг влево 4-байтного числа,
rlf TimerM,F ; записанного в группе регистров
rlf TimerH,F ; TimerL/TimerM/TimerH/TimerHH, на одну
rlf TimerHH,F ; позицию через бит С регистра Status.

Если C=0 (bcf Status,C), то в самый младший разряд результата измерения будут
выводиться четные числа, а если C=1 (bsf Status,C), то нечетные.
Это кому как нравится. Я установил в С ноль.
В любом случае, "шаг" измерения частоты равен двум герцам.
Вот, собственно говоря, и всё.
Остальное стандартно. В том смысле, что "разложено на молекулы" ранее.
Примечание: во избежание теоретически возможного "рака мозга", "через две
ступеньки прыгать" не нужно. Я дружески предупредил.
Ну и последнее.
Для того чтобы свести на нет ошибку первого (после включения питания устройства)
замера частоты, я, в ПП START, заблокировал счетный вход (запрет счета):

18
;================================================================================
START
......................................
......................................
clrf PortA ; Сброс защелок порта А (обеспечение закрытия
; транзистора и блокировки счета).
......................................
......................................
movlw b'11110011' ; RA2 работает на выход, RA3 блокирует счет.
movwf TrisA ; Остальные RA.. работают на вход.
......................................
......................................

Программа BP_F.asm, в которой реализовано сказанное, прилагается

Эту программу можно рассматривать как одну из "дочерей матки" (BP_MOD_1.asm).


Таких "дочерей" может быть несколько.
Это кто во что горазд.
В данном случае, свою задачу я вижу в том, чтобы на практике показать "приемы
микроконтроллерной камасутры" (советую вдуматься в это определение).
Смеяться не нужно. Это сказано на полном серьёзе.
К любви нужно относиться серьёзно. Это совсем не "хи-хи".
И вообще, и в частности.
В нашем деле, без любви, будет полный конфуз и сплошное недоразумение.

Технические характеристики МОДУЛЯ ДЛЯ БЛОКОВ ПИТАНИЯ С ФУНКЦИЕЙ ЧАСТОТОМЕРА

Количество команд программы: 3219 (без учета "ефрейторского суперзазорища").


Программа работает на двух страницах памяти программ.
Программа оптимизирована (командная оптимизация).
Количество "однострочных" надписей: 47.
Основные составные части устройства.
Используется м/контроллер PIC16F873А -I/SP.
Элемент индикации: ЖК-модуль компании МЭЛТ MT-16S2D-2YLG (7-я версия).
Термодатчик: DS1820/18S20 фирмы Dallas.
Кварц: 20 Мгц (1 м.ц. = 0,2 мкс.).
Коммутации нагрузки, которая подключена к блоку питания, осуществляются с
помощью полевого транзистора IRFZN44N, который, в открытом состоянии, имеет
очень малое сопротивление.
Элемент измерения тока: резистор 0,01 ом. (от мультиметра M-830В/DT-830B).
Буферно-усилительный элемент: сдвоенный ОУ LM358N (или ему подобный).
Элемент охлаждения: компьютерный (или иной) вентилятор.
"Пищалка": пъезоизлучатель, обеспечивающий приемлемую громкость.
Виды нагрузок: активная и активо-емкостная.
Величина интервала времени "мягкого" включения нагрузки: задается
пользователем.
Напряжения питания.
- для PIC16F873А -I/SP, ЖК-модуля и термодатчика à 5,12 в. (стабилизированное),
- для м/схемы LM358N à 9 в. (стабилизированное),
- для вентилятора à 12 … 14 в. (стабилизированное или нестабилизированное).
Потребляемый ток.
- по цепи +9 в.: около 1 ма.
- по цепи +5,12 в.: около 30 ма. (зависит от величины тока подсветки ЖК-модуля.
В данном случае, это ток около 20 ма.), плюс ток, потребляемый входным
формирователем.
- по цепи +12 … 14 в. à зависит от применяемого вентилятора.
Наихудшие и наилучшие инерционности срабатывания защит.
Наихудшее время срабатывания защиты по превышению порогов U/I (в
19
комплексе), равно 90 мкс. (округлено в сторону увеличения).
Наилучшее время срабатывания защиты по превышению порога тока, равно 43
мкс. (округлено в сторону увеличения).
Таким образом, в диапазоне от 43 до 90 мкс., в зависимости от момента
возникновения факта превышения порога тока, инерционность срабатывания защиты
по току может быть различной (шаг 0,2 мкс.), но она не выйдет за пределы этого
диапазона по причине того, что весь рабочий цикл режима ЗАЩИТА ВКЛЮЧЕНА
(цикл слежения) находится в "зоне" разрешения прерываний ("провалы" отсутствуют).
Если частотомер выключен
Наихудшее время срабатывания защиты от короткого замыкания, равно 650 мкс.
(округлено в сторону увеличения).
Наилучшее время срабатывания защиты от короткого замыкания, равно 43 мкс.
(округлено в сторону увеличения).
Таким образом, в диапазоне от 43 до 650 мкс., в зависимости от момента
возникновения факта короткого замыкания, инерционность срабатывания КЗ-защиты
может быть различной, но она не выйдет за пределы этого диапазона.
Если частотомер включен
Наихудшее время срабатывания защиты от короткого замыкания, равно
примерно 502 мс.
Наилучшее время срабатывания защиты от короткого замыкания, равно 43 мкс.
(округлено в сторону увеличения).
Таким образом, в диапазоне от 43 мкс. до 502 мс., в зависимости от момента
возникновения факта короткого замыкания, инерционность срабатывания КЗ-защиты
может быть различной, но она не выйдет за пределы этого диапазона.
Нужно учесть, что после включения частотомера, наихудшее время
срабатывания защиты от короткого замыкания значительно увеличивается
(реализован принцип "лучше хотя бы что-то, чем вообще ничего").
Для того чтобы обеспечить более эффективную защиту нагрузки (если она
подключена), нужно либо перейти в режим ЗАЩИТА ВКЛЮЧЕНА (наилучший
вариант), либо продолжить работу в режиме ЗАЩИТА ВЫКЛЮЧЕНА, но с
выключенным частотомером.
Если нагрузка не подключена, то по причине того, что в этом случае, защищать
нечего, такой проблемы нет.
Инерционность срабатывания термозащиты зависит от инерционности нагрева
того, температура чего контролируется.
Наименьшая инерционность срабатывания термозащиты будет достигнута в случае
наличия надежного и качественного теплового контакта термодатчика (желательно
применение теплопроводной пасты) с непосредственным источником нагрева.
Если частотомер включен, то в наихудшем случае, инерционность срабатывания
термозащиты увеличится примерно на 502 мс.
Диапазоны.
Диапазон измерения напряжения: от 0,1 в. до 99,9 в., с шагом 0,1 в.
Показания выше 99,9 в. блокируются нулями.
Диапазон измерения тока: от 0,01 а. до 9,99 а., с шагом 0,01 а.
Показания выше 9,99 а. блокируются нулями.
Диапазон измерения частоты: от нескольких герц (зависит от входного
формирователя), до верхней "границы" быстродействия предделителя
конкретного ПИКа (как минимум, 30 Мгц. Граница программного быстродействия
гораздо выше границы аппаратного быстродействия примененного ПИКа).
Количество индицируемых десятичных разрядов: 8.
Шаг измерения: 2 гц. (интервал времени измерения равен 500 000 мкс. Двоичный
результат измерения умножается на два).
Диапазон изменения значений порога U: от 0 в. до 99,2 в., с шагом 0,4 в.
Диапазон изменения значений порога I: от 0 а. до 9,92 а., с шагом 0,04 а.
После достижения нулевых значений порогов, все действия, направленные на
дальнейшее их уменьшение, блокируются.
После достижения максимальных значений порогов, происходит работа по кольцу.
Диапазон изменения значений нижнего температурного порога: от 30 градусов

20
до 90 градусов, с шагом 1 градус.
Диапазон изменения значений верхнего температурного порога: от 35 градусов
до 95 градусов, с шагом 1 градус.
Все значения верхнего температурного порога, которые превышают значения нижнего
температурного порога менее чем на 5 градусов, автоматически ("принудительно")
фиксируются на уровне Тв. = (Тн. + 5) градусов.
То есть, превышения Tв. над Тн., менее чем на 5 градусов, технически невозможны.
Более - можно.
После достижения минимального значения порогов, все действия, направленные на
дальнейшее их уменьшение, блокируются.
После достижения максимального значения порогов, все действия, направленные на
дальнейшее их увеличение, блокируются.
Диапазон изменения значений КЗ-порога: от 1,0 а. до 9,9 а., с шагом 0,1 а.
После достижения минимального значения КЗ-порога, все действия, направленные на
дальнейшее его уменьшение, блокируются.
После достижения максимального значения КЗ-порога, все действия, направленные
на дальнейшее его увеличение, блокируются.
Функциональность.
Любое изменение функциональности сопровождается надписями, которые отражают
это изменение, а также и подсказками.
После каждого включения питания, производится тест термодатчика на предмет
наличия или отсутствия его электрического подключения.
В зависимости от результатов этого теста, программные процедуры, связанные с
работой термодатчика, либо исполняются (термозащита работает), либо не
исполняются (термозащита не работает).
После окончания теста термодатчика, устройство может работать в одном из двух
основных режимов (ЗАЩИТА ВЫКЛЮЧЕНА и ЗАЩИТА ВКЛЮЧЕНА), с
возможностью "ручного" перехода в меню установки порогов.
В режиме ЗАЩИТА ВЫКЛЮЧЕНА, осуществляются:
- визуальный контроль текущих значений напряжения,
- визуальный контроль текущих значений тока,
- визуальный контроль текущих значений температуры,
- ШИМ-регулирование количества оборотов вентилятора
(в зависимости от температуры),
- защита от перегрева,
- защита от короткого замыкания,
- визуальный контроль текущих значений частоты
(если частотомер включен).
За 3 градуса до срабатывания термозащиты, выдается предупреждение, с визуально-
слуховым указанием количества градусов, оставшихся до срабатывания термозащиты.
После срабатывания термозащиты, на индикацию выводятся текущие значения
температуры и значения обеих термопорогов.
Если, в интервале времени менее 5-ти минут, текущая температура опустится ниже
нижнего температурного порога, происходит авторазблокировка и возврат в режим
ЗАЩИТА ВЫКЛЮЧЕНА.
Блок питания выключается (если используется устройство аварийного отключения БП):
- если сработала защита от короткого замыкания,
- если после срабатывания термозащиты, в течение примерно 5-ти минут,
температура не опустится ниже нижнего температурного порога,
- если после срабатывания термозащиты, температура поднимется более чем
на 3 градуса.
В режиме ЗАЩИТА ВКЛЮЧЕНА, осуществляются:
- визуальный контроль текущих значений напряжения,
- визуальный контроль текущих значений тока,
- защита от превышения порога напряжения,
- защита от превышения порога тока.
После срабатывания защиты по превышению порогов U/I, на индикацию выводится
числовое значение этого превышения с шагом:

21
- для U: 0,4 вольта,
- для I : 0,04 ампера.
Информирующие звуковые сигналы формируются после
- необнаружения электрического или программного подключения
термодатчика,
- срабатывания любого типа защиты,
- приближения к порогу срабатывания термозащиты от 3-х градусов и
менее,
- в случаях изменений числовых значений порогов, задаваемых в первых
трех пунктах меню установки порогов,
Устройство энергонезависимо запоминает:
- текущий режим работы,
- значения текущих порогов напряжения и тока,
- значения нижнего и верхнего температурных порогов,
- значение тока короткого замыкания,
- признак программного включения или выключения термодатчика,
- признак программного включения или выключения частотомера.
После включения питания устройства, эти параметры выставляются автоматически.
После "прошивки" PIC16F873А -I/SP, по умолчанию, выставляются:
- режим ЗАЩИТА ВЫКЛЮЧЕНА,
- порог U = 10,0 в., порог I = 1,00 а.,
- нижний Т-порог = 60 градусов, верхний Т-порог = 80 градусов,
- ток короткого замыкания = 9,9 ампера,
- термодатчик программно включен,
- частотомер программно выключен.
Энергонезависимое запоминание текущего режима работы происходит при каждом
переходе из режима в режим.
Значения остальных параметров пользователь может изменить в меню установки
порогов. При этом они автоматически запоминаются.
В меню установки порогов осуществляются:
- задание значений порогов U/I (защита по превышению порогов U/I),
- задание значений нижнего и верхнего термопорогов (термозащита),
- задание значения КЗ-порога (защита от короткого замыкания),
- программное включение или выключение термодатчика ( если он
электрически подключен),
- программное включение или выключение частотомера,
- возврат из меню в тот основной режим, из которого вызвано меню.
Внутри рабочих циклов обеих основных режимов, пользователь может вручную
отключить нагрузку от блока питания или подключить ее к нему.
Это происходит по "принципу RS-триггера".
Вентилятор.
Имеет место быть ШИМ-регулирование количества оборотов.
После включения питания устройства, вентилятор "разгоняется" до максимального
количества оборотов.
Если термодатчик электрически или программно отключен, то в дальнейшем,
количество оборотов не изменится и будет максимальным (в программе, можно
задать другое их количество).
Если термодатчик электрически и программно подключен, то после "разгона"
вентилятора, количество оборотов уменьшается до значения, определяемого первым
замером температуры.
Этот замер происходит непосредственно перед "влётом" в рабочий цикл любого из
режимов.
В рабочем цикле режима ЗАЩИТА ВКЛЮЧЕНА, количество оборотов и останется
таковым в течение всего времени слежения.
В рабочем цикле режима ЗАЩИТА ВЫКЛЮЧЕНА, количество оборотов вентилятора
будет прямо пропорционально зависеть от текущих значений температуры, которая
периодически замеряется.
В случае срабатывания термозащиты (превышен верхний температурный порог),
вентилятор переводится на максимальное количество оборотов (интенсивное
22
охлаждение).
В случае если в интервале времени менее 5-ти минут, температура опустится ниже
нижнего температурного порога, происходит авторазблокировка, и количество
оборотов вентилятора снова будет зависеть от текущих значений температуры.
Если термодатчик электрически и программно подключен, то в случае срабатывания
защиты от короткого замыкания, количество оборотов зафиксируется на том уровне,
который имел место быть на момент срабатывания этой защиты.

23
"Практикум по конструированию устройств на PIC контроллерах"      http://ikarab.narod.ru       E-mail: karabea@lipetsk.ru

24

Вам также может понравиться