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

2-2/20. "Влажная уборка" (минус 240 команд).

Увеличение "массы ефрейторского


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

Вы уже должны заметить, что каждый подраздел этой темы посвящен поэтапному
решению конкретных и реально выполнимых задач.
Для того чтобы их решать, их нужно сформулировать.
Сначала на "глобальном" (или "подглобальном") уровне.
В большинстве случаев, "глобальная" задача состоит из того или иного количества
более "мелких" подзадач (что-то типа "ветвления").
Умение качественно решать отдельные подзадачи, без умения свести их в единое
целое, это как велосипед со спущенными шинами, на котором далеко не уедешь.
Для того чтобы качественно решить "глобальную" задачу, нужно уметь делать оба этих
дела. В комплексе. Неразрывно (должно работать "боковое зрение").
То есть, решая ту или иную "подзадачу", нужно постоянно анализировать последствия
ее решения, на предмет их "вписывания в общий, глобальный контекст".
Это что-то типа врачебного принципа "вылечи и не навреди".
Ведь как зачастую бывает: например, врач лечит почки.
Вылечил. Но после этого печень отвалилась (или наоборот).
Заключение: может быть этот врач и распрекрасный человек, но учиться ему
архинужно.
Хотя бы в целях самосохранения, ведь можно "нарваться" на большие неприятности.
Врач-профи вылечит почки так, что печень вообще не отвалится.
Это и есть истинный гуманизм. Не на словах, а на деле.
В нашей "епархии" - то же самое.
Только вместо врача - конструктор, а вместо пациента - программа/"железяка".
Если конструктор проявит указанный выше, истинный гуманизм, то в дальнейшем,
программа/"железяка" и бутылочку коньячку (или чего-то еще) поднесет, и слезы
благодарности прольет, и позаботится о создании репутации типа "ого-го".
А теперь ближе к делу.
В настоящее время, имеется программа, отдаленно претендующая на звание "базовой".
Вопрос: "Можно ли расширить ее функциональность"?
Ответ: можно. И нужно.
Но только после того, как будет "выдана на гора" эта самая "базовая" программа.
Сие есть мнение моего "внутреннего цензора", с которым я согласен.
А раз это так, то нужно довести программу до соответствующего состояния.
В связи с этим, возникают три "глобальные" задачи:

1. Нужно произвести "влажную уборку". То есть, "заоптимизировать" то,


что еще не "заоптимизировано". В результате этого, "масса" программы
уменьшится, а "масса ефрейторского суперзазорища" возрастет, что
сулит всяческие, радужные перспективы.
2. Так как имеется потенциальная возможность уменьшения наихудшей
инерционности срабатывания защиты по превышению порогов U/I, то
почему бы это не сделать?
3. Так как имеется потенциальная возможность включения, в "зону"
разрешения прерываний, двух задержек ПП DQ_INIT, то почему бы и это
тоже не сделать, ведь в результате этого, улучшатся параметры
защиты от КЗ ?

В целях минимизации трудозатрат, эти задачи выгодно решать именно в указанной


выше последовательности.

1. "Влажная уборка".

Речь идет об оптимизации, причем об оптимизации типа "тонкая, окончательная (или


почти окончательная) зачистка".

1
Эта работа, в идеале, должна быть сделана так, чтобы после нее, нЕчего было бы
"зачищать".
И ее обязательно нужно сделать, так как для "базовой" программы, функциональность
которой, в дальнейшем, будет наращиваться, это очень актуально.
Особенно в части касающейся "ефрейторского суперзазорища".
К тому же, совсем не помешает навести окончательный порядок в
"текущенавороченном".
Голос из-за кулис: "ЗадолбАл ты своей оптимизацией. Сколько можно"!
Ответ: сколько нужно, столько и можно.
А нужно практически всегда.
В идеале, в течение всего процесса работы над программой.
Если бы я ранее этого не делал, то пришлось бы поневоле задуматься о переходе с
PIC16F873A на PIC16F876A.
Вопрос: "Какая оптимизация нужна"?
Ответ: нужна командная оптимизация (результат - уменьшение количества команд).
Компромиссная оптимизация отпадает.
Вопрос: "Что нужно заоптимизировать"?
Ответ: все те же дублирующиеся состояния, только не в приложении к таблицам ПП
вычисляемых переходов ("рулевые" группы команд не в счет), а в приложении к
остальному.
Проще говоря, речь идет о дублирующихся группах команд, которые не входят в
состав этих таблиц.
Ранее, в ходе предварительной оптимизации, подобное имело место быть.
В данном случае, по своей сути, всё то же самое, только "рангом помельче".
В том смысле, что речь идет о достаточно "худосочных" группах команд малого
"объема", но за счет того, что их количество велико, можно "высвободить" вполне
приличное количество ячеек PC.
Поехали.
Примечание: используется все тот же строго поэтапный принцип работы.

Исходя из прагматических соображений, орлиный взор устремляется на то, что


"пожирнее".
Это подпрограммы записи в EEPROM и чтения из EEPROM.
ПП записи в EEPROM - самые "жирные".
С них и начну.
1.
Например, ПП записи значения порога U.
Изначально, она выглядит так:
....................................
....................................
;================================================================================
; ПП записи значения порога U.
;================================================================================
WRITE_U bsf Status,RP1 ; Переход
bcf Status,RP0 ; во 2-й банк.
movlw 1 ; Выбор ячейки EEPROM
movwf EEAdr ; с адресом 01h.
movf Porog_U,W ; Porog_U -> W.

movwf EEData ; Porog_U -> 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 ; Если не завершена,то "плавающая" задержка

2
bcf Status,RP0 ; Если завершена, то
bcf Status,RP1 ; переход в 0-й банк.

return ; Возврат по стеку.


;================================================================================
....................................
....................................

Сравниваю ее с другими ПП записи в EEPROM.


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

....................................
....................................
;================================================================================
; ПП записи значения порога U.
;================================================================================
WRITE_U bsf Status,RP1 ; Переход
bcf Status,RP0 ; во 2-й банк.
movlw 1 ; Выбор ячейки EEPROM
movwf EEAdr ; с адресом 01h.
movf Porog_U,W ; Porog_U -> W.
call WRITE ; Переход в элемент ПП записи.
return ; Возврат по стеку.
;================================================================================
....................................
....................................
;================================================================================
; Элемент ПП записи.
;================================================================================
WRITE movwf EEData ; Загрузка данных (через W).
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-й банк.
return ; Возврат по стеку.
;================================================================================
....................................
....................................

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


команд, которая выделена красным цветом, а вместо нее "настукивается" call WRITE,
и все дела.
Сейчас и далее, выигрыш по командам получается за счет того, что вместо
"дебильной" отработки нескольких совершенно одинаковых групп команд,
отрабатывается одна-разъединственная ПП WRITE (или подобная ей).

2.
То же самое (по сути) "дельце проворачивается" и с подпрограммами чтения из
EEPROM.
Например, ПП чтения, из EEPROM, текущих порогов U/I.

3
Изначально, она выглядит так:
....................................
....................................
;================================================================================
; Чтение, из EEPROM, текущих порогов U/I.
;================================================================================
; Чтение порога U.
;-----------------------------------
READ_UI 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 ; Считывание байта из выбранной ячейки,
; в регистр Porog_U.
;-----------------------------------
; Чтение порога I.
;-----------------------------------
movlw 2 ; Выбор ячейки EEPROM с адресом 02h.
movwf EEAdr ;
bsf Status,RP0 ;
bcf EECon1,7 ; Аналогично, только для
bsf EECon1,0 ; адреса 02h и регистра Porog_I.
bcf Status,RP0 ;
movf EEData,W ;
movwf Porog_I ; Считывание байта из выбранной ячейки,
; в регистр Porog_I.
bcf Status,RP1 ; Переход в 0-й банк.
return ; Возврат по стеку.
;================================================================================
....................................
....................................

А в конечном итоге, получилось это:

....................................
....................................
;================================================================================
; Чтение, из EEPROM, текущих порогов U/I.
;================================================================================
; Чтение порога U.
;-----------------------------------
READ_UI bsf Status,RP1 ; Переход
bcf Status,RP0 ; во 2-й банк.
movlw 1 ; Выбор ячейки EEPROM с адресом 01h.
call READ ; Переход в элемент ПП чтения.
movwf Porog_U ; Считывание байта из выбранной ячейки,
; в регистр Porog_U.
;-----------------------------------
; Чтение порога I.
;-----------------------------------
movlw 2 ; Выбор ячейки EEPROM с адресом 02h.
call READ ; Переход в элемент ПП чтения.
movwf Porog_I ; Считывание байта из выбранной ячейки,
; в регистр Porog_I.
bcf Status,RP1 ; Переход в 0-й банк.
return ; Возврат по стеку.
;================================================================================
....................................
....................................
;================================================================================

4
; Элемент ПП чтения.
;================================================================================
READ movwf EEAdr ; Загрузка адреса ячейки.
bsf Status,RP0 ; Переход в 3-й банк.
bcf EECon1,7 ; Работа с EEPROM.
bsf EECon1,0 ; Инициализация чтения.
bcf Status,RP0 ; Переход во 2-й банк.
movf EEData,W ; Считывание байта, из выбранной ячейки
return ; Возврат по стеку.
;================================================================================
....................................
....................................

Из всех остальных ПП чтения из EEPROM, удаляется та дублирующаяся группа


команд, которая выделена красным цветом, а вместо нее "настукивается"
call READ.
После всех этих "катаклизмов", связанных с записью в EEPROM и чтением из
EEPROM, в целях комфортного упорядочения нижней "обслуги" 2-й страницы памяти
программ, я скомпановал (на свой вкус) эти ПП таким образом, что получились
компактные группы подпрограмм записи в EEPROM и чтения из EEPROM (раньше эти
ПП были "разбросаны как попало").
Напоминаю, что текст программы составлен таким образом, что в пределах нижних
"обслуг" обеих страниц памяти программ, подпрограммы можно переставить как угодно.
Примечание1: так как название READ присвоено элементу ПП чтения, то название
ПП чтения, из EEPROM, байта текущего режима работы, зачений
нижнего/верхнего Т-порогов и КЗ-порога изменено с READ на READ_R (вызывается
из ПП START).
Примечание2: я убрал из текста программы все "указивки" типа
;----> Возврат по стеку из ПП ...
Надеюсь на то, что Ваше сознание/подсознание к ним достаточно привыкло и теперь
можно обойтись без них.

3.
Перехожу на то, что "помельче", но что дублируется большое количество раз.
Например, изначально имеется:

....................................
....................................
;================================================================================
; Вывод на индикацию числовых значений температуры.
;================================================================================
IND_TERMO movf LED1,W ; LED1 -> W.
movwf PortB ; содержимого LED1.
bsf PortC,RS ;
call ENTER_BF ;

movf LED0,W ; LED0 -> W.


movwf PortB ; содержимого LED0.
bsf PortC,RS ;
call ENTER_BF ;
return ; Возврат по стеку.
;================================================================================
; Вывод на индикацию, в 1-ю строку, фиксированной надписи " СЛУШАЮСЬ и ".
;================================================================================
SL_I_POVIN movlw high TEXT_17; Выбор PCH 1-й команды ПП TEXT_17
movwf PCLATH ; (находится на 1-й странице).

movlw b'10000000' ; Установка курсора в крайнее


call ENTER_BF ; левое знакоместо 1-й строки.
movlw .16 ;
movwf Count ;
movf Count,W ; Аналогично, только
sublw .16 ; для TEXT_17.
5
call TEXT_17 ;
bsf PortC,RS ; для TEXT_17.
call ENTER_BF ;
decfsz Count,F ;
goto $-6 ;
;================================================================================
....................................
....................................

В процедурах вывода на индикацию символов, которые (процедуры) не связаны с


вычисляемыми переходами, дублируется группа из 3-х команд (выделено синим
цветом).
В процедурах вывода на индикацию символов, которые (процедуры) связаны с
вычисляемыми переходами ("рулевые" группы команд), дублируется группа из 2-х
команд (выделено темно-красным цветом).
В результате, получилось это:

....................................
....................................
;================================================================================
; ПП вывода на индикацию символа.
;================================================================================
SIMVOL movwf PortB ; Вывод на
SIMVOL_T bsf PortC,RS ; индикацию
call ENTER_BF ; символа.
return ; Возврат по стеку.
;================================================================================
....................................
....................................
;================================================================================
; Вывод на индикацию числовых значений температуры.
;================================================================================
IND_TERMO movf LED1,W ; LED1 -> W.
call SIMVOL ; Вывод на индикацию содержимого LED1.
movf LED0,W ; LED0 -> W.
call SIMVOL ; Вывод на индикацию содержимого LED0.
return ; Возврат по стеку.
;================================================================================
; Вывод на индикацию, в 1-ю строку, фиксированной надписи " СЛУШАЮСЬ и ".
;================================================================================
SL_I_POVIN movlw high TEXT_17; Выбор PCH 1-й команды ПП TEXT_17
movwf PCLATH ; (находится на 1-й странице).

movlw b'10000000' ; Установка курсора в крайнее


call ENTER_BF ; левое знакоместо 1-й строки.
movlw .16 ;
movwf Count ;
movf Count,W ; Аналогично, только
sublw .16 ; для TEXT_17.
call TEXT_17 ;
call SIMVOL_T ; Вывод символа на индикацию.
decfsz Count,F ;
goto $-5 ;
;================================================================================
....................................
....................................

То, что Вы видите выше, относится к 1-й странице памяти программ.


Этот же принцип применяется и на 2-й странице, только вызывается "клон":

;================================================================================
; ПП вывода на индикацию символа.
;================================================================================
SIMVOL_1 movwf PortB ; Вывод на

6
SIMVOL_T_1 bsf PortC,RS ; индикацию
call ENTER_BF_1 ; символа.
return ; Возврат по стеку.
;================================================================================

4.
"Сканирую" далее.
"Упираюсь" в группу команд задания адреса.
Например, изначально имеется:

....................................
....................................
;LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
; Установка нижнего Т-порога.
;LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
; Задание адреса знакоместа, с которого начнется вывод на индикацию.
;--------------------------------------------------------------------------------
movlw b'11000010' ; 2-я строка, 3-е знакоместо. Адрес 02h.
movwf PortB ;
call ENTER_BF ;
;--------------------------------------------------------------------------------
; Вывод на индикацию символа активности (маркера).
;--------------------------------------------------------------------------------
movlw 0DCh ; Символ ">|"
call SIMVOL ; Вывод на индикацию этого символа
; (взамен символу "=").
....................................
....................................

Дублируется группа из 2-х команд (выделено красным цветом).


В результате, получилось это:

....................................
....................................
;================================================================================
; ПП задания адреса.
;================================================================================
ADRES movwf PortB ; W -> PortB.
call ENTER_BF ; Переход в ПП ENTER_BF.
return ; Возврат по стеку.
;================================================================================
....................................
....................................
;LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
; Установка нижнего Т-порога.
;LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
; Задание адреса знакоместа, с которого начнется вывод на индикацию.
;--------------------------------------------------------------------------------
movlw b'11000010' ; 2-я строка, 3-е знакоместо. Адрес 02h.
call ADRES ; Установка адреса.
;--------------------------------------------------------------------------------
; Вывод на индикацию символа активности (маркера).
;--------------------------------------------------------------------------------
movlw 0DCh ; Символ ">|"
call SIMVOL ; Вывод на индикацию этого символа
; (взамен символу "=").
....................................
....................................

То, что Вы видите выше, относится к 1-й странице памяти программ.


Этот же принцип применяется и на 2-й странице, только вызывается "клон":

;================================================================================
; ПП задания адреса.
7
;================================================================================
ADRES_1 movwf PortB ; W -> PortB.
call ENTER_BF_1 ; Переход в ПП ENTER_BF_1.
return ; Возврат по стеку.
;================================================================================

5.
"Упираюсь" в группу команд противодребезговой задержки.
После вывода надписи СЛУШАЮСЬ и ПОВИНУЮСЬ! , эта задержка отрабатывается
всегда:

....................................
....................................
;--------------------------------------------------------------------------------
; Вывод на индикацию фиксированной надписи " СЛУШАЮСЬ и / ПОВИНУЮСЬ! ".
;--------------------------------------------------------------------------------
call SL_I_POVIN ; Переход в ПП вывода на индикацию
; этой надписи.
;--------------------------------------------------------------------------------
; Противодребезговая задержка.
;--------------------------------------------------------------------------------
call PAUSE_UI ; Переход в ПП PAUSE_UI.
;--------------------------------------------------------------------------------
....................................
....................................

А раз это так, то зачем осуществлять переходы в ПП PAUSE_UI каждый раз после
отработки ПП SL_I_POVIN ?
Можно просто включить команду call PAUSE_UI в концовку ПП SL_I_POVIN.
При этом, с учетом достаточно большого количества процедур выбора адреса,
худо-бедно, а командный выигрыш будет иметь место быть.
Это выглядит так.
Все команды call PAUSE_UI (а также и команды call PAUSE_UI_1, если речь идет о
2-й странице памяти программ), следующие после команд call SL_I_POVIN (выделено
красным цветом), "убиваются", а в концовку ПП SL_I_POVIN добавляется
одна-разъединственная команда call PAUSE_UI.
Получилось это:

....................................
....................................
;================================================================================
; Вывод на индикацию, в 1-ю строку, фиксированной надписи " СЛУШАЮСЬ и ".
;================================================================================
SL_I_POVIN movlw high TEXT_17; Выбор PCH 1-й команды ПП TEXT_17
movwf PCLATH ; (находится на 1-й странице).

movlw b'10000000' ; Установка курсора в крайнее


call ENTER_BF ; левое знакоместо 1-й строки.
movlw .16 ;
movwf Count ;
movf Count,W ; Аналогично, только
sublw .16 ; для TEXT_17.
call TEXT_17 ;
call SIMVOL_T ; Вывод символа на индикацию.
decfsz Count,F ;
goto $-5 ;
;================================================================================
; Вывод на индикацию, во 2-ю строку, фиксированной надписи " ПОВИНУЮСЬ! ".
;================================================================================
movlw b'11000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 2-й строки.
movlw .16 ;
movwf Count ;

8
movf Count,W ;
sublw .16 ; Аналогично, только
call TEXT_18 ; для TEXT_18.
call SIMVOL_T ; Вывод символа на индикацию.
decfsz Count,F ;
goto $-5 ;

call PAUSE_UI ; Противодребезговая задержка.


return ; Возврат по стеку.
;================================================================================
....................................
....................................

Добавленная команда выделена синим цветом.


При этом нужно "не выпускать из поля зрения" команды goto $+х (где х - "число
прыжка") , находящиеся в начале некоторых процедур опросов кнопок.
То есть, если эти команды имеют место быть, то после удаления команды
call PAUSE_UI (или call PAUSE_UI_1), "число прыжка" нужно уменьшить на единицу.

6.
Две команды можно "сэкономить" при переходе с двухкомандного на однокомандный
вариант работы с регистром PCLATH.
Это первый случай:
;================================================================================
; Вывод на индикацию, во 2-ю строку, фиксированной надписи " температуры ".
;================================================================================
...................................
...................................
;================================================================================
; Обеспечение необходимого времени "высвечивания" надписи.
;================================================================================
;;; movlw high PAUSE_S; Выбор PCH 1-й команды ПП PAUSE_S
;;; movwf PCLATH ; (находится на 1-й странице).

bcf PCLATH,3 ; Выбор 1-й страницы.


call PAUSE_S ; Задержка.
movlw high TEXT_26; Выбор PCH 1-й команды ПП TEXT_26
movwf PCLATH ; (находится на 2-й странице).
;================================================================================

А это 2-й случай:

;================================================================================
; Вывод на индикацию, в 2-ю строку, фиксированной надписи " разблокировка ".
;================================================================================
...................................
...................................
;================================================================================
; Обеспечение необходимого времени "высвечивания" надписи.
;================================================================================
;;; movlw high PAUSE_S; Выбор PCH 1-й команды ПП PAUSE_S
;;; movwf PCLATH ; (находится на 1-й странице).

bcf PCLATH,3 ; Выбор 1-й страницы.


call PAUSE_S ; Задержка.
;--------------------------------------------------------------------------------

Оба этих случая имеют место быть на 2-й странице памяти программ.

7.
В сценарии включенной защиты, имеются две такие группы команд:

call PAUSE_UI ; PAUSE_UI.

9
clrf PCLATH ; Выбор 1-го блока 1-й страницы.
bsf Flag,3 ; Поднятие флага завершения смен надписей.
bsf Flag,2 ; Поднятие флага факта нажатия кнопки.
movlw .122 ; Обеспечение ухода в прерывание
movwf TMR2 ; сразу же после открытия транзистора.
bsf PortA,2 ; ОТКРЫТИЕ ТРАНЗИСТОРА.

А раз это так, то:

;================================================================================
; ПП подготовки.
;================================================================================
PODGOTOVKA call PAUSE_UI ; PAUSE_UI.
clrf PCLATH ; Выбор 1-го блока 1-й страницы.
bsf Flag,3 ; Поднятие флага завершения смен надписей.
bsf Flag,2 ; Поднятие флага факта нажатия кнопки.
movlw .122 ; Обеспечение ухода в прерывание
movwf TMR2 ; сразу же после открытия транзистора.
bsf PortA,2 ; ОТКРЫТИЕ ТРАНЗИСТОРА.
return ; Возврат по стеку.
;================================================================================
и call PODGOTOVKA.

В части касающейся идентификации тех групп команд, которые еще можно


"заоптимизировать", получив, в результате этого, какой-то существенный "командный
выигрыш", ничего достойного внимания пока не нахожу (а может быть и найду.
Позднее. Если захочется).
Это чисто субъективная оценка.

2. Уменьшение наихудшей инерционности срабатывания защиты по превышению


порогов U/I.

Изначально, имеется такой "расклад": наихудшая инерционность срабатывания защиты


по превышению порогов U/I (режим включенной защиты) = 100 мкс.
ПП прерывания отрабатывается за 86 мкс.
"Хвостик/довесок", в течение которого отрабатываются фрагменты "основного тела"
программы, = 14 мкс.
86 мкс. это "святое". "Трогать нельзя".
А вот 14 мкс. "трогать можно". И даже нужно. Как минимум, в воспитательных целях.
Как-то подозрительно "кучеряво этот хвостик/довесок живет".
Какой-то он излишне "откормленный" (речь идет о казенных харчах!).
Непорядок. Безобразие. Паразитизм.
Но это поправимо.
Для того чтобы жизнь медом не казалась, и в целях создания условий,
способствующих эффективной ловле мышей, пайку кота нужно урезать.
Но и меру тоже нужно знать, а то ведь, если ее слишком сильно урезать, помрет,
бедолага, с голодухи. Жалко будет.
Это и есть наиболее эффективный консенсус между массой казенных харчей и
результатом их потребления.
В соответствии с этой "концепцией", уменьшаю величину периода ухода в прерывания
со 100 мкс. до 90 мкс.
В этом случае, получается такой "расклад":
- ПП прерывания будет отрабатываться за те же 86 мкс.,
- "хвостик/довесок" будет отрабатываться не за 14, а за 4 мкс.
В принципе, время отработки "хвостика/довеска" можно "обкарнать" еще на 1, 2 и даже
3 мкс., но я не стал этого делать по причине гуманизма и любви к животным
(напоминаю про кота и про то, что я был юным другом природы).
А раз это так, то:

....................................
....................................
10
;********************************************************************************
; НАЧАЛО ИСПОЛНЕНИЯ ПРОГРАММЫ.
;********************************************************************************
; Подготовительные операции.
;================================================================================
START
....................................
....................................
movlw .111 ; Задание периода ухода в прерывания
movwf PR2 ; (PR2=.111, F=11,161 Кгц., T=89,5977 мкс.).
bcf Status,RP0 ; Переход в 0-й банк.
;--------------------------------------------------------------------------------
; Обеспечение "разгона" вентиллятора.
;--------------------------------------------------------------------------------
....................................
....................................

Коэффициент деления предделителя остался прежним.


В регистр PR2, вместо константы .124 (это было ранее), записывается константа .111
"Вышележащее" можно проверить в PIC-калькуляторе.
Действие - простейшее, но последствия этого действия "зело велики".
А именно, те циклы, которые лежат в "зонах" разрешения прерываний, будут
отрабатываться гораздо медленнее, чем до осуществления этой числовой коррекции.
Примечание: на времени отработки тех циклов, которые лежат в "зонах" запретов
прерываний, это не отразится.
Проще говоря, те надписи, которые находятся в "зонах" разрешения прерываний, будут
"высвечиваться" очень долго ("обкуришься" ожидаючи).
Вопрос: "От чего зависит время этого высвечивания"?
Ответ: от задержки PAUSE_UI, которая работает только в "границах" 1-й страницы
памяти программ (из 2-й страницы PC, уходить в прерывания нельзя).
Значит, для того чтобы избавиться от затягивания времени отработки тех циклов,
которые "лежат" в "зонах" разрешения прерываний, время отработки этой задержки
нужно уменьшить.
Эту задачу я решил так:
....................................
....................................
;================================================================================
; Задержка, определяющая скорость смены показаний
; и "добывание" результатов измерения.
;================================================================================
PAUSE_PRER movlw .150 ;
movwf Reg_2 ;
movlw 1 ; Задание констант.
movwf Reg_3 ;
goto PAUSE_UI_A ;

PAUSE_UI movlw .228 ;


movwf Reg_1 ;
movlw .144 ; Задание констант.
movwf Reg_2 ;
movlw .2 ;
movwf Reg_3 ;

PAUSE_UI_A decfsz Reg_1,F ; Стандартный,


goto $-1 ; 3-байтный,
decfsz Reg_2,F ; вычитающий
goto $-3 ; счетчик.
decfsz Reg_3,F ;
goto $-5 ;
return ; Возврат по стеку.
;================================================================================
....................................
....................................

11
Регистр младшего разряда (Reg_1) проигнорировал, так как "погоды он не делает".
Получилось "дешево и сердито".
Забегая вперед, скажу, что числовые значения констант я подобрал экспериментально
(в соответствии со своим ощущением времени).
После этого остается только заменить те вызовы ПП PAUSE_UI (находящиеся в
"зонах" разрешения прерываний), которые обеспечивают интервалы времени
"высвечивания тормозных надписей", на call PAUSE_PRER, что и сделано.
За исключением тех вызовов ПП PAUSE_UI, которые задают интервалы времени
"высвечивания" надписей НАГРУЗКА ВКЛЮЧЕНА и НАГРУЗКА ВЫКЛЮЧЕНА.
В этом случае (отрабатывается не одна, а несколько задержек PAUSE_UI), достаточно
просто уменьшить количество вызовов ПП PAUSE_UI, что и сделано.

Следующий момент.
В связи с уменьшением периода ухода в прерывания, необходимо скорректировать
числовое значение константы, которая обеспечивает уход в прерывание сразу же после
открытия транзистора.
То есть, в ПП PODGOTOVKA, вместо .122 (124-2=122), нужно "настучать"
.109 (111-2=109):

;================================================================================
; ПП подготовки.
;================================================================================
PODGOTOVKA call PAUSE_UI ; PAUSE_UI.
clrf PCLATH ; Выбор 1-го блока 1-й страницы.
bsf Flag,3 ; Поднятие флага завершения смен надписей.
bsf Flag,2 ; Поднятие флага факта нажатия кнопки.
movlw .109 ; Обеспечение ухода в прерывание
movwf TMR2 ; сразу же после открытия транзистора.
bsf PortA,2 ; ОТКРЫТИЕ ТРАНЗИСТОРА.
return ; Возврат по стеку.
;================================================================================

По этой же причине, необходимо скорректировать числовые значения констант ПП


PAUSE_2 (в сторону уменьшения задержки):

;================================================================================
; ПП задержки, обеспечивающей "пережидание" температурного преобразования.
; Tзадержки, с учетом ухода в прерывания, примерно = 200000мкс.
;================================================================================
PAUSE_2 bsf IntCon,7 ; РАЗРЕШЕНИЕ ПРЕРЫВАНИЙ.
movlw .168 ;
movwf Reg_1 ;
movlw .58 ;
movwf Reg_2 ;

decfsz Reg_1,F ;
goto $-1 ; K=4/90=0,0444
decfsz Reg_2,F ; 200000 -> 8880 x 5 = 44400 мц 168-58
goto $-3 ;
bcf IntCon,7 ; ЗАПРЕТ ПРЕРЫВАНИЙ.
return ; Возврат по стеку.
;================================================================================

С чувством выполненного долга и с уверенностью в победе, проверяю


"текущенавороченное" в "железе".
Что за ЁКЛМН !!!
Вот так неожиданность à "противные кракозябры на фоне мертвяка".
Прямо зла не хватает.
В таких случаях, всем врагам на зло, портить нервную систему не нужно, а нужно
"принять позу задумчивого удава, высматривающего добычу".

12
После "раскидывания мозгами", склоняешься к выводу, что сей "глюк" просто прекрасен
(первично, обругал под воздействием эмоций. Когда как следует подключается
сознание, то получается совсем другая "опера").
Он прекрасен с точки зрения выяснения истины, а заодно и с точки зрения "засечения
коварной и очень хитропопой бяки" (а это очччень крутой опыт!!!).
"Сканирую".
Точно. Имеется ошибка "в чистом виде".
Она выглядит так:

....................................
....................................
;-------------------------------------
; Подготовка к 2/10 преобразованию.
;-------------------------------------
movlw high BIN2_10_T; Выбор PCH 1-й команды ПП BIN2_10_T.
movwf PCLATH ; (находится на 2-й странице).

movf Temp_LSB,W ; Temp_LSB -> W.


;================================================================================
; 2/10 преобразование (1х2) с перекодировкой результата.
;================================================================================
call BIN2_10_T ; Переход в ПП 2/10 преобразования.
clrf PCLATH ; Выбор 1-го блока 1-й страницы.
;================================================================================
; Вывод на индикацию текущего значения температуры.
;================================================================================
....................................
....................................

На первый взгляд, никакой ошибки нет, но на второй взгляд, она есть.


Ошибка: ПП BIN2_10_T "лежит" на 2-й странице памяти программ, и эта ПП
отрабатывается в "зоне" разрешения прерываний.
Но ведь в прерывания нельзя уходить из 2-й страницы памяти программ (можно
только из 1-й).
Вот Вам и "глюк".
Ошибка типа "невнимательность".
На этом можно было бы успокоиться, посыпать голову пеплом и выправить дефект, но
русскому колобку стало маниакально интересно, почему, в программе BP_17.asm, этот
"глюк" вообще визуально никак не ощущается (а то бы заметил)?
Как говорится, дело принципа. И интереса тоже.
Те же самые литр кофе и пачка сигарет.
"Есть контакт!!! Кролик в желудке".
Объясняю в чем дело.
Если уход в прерывание произойдет из ПП BIN2_10_T, "дислоцирующейся" на 2-й
странице памяти программ, то в результате первой же отработки команды goto/call,
"дислоцирующейся" в ПП прерывания, произойдет переход не на нужную команду ПП
прерывания (она "лежит" на 1-й странице PC), а на ее "зеркальное отображение",
находящееся на 2-й странице памяти программ.
Визуально ощущаемого "глюка" нет потому, что это "зеркальное отображение"
находится внутри ПП, входящей в состав "обслуги" 2-й страницы PC, и перед
командой return.
Таким образом получается, что переполнения стека не происходит, так как после
"виртуального" call (эта команда исполняется в начале ухода в прерывание),
отрабатывается команда return (вроде как "повезло". В кавычках).
При таком "раскладе", ПП BIN2_10_T отрабатывается без ошибок, да вот только ПП
прерывания отрабатывается не полностью (только самое начало).
Толку от такой "кастрированной" отработки - ноль (и даже меньше).
Это эквивалентно исключению ПП BIN2_10_T из "зоны" разрешения прерываний, хотя,
формально, она в ней находится.
Вот и получается, что визуально ощущаемого "глюка" нет, и при этом, ПП BIN2_10_T,
как бы, коварно/гнусно "самоисключается" из "зоны" разрешения прерываний.
13
Короче, самая натуральная "подрывная деятельность агентов вражеских спецслужб",
которая имеет место быть в результате халатности (моей).
Стыдно, но утешает то, что за одного битого двух небитых дают, а также и то, что в
ходе работы над ошибками, можно узнать много важной информации.
Остается только отметить, что после осуществления оптимизации, текст программы
сместился таким неудачным образом, что в конечном итоге, это привело либо к
переполнению стека, либо к неучтенному "прыжку" (в ходе отработки того, что "лежит"
ниже "точки зеркального отображения") в какие-то совсем не нужные и губительные
"дали".
После того, как проблема выявлена и "опущена" до уровня типа "это и коню понятно",
ее можно/нужно спокойно и по-деловому "придушить" (напоминаю про следователя,
субстанцию и камеру с уголовниками).
А именно:

1. ПП BIN2_10_T переносится, из 2-й страницы памяти программ, в нижнюю "обслугу"


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

2. В сценарии выключенной защиты (находится на 1-й странице PC), "PCLATH-конвой",


с вызова команды call BIN2_10_T, снимается:

....................................
....................................
;-------------------------------------
; Подготовка к 2/10 преобразованию.
;-------------------------------------
movf Temp_LSB,W ; Temp_LSB -> W.
;================================================================================
; 2/10 преобразование (1х2) с перекодировкой результата.
;================================================================================
call BIN2_10_T ; Переход в ПП 2/10 преобразования.
;================================================================================
; Вывод на индикацию текущего значения температуры.
;================================================================================
....................................
....................................

Примечание: сравните это с "вышележащим куском" программы.

3. Вызовы ПП BIN2_10_T, имеющие место быть на 2-й странице памяти программ,


"укомплектовываются PCLATH-конвоем" (выделено красным цветом):

;================================================================================
; 2/10 преобразование (1х2) с перекодировкой результата.
;================================================================================
bcf PCLATH,3 ; Выбор 1-й страницы.
call BIN2_10_T ; Переход в ПП 2/10 преобразования.
bsf PCLATH,3 ; Выбор 2-й страницы.
;================================================================================

4. В связи с тем, что на 1-й странице памяти программ, "PCLATH-конвой", с вызовов


ПП BIN2_10_T, снят, ПП BIN_DEC стала такой "до неприличия тщедушной" (кожа да
кости), что исходя из гуманных соображений, я ее "убил" (чтобы не мучилась), а ее
"тщедушное" содержимое "перебазировал" в те "места" (2 штуки), из которых она
вызывалась.
После осуществления всех этих "катаклизмов", иду в окно ROM и смотрю, каковы
"блочные дела".
Как-то слабовато они мне нравятся: в части касающейся "стыка" между 2-м и 3-м
блоком - "на грани фола".
Чтобы устранить сие "безобразие", "врезаю в этот стык" ПП КОНСТАНТА (перенесена
из нижней "обслуги" 1-й страницы), ПП PAUSE_1MKS (перенесена из 3-го блока 1-й
страницы).
14
Вот теперь нормально.
"Перекрестясь" (мало ли что? Вдруг взбрыкнет? Дури полно), включаю "железяку".
"Глюка" нет. Моль съела. Полная ляпота.
На бутылочку пива имею моральное право …
То, что программа, в некоторых случаях, "еле ногами перебирает" - абсолютно
нормально и вполне закономерно, ведь "хвостик/довесок"-то уменьшился.
Это совсем не беда (беда была ранее).
Еще раз напоминаю, что "тормозится" вывод на индикацию только тех надписей,
которые отрабатываются в "зонах" разрешения прерываний.
Ранее, "тормоза", с части из них, были сняты. Но не со всех.
Снимаю их с остальных.

1. "Тормоза" с надписей ПП проверки превышения/не превышения порогов (PROV_U_I)


снимаются путем банального переноса команды bcf IntCon,7 (запрет прерываний) в то
"место", которое расположено выше вызова задержки PAUSE_UI.
Ранее, эта задержка находилась в "зоне" разрешения прерываний.
Поэтому и был "тормоз".
Этот перенос не в коем разе не ухудшит инерционность срабатывания защиты по
превышению порогов U/I, так как указанная выше команда, не входит в рабочий цикл
сценария включенной защиты.
Это выглядит так:

....................................
....................................
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
; ПП ПРОВЕРКИ ПРЕВЫШЕНИЯ/НЕ ПРЕВЫШЕНИЯ ПОРОГОВ. &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
PROV_U_I movlw .10 ; Задание количества отрабатываемых
movwf Temp ; циклов ("ставятся на счетчик").

SNOVA_1 bsf IntCon,7 ; РАЗРЕШЕНИЕ ПРЕРЫВАНИЙ.


;--------------------------------------------------------------------------------
; Проверка наличия/отсутствия признаков срабатывания защиты
; (малое кольцо проверки).
;--------------------------------------------------------------------------------
btfsc Flag,5 ; Защита по U сработала или нет ?
goto $+4 ; Если сработала, то ПП проверки
; отрабатывается далее.
btfsc Flag,4 ; Если не сработала, то защита по I сработала
; или нет ?
goto $+2 ; Если сработала, то ПП проверки
; отрабатывается далее.
return ; Если защита по U и по I не сработала,
; то возврат по стеку.
bcf PortA,2 ; ТРАНЗИСТОР ЗАКРЫВАЕТСЯ.
bcf IntCon,7 ; ЗАПРЕТ ПРЕРЫВАНИЙ.
;--------------------------------------------------------------------------------
; Обеспечение "штатных" условий отработки сценария "ЗАЩИТА ВКЛЮЧЕНА",
; в случае возврата из ПП PROV_U_I в сценарий "ЗАЩИТА ВКЛЮЧЕНА".
;--------------------------------------------------------------------------------
bcf Flag_1,5 ; Перевод флага ручного отключения нагрузки
; в состояние "нагрузка выключена".
;--------------------------------------------------------------------------------
; Обеспечение выполнения сценария-подсказки №1, после возвратов из ПП PROV_U_I
; (в случаях, если имели место быть превышения порогов U/I, которые устранены).
;--------------------------------------------------------------------------------
bcf Flag,3 ; Сброс флага завершения смен надписей.
bcf Flag,2 ; Сброс флага факта нажатия кнопки.
movlw .3 ; Задание количества смен надписи
movwf Temp_2 ; "РЕЖИМ СЛЕЖЕНИЯ / U=хх,x I=х,хха" на
; надпись " Вкл. | нагрузки / кнопка "+/Да". "
; (и наоборот).
;================================================================================

15
; Обеспечение необходимой скорости смены показаний.
;================================================================================
call PAUSE_UI ; Задержка.

;;; bcf IntCon,7 ; ЗАПРЕТ ПРЕРЫВАНИЙ.


;================================================================================
; Формирование сигнала аварии.
;================================================================================
....................................
....................................

Серым цветом выделено "старое место дислокации".


Красным цветом выделено "новое место дислокации".

2. Имеется "тормоз" при выводе на индикацию надписей температурной


"предупреждалки" (в части касающейся 2-х и 3-х градусов).
Он снимается путем уменьшения числовых значений констант, задающих длительность
"писка" и паузы между ними.
Я уменьшил их "на свой вкус".
И паузы между "писками" сделал более короткими (по сравнению с длительностью
"писка").
Так, на мой взгляд, более симпатично слушается.

3. Включение, в "зону" разрешения прерываний, двух задержек ПП DQ_INIT.

Если, в "зону" разрешения прерываний, удастся включить задержки ПП DQ_INIT


величиной 500 мкс. и 250 мкс., то инерционность срабатывания защиты от КЗ будет
довольно-таки существенно улучшена.
С этими задержками, такое проделать можно, так как, в отличие от задержки в
70 мкс., которая критична к времени ее отработки (оно должно находиться в
определенном диапазоне), время отработки задержек величиной 500 и 250 мкс., в
сторону увеличения (но не в сторону уменьшения), не лимитировано.
То есть, в случае включения этих задержек в "зоны" разрешения прерываний, их
значения можно сделать бОльшими, чем указанные.
Ничего особо плохого в этом нет, так как чем бОльшим будет это увеличение, тем
бОльшей будет вероятность того, что факт КЗ произойдет во время отработки "зоны"
разрешения прерываний.
Но и излишне затягивать их не стОит, так как это увеличивает время отработки ПП
TERMO.
Вот такая исходная теория.
В полном соответствии со сказанным ранее, в нижней "обслуге" 1-й страницы памяти
программ, организую вот такую, универсальную ПП задержки (вернее, 2-х задержек):

....................................
....................................
;================================================================================
; Задержки, использующиеся в процедуре инициализации термодатчика.
;================================================================================
PAUSE_3 bsf IntCon,7 ; РАЗРЕШЕНИЕ ПРЕРЫВАНИЙ.
movlw .250 ;
movwf Reg_1
goto $+4

PAUSE_4 bsf IntCon,7 ; РАЗРЕШЕНИЕ ПРЕРЫВАНИЙ.


movlw .250 ;
movwf Reg_1

decfsz Reg_1,F
goto $-1
bcf IntCon,7 ; ЗАПРЕТ ПРЕРЫВАНИЙ.
return ; Возврат по стеку.
;================================================================================
16
....................................
....................................

Особенность этой ПП состоит в том, что можно задать две различные задержки
(зависит от того, на какую метку осуществлен переход), и любая из них будет
отработана в "зоне" разрешения прерывания.
Изначально, выставляю заведомо большИе задержки ("с избытком").
Это только увеличит время отработки цикла ПП TERMO (на стадии эксперимента, это
приемлемо), и не более того.
Но зато, с учетом уходов в прерывания, имеется полная гарантия того, что задержки
будут отработаны за время, не меньшее, чем нужно (см. предельные, временные
характеристики).
Вношу соответствующие коррективы в ПП DQ_INIT:

....................................
....................................
;################################################################################
; НИЖНЯЯ "ОБСЛУГА" 2-й СТРАНИЦЫ.
;################################################################################
; Инициализация термодатчика.
;================================================================================
; Установка на линии DQ 1.
;-----------------------------------
DQ_INIT call PIN_HI ; Установка вывода в высокоимпедансное
; состояние: за счет подтягивающего резистора,
; на линии устанавливается 1.
;-----------------------------------
; Установка на линии DQ 0.
;-----------------------------------
call PIN_LO ; Установка на линии DQ нуля.
;-----------------------------------
; Задержка 500 мкс. (условно)
;-----------------------------------
bcf PCLATH,3 ; Выбор 1-й страницы.
call PAUSE_3 ; Переход в ПП задержки.
bsf PCLATH,3 ; Выбор 2-й страницы.
;-----------------------------------
; Установка на линии DQ 1.
;-----------------------------------
call PIN_HI ; Установка вывода в высокоимпедансное
; состояние: за счет подтягивающего резистора,
; на линии устанавливается 1.
;-----------------------------------
; Задержка 70 мкс.
;-----------------------------------
movlw .7 ; Установка количества проходов по 10мкс.
call PAUSE_X1 ; Переход в ПП задержки (задержка=7х10=70мкс.)
;--------------------------------------------------------------------------------
; Определение наличия (или нет) отклика на импульс сброса.
;--------------------------------------------------------------------------------
btfsc PortC,DQ ; На линии DQ 0 или 1 (отклик есть или нет)?
bsf Flag,1 ; Если отклика нет (1), то флаг наличия
; термодатчика поднимается.
; Если отклик есть (0), то флаг наличия
; термодатчика остается опущенным и программа
; исполняется далее.
;-----------------------------------
; Задержка 250 мкс. (условно)
;-----------------------------------
bcf PCLATH,3 ; Выбор 1-й страницы.
call PAUSE_4 ; Переход в ПП задержки.
bsf PCLATH,3 ; Выбор 2-й страницы.

return ; Возврат по стеку.

17
;================================================================================
....................................
....................................

Включаю "железяку".
Опять ЁКЛМН!!!
Значит где-то "прокол".
Подключенный датчик не идентифицируется (со всеми вытекающими последствиями).
То есть, датчик есть, а отклика от него нет. Хотя, должен быть.
"Разборки" были не долги.
Причина "глюка": идентификация датчика производится до разрешения прерываний от
периферийных модулей и до разрешения прерываний по перполнению TMR2.
Соответственно, в ПП PAUSE_3 / PAUSE_4, уходов в прерывания происходить не будет
и эти задержки будут отрабатываться не "кусочно-рвано", а за один "присест".
Поэтому, формируется задержка меньшая (и прилично), чем нужно.
Это приводит к нарушению работы термодатчика, что и наблюдалось.
Устранить этот "дефект" достаточно просто.
Группа команд концовки ПП START "вырезается" со своего "старого места" и
"врезается" перед вызовом ПП DQ_INIT.
Получилось это:

....................................
....................................
;================================================================================
; Процедура инициализации ЖКИ модуля.
;================================================================================
.....................................
.....................................
;----------------------------------------
; Концовка ПП START.
;----------------------------------------
bsf Status,RP0 ; Переход в 1-й банк.
movlw b'01000000' ; Глобальный запрет прерываний и разрешение
movwf IntCon ; прерываний от периферийных модулей.
movlw b'00000010' ; Разрешение прерываний
movwf PIE1 ; по переполнению TMR2.
bcf Status,RP0 ; Переход в 0-й банк.
;ОООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООО
; Проверка наличия/отсутствия отклика от термодатчика.
;ОООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООО
bsf PCLATH,3 ; Выбор текущего блока 2-й страницы.
call DQ_INIT ; Переход в ПП инициализации термодатчика.
.....................................
.....................................

При этом, метка START_1 "остается не у дел" и ее можно убрать, после чего нужно
заменить две команды goto START_1 на команды goto INKEY.
А вот теперь ладушки.
Так как величины констант ПП PAUSE_3 / PAUSE_4 излишне "числомассивны", то их
нужно уменьшить и довести до приемлемого "уровня".
В данном случае, поправочный коэффициент = 4 мкс. / 90 мкс. = 0,0444 (и 4 в периоде.
Округлил).
Значит, задержке в 500 мкс. будет соответствовать константа .36, а задержке в
250 мкс. будет соответствовать константа .18.
Выставляю. Включаю "железяку".
Опять ЁКЛМН!!!
Значит опять где-то "прокол" (это уже начинает бесить. И это хорошо).
Если увеличивать числовые значения этих констант, то получаются ладушки, но это
соответствует времени отработки задержки, которое выше рассчетного.
Вопрос: "В чем еще раз собака порылась"?

18
Ответ: она порылась в том, что применяемая формула рассчитана на уход, в первое
прерывание (имеется ввиду первое прерывание, которое возникает по ходу отработки
задержки), в самом начале отработки задержки.
И в самом деле, в данном случае, никакой "привязки", к моменту ухода в первое
прерывание, нет, а есть "анархия" ("шаляй-валяй") величиной в 90 мкс. (период ухода в
прерывания).
Уход в первое прерывание может произойти в любой момент ("шаг" 0,2 мкс.) этого
"анархического" интервала времени ("как Бог на душу положит"), так как, после
разрешения работы модуля TMR2, он работает все время.
В том числе, может иметь место быть не фиксированная (это еще куда не шло), а
"плавающая анархия" (вообще тоска …). Это зависит от программы.
Предположим, что непосредственно перед разрешением прерываний (в "зоне" запрета
прерываний), началось формирование "нового" периода TMR2.
В этом случае, в начале отработки задержки, ухода в прерывание не произойдет.
Он произойдет только через 90 мкс.
И в течение всего этого времени, задержка должна отрабатываться.
То есть, если речь идет о наихудшем варианте, то время отработки задержки должно
быть, как минимум, на 90 мкс. больше рассчетного (см. формулу).
И это особенно актуально тогда, когда величина задержки более-менее соизмерима с
периодом ухода в прерывания.
Например, для "плюс-минус-двухлаптевой" задержки PAUSE_2, и особенно на "фоне" ее
"внушительной массы", это не актуально.
А вот для "слабосильных" задержек типа PAUSE_3 / PAUSE_4, это актуально.
И даже очень. Это подтверждается тем, что выше выделено красным цветом.
Решение этой проблемы на удивление простое: в начале задержки, нужно
принудительно обеспечить уход в 1-е прерывание.
Это мы раньше уже проходили.
Получилось это:

.....................................
.....................................
;================================================================================
; Задержки, использующиеся в процедуре инициализации термодатчика.
;================================================================================
PAUSE_3 bsf IntCon,7 ; РАЗРЕШЕНИЕ ПРЕРЫВАНИЙ.
movlw .36 ; 500 -> 22,2 х 5 = 111 мц .36
movwf Reg_1 ; K=4/90=0,0444
goto $+4
PAUSE_4 bsf IntCon,7 ; РАЗРЕШЕНИЕ ПРЕРЫВАНИЙ.
movlw .18 ; 250 -> 11 x 5 = 55 мц .18
movwf Reg_1
movlw .109 ; Обеспечение ухода в прерывание
movwf TMR2 ; в начале отработки задержки.
decfsz Reg_1,F
goto $-1
bcf IntCon,7 ; ЗАПРЕТ ПРЕРЫВАНИЙ.
return ; Возврат по стеку.
;================================================================================
.....................................
.....................................

Внесенные изменения выделены красным цветом.


В ПП PAUSE_2, я не стал производить коррекцию содержимого TMR2.
Зачем "плодить" дополнительные команды, если в данном случае, без этого вполне
можно обойтись?
Активирую орлиный взор и высматриваю, что бы еще такое "придушить".
"Есть боевой контакт"!
В связи с "введением в эксплуатацию" задержек PAUSE_3 / PAUSE_4, ПП PAUSE_X1
используется всего один раз.
"Убиваю" ее (кстати, она довольно-таки "упитанная") и "перепоручаю" ее функции
задержке PAUSE_X2.
19
70 мкс. (350 м.ц.) она "спокойно потянет" (константа .116).
Далее, в целях обеспечения "орфографическоарифметического порядка",
переименовываю ПП PAUSE_X2 в ПП PAUSE_X1.
Так оно как-то симпатичнее (в противном случае, 2 есть, а 1 нет. Бардак!).
Получилось это:

.....................................
.....................................
;################################################################################
; НИЖНЯЯ "ОБСЛУГА" 2-й СТРАНИЦЫ.
;################################################################################
; Инициализация термодатчика.
;================================================================================
; Установка на линии DQ 1.
;-----------------------------------
DQ_INIT call PIN_HI ; Установка вывода в высокоимпедансное
; состояние: за счет подтягивающего резистора,
; на линии устанавливается 1.
;-----------------------------------
; Установка на линии DQ 0.
;-----------------------------------
call PIN_LO ; Установка на линии DQ нуля.
;-----------------------------------
; Задержка 500 мкс. (условно)
;-----------------------------------
bcf PCLATH,3 ; Выбор 1-й страницы.
call PAUSE_3 ; Переход в ПП задержки.
bsf PCLATH,3 ; Выбор 2-й страницы.
;-----------------------------------
; Установка на линии DQ 1.
;-----------------------------------
call PIN_HI ; Установка вывода в высокоимпедансное
; состояние: за счет подтягивающего резистора,
; на линии устанавливается 1.
;-----------------------------------
; Задержка 70 мкс.
;-----------------------------------
movlw .116 ;
call PAUSE_X1 ; Задержка.

;;; movlw .7 ; Установка количества проходов по 10мкс.


;;; call PAUSE_X1 ; Переход в ПП задержки
;;; ; (задержка=7х10=70мкс.)
;--------------------------------------------------------------------------------
; Определение наличия (или нет) отклика на импульс сброса.
;--------------------------------------------------------------------------------
btfsc PortC,DQ ; На линии DQ 0 или 1 (отклик есть или нет)?
bsf Flag,1 ; Если отклика нет (1), то флаг наличия
; термодатчика поднимается.
; Если отклик есть (0), то флаг наличия
; термодатчика остается опущенным и программа
; исполняется далее.
;-----------------------------------
; Задержка 250 мкс. (условно)
;-----------------------------------
bcf PCLATH,3 ; Выбор 1-й страницы.
call PAUSE_4 ; Переход в ПП задержки.
bsf PCLATH,3 ; Выбор 2-й страницы.

return ; Возврат по стеку.


;================================================================================
.....................................
.....................................

Внесенные изменения выделены красным цветом.


20
"Убитое" выделено серым цветом.
Остальные два вызова задержки, с измененным названием (PAUSE_X1), находятся в
ПП WIRE.
"Разрисовывать" не стал. Надеюсь, что сообразите.
После этих "катаклизмов", смотрю в окно ROM.
Имеется "бяка": в результате "убийства" ПП задержки, кратной 10 мкс., "граница" между
1-м и 2-м блоками 2-й страницы PC "залезла" в таблицу вычисляемого перехода
(ПП TEXT_44).
"Гитлер капут" получается.
Значит, нужно как-то скомпенсировать эту потерю.
Из нижней "обслуги" 2-й страницы PC, в "стык" между 1-м и 2-м блоками 2-й страницы
PC, перемещаю ПП задания адреса (ADRES_1) и ПП вывода на индикацию символа
(SIMVOL_1 / SIMVOL_T_1).
Теперь все в порядке.
"Загоняю все это безобразие в железо". Включаю.
Никакого ЁКЛМН !!! Душа ликует и поёт !!!
Зачем водку пить, если в жизни существуют такие приятные моменты? (в одном
флаконе и адреналин, и гормоны счастья)
Примечание: выставленные константы (.36 и .18) ориентированы на наихудший вариант.
Реально же, временнЫе параметры термодатчика лучше предельных, временнЫх
параметров, указанных разработчиками (частенько даже в разы).
То есть, числовые значения этих констант можно подобрать экспериментально
(постепенно уменьшая их значения), ориентируясь на факт сбоя в работе конкретного
термодатчика.
Потом нужно немного "накинуть сверху" (процентов 20 от "сбойного варианта"), и все
дела.
Наученный горьким опытом ("фингал" еще свежий и синий, но это не должно
смущать), внимательно проверяю текст программы на предмет отсутствия, в "зонах"
разрешения прерываний, переходов на 2-ю страницу памяти программ.
Нет их. Ну и ладушки.

"Фингал заживет", а опыт останется (извилина крепчает).


Советую поместить это "философское" высказывание в красивую рамку (можно даже и
в позолоченную) и вывесить его на почетном месте.

Итак, все задачи, сформулированные в начале этого подраздела, выполнены.


Каковы "девиденды" от этих усилий?
Они таковы:

1. Наихудшая инерционность срабатывания защиты по превышению порогов


U/I (в комплексе) уменьшена со 100 мкс. до 90 мкс. (а если точнее, то до
89,5977 мкс.). Можно и еще уменьшить на 1, 2 и даже 3 мкс.
Дерзайте, если есть желание.
2. Параметры защиты от КЗ существенно улучшились.
3. "Масса" текста программы (без учета "ефрейторского суперзазорища")
сократилась на 3137 – 2897 = 240 команд.
4. "Масса ефрейторского суперзазорища" возросла до 115-ти ячеек PC. В
будущем, это позволяет существенно нарастить функциональность
"базовой" программы.

В "матке" программы, более четко "проглядываются администраторские" функции, что,


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

21
Для Вас (я, как автор, сориентируюсь легко), это черевато понятийными проблемами,
которые совсем не нужны.
Даже без учета этого, программа "скомпрессирована" очень даже прилично.
С учетом того, какое количество дел "вытворяется" в этой программе, ее
"скомпрессированную массу" можно уподобить "массе" архивного файла, в котором
"скомпрессирован", к примеру, текстовый файл (уменьшение исходной "массы" в разы,
при полном сохранении функциональности).
В этом и заключается искусство оптимизации.
Человек, который владеет этим искусством, "засунет", в один и тот же объем PC,
гораздо больше функциональностей, нежели человек, который этим искусством не
владеет.
Польза от этого очевидна. Поэтому и "трепыхаюсь".

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


Принципиальная схема - без изменений.

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

22