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

2-2/4. Объяснение работы программы черновика №2.

Программа, обслуживающая "железяку", речь о которой шла в предыдущем подразделе,


называется BP_2.asm (прилагается).
Принципиальная схема, с учетом внесенных изменений (см. предыдущий подраздел),
выглядит так:

Перехожу к объяснению работы программы BP_2.asm.

;********************************************************************************
; НАЧАЛО ИСПОЛНЕНИЯ ПРОГРАММЫ.
;********************************************************************************
; Подготовительные операции.
;================================================================================
START bcf Status,RP0 ; Подтверждение установки
bcf Status,RP1 ; 0-го банка.
clrf Flag ; Все флаги сбрасываются.
clrf PortA ; Сброс защелок порта А
; (обеспечение закрытия транзистора).
clrf PortC ; Сброс защелок порта С (RS=0, RW=0, E=0).
clrf PortB ; Сброс защелок порта B.
clrf IntCon ; Запрет всех прерываний.
movlw b'00000100' ; Модуль TMR2 включен с Кдел. предделителя = 1
movwf T2CON ; и Кдел. выходного делителя = 1.
;--------------------------------------------------------------------------------
; Чтение, из EEPROM, байта текущего режима работы ("защита вкл. или выкл.").
;--------------------------------------------------------------------------------
bsf Status,RP1 ; Переход
bcf Status,RP0 ; во 2-й банк.
movlw 0 ; Выбор ячейки EEPROM
movwf EEAdr ; с адресом 00h.
bsf Status,RP0 ; Переход в 3-й банк.
bcf EECon1,7 ; Работа с EEPROM.
bsf EECon1,0 ; Инициализация чтения.
bcf Status,RP0 ; Переход во 2-й банк.
movf EEData,W ; Считывание байта, из выбранной ячейки
movwf Trig ; EEPROM, в "режимный" регистр Trig.
;--------------------------------------------------------------------------------
bcf Status,RP1 ; Переход
bsf Status,RP0 ; в 1-й банк.
bcf OptionR,7 ; Включение подтягивающих R порта В.
1
movlw b'11111011' ; RA2 работает на выход,
movwf TrisA ; а остальные - на вход.
clrf TrisB ; Все выводы порта В работают на выход.
clrf TrisC ; Все выводы порта С работают на выход.
movlw b'10000000' ; Диапазон квантования напряжения от -Vss до
movwf Adcon1 ; + Vdd, все 5 каналов АЦП активны,
; правое выравнивание.
movlw .249 ; Задание периода ухода в
movwf PR2 ; прерывания = 250 мкс. (F = 4 Кгц.).
bcf Status,RP0 ; Переход в 0-й банк.
;================================================================================
; Подпрограмма инициализации ЖКИ модуля.
;================================================================================
........................
........................
;--------------------------------------------------------------------------------
; Предварительное (с глобальным запретом) разрешение прерываний
; по переполнению TMR2.
;--------------------------------------------------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
movlw b'01000000' ; Глобальный запрет прерываний и разрешение
movwf IntCon ; прерываний от периферийных модулей.
movlw b'00000010' ; Разрешение прерываний
movwf PIE1 ; по переполнению TMR2.
bcf Status,RP0 ; Переход в 0-й банк.
........................
........................

Дополнения (по отношению к ПП START программы BP_1.asm) выделены красным


цветом.
Особенности:

1. Все флаги сбрасываются (clrf Flag). Для порядка. Настоящего и будущего: могут
быть задействованы и еще какие-нибудь флаги (так как свободные биты есть).
Обстоятельства разные бывают. Лучше упредить.
2. В соответствии с ранее выработанной стратегией, транзистор закрывается
(clrf PortA). В ноль сбрасываются все защелки, но в данном случае, важен
сброс только защелки вывода RA2. Остальные - "по барабану", так как в
дальнейшем, они будут настроены на работу "на вход".
3. От обеспечения начала отсчета TMR2, от нуля, отказался, так как какого-то
великого смысла в этом нет, ведь речь идет не об одном измерении, а о "пачке"
измерений.
4. В "тело" ПП START, осуществлена "врезка" процедуры Чтения, из EEPROM памяти
данных ПИКа, байта текущего режима работы. "Режимный" байт копируется в
регистр Trig. Далее, по биту №0 этого байта, будет осуществлен программный
переход в режим типа "по умолчанию".
5. К выводам порта В, работающим "на вход", подключаются подтягивающие
резисторы (bcf OptionR,7). Потому, что используется клавиатура без внешней
"подтяжки". Это обязательно нужно сделать, так как по умолчанию, внутренняя
"подтяжка" выключена.
6. Светодиод подключен к выводу RA2. Поэтому, вывод RA2 настраивается на работу
"на выход" (movlw b'11111011' и movwf TrisA). Для обеспечения задуманного,
все остальные выводы порта А должны быть настроены на работу "на вход", что
и имеет место быть.
7. В соответствии со сказанным в предыдущем подразделе, "активируются" все 5
каналов АЦП (movlw b'10000000' и movwf Adcon1).
8. Разрешение прерываний по переполнению TMR2, в ПП START, аннулировано.
(мотивация - см. предыдущий подраздел).

Подпрограмма инициализации ЖК-модуля - без изменений.

2
Сразу же после ее отработки, происходит предварительное разрешение прерываний по
переполнению TMR2.
Это то же самое, что и в программе BP_1.asm, но "перебазированное" в другое
"место" и с глобальным запретом прерываний.
Флаг TMR2IF сбрасывать не стал, так как в условиях наличия "пачек" уходов в
прерывания, практического смысла в этом маловато.
На этом, ПП START заканчивается и начинается цикл программы от 2-го "витка" и
далее. Большой цикл.
Примечание: внутри этого большого цикла, "дислоцируются" его внутренние (малые)
циклы (например, аварийный).
Большой цикл программы начинается с процедуры опроса клавиатуры:
........................
........................
;********************************************************************************
; НАЧАЛО ЦИКЛА ПРОГРАММЫ ОТ 2-го "ВИТКА" И ДАЛЕЕ.
;********************************************************************************
; Опрос клавиатуры.
;================================================================================
INKEY bcf IntCon,7 ; ЗАПРЕТ ПРЕРЫВАНИЙ (так как возможен
; переход с разрешенными прерываниями).
btfsc PortB,0 ; Кнопка "Переключение режимов" нажата
; или отжата ?
goto KNOPKA_NO ; Если отжата, то обход смены режима
; (текущий режим сохраняется).
;-------------------------------------------------------
; Противодребезговая задержка.
;-------------------------------------------------------
call PAUSE_UI ; Переход в ПП PAUSE_UI.
;----> Возврат по стеку из ПП PAUSE_UI.
;-------------------------------------------------------
; Ожидание отжатия клавиатуры ("плавающая" задержка).
;-------------------------------------------------------
btfss PortB,0 ; Кнопка "Переключение режимов" нажата
; или отжата ?
goto $-1 ; Если нажата, то ожидание отжатия.
;-------------------------------------------------------
; Смена режима ("защита вкл./выкл.") на противоположный.
;-------------------------------------------------------
incf Trig,F ; Проще не бывает (можно и decf).
;--------------------------------------------------------------------------------
; Запись измененного значения регистра Trig, в ячейку EEPROM, с адресом 00h.
;--------------------------------------------------------------------------------
bsf Status,RP1 ; Переход
bcf Status,RP0 ; во 2-й банк.
movlw 0 ; Выбор ячейки EEPROM
movwf EEAdr ; с адресом 00h.
movf Trig,W ;
movwf EEData ; Trig -> EEData.
bsf Status,RP0 ; Переход в 3-й банк.
bcf EECon1,7 ; Работа с EEPROM.
bsf EECon1,2 ; Разрешение записи.
movlw 0x55 ; Обязательная
movwf EECon2 ; последовательность
movlw 0xAA ; команд
movwf EECon2 ; записи.
bsf EECon1,1 ; Инициализация записи.
bcf EECon1,2 ; Запрещение записи.
btfsc EECon1,1 ; Запись завершена или нет ?
goto $-1 ; Если не завершена, то "плавающая" задержка.
bcf Status,RP0 ; Если завершена, то
bcf Status,RP1 ; переход в 0-й банк.
;--------------------------------------------------------------------------------
; Если кнопка "Сброс" отжата, а также и после смены режима.
;--------------------------------------------------------------------------------

3
KNOPKA_NO btfsc Trig,0 ; Защита включена или выключена ?
goto Z_VKL ; Если включена (1), то переход
; в сценарий включения защиты.
; Если выключена (0), то переход
; в сценарий выключения защиты.
;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
; Сценарий "ЗАЩИТА ВЫКЛЮЧЕНА".
;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
........................
........................

Процедура опроса клавиатуры организована в полном соответствии с ранее


сформулированным алгоритмом опроса клавиатуры (см. предыдущий подраздел).
На мой взгляд, сие есть наиболее простой и эффективный вариант реализации этого
алгоритма.
Группа команд записи в EEPROM выделена темно-синим цветом.
Обращаю Ваше внимание на то, что "плавающая" задержка, отслеживающая
завершение записи (выделена красным цветом), перемещена из начала процедуры
записи (в даташите, она "дислоцируется" в начале), в ее конец.
Если не сделать этой перестановки, то будет нарушено чтение из EEPROM (оно
производится позднее).
Мотивация: в процедуру чтения из EEPROM, нужно входить с нулевым значением бита
№1 регистра EECon1 (критерий завершенности записи).
Если этот бит не будет сброшен, то с последующим чтением будет большой конфуз
(чтения не будет).
Общее пояснение: я не буду детально "расписывать" все команды.
Имея перед глазами предоставляемые Вам "куски" программы, и соответствующие
блок-схемы предыдущего подраздела, с учетом достаточно подробных комментариев,
Вы вполне можете разобраться с деталями самостоятельно.
Заверяю Вас, что после такой "солидной предартподготовки", которая имела место
быть, каких-то великих проблем с "въездом" не будет.
Нужно только немножко подумать.

Сценарий выключенной защиты:


........................
........................
;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
; Сценарий "ЗАЩИТА ВЫКЛЮЧЕНА".
;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
; Выключение защиты (установка максимальных порогов).
;--------------------------------------------------------------------------------
movlw .255 ; Установка
movwf Porog_U ; максимальных
movwf Porog_I ; порогов.
;================================================================================
; "Добыча" результатов измерения и обеспечение необходимой
; скорости смены показаний.
;================================================================================
bsf IntCon,7 ; РАЗРЕШЕНИЕ ПРЕРЫВАНИЙ.
call PAUSE_UI ; Задержка.
;----> Возврат по стеку из ПП PAUSE_UI.
bcf IntCon,7 ; ЗАПРЕТ ПРЕРЫВАНИЙ.
;================================================================================
; 2/10 преобразование ранее "добытого" результата измерения напряжения и тока.
;================================================================================
call BIN2_10_U ; Вызов ПП 2/10 преобразования
; результата измерения U.
;----> Возврат по стеку из ПП BIN2_10_U.
call BIN2_10_I ; Вызов ПП 2/10 преобразования
; результата измерения I.
;----> Возврат по стеку из ПП BIN2_10_I.
;================================================================================
; Вывод на индикацию, в 1-ю строку, фиксированной надписи "ЗАЩИТА ВЫКЛЮЧЕНА".
4
;================================================================================
movlw b'10000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 1-й строки.
;----> Возврат по стеку из ПП ENTER_BF.
movlw .16 ; Запись числа .16 (количества выводимых в
movwf Count ; строку символов) в регистр Count.
movf Count,W ; Count -> W.
sublw .16 ; .16 - Count = ... (результат -> W).
call TEXT_1 ; Условный переход в ПП TEXT_1.
;----> Возврат по стеку из ПП TEXT_1.
bsf PortC,RS ; Установка на линии RS "1"
; (режим записи данных).
call ENTER_BF ; "Плавающая" задержка со стробом под вывод
; данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.
decfsz Count,F ; Подготовка к выводу на индикацию
; следующего символа таблицы.
goto $-6 ; Если результат декремента не=0, то
; вывод на индикацию следующего символа.
; Если результат декремента =0, то программа
; исполняется далее.
;================================================================================
; Вывод на индикацию, во 2-ю строку, фиксированной надписи
; "U= в I= а" и результатов измерения U/I.
;================================================================================
call DISPLAY_UI ; Вывод на индикацию оного.
;----> Возврат по стеку из ПП DISPLAY_UI.
;--------------------------------------------------------------------------------
; Окончание цикла программы (для сценария "защита выключена").
;--------------------------------------------------------------------------------
bsf PortA,2 ; ОТКРЫТИЕ ИЛИ ПОДТВЕРЖДЕНИЕ ОТКРЫТИЯ
; ТРАНЗИСТОРА.
goto INKEY ; Переход на следующий цикл программы.
;********************************************************************************
........................
........................

Перво-наперво, выставляются максимальные пороги защиты по U и I (выделено


красным цветом).
В переводе с 1-байтного на 2-байтный результат, это соответствует
(255 х 4) + 4 (погрешность) = 1024-м квантовкам (максимум).
Затем, происходит "добыча" результатов измерения (задержка в "зоне" разрешения
прерываний). Выделено темно-синим цветом.
После этого, ничто не мешает "протащить добытое" через сдвоенную процедуру 2/10
преобразования, в которой ничего нового нет (просто "передрана" из программы
BP_1.asm).
Общее замечание: здесь и далее, те подпрограммы, которые требуются более одного
раза, вынесены в "обслугу" (вызываются командами call).
Далее, следуют "дисплейные дела" (выделено темно-красным цветом), в которых тоже
нет ничего нового.
После этого, на 1-м "витке" этого сценария, транзистор открывается и производится
"закольцовка" на начало опроса клавиатуры (все повторяется снова).
Этим обеспечивается динамика в смене показаний.
От 2-го "витка" и далее, открытие транзистора периодически подтверждается.

Сценарий включенной защиты:


........................
........................
;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
; Сценарий "ЗАЩИТА ВКЛЮЧЕНА".
;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
; Чтение, из EEPROM, текущих порогов U/I.
;================================================================================

5
; Чтение порога U.
;-----------------------------------
Z_VKL bsf Status,RP1 ; Переход
bcf Status,RP0 ; во 2-й банк.

movlw 1 ; Выбор ячейки EEPROM


movwf EEAdr ; с адресом 01h.
bsf Status,RP0 ; Переход в 3-й банк.
bcf EECon1,7 ; Работа с EEPROM.
bsf EECon1,0 ; Инициализация чтения.
bcf Status,RP0 ; Переход во 2-й банк.
movf EEData,W ; Считывание байта из выбранной
movwf Porog_U ; ячейки EEPROM в регистр Porog_U.
;-----------------------------------
; Чтение порога I.
;-----------------------------------
movlw 2 ;
movwf EEAdr ;
bsf Status,RP0 ;
bcf EECon1,7 ; Аналогично, только для
bsf EECon1,0 ; адреса 02h и регистра Porog_I.
bcf Status,RP0 ;
movf EEData,W ;
movwf Porog_I ;

bcf Status,RP1 ; Переход в 0-й банк.


;================================================================================
; Циклическая подпрограмма слежения.
;================================================================================
; "Добыча" результатов измерения и обеспечение необходимой скорости
; смены показаний.
;================================================================================
KOL_MOZALO bsf IntCon,7 ; РАЗРЕШЕНИЕ ПРЕРЫВАНИЙ.
call PAUSE_UI ; Задержка.
;----> Возврат по стеку из ПП PAUSE_UI.
;--------------------------------------------------
; Далее, прерывания не запрещаются (за исключением
; "закольцовки" в аварийном сценарии).
;================================================================================
; Проверка превышения порогов.
;================================================================================
call PROV_U_I ; Переход в ПП проверки превышения/нет порогов
;----> Возврат по стеку из ПП PROV_U_I.
;================================================================================
; 2/10 преобразование ранее "добытого" результата измерения напряжения и тока.
;================================================================================
call BIN2_10_U ; Вызов ПП 2/10 преобразования
; результата измерения U.
;----> Возврат по стеку из ПП BIN2_10_U.
call BIN2_10_I ; Вызов ПП 2/10 преобразования
; результата измерения I.
;----> Возврат по стеку из ПП BIN2_10_I.
;================================================================================
; Вывод на индикацию, во 1-ю строку, фиксированной надписи " РЕЖИМ СЛЕЖЕНИЯ ".
;================================================================================
movlw b'10000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 1-й строки.
movlw .16 ;
movwf Count ;
movf Count,W ;
sublw .16 ; Аналогично, только
call TEXT_4 ; для TEXT_4.
bsf PortC,RS ;
call ENTER_BF ;
decfsz Count,F ;
goto $-6 ;
6
;================================================================================
; Вывод на индикацию, во 2-ю строку, фиксированной надписи
; "U= в I= а" и результатов измерения U/I.
;================================================================================
call DISPLAY_UI ; Вывод на индикацию оного.
;----> Возврат по стеку из ПП DISPLAY_UI.
;================================================================================
; Проверка состояния кнопки "Переключение режимов".
;--------------------------------------------------------------------------------
btfss PortB,0 ; Кнопка "Переключение режимов" нажата
; или отжата ?
goto INKEY ; Если нажата, то переход на опрос клавиатуры.
; Если отжата, то программа исполняется далее.
;--------------------------------------------------------------------------------
; Окончание цикла программы (для сценария "защита включена").
;--------------------------------------------------------------------------------
bsf PortA,2 ; ОТКРЫТИЕ ИЛИ ПОДТВЕРЖДЕНИЕ ОТКРЫТИЯ
; ТРАНЗИСТОРА.
goto KOL_MOZALO ; Переход на начало следующего цикла слежения.
;********************************************************************************
........................
........................

Сначала, из EEPROM-памяти данных ПИКа, производится чтение значений текущих


порогов (выделено фиолетовым цветом).
В том случае, если произошла смена режима, это чтение уничтожает значения
максимальных порогов (путем записи по верху).
Далее, прерывания по переполнению TMR2 разрешаются на все время отработки
рабочего подрежима режима включенной защиты (без учета цикла большого кольца
проверки).
В данном случае, фиксированная задержка нужна не столько для "добычи" результатов
измерения (хотя и это есть), сколько для обеспечения необходимой скорости смены
показаний.
Изменяя ее "номинал", можно регулировать эту скорость.
Далее, производится проверка на превышение/не превышение порогов
Предположим, что превышения порогов нет.
В этом случае, будет отработано малое кольцо проверки:
........................
........................
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
; ПП ПРОВЕРКИ ПРЕВЫШЕНИЯ/НЕ ПРЕВЫШЕНИЯ ПОРОГОВ.
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
PROV_U_I bsf IntCon,7 ; РАЗРЕШЕНИЕ ПРЕРЫВАНИЙ.
;--------------------------------------------------------------------------------
; Проверка наличия/отсутствия признаков срабатывания защиты
; (малое кольцо проверки).
;--------------------------------------------------------------------------------
btfsc Flag,5 ; Защита по U сработала или нет ?
goto $+4 ; Если сработала, то ПП проверки
; отрабатывается далее.
btfsc Flag,4 ; Если не сработала, то защита по I сработала
; или нет ?
goto $+2 ; Если сработала, то ПП проверки
; отрабатывается далее.
return ; Если защита по U и по I не сработала,
; то возврат по стеку.
........................
........................

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

7
Это обеспечивает строго "метрономный" (с равномерным периодом) уход в прерывания.
После возврата из малого кольца проверки, все то же самое, о чем говорилось выше,
только в 1-ю строку ЖК-модуля выводится другая надпись.
Что касается числовых результатов измерений, то если нет перехода в большое
кольцо аварийного подрежима (если пороги не превышены), они будут точно такими
же, как и в случае выключенной защиты (догадайтесь, почему?).
То есть, при переключениях из режима в режим, если уровень измеряемого
напряжения не "гуляет" (стабилен), во 2-й строке ЖК-модуля ничего не меняется.
Далее, с целью обеспечения возможности переключения режимов, опрашивается
состояние кнопки "Переключение режимов".
С этой целью, "прямолинейно закольцовывать" цикл рабочего подрежима на начало ПП
INKEY (так, как сделано в режиме выключенной защиты) нельзя, так как в ПП INKEY
прерывания запрещаются.
Значит, нужно действовать "криволинейно".
Поэтому и организована проверка состояния кнопки.
Если она отжата, то перехода в ПП INKEY не будет, и цикл рабочего режима
продолжит исполняться "как не в чем не бывало" (выхода из "зоны" разрешения
прерываний не будет).
А если нажата, то и нечего горевать о запрете прерываний, так как режим сменится.
Допустим, что кнопка отжата.
Далее, ничто не мешает открыть транзистор (или подтвердить его открытие) и "уйти"
на начало следующего цикла рабочего подрежима (что такое KOL_MOZALO, я надеюсь,
понятно).
Это можно назвать циклом слежения.

А теперь, для разнообразия, слегка отвлекусь на "политинформацию", ведь "глядеть


нужно дальше и мыслить нужно шире/ширше/ширее" (это кому как нравится).
По большому счету, речь идет о стратегическом принципе конструирования достаточно
обширного класса устройств непрерывного и малоинерционного слежения за "всем, что
шевелится".
При этом, речь идет об обеспечении максимально комфортного и
"информационноемкого" отображения результатов этого слежения.
Причем, без ущерба для инерционности слежения.
В данном случае, "просто и незамысловато" измеряется то, что проще всего измерить.
А теперь вспомните о датчиках.
Существует достаточно большое количество аналоговых датчиков, измеряющих всякие
полезности, результаты работы которых можно привести к уровням напряжения.
Выводы делайте сами.
А я, со спокойной совестью, "поковылял" дальше.
........................
........................
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
; ПП ПРОВЕРКИ ПРЕВЫШЕНИЯ/НЕ ПРЕВЫШЕНИЯ ПОРОГОВ.
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
PROV_U_I bsf IntCon,7 ; РАЗРЕШЕНИЕ ПРЕРЫВАНИЙ.
;--------------------------------------------------------------------------------
; Проверка наличия/отсутствия признаков срабатывания защиты
; (малое кольцо проверки).
;--------------------------------------------------------------------------------
btfsc Flag,5 ; Защита по U сработала или нет ?
goto $+4 ; Если сработала, то ПП проверки
; отрабатывается далее.
btfsc Flag,4 ; Если не сработала, то защита по I сработала
; или нет ?
goto $+2 ; Если сработала, то ПП проверки
; отрабатывается далее.
return ; Если защита по U и по I не сработала,
; то возврат по стеку.
;================================================================================
; "Добыча" результатов измерения и обеспечение
; необходимой скорости смены показаний.

8
;================================================================================
call PAUSE_UI ; Задержка.
;----> Возврат по стеку из ПП PAUSE_UI.
bcf IntCon,7 ; ЗАПРЕТ ПРЕРЫВАНИЙ.
;********************************************************************************
; Работа с порогом защиты по напряжению.
;********************************************************************************
; Вычисление величины превышения порога защиты по напряжению.
;--------------------------------------------------------------------------------
movf Porog_U,W ; Porog_U -> W.
subwf Mem_UL,W ; Mem_UL - Porog_U = ... (Результат -> W).

btfsc Status,C ; Результат вычитания "+"/=0 или "-" ?


goto $+3 ; Если "+"/=0 (порог превышен), то блокировки
; (нулем) результата вычисления нет.
clrf Temp_UL ; Если "-" (порог не превышен), то блокировка
goto $+2 ; (нулем) результата вычисления есть.

movwf Temp_UL ; Копирование разницы в Temp_UL.


clrf Temp_UH ; Temp_UH = 0.
;--------------------------------------------------------------------------------
; Умножение числового значения Temp_UH/Temp_UL на 4.
;--------------------------------------------------------------------------------
bcf Status,C ; C = 0.
rlf Temp_UL,F ; 1-й сдвиг влево содержимого
rlf Temp_UH,F ; Temp_UH/Temp_UL.

bcf Status,C ; C = 0.
rlf Temp_UL,F ; 2-й сдвиг влево содержимого
rlf Temp_UH,F ; Temp_UH/Temp_UL.
;--------------------------------------------------------------
; Результат -> Temp_UH/Temp_UL и готов для 2/10 преобразования.
;********************************************************************************
; Работа с порогом защиты по току.
;********************************************************************************
........................ АНАЛОГИЧНО
........................
;--------------------------------------------------------------
; Результат -> Temp_IH/Temp_IL и готов для 2/10 преобразования.
;================================================================================
; 2/10 преобразование результата превышения порога защиты по напряжению и по току
;================================================================================
call BIN2_10_U ; Вызов ПП 2/10 преобразования
; (работа с результатом измерения напряжения).
;----> Возврат по стеку из ПП BIN2_10_U.
call BIN2_10_I ; Вызов ПП 2/10 преобразования
; (работа с результатом измерения тока).
;----> Возврат по стеку из ПП BIN2_10_I.
;================================================================================
; Вывод на индикацию, во 1-ю строку, фиксированной надписи "Превышение Uп/Iп".
;================================================================================
movlw b'10000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 1-й строки.
movlw .16 ;
movwf Count ;
movf Count,W ;
sublw .16 ; Аналогично, только
call TEXT_3 ; для TEXT_3.
bsf PortC,RS ;
call ENTER_BF ;
decfsz Count,F ;
goto $-6 ;
;================================================================================
; Вывод на индикацию, во 2-ю строку, фиксированной надписи "U= в I= а"
; и результатов вычисления величин превышения порогов защиты по U/I.
;================================================================================
9
call DISPLAY_UI ; Вывод на индикацию оного.
;----> Возврат по стеку из ПП DISPLAY_UI.
;================================================================================
goto PROV_U_I ; Переход на новый цикл проверки
; превышения порогов U/I.
;********************************************************************************
........................
........................
То, что выделено красным цветом, "расписано" выше (малое кольцо проверки).
Если в малом кольце проверки обнаружена "бяка" (хотя бы один из флагов поднялся),
то происходит переход в большое кольцо проверки.
Большое кольцо проверки начинается с "добычи" результатов измерения и обеспечения
необходимой скорости смены показаний.
То есть, все с той же задержки, которая применялась ранее.
После ее отработки, прерывания запрещаются, так как нет смысла "тормозить"
отработку дальнейшего, ведь защита-то сработала ранее ("миссия выполнена").
После этого, без суеты, с толком и расстановкой, производятся действия, конечным
итогом которых является вывод на индикацию значений превышений порогов защиты
по напряжению и по току.
В части касающейся напряжения, определение разницы выглядит так:

;********************************************************************************
; Работа с порогом защиты по напряжению.
;********************************************************************************
; Вычисление величины превышения порога защиты по напряжению.
;--------------------------------------------------------------------------------
movf Porog_U,W ; Porog_U -> W.
subwf Mem_UL,W ; Mem_UL - Porog_U = ... (Результат -> W).

btfsc Status,C ; Результат вычитания "+"/=0 или "-" ?


goto $+3 ; Если "+"/=0 (порог превышен), то блокировки
; (нулем) результата вычисления нет.
clrf Temp_UL ; Если "-" (порог не превышен), то блокировка
goto $+2 ; (нулем) результата вычисления есть.

movwf Temp_UL ; Копирование разницы в Temp_UL.


clrf Temp_UH ; Temp_UH = 0.

В регистре Mem_UL, "лежит" значение текущего измерения напряжения, приведенное к


одному байту.
Естественно, что и числовое значение заданного порога защиты по напряжению нужно
привести к одному байту (см. ПП прерывания).
Например, если нужно выставить этот порог на 52-й квантовке, то в качестве порога
защиты нужно задать число (52 – 4):4 = .12 (0Ch).
В EEPROM-память программы BP_2.asm, записаны именно такие пороги (оба).
Так как имеет место быть вычитание одного байта из одного байта, то в наличии
имеется "святая простота" (subwf).
Далее, проверяется знак результата.

1. Если порог превышен (результат "+"/=0), то разница просто копируется в регистр


Temp_UL.
Вопрос: "Почему именно в регистр Temp_UL"?
Ответ: потому, что нужно видеть дальше собственного носа.
А именно, "глаз ложить" нужно на "дальнейшенеизбежную" ПП 2/10 преобразования.
В ней применяется 2-байтный регистр Temp_UH/Temp_UL.
Temp_UL есть, а "начинку" Temp_UH нужно "симитировать", путем записи в него нуля.
Вот Вам и необходимость применения команды clrf Temp_UH.

2. Если порог не превышен, то и в Temp_UL, и в Temp_UH записываются нули.


Дело в том, что при уходе в аварийный сценарий, например, в случае превышения
порога защиты по току и существенном "принижении", выходным напряжением, порога

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

Далее, следует учесть, что для того чтобы привести результат вычисления к своему
истинному значению, его нужно умножить на 4 (так как ранее, в ПП прерывания,
производилось деление на 4).
Это выглядит так:
;--------------------------------------------------------------------------------
; Умножение числового значения Temp_UH/Temp_UL на 4.
;--------------------------------------------------------------------------------
bcf Status,C ; C = 0.
rlf Temp_UL,F ; 1-й сдвиг влево содержимого
rlf Temp_UH,F ; Temp_UH/Temp_UL.

bcf Status,C ; C = 0.
rlf Temp_UL,F ; 2-й сдвиг влево содержимого
rlf Temp_UH,F ; Temp_UH/Temp_UL.
;--------------------------------------------------------------
; Результат -> Temp_UH/Temp_UL и готов для 2/10 преобразования.

После этого, можно смело "уходить" в ПП 2/10 преобразования.


Примечание: то, о чем шла речь выше, относится и к "токовым делам".
Разница только в названиях регистров.
Далее, следует то, что в очередной раз я повторять не буду.
После этого - "закольцовка" на следующий цикл аварийного сценария, и все
повторяется снова.
Этим и обеспечивается динамика смены показаний.
Такое "на колу мочало" будет продолжаться до тех пор, пока не будет устранено
превышение обеих порогов.
То есть, до тех пор, пока оба флага превышения/не превышения порога защиты не
опустятся.
Как только это произойдет, рабочая точка программы "улетит" (возврат по стеку), из
малого цикла проверки, в цикл рабочего подрежима режима включенной защиты, в
котором и благополучно "закольцуется" (слежение), до момента возникновения текущей
"бяки".
По-моему, осознание сказанного совсем не является "полетом в космос".

Перехожу к ПП прерывания, ведь нужно же выяснить, как именно осуществляются


замеры величин U/I, в контексте ветвления оного на два результата (1-байтный и 2-
байтный):
........................
........................
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; ПОДПРОГРАММА ПРЕРЫВАНИЯ. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; Процедура сохранения содержимого регистров Status и W.
;================================================================================
; Определение банка, из которого осуществлен уход в прерывание.
;--------------------------------------------------------------------------------
btfsc Status,RP0 ; Из какого банка осуществлен уход
; в прерывание ?
goto BANK_1 ; Если это 1-й банк, то переход
; на метку BANK_1.
; Если это 0-й банк, то программа
; исполняется далее.
;--------------------------------------------------------------------------------
; Процедура сохранения Status и W в регистрах 0-го банка (Stat_Temp, W_Temp).
;--------------------------------------------------------------------------------
movwf W_Temp ; W -> W_Temp.
11
swapf Status,W ; Смена п/байтов регистра Status.
; Результат -> W.
movwf Stat_Temp ; W -> Stat_Temp.
bcf Flag,7 ; Сброс флага признака банка
; (Flag,7=0: 0-й банк).
; Используется при восстановлении.
goto ZAMER ; Переход на начало АЦП.
;--------------------------------------------------------------------------------
; Процедура сохранения Status и W в регистрах 1-го банка (Stat_Temp1, W_Temp1).
;--------------------------------------------------------------------------------
BANK_1 movwf W_Temp1 ; W -> W_Temp1.
swapf Status,W ; Смена п/байтов регистра Status.
; Результат -> W.
movwf Stat_Temp1 ; W -> Stat_Temp1.
bcf Status,RP0 ; Установка 0-го банка.
bsf Flag,7 ; Установка флага признака банка
; (Flag,7=1: 1-й банк).
; Используется при восстановлении.
;********************************************************************************
; 1-е АЦП (напряжение). *********************************************************
;********************************************************************************
; Работа с регистром Adcon0.
;--------------------------------------------------------------------------------
ZAMER clrf Mem_IL ; Сброс предыдущего результата превышения тока
; (если ранее таковой имел место быть).
movlw b'01000001' ; Включение модуля АЦП, выбор канала AN0
movwf Adcon0 ; (RA0), источник тактового сигнала Fosc/8,
; состояние ожидания, конденсатор подключен к
; выбранному аналоговому входу и начал
; перезаряжаться.
call PAUSE ; Задержка для перезаряда конденсатора Hold.
;----> Возврат по стеку из ПП PAUSE.
;--------------------------------------------------------------------------------
; Начало аналого-цифрового преобразования.
;--------------------------------------------------------------------------------
bsf Adcon0,GO ; Включение преобразования. Конденсатор
; отключается от аналогового входа на время
; преобразования.
;--------------------------------------------------------------------------------
; Ожидание окончания АЦП ("плавающая" задержка).
;--------------------------------------------------------------------------------
btfsc Adcon0,GO ; Ожидание окончания аналого-цифрового
goto $-1 ; преобразования.
;------------------------------------------------
; 1-е АЦП закончено. Результат - в AdresH/AdresL.
;================================================================================
; Проверка состояния флага разрешения/запрета изменения
; результата измерения, который выводится на индикацию.
;--------------------------------------------------------------------------------
btfsc Flag,6 ; Каково состояние флага ?
goto OBH_1 ; Если поднят (1), то изменения
; Temp_UH/Temp_UL запрещаются.
; Если опущен (0), то изменения
; Temp_UH/Temp_UL разрешаются.
;--------------------------------------------------------------------------------
; Отрабатывается, если изменения Temp_UH/Temp_UL разрешаются.
;--------------------------------------------------------------------------------
movf AdresH,W ; AdresH --> W.
movwf Temp_UH ; W --> Temp_UH (для измерения).
movwf Mem_UH ; W --> Mem_UH (для деления на 4).

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


movf AdresL,W ; AdresL --> W.
bcf Status,RP0 ; Переход в 0-й банк.
movwf Temp_UL ; W --> Temp_UL (для измерения).
movwf Mem_UL ; W --> Mem_UL (для деления на 4).
12
goto POROG_U ; Переход в ПП работы с порогом напряжения.
;--------------------------------------------------------------------------------
; Отрабатывается, если изменения Temp_UH/Temp_UL запрещаются.
;--------------------------------------------------------------------------------
OBH_1 movf AdresH,W ; AdresH --> W.
movwf Mem_UH ; W --> Mem_UH (для деления на 4).

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


movf AdresL,W ; AdresL --> W.
bcf Status,RP0 ; Переход в 0-й банк.
movwf Mem_UL ; W --> Mem_UL (для деления на 4).
;================================================================================
; Приведение 2-байтного результата измерения напряжения к 1-байтному.
;================================================================================
; Деление результата измерения на 4.
;--------------------------------------------------------------------------------
POROG_U rrf Mem_UH,F ; 1-й сдвиг вправо
rrf Mem_UL,F ; на 1 бит.
rrf Mem_UH,F ; 2-й сдвиг вправо
rrf Mem_UL,F ; на 1 бит.
movf Mem_UL,W ; Mem_UL -> W.
;-----------------------------------
; В Mem_UL - результат деления на 4.
;--------------------------------------------------------------------------------
; Проверка на превышение порога.
;--------------------------------------------------------------------------------
bcf Flag,5 ; Сброс флага превышения порога защиты
; по напряжению.
subwf Porog_U,W ; Porog_U - Mem_UL = ... (Результат -> W).
btfsc Status,C ; Результат "+"/=0 или "-" ?
goto ACP_2 ; Если "+"/=0, то переход на 2-е АЦП.
bcf PortA,2 ; Если "-", то блокировка срабатывает и флаг
bsf Flag,5 ; превышения порога защиты, по напряжению,
; поднимается.
goto ACP_END ; Переход в процедуру выхода из прерывания.

;********************************************************************************
; 2-е АЦП (сила тока). **********************************************************
;********************************************************************************
; Работа с регистром Adcon0.
;--------------------------------------------------------------------------------
ACP_2 bsf Adcon0,3 ; Выбор канала AN1 (RA1). Остальные
; настройки Adcon0 не меняются.
call PAUSE ; Аналогично.
;----> Возврат по стеку из ПП PAUSE.
;--------------------------------------------------------------------------------
; Начало аналого-цифрового преобразования.
;--------------------------------------------------------------------------------
bsf Adcon0,GO ; Аналогично.
;--------------------------------------------------------------------------------
; Ожидание окончания АЦП ("плавающая" задержка).
;--------------------------------------------------------------------------------
btfsc Adcon0,GO ; Аналогично.
goto $-1 ; ----"----
;------------------------------------------------
; 2-е АЦП закончено. Результат - в AdresH/AdresL.
;================================================================================
; Проверка состояния флага разрешения/запрета изменения
; результата измерения, который выводится на индикацию.
;--------------------------------------------------------------------------------
btfsc Flag,6 ; Аналогично, только для
goto OBH_2 ; регистров Temp_IH/Temp_IL.
;--------------------------------------------------------------------------------
; Отрабатывается, если изменения Temp_IH/Temp_IL разрешаются.
;--------------------------------------------------------------------------------
13
movf AdresH,W ; ----"----
movwf Temp_IH ; ----"----
movwf Mem_IH ; ----"----
bsf Status,RP0 ; Аналогично, только для
movf AdresL,W ; регистров Temp_IH/Temp_IL
bcf Status,RP0 ; и Mem_IH/Mem_IL.
movwf Temp_IL ; ----"----
movwf Mem_IL ; ----"----
goto POROG_I ; Переход в ПП работы с порогом тока.
;--------------------------------------------------------------------------------
; Отрабатывается, если изменения Temp_IH/Temp_IL запрещаются.
;--------------------------------------------------------------------------------
OBH_2 movf AdresH,W ; ----"----
movwf Mem_IH ; ----"----
bsf Status,RP0 ; Аналогично, только для
movf AdresL,W ; и Mem_IH/Mem_IL.
bcf Status,RP0 ; ----"----
movwf Mem_IL ; ----"----
;================================================================================
; Приведение 2-байтного результата измерения тока к 1-байтному.
;================================================================================
; Деление результата измерения на 4.
;--------------------------------------------------------------------------------
POROG_I rrf Mem_IH,F ; ----"----
rrf Mem_IL,F ; Аналогично, только для
rrf Mem_IH,F ; регистров Mem_IH/Mem_IL.
rrf Mem_IL,F ; ----"----
movf Mem_IL,W ; ----"----
;-----------------------------------
; В Mem_IL - результат деления на 4.
;--------------------------------------------------------------------------------
; Проверка на превышение порога.
;--------------------------------------------------------------------------------
bcf Flag,4 ; Сброс флага превышения порога защиты
; по току.
subwf Porog_I,W ; Аналогично, только
btfsc Status,C ; Porog_I - Mem_IL = ...
goto ACP_END ; ----"----
bcf PortA,2 ; <-В этом случае, блокировка срабатывает и
bsf Flag,4 ; флаг превышения порога защиты, по току,
; поднимается.
;--------------------------------------------------------------------------------
; Теперь модуль АЦП можно выключить (начало выхода из прерывания).
;--------------------------------------------------------------------------------
ACP_END clrf Adcon0 ; Для снижения потребляемого устройством тока,
; модуль АЦП выключается до конца отработки
; текущего полного цикла программы.
;================================================================================
; Процедура восстановления содержимого регистров Status, W
; и выхода из прерывания.
;================================================================================
btfss Flag,7 ; Каково состояние флага признака банка ?
goto VOSST_0 ; Если 0-й банк (Flag,7=0), то работа
; с Stat_Temp и W_Temp.
; Если 1-й банк (Flag,7=1), то работа
; с Stat_Temp1 и W_Temp1.
;--------------------------------------------------------------------------------
; Процедура восстановления Status и W из содержимого регистров 1-го банка
; (Stat_Temp1, W_Temp1).
;--------------------------------------------------------------------------------
bcf PIR1,TMR2IF ; Сброс флага прерывания по переполнению TMR2.

bsf Status,RP0 ; Установка 1-го банка.


swapf Stat_Temp1,W; Обмен п/байтами. Результат -> W.
movwf Status ; W -> Status.
swapf W_Temp1,F ; Обмен п/байтами. Результат -> W_Temp1.
14
swapf W_Temp1,W ; Обмен п/байтами. Результат -> W.
retfie ; Возврат из прерывания с 1-м банком (с 1-м
; банком вошли в прерывание, с 1-м банком
; и вышли).
;--------------------------------------------------------------------------------
; Процедура восстановления Status и W из содержимого регистров 0-го банка
; (Stat_Temp, W_Temp).
;--------------------------------------------------------------------------------
VOSST_0 swapf Stat_Temp,W ; Обмен п/байтами. Результат -> W.
movwf Status ; W -> Status.
swapf W_Temp,F ; Обмен п/байтами. Результат -> W_Temp.
swapf W_Temp,W ; Обмен п/байтами. Результат -> W.

bcf PIR1,TMR2IF ; Сброс флага прерывания по переполнению TMR2.


retfie ; Возврат из прерывания с 0-м банком (с 0-м
; банком вошли в прерывание, с 0-м банком
; и вышли).
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
........................
........................

Темно-синим цветом выделено то, что относится к процедурам


сохранения/восстановления содержимого регистров W и Status.
Красным цветом выделены изменения и дополнения (по отношению к ПП прерывания
программы BP_1.asm).

За основу взята ПП прерывания программы BP_1.asm.


Процедура сохранения/восстановления содержимого регистров W и Status - та же
самая, что и в программе BP_1.asm.
Да и многое другое - тоже.
Откомментирую команды, выделенные красным цветом.
В связи с "вершением", в ПП прерывания, "пороговых дел", организованы две пары
регистров: Mem_UH/Mem_UL (для напряжения) и Mem_IH/Mem_IL (для тока).
"Привяжусь" к измерению напряжения.
В части касающейся Проверки состояния флага разрешения/запрета изменения
результата измерения, который выводится на индикацию, копирование результата АЦП
производится в 2 пары регистров: Temp_UH/Temp_UL и Mem_UH/Mem_UL.
В дальнейшем, регистры Temp_UH/Temp_UL используются в ПП 2/10 преобразования.
С этим, я надеюсь, все ясно (а кому не ясно, см. предыдущие подразделы).
А что такое Mem_UH/Mem_UL ?
Это регистры оперативной памяти процедуры приведения 2-байтного результата
измерения к 1-байтному.
Вопрос: "Зачем приводить 2-байтный результат измерения (результат измерения
является 2-байтным) к 1-байтному"?
Ответ: для того, чтобы минимизировать интервал времени отработки ПП прерывания, и
вообще, "компромиссно облегчить жизнь".
Процедура деления результата измерения на 4 - простейшая:

;================================================================================
; Приведение 2-байтного результата измерения напряжения к 1-байтному.
;================================================================================
; Деление результата измерения на 4.
;--------------------------------------------------------------------------------
POROG_U rrf Mem_UH,F ; 1-й сдвиг вправо
rrf Mem_UL,F ; на 1 бит.
rrf Mem_UH,F ; 2-й сдвиг вправо
rrf Mem_UL,F ; на 1 бит.
movf Mem_UL,W ; Mem_UL -> W.
;------------------------------------
; В Mem_UL - результат деления на 4.

Результат деления "оседает" в регистре Mem_UL.


15
А теперь, вычесть, из значения порога, значение результата измерения, - проще
простого.
При условии, что значение порога есть также однобайтное число:

;--------------------------------------------------------------------------------
; Проверка на превышение порога.
;--------------------------------------------------------------------------------
bcf Flag,5 ; Сброс флага превышения порога защиты
; по напряжению.
subwf Porog_U,W ; Porog_U - Mem_UL = ... (Результат -> W).
btfsc Status,C ; Результат "+"/=0 или "-" ?
goto ACP_2 ; Если "+"/=0, то переход на 2-е АЦП.
bcf PortA,2 ; Если "-", то блокировка срабатывает и флаг
bsf Flag,5 ; превышения порога защиты, по напряжению,
; поднимается.
goto ACP_END ; Переход в процедуру выхода из прерывания.

А теперь обратите внимание на операции с битом №5 регистра Flag.


Это флаг превышения/не превышения порога защиты по напряжению (а по току - бит №4)
Поднятие/"опущение" этого флага есть критерий срабатывания/не срабатывания защиты.
Это необходимо для обеспечения дальнейшего перехода (в "основном теле"
программы), из рабочего подрежима режима включенной защиты (из режима слежения),
в аварийный подрежим режима включенной защиты (если флаг поднялся), а также и
для обратного перехода (если флаг опустился).
При таком "раскладе", речь идет не о "кнопочно-тумблерной" разблокировке, а об
автоматической разблокировке (по напряжению. С током есть специфика).
То есть, после срабатывания защиты и устранения причины, приведшей к блокировке
по превышению порога U (например, путем снижения напряжения), происходит
автоматическая разблокировка.
При этом, ни на что "жать" и ничем "клацать" не нужно, так как железяка сама
решит", когда ей заблокироваться, а когда ей разблокироваться.
После блокировки, в ходе "кусочно-рваной" отработки "основного тела" программы, на
дисплей, в динамике, будет выведен результат превышения порога, с погрешностью в
4 квантовки ("расплата" за однобайтный результат).
Что касается команды,
goto ACP_END ; Переход в процедуру выхода из прерывания.
то она введена по причине здравого смысла.
Зачем, после срабатывания защиты по напряжению, отрабатывать "токовые дела", ведь
нагрузка-то отключилась (зачем замерять нулевой ток?).
Вот я эти "токовые дела" и обошел (в случае срабатывания защиты по напряжению).
Примечание: напряжение будет замеряться не после транзистора, а до него.
То есть, измерения уровней напряжения будут происходить во всех режимах, но в
случае превышения порога срабатывания защиты по напряжению, оно (напряжение)
будет отключено от нагрузки.
Напоминаю, что алгоритм программы "выстроен" так, что если, в момент включения
блока питания, имеет место быть превышение порога защиты по напряжению, то
рабочая точка программы сразу же "закольцуется" в аварийном цикле (нагрузка
отключена от блока питания), а первое включение транзистора (в ПП START он
выключается) возможно только после выхода из этого аварийного цикла, в конце
отработки текущего, рабочего цикла.
Если "бяк" нет, то в дальнейшем, в режиме слежения, открытие транзистора
многократно подтверждается.
Первейшим условием подключения нагрузки к выходу блоку питания, является наличие
уровня напряжения, который ниже порога срабатывания защиты по напряжению.
Только в этом случае возможны дальнейшие "токовые дела".
Вернусь к ПП прерывания.
"Токовые дела делаются" точно так же, как и "напряженческие", только используются
другие пары регистров (Temp_IH/Temp_IL и Mem_IH/ Mem_IL), результат деления на 4
"оседает" в регистре Mem_IL и задействуется бит №4 регистра Flag.

16
Обратите внимание на это:

ZAMER clrf Mem_IL ; Сброс предыдущего результата превышения тока


; (если ранее таковой имел место быть).
Мотивация: при наличии "напряженческой бяки", процедура замера тока обходится.
Это черевато тем, что на момент появления "напряженческой бяки", результат
превышения порога защиты по току (если он имел место быть "до того") надолго
"заторчит"/зафиксируется в дисплее (напоминаю про оперативную память ЖК-модуля).
Даже после того, как "токовая бяка" будет устранена.
Вот я его и "принудительно-упредительно задолбал" нулем (прочитал и ужаснулся, но
по-моему это должно быть доходчивым).
Короче, если превышен порог защиты по напряжению, то ни о каких "токовых делах"
не может быть и речи (по причине обхода), и в части касающейся тока, на индикацию
выведутся нулевые показания.

В конечном итоге, на выходе из прерывания, в "оперативных закромах, будет лежать"


следующее:
- В регистрах Temp_UH/Temp_UL, "осядет" результат измерения текущего
значения напряжения, предназначенный для вывода на индикацию (в режиме
выключенной защиты и в рабочем сценарии режима включенной защиты).
- В регистрах Temp_IH/Temp_IL, "осядет" результат измерения текущего
значения тока, предназначенный для вывода на индикацию (в режиме
выключенной защиты и в рабочем сценарии режима включенной защиты).
- В регистре Mem_UL, "осядет" результат измерения текущего значения
напряжения, (1- байтный результат), предназначенный для вычисления
величины превышения порога защиты по напряжению.
В дальнейшем, результат этого вычисления будет выведен на индикацию
в аварийном сценарии режима включенной защиты,
- В регистре Mem_IL, "осядет" результат измерения текущего значения
тока, (1-байтный результат), предназначенный для вычисления величины
превышения порога защиты по току.
В дальнейшем, результат этого вычисления будет выведен на индикацию
в аварийном сценарии режима включенной защиты.
- В бите №5 регистра Flag, "осядет" признак срабатывания или не
срабатывания защиты по напряжению, который является критерием
выбора рабочего или аварийного сценария режима включенной защиты.
Поднятие этого флага свидетельствует о закрытии транзистора.
- В бите №4 регистра Flag, "осядет" признак срабатывания или не
срабатывания защиты по току, который является критерием выбора
рабочего или аварийного сценария режима включенной защиты.
Поднятие этого флага свидетельствует о закрытии транзистора.

Это и есть то, что "добывается" в ПП прерывания.

Если "токовые дела" обходятся (сработала защита по напряжению), то на индикацию


будет выведено нулевое превышение тока.
После дальнейшего устранения "напряженческой бяки", а равно и в случае, если при
включении блока питания, превышения порога защиты по напряжению нет, будет
осуществлен возврат/переход в цикл рабочего подрежима режима включенной защиты.
В конце отработки рабочего цикла, транзистор откроется.
Если не будет превышения порогов защиты по U и I, то рабочая точка программы
"закольцуется" в цикле рабочего подрежима режима включенной защиты (открытие
транзистора подтверждается), и на индикацию, в динамике, будут выводиться текущие
результаты измерения U/I.

Если же, при отсутствии "напряженческой бяки", произойдет превышение порога защиты
по току, то будет следующее (рассуждаю на теоретическом уровне):
В результате первой же проверки на превышение порога защиты по току (в ПП
прерывания), "бяка" будет обнаружена и транзистор закроется.
17
Ток станет нулевым вплоть до конца отработки "пачки" измерений.
Следовательно, в результате следующих измерений "пачки", превышения порога
защиты по току обнаружено не будет.
На момент окончания "пачки" измерений, будет зафиксировано нулевое значение тока,
флаг превышения/не превышения порога защиты по току будет опущен, а транзистор
закрыт.
А раз это так, то будет отрабатываться цикл рабочего подрежима режима включенной
защиты, и на индикацию будут выведены "дебильные" нули (в части касающейся тока).
В конце этого цикла, транзистор откроется, и соответственно, в дальнейшем (в ПП
прерывания), опять будет обнаружена "токовая бяка".
Транзистор опять закроется. И т.д.
Короче, вопиющее, автоколебательное "безобразие".
При том "раскладе", который сейчас есть, эта "бяка" не ощущается по причине того,
что транзистор симитирован светодиодом (обратной связи нет).
Но в дальнейшем, мимо этого никак не пройдешь (работаю на упреждение).
Вот и одна из задач на будущее.
Раньше времени, "дергаться" совсем не буду (провокаторы в трауре).
Когда буду работать с транзистором, то что-нибудь соображу.
Спокойно, "удавно" и в рабочем порядке.
Пока не знаю что, но "голь на выдумки хитра" (извилиной эффективно пошевелить
нужно). А пока и так вполне сойдет.

А теперь о "клавиатурных делах".


........................
;================================================================================
; ПП "плавающей" задержки на основе анализа состояния флага занятости BF
; (вариант для 4-разрядного интерфейса).
;================================================================================
ENTER_BF ........................
........................
;-----------------------------------
; Завершение процедуры.
;-----------------------------------
clrf PortC ; Сброс в "0" всех защелок порта А
; (RW=0, RS=0, E=0).
bsf Status,RP0 ; Переход в 1-й банк.
movlw b'00001111' ; RB0...RB3 работают на вход,
movwf TrisB ; RB4...RB7 работают на выход.
bcf Status,RP0 ; Переход в 0-й банк.
return ; Возврат по стеку.
;================================================================================
........................
Вы видите концовку ПП ENTER_BF.
В исходном варианте, все выводы порта В были настроены на работу "на выход"
(clrf TrisB).
Выводы RB0…RB3 я зарезервировал под настоящую и будущую клавиатуру.
При таком "раскладе", эти выводы постоянно работают "на вход" (см. выделенное
красным цветом), и никаких электрических конфликтов можно не опасаться.
А тот полубайт, который задействован в процессе обмена данными между ПИКом и
ЖК-модулем, дальше защелок выводов RB0…RB3, выходы которых (защелок)
электрически не подключены к этим выводам, "не уйдет".
И это вполне устраивает ("ЖК-бяк" нет, и клавиатура "цветет & пахнет").

Желающие своими глазами увидеть "железячный" результат сказанного, могут спаять и


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

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

18