Академический Документы
Профессиональный Документы
Культура Документы
;********************************************************************************
; НАЧАЛО ИСПОЛНЕНИЯ ПРОГРАММЫ.
;********************************************************************************
; Подготовительные операции.
;================================================================================
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-й банк.
........................
........................
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), то переход
; в сценарий выключения защиты.
;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
; Сценарий "ЗАЩИТА ВЫКЛЮЧЕНА".
;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
........................
........................
5
; Чтение порога U.
;-----------------------------------
Z_VKL bsf Status,RP1 ; Переход
bcf Status,RP0 ; во 2-й банк.
Обратите внимание на то, что все команды малого кольца проверки находятся в "зоне"
разрешения прерываний.
В конечном итоге, прерывания будут разрешены в течение всего времени отработки
рабочего подрежима режима включенной защиты.
7
Это обеспечивает строго "метрономный" (с равномерным периодом) уход в прерывания.
После возврата из малого кольца проверки, все то же самое, о чем говорилось выше,
только в 1-ю строку ЖК-модуля выводится другая надпись.
Что касается числовых результатов измерений, то если нет перехода в большое
кольцо аварийного подрежима (если пороги не превышены), они будут точно такими
же, как и в случае выключенной защиты (догадайтесь, почему?).
То есть, при переключениях из режима в режим, если уровень измеряемого
напряжения не "гуляет" (стабилен), во 2-й строке ЖК-модуля ничего не меняется.
Далее, с целью обеспечения возможности переключения режимов, опрашивается
состояние кнопки "Переключение режимов".
С этой целью, "прямолинейно закольцовывать" цикл рабочего подрежима на начало ПП
INKEY (так, как сделано в режиме выключенной защиты) нельзя, так как в ПП INKEY
прерывания запрещаются.
Значит, нужно действовать "криволинейно".
Поэтому и организована проверка состояния кнопки.
Если она отжата, то перехода в ПП INKEY не будет, и цикл рабочего режима
продолжит исполняться "как не в чем не бывало" (выхода из "зоны" разрешения
прерываний не будет).
А если нажата, то и нечего горевать о запрете прерываний, так как режим сменится.
Допустим, что кнопка отжата.
Далее, ничто не мешает открыть транзистор (или подтвердить его открытие) и "уйти"
на начало следующего цикла рабочего подрежима (что такое KOL_MOZALO, я надеюсь,
понятно).
Это можно назвать циклом слежения.
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).
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).
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-е АЦП (сила тока). **********************************************************
;********************************************************************************
; Работа с регистром 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.
;================================================================================
; Приведение 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 ; Переход в процедуру выхода из прерывания.
16
Обратите внимание на это:
Если же, при отсутствии "напряженческой бяки", произойдет превышение порога защиты
по току, то будет следующее (рассуждаю на теоретическом уровне):
В результате первой же проверки на превышение порога защиты по току (в ПП
прерывания), "бяка" будет обнаружена и транзистор закроется.
17
Ток станет нулевым вплоть до конца отработки "пачки" измерений.
Следовательно, в результате следующих измерений "пачки", превышения порога
защиты по току обнаружено не будет.
На момент окончания "пачки" измерений, будет зафиксировано нулевое значение тока,
флаг превышения/не превышения порога защиты по току будет опущен, а транзистор
закрыт.
А раз это так, то будет отрабатываться цикл рабочего подрежима режима включенной
защиты, и на индикацию будут выведены "дебильные" нули (в части касающейся тока).
В конце этого цикла, транзистор откроется, и соответственно, в дальнейшем (в ПП
прерывания), опять будет обнаружена "токовая бяка".
Транзистор опять закроется. И т.д.
Короче, вопиющее, автоколебательное "безобразие".
При том "раскладе", который сейчас есть, эта "бяка" не ощущается по причине того,
что транзистор симитирован светодиодом (обратной связи нет).
Но в дальнейшем, мимо этого никак не пройдешь (работаю на упреждение).
Вот и одна из задач на будущее.
Раньше времени, "дергаться" совсем не буду (провокаторы в трауре).
Когда буду работать с транзистором, то что-нибудь соображу.
Спокойно, "удавно" и в рабочем порядке.
Пока не знаю что, но "голь на выдумки хитра" (извилиной эффективно пошевелить
нужно). А пока и так вполне сойдет.
18