Вы уже должны заметить, что каждый подраздел этой темы посвящен поэтапному
решению конкретных и реально выполнимых задач.
Для того чтобы их решать, их нужно сформулировать.
Сначала на "глобальном" (или "подглобальном") уровне.
В большинстве случаев, "глобальная" задача состоит из того или иного количества
более "мелких" подзадач (что-то типа "ветвления").
Умение качественно решать отдельные подзадачи, без умения свести их в единое
целое, это как велосипед со спущенными шинами, на котором далеко не уедешь.
Для того чтобы качественно решить "глобальную" задачу, нужно уметь делать оба этих
дела. В комплексе. Неразрывно (должно работать "боковое зрение").
То есть, решая ту или иную "подзадачу", нужно постоянно анализировать последствия
ее решения, на предмет их "вписывания в общий, глобальный контекст".
Это что-то типа врачебного принципа "вылечи и не навреди".
Ведь как зачастую бывает: например, врач лечит почки.
Вылечил. Но после этого печень отвалилась (или наоборот).
Заключение: может быть этот врач и распрекрасный человек, но учиться ему
архинужно.
Хотя бы в целях самосохранения, ведь можно "нарваться" на большие неприятности.
Врач-профи вылечит почки так, что печень вообще не отвалится.
Это и есть истинный гуманизм. Не на словах, а на деле.
В нашей "епархии" - то же самое.
Только вместо врача - конструктор, а вместо пациента - программа/"железяка".
Если конструктор проявит указанный выше, истинный гуманизм, то в дальнейшем,
программа/"железяка" и бутылочку коньячку (или чего-то еще) поднесет, и слезы
благодарности прольет, и позаботится о создании репутации типа "ого-го".
А теперь ближе к делу.
В настоящее время, имеется программа, отдаленно претендующая на звание "базовой".
Вопрос: "Можно ли расширить ее функциональность"?
Ответ: можно. И нужно.
Но только после того, как будет "выдана на гора" эта самая "базовая" программа.
Сие есть мнение моего "внутреннего цензора", с которым я согласен.
А раз это так, то нужно довести программу до соответствующего состояния.
В связи с этим, возникают три "глобальные" задачи:
1. "Влажная уборка".
1
Эта работа, в идеале, должна быть сделана так, чтобы после нее, нЕчего было бы
"зачищать".
И ее обязательно нужно сделать, так как для "базовой" программы, функциональность
которой, в дальнейшем, будет наращиваться, это очень актуально.
Особенно в части касающейся "ефрейторского суперзазорища".
К тому же, совсем не помешает навести окончательный порядок в
"текущенавороченном".
Голос из-за кулис: "ЗадолбАл ты своей оптимизацией. Сколько можно"!
Ответ: сколько нужно, столько и можно.
А нужно практически всегда.
В идеале, в течение всего процесса работы над программой.
Если бы я ранее этого не делал, то пришлось бы поневоле задуматься о переходе с
PIC16F873A на PIC16F876A.
Вопрос: "Какая оптимизация нужна"?
Ответ: нужна командная оптимизация (результат - уменьшение количества команд).
Компромиссная оптимизация отпадает.
Вопрос: "Что нужно заоптимизировать"?
Ответ: все те же дублирующиеся состояния, только не в приложении к таблицам ПП
вычисляемых переходов ("рулевые" группы команд не в счет), а в приложении к
остальному.
Проще говоря, речь идет о дублирующихся группах команд, которые не входят в
состав этих таблиц.
Ранее, в ходе предварительной оптимизации, подобное имело место быть.
В данном случае, по своей сути, всё то же самое, только "рангом помельче".
В том смысле, что речь идет о достаточно "худосочных" группах команд малого
"объема", но за счет того, что их количество велико, можно "высвободить" вполне
приличное количество ячеек PC.
Поехали.
Примечание: используется все тот же строго поэтапный принцип работы.
2
bcf Status,RP0 ; Если завершена, то
bcf Status,RP1 ; переход в 0-й банк.
....................................
....................................
;================================================================================
; ПП записи значения порога 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 ; Возврат по стеку.
;================================================================================
....................................
....................................
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 ; Возврат по стеку.
;================================================================================
....................................
....................................
3.
Перехожу на то, что "помельче", но что дублируется большое количество раз.
Например, изначально имеется:
....................................
....................................
;================================================================================
; Вывод на индикацию числовых значений температуры.
;================================================================================
IND_TERMO movf LED1,W ; LED1 -> W.
movwf PortB ; содержимого LED1.
bsf PortC,RS ;
call ENTER_BF ;
....................................
....................................
;================================================================================
; ПП вывода на индикацию символа.
;================================================================================
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-й странице).
;================================================================================
; ПП вывода на индикацию символа.
;================================================================================
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 ; Вывод на индикацию этого символа
; (взамен символу "=").
....................................
....................................
....................................
....................................
;================================================================================
; ПП задания адреса.
;================================================================================
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 ; Вывод на индикацию этого символа
; (взамен символу "=").
....................................
....................................
;================================================================================
; ПП задания адреса.
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-й странице).
8
movf Count,W ;
sublw .16 ; Аналогично, только
call TEXT_18 ; для TEXT_18.
call SIMVOL_T ; Вывод символа на индикацию.
decfsz Count,F ;
goto $-5 ;
6.
Две команды можно "сэкономить" при переходе с двухкомандного на однокомандный
вариант работы с регистром PCLATH.
Это первый случай:
;================================================================================
; Вывод на индикацию, во 2-ю строку, фиксированной надписи " температуры ".
;================================================================================
...................................
...................................
;================================================================================
; Обеспечение необходимого времени "высвечивания" надписи.
;================================================================================
;;; movlw high PAUSE_S; Выбор PCH 1-й команды ПП PAUSE_S
;;; movwf PCLATH ; (находится на 1-й странице).
;================================================================================
; Вывод на индикацию, в 2-ю строку, фиксированной надписи " разблокировка ".
;================================================================================
...................................
...................................
;================================================================================
; Обеспечение необходимого времени "высвечивания" надписи.
;================================================================================
;;; movlw high PAUSE_S; Выбор PCH 1-й команды ПП PAUSE_S
;;; movwf PCLATH ; (находится на 1-й странице).
Оба этих случая имеют место быть на 2-й странице памяти программ.
7.
В сценарии включенной защиты, имеются две такие группы команд:
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.
....................................
....................................
10
;********************************************************************************
; НАЧАЛО ИСПОЛНЕНИЯ ПРОГРАММЫ.
;********************************************************************************
; Подготовительные операции.
;================================================================================
START
....................................
....................................
movlw .111 ; Задание периода ухода в прерывания
movwf PR2 ; (PR2=.111, F=11,161 Кгц., T=89,5977 мкс.).
bcf Status,RP0 ; Переход в 0-й банк.
;--------------------------------------------------------------------------------
; Обеспечение "разгона" вентиллятора.
;--------------------------------------------------------------------------------
....................................
....................................
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 ; Возврат по стеку.
;================================================================================
;================================================================================
; ПП задержки, обеспечивающей "пережидание" температурного преобразования.
; 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-й странице).
....................................
....................................
;-------------------------------------
; Подготовка к 2/10 преобразованию.
;-------------------------------------
movf Temp_LSB,W ; Temp_LSB -> W.
;================================================================================
; 2/10 преобразование (1х2) с перекодировкой результата.
;================================================================================
call BIN2_10_T ; Переход в ПП 2/10 преобразования.
;================================================================================
; Вывод на индикацию текущего значения температуры.
;================================================================================
....................................
....................................
;================================================================================
; 2/10 преобразование (1х2) с перекодировкой результата.
;================================================================================
bcf PCLATH,3 ; Выбор 1-й страницы.
call BIN2_10_T ; Переход в ПП 2/10 преобразования.
bsf PCLATH,3 ; Выбор 2-й страницы.
;================================================================================
....................................
....................................
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
; ПП ПРОВЕРКИ ПРЕВЫШЕНИЯ/НЕ ПРЕВЫШЕНИЯ ПОРОГОВ. &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
PROV_U_I movlw .10 ; Задание количества отрабатываемых
movwf Temp ; циклов ("ставятся на счетчик").
15
; Обеспечение необходимой скорости смены показаний.
;================================================================================
call PAUSE_UI ; Задержка.
....................................
....................................
;================================================================================
; Задержки, использующиеся в процедуре инициализации термодатчика.
;================================================================================
PAUSE_3 bsf IntCon,7 ; РАЗРЕШЕНИЕ ПРЕРЫВАНИЙ.
movlw .250 ;
movwf Reg_1
goto $+4
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-й страницы.
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 ; Возврат по стеку.
;================================================================================
.....................................
.....................................
.....................................
.....................................
;################################################################################
; НИЖНЯЯ "ОБСЛУГА" 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 ; Задержка.
21
Для Вас (я, как автор, сориентируюсь легко), это черевато понятийными проблемами,
которые совсем не нужны.
Даже без учета этого, программа "скомпрессирована" очень даже прилично.
С учетом того, какое количество дел "вытворяется" в этой программе, ее
"скомпрессированную массу" можно уподобить "массе" архивного файла, в котором
"скомпрессирован", к примеру, текстовый файл (уменьшение исходной "массы" в разы,
при полном сохранении функциональности).
В этом и заключается искусство оптимизации.
Человек, который владеет этим искусством, "засунет", в один и тот же объем PC,
гораздо больше функциональностей, нежели человек, который этим искусством не
владеет.
Польза от этого очевидна. Поэтому и "трепыхаюсь".
22