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

2-2/11. Расширение функциональности: работа с температурой.

"Ваяние"
системы автоматического терморегулирования (термодатчик DS1820/18S20,
компьютерный вентиллятор) с ШИМ-регулированием количества оборотов и
функцией автоопознавания наличия/отсутствия термодатчика.
Разработка сценария-помощника (подсказки) №3.

Предлагаю Вашему вниманию текущую (она тоже "течет") принципиальную схему:

Для "сглаживания броска" тока, применен однозвенный ФНЧ (R3,C4), с разрядной


"цепочкой" VD1,R4.
Диод - практически любой. Я использовал "малогабаритную красатульку".
Постоянную времени этого ФНЧ специально выбрал большой, для того чтобы было
видно, что после "отмашки" на включение нагрузки, светодиод наращивает свою
яркость постепенно ("бросок" тока "сглаживается").
И это четко будет видно (сделано в познавательно-"прошибательных" целях. Лучше
1 раз …).
Также будет видно и то, что после срабатывания блокировки, светодиод "резко
погаснет".
За что ранее "и кровь проливалась".
Естественно, что в дальнейшем, эту постоянную времени можно уменьшить (увеличить
частоту среза ФНЧ), и прежде всего за счет уменьшения емкости конденсатора C4.
Все это происходит "на фоне электролита" номиналом 500 мкф., подключенного к
активной нагрузке (активно-емкостная нагрузка).
"По барабану". При таком "раскладе", "бросок" тока будет "безжалостно задушен".
Правда, "медленновато" (смахивает на садизм. Даже "убивать врагов" нужно гуманно.
Чтобы меньше страдали), ну ничего… Еще не вечер.
Пока, самое главное - принцип и наглядность, а потом и "гуманизм подрихтуем".
На схеме, фиолетовым цветом выделены резисторы нижнего и верхнего плеча
делителя напряжения (Rн,Rв).
Можно реализовать два варианта:
1. Для шага измерения напряжения 0,1 в, Кделения делителя должен быть 1:20
(диапазон измерения от 0 до 99,9 в. С учетом программного "убийства" ненужных
квантовок).
2. Для шага измерения напряжения 0,05 в, Кделения делителя должен быть 1:10
(диапазон измерения от 0 до 49,9 в. С учетом того же сАмого).

1
Напоминаю, что в данном случае, речь идет о визуальном отображении одного
десятичного разряда после запятой, а не двух, и поэтому, какого-то "могучего" смысла,
в использовании 2-го варианта, нет.
Вот если бы после запятой было 2 десятичных разряда, тогда совсем другое дело
(обычно, более 50-ти вольт не требуется).
В этом случае, точность замера U повысится в 2 раза.
В будущем, "и это дельце можно провернуть" (требуется вполне приличная,
программная доработка), а пока, лучше поработать с тем, что есть и ориентироваться
на Кделения = 1:20.
Номиналы резисторов Rн,Rв могут выбираться (с учетом Кдел.) в широком диапазоне,
так как входное сопротивление неинвертирующего ОУ, с единичным Кусиления, очень
высоко.
Например, номинал Rн можно выбрать = 10 Ком, а затем "просчитать" Rв. И т.д.
Это кому как удобнее и "у кого что под рукой".
В делителе напряжения, желательно использовать резисторы с малым температурным
коэффициентом сопротивления.
Пока, я не буду заниматься делителем напряжения, так как это, как говорится, "дело
техники", которое "никуда не денется", а буду пользоваться все той же имитацией (см.
резистор R1), так как, "на стадии экспериментов", она удобна.
Желающие могут заняться делителем U и что-нибудь поизмерять.
Никаких препятствий этому нет. Измеряйте на здоровье.
Я же сейчас "пойду туда, где Макар телят еще не гонял" (там, кстати, "кирпичи
летают").
Речь идет о "введении в эксплуатацию" дополнительной функции
терморегулирования/термозащиты.
Слава Богу, настало время "боевого" применения ранее "термонарытого"…
Использовать буду термодатчик DS1820 (DS18S20).
Контроль температуры будет осуществляться с целью сравнения числовых значений
текущих замеров температуры с неким температурным порогом, после превышения
которого, защита срабатывает, а также с целью авторегулирования числа оборотов
"пропеллера" (о нем - ниже).
"Челюсть максимально выдвинута. Начинаю ей громко и неприлично клацать".
Для начала, кликаю летающую корову по кличке "Термодатчик" (Нет. На быка похоже.
Лучше "Термодатчица").
Прилетела, родимая. Жалобно мычит.
Понятно… Вымя так и пучит. На дойку напрашивается, бедолага.
Нет проблем. Подоим. Когда молока много, это очень хорошо и приятно.
С какой сиськи начать? Да все с той же - с главной (из нее аж капает).
Имеются 2 сценария, во время отработки любого из которых, транзистор может быть
открыт (а если закрыт, то и ничего перегреваться не будет): сценарий выключенной
защиты и сценарий включенной защиты.
Со сценарием выключенной защиты, нет никаких проблем.
Со сценарием включенной защиты, есть большущая проблема.
1-Wire протокол это протокол, в основе своей, "жестко привязанный" к времени
отработки некоторых его составляющих.
В течение интервалов времени некоторых его "кусков" (например, в интервале времени
температурного преобразования, если используется фиксированная задержка),
прерывания вполне можно разрешить.
Но это "счастье совсем не всеобъемлюще", так как, например, временнЫе параметры
обмена байтами "жестко регламентированы".
Если в него, с дуру или по незнанию, вмешаться (затянуть) посредством ухода в
прерывания, то "взаимопонимание" между термодатчиком и ПИКом будет капитально
нарушено.
Что, в этом случае, будет? Правильно. "Гитлер капут/некролог, венки" и т.п.
Причем, это, в данном случае (период ухода в прерывания 200 мкс.) фатально.
Без вариантов. "Просканировано" ранее.
Можно "ущипнуть проблему" где-нибудь "в другом месте", но как только начинается
обмен байтами, каждый такой "щипок смерти подобен".
Таков протокол ("правила игры").
2
Вывод: даже если, в ПП работы с термодатчиком, разрешить прерывания везде, где
это только возможно, то все-равно будут иметь место быть "локальные зоны" запретов
прерываний, которые "на кривой козе не объедешь".
А если и "объедешь", то только через "некролог" в честь "усопшей" программы.
Если, в ПП работы с термодатчиком, будет реализован самый "оптимистический"
вариант "уходов" в прерывания, протяженность (во времени) "локальных зон" запретов
прерываний можно существенно уменьшить.
Но не до нуля.
Это означает то, что в случае вызовов ПП работы с термодатчиком из сценария
включенной защиты, существует вероятность "затягивания" интервалов времени уходов
в прерывания, что есть увеличение инерционности срабатывания защиты.
В принципе, такая вероятность не так уж и велика, и поэтому бОльшую часть времени
устройство будет работать "как и положено" (в смысле заданной инерционности), но
иногда будут "проскакивать и затяжки".
В данном случае, полностью избавиться от них нельзя.
Их только можно попытаться минимизировать как по усредненной протяженности (во
времени) "хвостиков"/"довесков", так и по усредненному количеству "затяжек",
"проскакивающих" за какой-то фиксированный интервал времени (по интенсивности).
С целью "свершения" этого, можно "спровоцировать" отложенные прерывания (в
рассматриваемом случае, возникновение отложенных прерываний исключено) и сделать
так, чтобы вызов ПП работы с термодатчиком происходил не на каждом цикле
сценария включенной защиты, а например, на каждом 10-м, 20-м, 50-м и т.д. (можно
задать любое число).
Первое требует самой натуральной, исследовательско-опытной работы, а второе не
требует практически ничего - банальная "постановка на счетчик".
Вопрос: "Как быть? Куда вектор (орлиный взор) направлять"?
Ответ: см. закон Ома. Чего "вожделеет" ток? Пути наименьшего сопротивления.
Примечание: ток придумали не люди, а кое-кто/что гораздо поумнее.
Вывод: имеется прямая выгода от "дужбы с этой концепцией" ("от простого к
сложному" - из этой же "оперы").
А раз это так, то "текущепадаю" на "укомплектование" сценария выключенной защиты
процедурой работы с термодатчиком, но "злобу на сценарий включенной защиты
текущезатаил"… (буду "огрызаться, кусаться и тявкать")
Сначала, нужно определиться с "глобальным".
То, что по факту превышения температурного порога (в дальнейшем, Т-порога) нужно
"вырубить" транзистор, понятно.
То, что нужно организовать температурный гистерезис, тоже понятно.
И все?
Скучновато как-то. Вентиллятор/пропеллер нужен.
С ним, гораздо веселее/шустрее ("Есть одна у летчика мечта …").
А также:
- авторегулировка количества оборотов вентиллятора (ШИМ-управление),
- автоопределение наличия/отсутствия термодатчика (с последующими
"оргвыводами"),
- аварийные сигналы срабатывания термозащиты и отсутствия
термодатчика,
- визуальный контроль текущей температуры, в интервале температур
петли температурного гистерезиса, в сравнении с текущим Т-порогом
("два в одном флаконе"),
- автоматическо-ручная терморазблокировка (на выбор).
Пока достаточно, а то "пупок можно надорвать" ("фиксатор сработал").
В перспективе:
- выбор пользователем, из предлагаемого меню, значений Т-порогов,
- автоустановка (по значению Т-порога) ширины петли температурного
гистерезиса,
- еще что-нибудь (Если это "что-нибудь" нужно. Выяснится по ходу дела).
После осознания "сермяжной сути вышележащего", поначалу, становится немного
жутковато, но зато весело и задиристо (стимулирует нужный тонус).

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

Одна из этих надписей "высвечивается" сразу же после включения питания, в течение


примерно 3 секунд.
Затем она "пропадает" и начинается отработка сценария того режима, который имел
место быть на момент предыдущего выключения питания (с учетом сценариев-
подсказок).
Выше, это названо "сценариями отключенного/подключенного датчика".
Программно, автоопределение наличия/отсутствия термодатчика выглядит так:
.....................................
.....................................
;-----------------------------------
; Надпись " Термодатчик "
;-----------------------------------
TEXT_19 addwf PC,F ; -----"-----
dt 0x20,0x20,0x54,0x65,0x70,0xBC,0x6F,0xE3
dt 0x61,0xBF,0xC0,0xB8,0xBA,0x20,0x20,0x20
;-----------------------------------
; Надпись " ПОДКЛЮЧЕН "
;-----------------------------------
TEXT_20 addwf PC,F ; -----"-----
dt 0x20,0x20,0x20,0xA8,0x4F,0xE0,0x4B,0xA7
dt 0xB0,0xAB,0x45,0x48,0x20,0x20,0x20,0x20
;-----------------------------------
; Надпись " ОТКЛЮЧЕН "
;-----------------------------------
TEXT_21 addwf PC,F ; -----"-----
dt 0x20,0x20,0x20,0x20,0x4F,0x54,0x4B,0xA7
dt 0xB0,0xAB,0x45,0x48,0x20,0x20,0x20,0x20
.....................................
.....................................
;================================================================================
; Аварийная "пищалка" (мультивибратор, формирующий "пачку" импульсов).
;================================================================================

4
MULTI movlw .250 ; "Пищать" будем
movwf Reg_2 ; 250 периодов.

bcf PortC,4 ; Установка на выходе защелки RC4 уровня 0.


movlw .50 ; Задание периода
movwf Reg_3 ; (частоты).

decfsz Reg_3,F ; Формирование


goto $-1 ; полупериода.

btfsc PortC,4 ; Если на выходе защелки RC4 уровень 1,


goto $-6 ; то дальнейшая его смена на уровень 0.
decf Reg_2,F ; Если на выходе защелки RC4 уровень 0,
; то Reg_2 - 1 = ... и программа
; исполняется далее.
btfsc Status,Z ; Каков результат декремента ?
return ; Если =0, то "пачка" импульсов сформирована
; и выход из "пищалки".
bsf PortC,4 ; Если не=0, то установка на выходе
; защелки RC4 уровня 1.
goto $-.10 ; Переход на формирование следующего периода.
;================================================================================
.....................................
.....................................
;********************************************************************************
; НАЧАЛО ИСПОЛНЕНИЯ ПРОГРАММЫ.
;********************************************************************************
; Подготовительные операции.
;================================================================================
START ...............................
.....................................
clrf Flag ; Все флаги сбрасываются.
.....................................
.....................................
;================================================================================
; Процедура инициализации ЖКИ модуля.
;================================================================================
.....................................
.....................................
;ОООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООО
; Проверка наличия/отсутствия отклика от термодатчика.
;ОООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООО
call DQ_INIT ; Переход в ПП инициализации термодатчика.
;----> Возврат по стеку из ПП DQ_INIT.
;================================================================================
; Вывод на индикацию, в 1-ю строку, фиксированной надписи " Термодатчик ".
;================================================================================
movlw b'10000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 1-й строки.

bsf PCLATH,0 ; Так как далее будет исполнен вычисляемый


; переход, лежащий во 2-м блоке PC.
movlw .16 ;
movwf Count ;
movf Count,W ;
sublw .16 ;
call TEXT_19 ; Аналогично, только
bsf PortC,RS ; для TEXT_19.
call ENTER_BF ;
decfsz Count,F ;
goto $-6 ;
;--------------------------------------------------------------------------------
; Анализ состояния флага наличия/отсутствия термодатчика.
;--------------------------------------------------------------------------------
btfsc Flag,1 ; Если флаг поднят, выводится надпись
; " ОТКЛЮЧЕН "
5
goto TERMO_OTKL ; Если флаг опущен, выводится надпись
; " ПОДКЛЮЧЕН ".
;================================================================================
; Вывод на индикацию, во 2-ю строку, фиксированной надписи " ПОДКЛЮЧЕН ".
;================================================================================
movlw b'11000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 2-й строки.
movlw .16 ;
movwf Count ;
movf Count,W ;
sublw .16 ; Аналогично, только
call TEXT_20 ; для TEXT_20.
bsf PortC,RS ;
call ENTER_BF ;
decfsz Count,F ;
goto $-6 ;
;================================================================================
; Обеспечение необходимого времени "высвечивания" надписи.
;================================================================================
call PAUSE_S ; Задержка.
;----> Возврат по стеку из ПП PAUSE_S.
clrf PCLATH ; Так как далее будет исполнен вычисляемый
; переход, лежащий в 1-м блоке PC.
goto START_1 ; Переход на метку START_1 (обход).
;================================================================================
; Вывод на индикацию, во 2-ю строку, фиксированной надписи " ОТКЛЮЧЕН ".
;================================================================================
TERMO_OTKL movlw b'11000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 2-й строки.
movlw .16 ;
movwf Count ;
movf Count,W ;
sublw .16 ; Аналогично, только
call TEXT_21 ; для TEXT_21.
bsf PortC,RS ;
call ENTER_BF ;
decfsz Count,F ;
goto $-6 ;
;================================================================================
; Формирование звукового сигнала отсутствия термодатчика.
;================================================================================
movlw 3 ; Задание количества
movwf Temp ; "писков".

call PAUSE_UI ; Задержка.


;----> Возврат по стеку из ПП PAUSE_UI.

call MULTI ; Переход в ПП аварийной "пищалки".


;----> Возврат по стеку из ПП MULTI.
decfsz Temp,F ; "Постановка на счетчик"
goto $-3 ; количества "писков".
;================================================================================
; Обеспечение необходимого времени "высвечивания" надписи.
;================================================================================
call PAUSE_S ; Задержка.
;----> Возврат по стеку из ПП PAUSE_S.
;================================================================================
; Перевод вентиллятора на заданное количество оборотов
; (в данном случае, на максимальные).
;================================================================================
movlw .255 ;
movwf CCPR1L ; CCPR1L = 11111111
;================================================================================
clrf PCLATH ; Так как далее будет исполнен вычисляемый
; переход, лежащий в 1-м блоке PC.
;================================================================================
6
; Предварительное (с глобальным запретом) разрешение прерываний
; по переполнению TMR2.
;================================================================================
START_1
.....................................
.....................................
;================================================================================
; Инициализация термодатчика.
;================================================================================
; Установка на линии DQ 1.
;-----------------------------------
DQ_INIT call PIN_HI ; Установка вывода в высокоимпедансное
; состояние: за счет подтягивающего резистора,
; на линии устанавливается 1.
;----> Возврат по стеку из ПП PIN_HI.
;-----------------------------------
; Установка на линии DQ 0.
;-----------------------------------
call PIN_LO ; Установка на линии DQ нуля.
;----> Возврат по стеку из ПП PIN_LO.
;-----------------------------------
; Задержка 600 мкс.
;-----------------------------------
movlw .60 ; Установка количества проходов по 10мкс.
call PAUSE_X1 ; Переход в ПП задержки
; (задержка=60х10=600мкс.).
;----> Возврат по стеку из ПП PAUSE_X1.
;-----------------------------------
; Установка на линии DQ 1.
;-----------------------------------
call PIN_HI ; Установка вывода в высокоимпедансное
; состояние: за счет подтягивающего резистора,
; на линии устанавливается 1.
;----> Возврат по стеку из ПП PIN_HI.
;-----------------------------------
; Задержка 70 мкс.
;-----------------------------------
movlw .7 ; Установка количества проходов по 10мкс.
call PAUSE_X1 ; Переход в ПП задержки
; (задержка=7х10=70мкс.).
;----> Возврат по стеку из ПП PAUSE_X1.
;--------------------------------------------------------------------------------
; Определение наличия (или нет) отклика на импульс сброса.
;--------------------------------------------------------------------------------
btfsc PortC,DQ ; На линии DQ 0 или 1 (отклик есть или нет)?
bsf Flag,1 ; Если отклика нет (1), то флаг наличия
; термодатчика поднимается.
; Если отклик есть (0), то флаг наличия
; термодатчика остается опущенным и программа
; исполняется далее.
;-----------------------------------
; Задержка 500 мкс.
;-----------------------------------
movlw .50 ; Установка количества проходов по 10мкс.
call PAUSE_X1 ; Переход в ПП задержки
; (задержка=50х10=500мкс.).
;----> Возврат по стеку из ПП PAUSE_X1.
return ; Возврат по стеку.
;================================================================================
.....................................
.....................................
;================================================================================
; Формирование на линии уровня "1" за счет подтягивающего резистора.
;================================================================================
PIN_HI bsf Status,RP0 ; Переход в банк 1.
bsf TrisC,DQ ; Настройка вывода RC0 на работу "на вход".
7
bcf Status,RP0 ; Переход в банк 0.
return ; Возврат по стеку.
;================================================================================
; Формирование на линии уровня "0" средствами микроконтроллера
;================================================================================
PIN_LO bcf PortC,DQ ; Установка 0 на выходе защелки вывода RA4.
bsf Status,RP0 ; Переход в банк 1.
bcf TrisC,DQ ; Настройка вывода RC0 на работу "на выход".
bcf Status,RP0 ; Переход в банк 0.
return ; Возврат по стеку.
;================================================================================
; ПП задержки, кратной 10 мкс.
;================================================================================
; Задание количества проходов по 10 мкс.
;----------------------------------------
PAUSE_X1 movwf Count ; W --> Count.
;----------------------------------------
; Задержка 10 мкс.
;----------------------------------------
PAUSE_10 nop ;
goto $+1 ; Одноразрядный,
goto $+1 ; вычитающий
goto $+1 ; счетчик
decfsz Count,F ; с "врезкой".
goto PAUSE_10 ;
return ; Возврат по стеку.
;================================================================================
.....................................
.....................................
Процедура инициализации датчика - стандартная (например, как в программе
ds1820_1.asm), только в случае отсутствия отклика датчика, "закольцовки", на начало
ПП инициализации датчика, не происходит, а просто поднимается флаг
наличия/отсутствия термодатчика: бит №1 регистра Flag.
Если отклик есть, то этот флаг остается опущенным (все флаги, "оптом" опускаются в
ПП START).
В дальнейшем, состояние этого флага проверяется.
После возврата из процедуры инициализации датчика, на индикацию, в 1-ю строку,
всегда выводится надпись " Термодатчик ", так как она присутствует в любом
случае (см. "вышележащие" картинки).
Далее - проверка флага наличия/отсутствия термодатчика.
Соответственно, имеются 2 возможных сценария.
1. Если флаг наличия/отсутствия термодатчика опущен (датчик обнаружен), то сначала,
на индикацию, во 2-ю строку, выводится надпись " ПОДКЛЮЧЕН ", затем, для того
чтобы надпись " Термодатчик / ПОДКЛЮЧЕН " "помозолила глаза", отрабатывается
фиксированная задержка.
После этого, производятся числовая коррекция содержимого регистра PCLATH (это
нужно) и обход той программной процедуры, которая отрабатывается в случае
"необнаружения" датчика.
2. Если флаг наличия/отсутствия термодатчика поднят (датчик не обнаружен), то
сначала, на индикацию, во 2-ю строку, выводится надпись " ОТКЛЮЧЕН ", затем
отрабатывается ПП аварийной "пищалки", которая "поставлена на счетчик количества
писков".
В данном случае, задано 3 "писка", но можно и изменить это количество на свой вкус.
Задержка PAUSE_UI нужна для формирования временнЫх "зазоров" между "писками".
Так как ПП аварийной "пищалки" задействуется более одного раза, я назвал ее MULTI
и вынес в верхнюю "обслугу".
Далее, для того чтобы надпись " Термодатчик / ОТКЛЮЧЕН " "помозолила глаза",
отрабатывается фиксированная задержка.
После этого, вентиллятор переводится на фиксированное (заданное) количество
оборотов.
;================================================================================
; Перевод вентиллятора на заданное количество оборотов
8
; (в данном случае, на максимальные).
;================================================================================
movlw .255 ;
movwf CCPR1L ; CCPR1L = 11111111

Необходимо пояснить, что вентиллятор управляется сигналом ШИМ (задействован


модуль CCP), и изменяя коэффициент заполнения (числовое значение константы),
можно выставить те обороты, которые "греют конкретную душу".
Два младших бита (CCP1CON,5 и CCP1CON,4) "погоды не делают" потому, что они
младшие. Поэтому и работы с ними нет.
Об организации ШИМ-регулирования, речь пойдет ниже.
В данном случае, вентиллятор переводится на максимальное количество оборотов и
работает постоянно на этих оборотах, но можно задать и меньшее их количество.
Таким образом получается, что даже при отсутствии термодатчика, вентиллятор будет
работать, только на заданных в программе, фиксированных оборотах.
А если на максимуме он сильно шумит, то можно сделать обороты и поменьше.
После задания оборотов, производится числовая коррекция содержимого регистра
PCLATH, так как работа происходила с вычисляемыми переходами одного блока PC, а
в дальнейшем, будет происходить работа с вычисляемыми переходами другого блока
PC.
Далее, по ходу отработки программы, по факту поднятия флага наличия/отсутствия
термодатчика, все переходы в ПП работы с термодатчиком будут банально обойдены.
Это, в простейшем случае, выглядит так:
.....................................
.....................................
btfsc Flag,1 ; Флаг наличия/отсутствия термодатчика поднят
; или нет ?
goto $+2 ; Если поднят, то обход ПП работы с датчиком.
call TERMO ; Переход в ПП работы с датчиком.
;--> Возврат по стеку из ПП TERMO.
.....................................
.....................................

Или так (более сложный случай):


.....................................
.....................................
btfss Flag,1 ; Флаг наличия/отсутствия термодатчика поднят
; или нет ?
goto $+3 ; Если опущен, то работа с датчиком.
bsf PortA,2 ; Если поднят, то ОТКРЫТИЕ ТРАНЗИСТОРА
goto $+2 ; и обход работы с датчиком.
call TERMO ; Переход в ПП работы с датчиком.
;----> Возврат по стеку из ПП TERMO.
.....................................
.....................................

В случае же, если флаг наличия/отсутствия термодатчика опущен (датчик обнаружен),


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

Предположим, что датчик (DS1820/DS18S20) подключен.


Естественно, что сразу же возникает вопрос о подпрограмме, которая будет
обеспечивать замеры температуры.
Ну уж очень мне приглянулся, своей программной оригинальностью, "терморезультат"
"взлома" программы, обслуживающей терморегулятор, о котором шла речь в 3-м
разделе "Самоучителя по программно – аппаратному анализу".
Этот "терморезультат" и применил.
За основу взята программа Termo_30.asm (см. приложение 3а).
Естественно, что ее пришлось "опустить" до уровня подпрограммы и "адаптировать"
(подкорректировать) под ту программу, которой я сейчас занимаюсь.

9
Получилось вот что:
.....................................
.....................................
;================================================================================
; Универсальная задержка
;(время задержки определяется предустановленным содержимым W).
;================================================================================
PAUSE_X
.....................................
.....................................
;================================================================================
.....................................
.....................................
;********************************************************************************
; НАЧАЛО ИСПОЛНЕНИЯ ПРОГРАММЫ.
;********************************************************************************
; Подготовительные операции.
;================================================================================
START
.....................................
.....................................
bsf PortC,DQ ; DQ = 1.
.....................................
.....................................
;DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
; ПП работы с датчиком.
;DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
; "Администраторская" группа команд.
;--------------------------------------------------------------------------------
TERMO call DQ_INIT ; Инициализация датчика.
;--->Возврат по стеку из ПП DQ_INIT
movlw 0CCh ; Выполнение команды
call WIRE ; "Skip_ROM".
;--->Возврат по стеку из ПП WIRE
movlw 44h ; Выполнение команды
call WIRE ; "Start_Conv".
;--->Возврат по стеку из ПП WIRE
bsf Flag,0 ; Поднятие флага исполнения/обхода
; "плавающей" задержки.
call WIRE ; Исполнение процедуры 1-Wire протокола.
;--->Возврат по стеку из ПП WIRE
bcf Flag,0 ; Сброс флага исполнения/обхода
; "плавающей" задержки.
call DQ_INIT ; Инициализация датчика.
;--->Возврат по стеку из ПП DQ_INIT
movlw 0CCh ; Выполнение команды
call WIRE ; "Skip_ROM".
;--->Возврат по стеку из ПП WIRE
movlw 0BEh ; Выполнение команды
call WIRE ; "Read_Scratchpad".
;--->Возврат по стеку из ПП WIRE
;--------------------------------------------------------------------------------
; Чтение младшего байта температуры.
;--------------------------------------------------------------------------------
movlw b'11111111' ; "Нейтральный" байт.
call WIRE ; Чтение.
;--->Возврат по стеку из ПП WIRE
movwf Temp_LSB ; Результат замера температуры (младший байт)
; записывается в регистр Temp_LSB.
;--------------------------------------------------------------------------------
.....................................
.....................................
;--------------------------------------------------------------------------------
; Сравнение с температурным порогом.
;--------------------------------------------------------------------------------

10
movf T_Porog,W ; T_Porog -> W.
subwf Temp_LSB,W ; Temp_LSB - T_Porog =... (результат -> W)
btfsc Status,C ; Результат "+/=0" или "-"
; (порог превышен или нет) ?
goto PEREGREV ; Если порог превышен, то обход процедуры
; перевода числового значения младшего байта
; температуры в ширину импульсов.
;================================================================================
; Перевод числового значения младшего байта температуры в ширину импульсов.
;================================================================================
.....................................
.....................................
return ; Возврат по стеку.
;================================================================================
; Исполняется в случае превышения порога.
;================================================================================
PEREGREV bcf PortA,2 ; Если порог превышен, то
; ТРАНЗИСТОР ЗАКРЫВАЕТСЯ.
movlw .255 ; Перевод вентиллятора
movwf CCPR1L ; на максимальные обороты.

;********************************************************************************
; Начало сценария-помощника №3
;********************************************************************************
.....................................
.....................................
return ; Возврат по стеку.
;================================================================================
; Инициализация термодатчика.
;================================================================================
.....................................
.....................................
;WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
; ПРОЦЕДУРА 1-WIRE ПРОТОКОЛА.
;WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
WIRE movwf Wire ; W --> Wire.
movlw 8 ; Задание количества
movwf Temp ; обрабатываемых битов.
;================================================================================
; Передача бита в линию DQ.
;================================================================================
; Установка на линии DQ уровня 0, то есть,
; формирование строба (перепад от 1 к 0).
;-----------------------------------------
METKA bcf PortC,DQ ; DQ=0.
nop ; Задержка 1 м.ц.
nop ; Задержка 1 м.ц.
;----------------------------------------
; Анализ состояния бита №0 регистра Wire.
;----------------------------------------
btfsc Wire,0 ; Wire,0 = 1 или 0 ?
bsf PortC,DQ ; Если Wire,0 = 1, то DQ=1.
rrf Wire,F ; Если Wire,0 = 0, а также после исполнения
; предыдущей команды, происходит сдвиг
; содержимого Wire вправо.
;------------------------------------------------
; Задержка на 11 м.ц. (от movlw 2 до bcf Wire,7).
;------------------------------------------------
movlw 2 ; Предустановка.
call PAUSE_X ; Переход в ПП PAUSE_X.
;--->Возврат по стеку из ПП PAUSE_X

;================================================================================
; Прием бита с линии DQ.
;================================================================================
; Подготовка 7-го бита регистра Wire к записи в него уровня DQ.
11
;--------------------------------------------------------------
bcf Wire,7 ; Wire,7=0.
;--------------------------------------------
; Перестройка направления работы ("на вход").
;--------------------------------------------
bsf Status,RP0 ; Выбор 1-го банка.
bsf TrisC,DQ ; RC0 работает "на вход".
bcf Status,RP0 ; Выбор 0-го банка.
;--------------------------------------------------------------
; Анализ состояния линии DQ.
; Если DQ=1, то в бит №7 регистра Wire записывается 1.
; Если DQ=0, то в бите №7 регистра Wire остается
; "лежать" ранее предустановленный 0.
;--------------------------------------------------------------
btfsc PortC,DQ ; На линии DQ 1 или 0 ?
goto $+2 ; Если DQ=1, то обход следующей команды.
goto $+2 ; Если DQ=0, то обход следующей команды.
bsf Wire,7 ; Wire,7=1.
;--------------------------------------------
; Перестройка направления работы ("на выход").
;--------------------------------------------
bsf Status,RP0 ; Выбор 1-го банка.
bcf TrisC,DQ ; RC0 работает "на выход".
bcf Status,RP0 ; Выбор 0-го банка.
;---------------------------------------------------
; Задержка на 59 м.ц. (от movlw .18 до bsf PortC,DQ).
;---------------------------------------------------
movlw .18 ; Предустановка.
call PAUSE_X ; Переход в ПП PAUSE_X.
;--->Возврат по стеку из ПП PAUSE_X
;---------------------------------------------------
; Установка на линии DQ уровня 1
; (подготовка к формированию следующего строба).
;---------------------------------------------------
bsf PortC,DQ ; DQ=1.
nop ; Задержка 1 м.ц.
nop ; Задержка 1 м.ц.
;----------------------------------------
; Счет битов.
;----------------------------------------
decfsz Temp,F ; Декремент счетчика битов.
goto METKA ; Если отработаны не все биты, то
; переход на обработку следующего бита.
; Если все, то программа исполняется далее.
;--------------------------------------------------------------------------------
; Опрос состояния флага исполнения/обхода "плавающей" задержки.
;--------------------------------------------------------------------------------
btfss Flag,0 ; Флаг исполнения/обхода "плавающей" задержки
; поднят или опущен ?
goto $+6 ; Если опущен, то обход "плавающей" задержки.
; Если поднят, то "плавающая" задержка
; отрабатывается.
;--------------------------------------------------------------------------------
; Ожидание завершения процесса преобразования температуры ("плавающая" задержка).
;--------------------------------------------------------------------------------
movlw b'11111111' ; Запись в W числа FFh.
subwf Wire,W ; Temp - FFh = ...
btfss Status,Z ; Z=0 или Z=1 (нулевой результат)?
goto WIRE ; Если Z=0, то ждем дальше.
; Если Z=1 (Temp заполнен единицами, то есть,
; на линии появился и надежно зафиксировался
; уровень 1), то программа исполняется далее.
return ; Возврат по стеку.
;----------------------------------------
; Завершающий этап.
;----------------------------------------
12
movf Wire,W ; Wire --> W.
return ; Возврат по стеку.
;WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
.....................................
.....................................
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
end ; Конец программы.

ПП инициализации - та же самая, которая применялась при автоопределении


наличия/отсутствия термодатчика.
А раз это так (применяется более одного раза), то я ее вынес в "обслугу".
С учетом изменения названий некоторых регистров (а куда деваться?), все то же
самое, что и в программе Termo_30.asm, но имеется и "модернизация".
В данном случае, мне не нравится фиксированная задержка, применяемая для
"пережидания" процесса температурного преобразования (сердцу не прикажешь).
"Вожделею наишустрейшего", да и жизнь как-то разнообразить нужно.
Хотя бы, в познавательных целях.
Поэтому и применена "специфическо-оригинальная", "плавающая" задержка, речь о
которой шла в 1-й части "Практикума…".
Ее принцип "расписан" там же. Повторяться не буду.
Но особенность заключается в том, что так легко и просто, как это делалось в
"Практикуме…", ее, в ту процедуру замера температуры, которая применяется, не
"врежешь" .
"Плавающая" задержка должна отрабатываться только в случае исполнения
температурного преобразования, а во всех остальных случаях, она должна быть
обойдена.
Специфика данной ПП замера температуры такова, что "плавающую" задержку нужно
"врезать" во внутренний цикл ПП WIRE, а это вызывает необходимость во "вводе в
эксплуатацию" флага исполнения/обхода "плавающей" задержки (в данном случае,
бит №0 регистра Flag).
То есть, в случае исполнения температурного преобразования, "плавающая" задержка
будет отрабатываться, а во всех остальных случаях, нет.
Что и имеет место быть (выделено красным цветом).
В первом случае, содержимое регистра Wire - "по барабану", и поэтому сразу же
после отработки "плавающей" задержки, происходит возврат по стеку.
После такой "модернизации", цикл процедуры замера температуры будет
отрабатываться быстрее, чем в случае применения фиксированной задержки.
А если в дальнейшем будут сложности с помещением этой "плавающей" задержки в
"зону" разрешения прерываний (а они будут), то заменить ее на фиксированную
задержку - "пять секунд".
После считывания младшего байта температуры, задается верхний Т-порог (есть еще
и нижний, так как имеет место быть петля температурного гистерезиса), с которым и
сравнивается результат замера температуры.
Если Т-порог превышен, то срабатывает блокировка (транзистор закрывается) и
вентиллятор переводится на максимальные обороты.
Скорректировав числовое значение константы, можно выставить те обороты, которые
Вам нравятся (это и есть преимущество ШИМ-регулирования).
Далее, начинается отработка сценария-подсказки №3, речь о котором пойдет ниже.
В конечном итоге (после устранения "термобяки"), происходит возврат по стеку в то
"место", из которого была вызвана ПП работы с термодатчиком.
Если Т-порог не превышен, то отрабатывается процедура перевода числового
значения младшего байта температуры в ширину импульсов (текущая коррекция
оборотов вентиллятора), после чего - все тот же возврат по стеку в то "место", из
которого была вызвана ПП работы с термодатчиком.

Вот я и плавненько "подрулил" к необходимости "разборок" с ШИМ-регулированием


оборотов двигателя.
Доподлинно известно, что при работе модуля CCP в режиме ШИМ, используется
модуль TMR2.

13
Но ведь модуль TMR2 уже задействован для организации периодических уходов в
прерывания!
Если не быть "хулиганом", то в такой ситуации остается только "закомплексованно
сложить лапки" и сожалеть о несбывшихся надеждах.
Но ведь "следствие ведут русские колобки"…
А они настолько раскрепощены, что им "по барабану" не только такая "мелочевка", но
и даже более "заковыристое" ("настройка внутренних биофункций").
Сейчас докажу.
При работе модуля ССР в режиме ШИМ, модуль TMR2 имеет "статус" составной части
модуля CCP (принимает участие в работе модуля CCP "на правах
периодоформировалки").
Это означает то, что если ранее была произведена настройка модуля TMR2 (а это, в
данном случае, и имеет место быть), то после "введения в эксплуатацию" модуля
CCP, он будет генерировать период, значение которого определяется ранее
произведенной настройкой модуля TMR2.
То есть, в данном случае, период ШИМ-сигнала будет равен 200 мкс., что
соответствует частоте ШИМ-сигнала = 5 Кгц.
Для "ШИМ-запитки" вентиллятора, эта частота вполне приемлема.
И тем более, что импульсная последовательность "протаскивается" через ФНЧ (об этом
- позднее).
Таким образом, в данном случае, в части касающейся периода, можно считать, что
имеет место быть "манна небесная".
В том смысле, что модуль TMR2 уже ранее настроен и перенастраивать его совсем
не нужно.
С учетом этого, нужно только включить модуль ССР, а после этого, в соответствии с
алгоритмом работы программы, "загрузить" в CCPR1L/CCP1CON,5,4 либо текущие
значения длительностей импульсов (определяются текущими результатами замеров
температуры), либо какие-то фиксированные значения длительностей импульсов.
Обращаю Ваше внимание на то, что при таком "раскладе" (после "ввода в
эксплуатацию" модуля CCP), будут обеспечены и уходы в прерывания с
периодичностью 200 мкс., и формирование непрерывного ШИМ-сигнала с той же
периодичностью.
Причем, "и то, и сё" будет засинхронизировано как относительно такта ПИКа, так и
относительно друг друга.
Задача еще более упрощается с учетом того, что с CCP1CON,5,4 можно не работать,
а работать только с CCPR1L.
Содержимое именно этого регистра (CCPR1L) и будет определять количество оборотов
двигателя вентиллятора.
Еще раз напоминаю о том, что CCP1CON,5,4 это биты двух "наимладшейших"
разрядов 10-разрядного ШИМ, которые "погоды не делают" (что в них лежит? По
барабану).
Теперь обращаю Ваше внимание на то, что Fшим = 5 Кгц. это частота звукового
диапазона, воспринимаемая ухом любого человека (если он не глухой).
Если запитать вентиллятор импульсной последовательностью с такой частотой, то он
(вентиллятор) будет просто-напросто "неприлично пищать" (кстати, противно).
Для предотвращения этого "конфуза", нужно применить простейший, однозвенный
RC фильтр нижних частот (сглаживающий фильтр). Что и сделано.
На рис. 1, это R11,C4.
В данном случае, я применил наиболее дешевый вариант управления вентиллятором -
с использованием n-p-n транзистора (VT2).
С расcчетом на вентиллятор достаточно "приличной" мощности, использован транзистор
КТ805БМ, но можно использовать и другой n-p-n транзистор средней или большой
мощности (зависит от мощности вентиллятора).
В своих "экспериментах", я использовал "слабосильный" компьютерный вентиллятор
CF-12510M (12 в., макс. ток 150 ма.), и поэтому не было необходимости в
использовании радиатора (транзистор, на максимальных оборотах, только немного
нагревался).

14
Если же речь идет об использовании достаточно мощного вентиллятора, то нужно
либо "посадить" n-p-n транзистор на радиатор, либо использовать мощный "полевик"
(например, все тот же IRFZ44N).
В последнем случае, радиатор не нужен, и емкость С4 можно уменьшить
до 0,047 мкф., а номинал резистора R11 увеличить до 1 Мом.
Программная реализация сказанного выглядит так:
.....................................
.....................................
;********************************************************************************
; НАЧАЛО ИСПОЛНЕНИЯ ПРОГРАММЫ.
;********************************************************************************
; Подготовительные операции.
;================================================================================
START
.....................................
movlw b'00000100' ; Модуль TMR2 включен с Кдел. предделителя = 1
movwf T2CON ; и Кдел. выходного делителя = 1.
.....................................
movlw .199 ; Задание периода ухода в
movwf PR2 ; прерывания =.199 (200 мкс.).
bcf Status,RP0 ; Переход в 0-й банк.
;--------------------------------------------------------------------------------
; Обеспечение "разгона" вентиллятора.
;--------------------------------------------------------------------------------
movlw .255 ; Обеспечение высокого
movwf CCPR1L ; коэффициента заполнения.
;--------------------------------------------------------------------------------
; Настройка модуля CCP.
;--------------------------------------------------------------------------------
movlw b'00001111' ; Включение
movwf CCP1CON ; режима ШИМ.
;================================================================================
; Процедура инициализации ЖКИ модуля.
;================================================================================
.....................................
.....................................
;ОООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООО
; Проверка наличия/отсутствия отклика от термодатчика.
;ОООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООООО
.....................................
.....................................
;================================================================================
; Перевод вентиллятора на заданное количество оборотов
; (в данном случае, на максимальные). "РАЗГОН" ВЕНТИЛЛЯТОРА
;================================================================================
movlw .255 ;
movwf CCPR1L ; CCPR1L = 11111111
;================================================================================
.....................................
.....................................
;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
; Сценарий "ЗАЩИТА ВЫКЛЮЧЕНА".
;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
; Опрос флага наличия/отсутствия термодатчика.
;--------------------------------------------------------------------------------
btfsc Flag,1 ; Флаг наличия/отсутствия термодатчика поднят
; или нет ?
goto $+2 ; Если поднят, то обход ПП работы с датчиком.
;--------------------------------------------------------------------------------
; Окончание "разгона" вентиллятора.
;--------------------------------------------------------------------------------
call TERMO ; Переход в ПП работы с датчиком, с целью
;--> Возврат по стеку из ПП TERMO. ; установки текущих оборотов вентиллятора.
.....................................
.....................................
15
;********************************************************************************
; Начало рабочего сценария выключенной защиты.
;********************************************************************************
.....................................
.....................................
;--------------------------------------------------------------------------------
; Опрос флага наличия/отсутствия термодатчика.
;--------------------------------------------------------------------------------
btfss Flag,1 ; Флаг наличия/отсутствия термодатчика поднят
; или нет ?
goto $+3 ; Если опущен, то работа с датчиком.
bsf PortA,2 ; Если поднят, то ОТКРЫТИЕ ТРАНЗИСТОРА
goto $+2 ; и обход работы с датчиком.
;--------------------------------------------------------------------------------
; Работа с текущей температурой.
;--------------------------------------------------------------------------------
call TERMO ; Переход в ПП работы с датчиком.
;----> Возврат по стеку из ПП TERMO.
.....................................
;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
; Сценарий "ЗАЩИТА ВКЛЮЧЕНА".
;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.....................................
.....................................
;--------------------------------------------------------------------------------
; Опрос флага наличия/отсутствия термодатчика.
;--------------------------------------------------------------------------------
btfsc Flag,1 ; Флаг наличия/отсутствия термодатчика поднят
; или нет ?
goto $+2 ; Если поднят, то обход ПП работы с датчиком.
;--------------------------------------------------------------------------------
; Окончание "разгона" вентиллятора.
;--------------------------------------------------------------------------------
call TERMO ; Переход в ПП работы с датчиком, с целью
;--> Возврат по стеку из ПП TERMO. ; установки текущих оборотов вентиллятора.
.....................................
.....................................
Напоминаю, что выходом модуля ССР, работающего в режиме ШИМ, является вывод
RC2.
Настройки модуля TMR2, которые и ранее, и сейчас имеют место быть (ничего не
изменено), выделены темно-красным цветом.
Добавления выделены темно-зеленым цветом.
То, что нужно включить модуль ССР в режиме ШИМ, не должно вызвать никаких
вопросов.
А вот на счет этого:
movlw .255 ; Обеспечение высокого
movwf CCPR1L ; коэффициента заполнения
нужно сказать пару слов.
После сброса по включению питания, а иными словами, после инициализации ПИКа,
значение CCPR1L непредсказуемо (см. даташит на PIC16F87xx).
То есть, если, в ПП START, не предпринять мер по ликвидации этой "анархии", то на
момент выхода из ПП START, о какой-то "оборотной" конкретности можно и не
мечтать.
Это раз.
При комнатной температуре, ШИМ-сигнал представляет собой импульсную
последовательность с импульсами "протяженностью" примерно в одну четверть
периода.
Это два.
То есть, будут иметь место быть достаточно малые обороты.
Настолько малые, что "пропеллер", иногда, просто не будет "крутиться".
Но если пальцем подтолкнуть, то "закрутится".
Последнее есть явно выраженный "маразм".

16
Значит, в ПП START, нужно "разогнать" вентиллятор, а иными словами,
"принудительно", обеспечить максимальные (или близкие к ним. Можно задать)
обороты.
Естественно, что в дальнейшем, после первого же замера температуры, вентиллятор
снизит обороты, но он снизит их от максимальных (или близких к максимальным)
оборотов, а не будет наращивать обороты от вполне вероятных, малых их значений,
что, согласитесь со мной, две разные "оперы".
В случае снижения оборотов от максимума, гарантировано дальнейшее "кручение-
верчение пропеллера" даже на очень низких оборотах.
Вот и получается, что в ПП START, вентиллятор нужно "разогнать".
Я задал максимальные обороты, но можно задать и поменьше.
Уменьшаете числовое значение константы, и все дела. Это на любителя.
Если термодатчик подключен, то этот "разгон" будет иметь место быть только до
первого замера температуры, а после него, количество оборотов вентиллятора будет
определяться результатом замера температуры.
Если таких замеров несколько, то в соответствии с текущей температурой, обороты
вентиллятора будут "текущекорректироваться".
При увеличении температуры, обороты "пропеллера" будут автоматически
увеличиваться, а при уменьшении температуры, автоматически уменьшаться.
Вот Вам и автоматическая система терморегулирования с обратной связью.
Если речь идет о долговременной "запитке" нагрузки более-менее стабильным током,
то конечным результатом работы такой системы будет долговременный термобалланс,
температура которого будет автоматически поддерживаться на каком-то также более-
менее стабильном уровне (что-то типа термостатирования).
И это "пахнет вполне солидными перспективами".
Голос внутреннего цензора: "Ну … Понеслась душа в рай. Смотри, пупок не надорви.
Перспективы перспективами, а недожаренные котлеты нужно дожарить".
Добрый совет ценю (это не "враг" и не "голос из-за кулис"). И поэтому повинуюсь.
Итак, в ПП START, обеспечен "разгон" вентиллятора.
И он будет "разогнан" до тех пор, пока не произойдет первый "уход" в ПП работы с
термодатчиком.
На данный момент, организовано три таких "ухода".
Два из них, производятся "на влете" (до входа во внутренние циклы) в сценарий
выключенной и в сценарий включенной защиты. .
А третий - внутри цикла выключенной защиты.
Первые два "знаменуют собой" окончание "разгона" вентиллятора.
Это означает переход вентиллятора с больших оборотов на те обороты, которые
соответствуют числовому значению результата соответствующего измерения
температуры.
Смысл окончания "разгона" вентиллятора в начале исполнения сценария выключенной
защиты - уменьшение времени нахождения вентиллятора в "разогнанном" состоянии.
Далее, во внутреннем цикле этого сценария, на каждом его "витке", происходит
многократное измерение текущей температуры, с соответствующей коррекцией
коэффициента заполнения, что и есть суть автоматического терморегулирования.
В данном случае, автоматическое терморегулирование, в буквальном понимании,
происходит только в сценарии выключенной защиты.
В сценарии включенной защиты, строго говоря, автоматического терморегулирования
нет, по причине, указанной выше (можно, но будут "зоны" запретов прерываний, что
плохо отразится на максимальной инерционности срабатывания защиты).
Но вентиллятор работать будет, ведь до входа во внутренний цикл сценария
включенной защиты (в нем, прерывания разрешены и "зоны" запретов прерываний
отсутствуют), произошел "уход" в ПП работы с термодатчиком.
Проще говоря, на время отработки сценария включенной защиты, обороты
вентиллятора будут соответствовать тому замеру температуры, который произошел на
"влете" в этот сценарий.
Я сделал именно так.
Но можно и по-другому.
Например, можно задать какие-то фиксированные обороты. На свой вкус.
Поняв предмет разговора, сделать это совсем не сложно.
17
"Уходить", в ПП работы с термодатчиком, из других подпрограмм сценария включенной
защиты, "лежащих" в "зоне" запрета прерываний, я не стал по причине того, что в
интервалах времени их исполнения, транзистор закрыт.
То есть, отсутствует потенциальная опасность роста температуры.
К тому же, в этих случаях, будет происходить достаточно быстрое охлаждение, ведь
вентиллятор-то, худо-бедно, но работает.
А вообще, это сделать можно. Если потребуется, то сделаю. Нет проблем.
call с организацией простого обхода, и все дела. Хоть сто раз.
Обращаю Ваше внимание на то, что я, со своими "термоделами", не в коем разе не
"посягнул" на "зону" разрешения прерываний внутреннего цикла сценария включенной
защиты.
Я сработал "на подлете" к ней.
И ПП прерывания тоже "осталась нетронутой".
Проще говоря, после всех этих "термодел", инерционность срабатывания защиты какой
была, такой и осталась.
Вопрос: "Что будет, если датчик не подключен"?
Ответ: в данном случае, вентиллятор постоянно будет работать на максимальных
оборотах. Тех, которые заданы в ПП START (для "разгона").
Еще раз повторяю, что их можно и уменьшить. Нет проблем.
А если вентиллятор не нужен, то его, и все то, что с ним связано (VT2 и т.д.), можно
просто не подключать ("демократия").
Что касается сценария выключенной защиты, то его "модернизация" тоже минимальна:
пара переходов, по стеку, в ПП работы с термодатчиком (с организацией
соответствующих обходов) и перенос открытия транзистора в процедуру опроса флага
наличия/отсутствия термодатчика.
Если датчик не подключен, то транзистор откроется именно таким образом.
Соответственно, для того чтобы открыть транзистор в случае наличия датчика, ПП
работы с термодатчиком должна быть "укомплектована" командой bsf PortA,2.
В том "куске" подпрограммы работы с термодатчиком, который "лежит" ниже, эта
команда выделена красным цветом.
А теперь, более подробно о переводе числового значения младшего байта
температуры в ширину импульсов:
.....................................
;================================================================================
; Перевод числового значения младшего байта температуры в ширину импульсов.
;================================================================================
; Определение момента начала "загрузки" в CCPR1L/CCP1CON,5,4.
;------------------------------------------------------------
bcf PIR1,TMR2IF ; Сброс флага прерывания по переполнению TMR2.
btfss PIR1,TMR2IF ; Проверка состояния флага
goto $-1 ; прерывания по переполнению TMR2.
;------------------------------------------------------------
; А это сама "загрузка".
;------------------------------------------------------------
bcf CCP1CON,5 ; Два младших бита 10-разрядного ШИМ
bcf CCP1CON,4 ; сбрасываются в ноль.
movf Temp_LSB,W ; В старшие 8 разрядов копируется содержимое
movwf CCPR1L ; регистра младшего байта температуры.
;------------------------------------
; Концовка.
;------------------------------------
bcf PIR1,TMR2IF ; Сброс флага прерывания по переполнению TMR2.
bsf PortA,2 ; Если порог не превышен, то ОТКРЫТИЕ ИЛИ
; ПОДТВЕРЖДЕНИЕ ОТКРЫТИЯ ТРАНЗИСТОРА.
return ; Возврат по стеку.
.....................................
Это то, что мы уже "проходили" ранее (при "разборках с ШИМом"), только проще, так
как состояния двух младших разрядов 10-разрядного ШИМ не важны.
Но все-таки, для порядка, я выставил в них нули.
А можно и не выставлять (вообще "забыть" про эти биты и убрать эти две команды)
или установить другую комбинацию состояний.

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

19
Практический результат реализации такого алгоритма, в комплексе со сказанным выше,
выглядит так:
После включения питания, и в случае, если термодатчик подключен, в течение
примерно 3-х секунд, "высвечивается" надпись Термодатчик подключен (см. картинку
выше).
Вентиллятор "разгоняется" до максимальных оборотов.
После этого, могут быть два варианта.
1. Если на момент предыдущего выключения питания, работа производилась в
сценарии включенной защиты, то "разгон" вентиллятора прекращается и количество
его оборотов приводится в соответствие той температуре, которая имеет место быть
на момент начала отработки сценария включенной защиты.
После этого, начинается отработка сценария-подсказки №1, со всеми вытекающими
последствиями (см. подраздел 2/2/8).
2. Если на момент предыдущего выключения питания, работа производилась в
сценарии выключенной защиты, то "разгон" вентиллятора прекращается и количество
его оборотов приводится в соответствие той температуре, которая имеет место быть
на момент начала отработки сценария выключенной защиты.
После этого, начинается отработка сценария-подсказки №2, со всеми вытекающими
последствиями (см. подраздел 2/2/9).
Если нажать на кнопку "+/Да", то будет то, о чем
говорилось в пункте 1.
Если нажать на кнопку "-/Нет", то будет осуществлен
переход в сценарий выключенной защиты, и Вы
увидите то, что изображено на картинке слева
(числовые значения результатов замеров могут быть
другими). В этом сценарии, ПП работы с
термодатчиком отрабатывается на каждом цикле этого сценария (слежение за
температурой), только результаты замеров температуры на индикацию не выводятся.
Так может продолжаться долго. При условии, что Т-порог не превышен.
Если то, к чему "прислонился" датчик, будет греться, то вентиллятор автоматически
увеличит свои обороты, вплоть до установления некоего термобалланса, который, в
дальнейшем, и будет автоматически поддерживаться.
Естественно, при условии более-менее фиксированного тока, потребляемого нагрузкой.
Если этот ток будет меняться, то и обороты вентиллятора тоже будут меняться.
При этом, система терморегулирования всегда будет стремиться к
термобаллансу.
В случае, если Т-порог будет превышен, вентиллятор переводится на максимальные
обороты и начинается отработка сценария-
подсказки №3, сопровождаемая аварийным
сигналом, представляющим собой "пачки" из 10-ти
"писков" (их количество можно изменить), с паузами
между ними.
Эти "пачки выдаются" в течение всего времени
превышения, текущей температурой, нижнего
Т-порога (его значение можно изменить).
Соответственно, речь идет о температурном
гистерезисе.
При этом, последовательно чередуются 3 надписи:
Караул! Убивают! ПЕРЕГРЕВ, Ждите понижения
температуры и Тпорога=хх град. Ттекущ.=хх град.
Соответствующие картинки Вы и видите.

20
Что касается последней картинки (вернее, трех картинок), то на них показана динамика
охлаждения.
Как не трудно догадаться, в 1-ю строку выводится числовое значение верхнего
Т-порога.
Причем, если программно изменить значение верхнего Т-порога, то оно и будет
выведено на индикацию.
Это сделано "с прицелом на дальнейшую перспективу".
Во 2-ю строку, выводятся текущие значения температуры.
То есть, можно, в динамике, отследить процесс охлаждения.
А он и будет иметь место быть, так как, после срабатывания термозащиты, нагрузка
перестает "запитываться".
В данном случае, процесс охлаждения можно визуально отследить только в пределах
петли температурного гистерезиса.
То есть, если значение текущей температуры становится ниже нижнего Т-порога, то
вся эта "свистопляска" автоматически заканчивается,
после чего, в течение примерно 3-х секунд
"высвечивается" та надпись, которую Вы видите на
картинке слева, и "железяка" автоматически
переходит (транзистор открывается) в "рабочий"
подрежим режима выключенной защиты.
При этом, происходит коррекция оборотов
вентиллятора (от максимума, в сторону понижения, до уровня, соответствующего
текущей температуре).
Если необходимо прервать исполнение сценария-подсказки №3, то нужно нажать/отжать
кнопку "+/Да".
При этом, в течение всего времени нажатия, будет "высвечиваться" надпись
СЛУШАЮСЬ и ПОВИНУЮСЬ!, а после отжатия, произойдет переход в "рабочий"
подрежим режима выключенной защиты.
Но при этом следует учесть, что если текущая температура находится выше верхнего
Т-порога, то "железяка", после отжатия кнопки, снова "термозаблокируется".
Программно, это выглядит так:
.....................................
.....................................
2-й блок PC
;-----------------------------------
; Надпись " СЛУШАЮСЬ и "
;-----------------------------------
TEXT_17 addwf PC,F ; -----"-----
dt 0x20,0x20,0x20,0x43,0xA7,0xA9,0xAC,0x41
dt 0xB0,0x43,0x62,0x20,0xB8,0x20,0x20,0x20
;-----------------------------------
; Надпись " ПОВИНУЮСЬ! "
;-----------------------------------
TEXT_18 addwf PC,F ; -----"-----
dt 0x20,0x20,0x20,0xA8,0x4F,0x42,0xA5,0x48
dt 0xA9,0xB0,0x43,0x62,0x21,0x20,0x20,0x20
.....................................
.....................................
;================================================================================
; Аварийная "пищалка" (мультивибратор, формирующий "пачку" импульсов).
;================================================================================
MULTI movlw .250 ; "Пищать" будем
movwf Reg_2 ; 250 периодов.

bcf PortC,4 ; Установка на выходе защелки RC4 уровня 0.


movlw .50 ; Задание периода
movwf Reg_3 ; (частоты).

decfsz Reg_3,F ; Формирование


goto $-1 ; полупериода.

btfsc PortC,4 ; Если на выходе защелки RC4 уровень 1,

21
goto $-6 ; то дальнейшая его смена на уровень 0.
decf Reg_2,F ; Если на выходе защелки RC4 уровень 0,
; то Reg_2 - 1 = ... и программа
; исполняется далее.
btfsc Status,Z ; Каков результат декремента ?
return ; Если =0, то "пачка" импульсов сформирована
; и выход из "пищалки".
bsf PortC,4 ; Если не=0, то установка на выходе
; защелки RC4 уровня 1.
goto $-.10 ; Переход на формирование следующего периода.
;================================================================================
.....................................
.....................................
3-й блок PC
;-----------------------------------
; Надпись "Караул! Убивают!"
;-----------------------------------
TEXT_22 addwf PC,F ; -----"-----
dt 0x4B,0x61,0x70,0x61,0x79,0xBB,0x21,0x20
dt 0xA9,0xB2,0xB8,0xB3,0x61,0xC6,0xBF,0x21
;-----------------------------------
; Надпись "хх ПЕРЕГРЕВ хх" (х-колокольчики)
;-----------------------------------
TEXT_23 addwf PC,F ; -----"-----
dt 0xED,0xED,0x20,0x20,0xA8,0x45,0x50,0x45
dt 0xA1,0x50,0x45,0x42,0x20,0x20,0xED,0xED
;-----------------------------------
; Надпись " Ждите понижения"
;-----------------------------------
TEXT_24 addwf PC,F ; -----"-----
dt 0x20,0xA3,0xE3,0xB8,0xBF,0x65,0x20,0xBE
dt 0x6F,0xBD,0xB8,0xB6,0x65,0xBD,0xB8,0xC7
;-----------------------------------
; Надпись " температуры "
;-----------------------------------
TEXT_25 addwf PC,F ; -----"-----
dt 0x20,0x20,0x20,0xBF,0x65,0xBC,0xBE,0x65
dt 0x70,0x61,0xBF,0x79,0x70,0xC3,0x20,0x20
;-----------------------------------
; Надпись "Тпорога= град."
;-----------------------------------
TEXT_26 addwf PC,F ; -----"-----
dt 0x54,0xBE,0x6F,0x70,0x6F,0xB4,0x61,0x3D
dt 0x20,0x20,0x20,0xB4,0x70,0x61,0xE3,0x2E
;-----------------------------------
; Надпись "Ттекущ.= град."
;-----------------------------------
TEXT_27 addwf PC,F ; -----"-----
dt 0x54,0xBF,0x65,0xBA,0x79,0xE6,0x2E,0x3D
dt 0x20,0x20,0x20,0xB4,0x70,0x61,0xE3,0x2E
;-----------------------------------
; Надпись " Автоматическая "
;-----------------------------------
TEXT_28 addwf PC,F ; -----"-----
dt 0x20,0x41,0xB3,0xBF,0x6F,0xBC,0x61,0xBF
dt 0xB8,0xC0,0x65,0x63,0xBA,0x61,0xC7,0x20
;-----------------------------------
; Надпись " разблокировка "
;-----------------------------------
TEXT_29 addwf PC,F ; -----"-----
dt 0x20,0x70,0x61,0xB7,0xB2,0xBB,0x6F,0xBA
dt 0xB8,0x70,0x6F,0xB3,0xBA,0x61,0x20,0x20
.....................................
.....................................
;================================================================================
; Универсальная задержка
22
; (время задержки определяется предустановленным содержимым W).
;================================================================================
PAUSE_X movwf Reg ; Стандартный, вычитающий,
decfsz Reg,F ; однобайтный
goto $-1 ; счетчик.
return ; Возврат по стеку.
;================================================================================
.....................................
.....................................
;DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
; ПП работы с датчиком.
;DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
; "Администраторская" группа команд.
;--------------------------------------------------------------------------------
TERMO call DQ_INIT ; Инициализация датчика.
;--->Возврат по стеку из ПП DQ_INIT
movlw 0CCh ; Выполнение команды
call WIRE ; "Skip_ROM".
;--->Возврат по стеку из ПП WIRE
movlw 44h ; Выполнение команды
call WIRE ; "Start_Conv".
;--->Возврат по стеку из ПП WIRE
bsf Flag,0 ; Поднятие флага исполнения/обхода "плавающей"
; задержки.
call WIRE ; Исполнение процедуры 1-Wire протокола.
;--->Возврат по стеку из ПП WIRE
bcf Flag,0 ; Сброс флага исполнения/обхода "плавающей"
; задержки.
call DQ_INIT ; Инициализация датчика.
;--->Возврат по стеку из ПП DQ_INIT
movlw 0CCh ; Выполнение команды
call WIRE ; "Skip_ROM".
;--->Возврат по стеку из ПП WIRE
movlw 0BEh ; Выполнение команды
call WIRE ; "Read_Scratchpad".
;--->Возврат по стеку из ПП WIRE
;--------------------------------------------------------------------------------
; Чтение младшего байта температуры.
;--------------------------------------------------------------------------------
movlw b'11111111' ; "Нейтральный" байт.
call WIRE ; Чтение.
;--->Возврат по стеку из ПП WIRE
movwf Temp_LSB ; Результат замера температуры (младший байт)
; записывается в регистр Temp_LSB.
;================================================================================
; 2/10 преобразование и сравнение результата замера температуры
; с температурным порогом.
;================================================================================
; Здесь программно задается значение температурного порога.
; Значение константы = (целое значение требуемого температурного порога) х 2.
; Например: 26 градусов х 2 = .52,
; 27 градусов х 2 = .54 и т.д.
; В данном случае, установлено 30 градусов.
;--------------------------------------------------------------------------------
movlw .60 ;
movwf T_Porog ; T_Porog = .60

bcf Status,C ; Деление


rrf T_Porog,W ; на 2.
;================================================================================
; 2/10 преобразование (1х2) с перекодировкой результата.
;================================================================================
call BIN2_10_T ; Переход в ПП 2/10 преобразования.
;--->Возврат по стеку из ПП BIN2_10_T
;--------------------------------------------------------------------------------
; Проверка состояния флага срабатывания термозащиты.
23
;--------------------------------------------------------------------------------
btfsc Flag_1,7 ; Флаг срабатывания термозащиты поднят
; или опущен ?
goto PEREGREV ; Если поднят, то сравнение с Т-порогом и
; текущая коррекция ШИМ обходятся.
; Если опущен, то не обходятся.
;--------------------------------------------------------------------------------
; Сравнение с температурным порогом.
;--------------------------------------------------------------------------------
movf T_Porog,W ; T_Porog -> W.
subwf Temp_LSB,W ; Temp_LSB - T_Porog =... (результат -> W)
btfsc Status,C ; Результат "+/=0" или "-"
; (порог превышен или нет) ?
goto PEREGREV ; Если порог превышен, то обход процедуры
; перевода числового значения младшего байта
; температуры в ширину импульсов.
;================================================================================
; Перевод числового значения младшего байта температуры в ширину импульсов.
;================================================================================
; Определение момента начала "загрузки" в CCPR1L/CCP1CON,5,4.
;------------------------------------------------------------
bcf PIR1,TMR2IF ; Сброс флага прерывания по переполнению TMR2.

btfss PIR1,TMR2IF ; Проверка состояния флага


goto $-1 ; прерывания по переполнению TMR2.
;------------------------------------------------------------
; А это сама "загрузка".
;------------------------------------------------------------
bcf CCP1CON,5 ; Два младших бита 10-разрядного ШИМ
bcf CCP1CON,4 ; сбрасываются в ноль.
movf Temp_LSB,W ; В старшие 8 разрядов копируется содержимое
movwf CCPR1L ; регистра младшего байта температуры.
;------------------------------------
; Концовка.
;------------------------------------
bcf PIR1,TMR2IF ; Сброс флага прерывания по переполнению TMR2.
bsf PortA,2 ; Если порог не превышен, то ОТКРЫТИЕ ИЛИ
; ПОДТВЕРЖДЕНИЕ ОТКРЫТИЯ ТРАНЗИСТОРА.
return ; Возврат по стеку.
;================================================================================
; Исполняется в случае превышения порога.
;================================================================================
PEREGREV bcf PortA,2 ; Если порог превышен, то ТРАНЗИСТОР
; ЗАКРЫВАЕТСЯ.
movlw .255 ; Перевод вентиллятора
movwf CCPR1L ; на максимальные обороты.

;********************************************************************************
; Начало сценария-подсказки №3
;********************************************************************************
; Вывод на индикацию, в 1-ю строку, фиксированной надписи " СЛУШАЮСЬ и ".
;================================================================================
movlw b'10000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 1-й строки.

bsf PCLATH,0 ; Так как далее будет исполнен вычисляемый


; переход, лежащий во 2-м блоке PC.
movlw .16 ;
movwf Count ;
movf Count,W ;
sublw .16 ;
call TEXT_17 ; Аналогично, только
bsf PortC,RS ; для TEXT_17.
call ENTER_BF ;
decfsz Count,F ;
goto $-6 ;
24
;================================================================================
; Вывод на индикацию, во 2-ю строку, фиксированной надписи " ПОВИНУЮСЬ! ".
;================================================================================
movlw b'11000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 2-й строки.
movlw .16 ;
movwf Count ;
movf Count,W ;
sublw .16 ; Аналогично, только
call TEXT_18 ; для TEXT_18.
bsf PortC,RS ;
call ENTER_BF ;
decfsz Count,F ;
goto $-6 ;
;================================================================================
; Опрос клавиатуры.
;================================================================================
; Опрос кнопки "+/Да".
;================================================================================
btfsc PortB,2 ; Кнопка "+/Да" нажата или отжата ?
goto $+7 ; Если отжата, то "рабочего действия
; после отжатия" не происходит.
;-----------------------------------
; Противодребезговая задержка.
;-----------------------------------
call PAUSE_UI ; Переход в ПП PAUSE_UI.
;----> Возврат по стеку из ПП PAUSE_UI.
;-----------------------------------
; Ожидание отжатия кнопки.
;-----------------------------------
btfss PortB,2 ; Кнопка "+/Да" нажата или отжата ?
goto $-1 ; Если нажата, то ожидание отжатия.
;OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
; Рабочее действие после отжатия.
;OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
clrf PCLATH ; Так как далее будет исполнен вычисляемый
; переход, лежащий в 1-м блоке PC.
bcf Flag_1,7 ; Флаг срабатывания термозащиты опускается.
return ; Возврат по стеку.

;////////////////////////////////////////////////////////////////////////////////
; ВЫВОД НА ИНДИКАЦИЮ НАДПИСЕЙ.
;////////////////////////////////////////////////////////////////////////////////
bcf PCLATH,0 ; Так как далее будет исполнен вычисляемый
bsf PCLATH,1 ; переход, лежащий в 3-м блоке PC.
;================================================================================
; Вывод на индикацию, в 1-ю строку, фиксированной надписи ""Караул! Убивают!"".
;================================================================================
movlw b'10000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 1-й строки.
movlw .16 ;
movwf Count ;
movf Count,W ;
sublw .16 ;
call TEXT_22 ; Аналогично, только
bsf PortC,RS ; для TEXT_22.
call ENTER_BF ;
decfsz Count,F ;
goto $-6 ;
;================================================================================
; Вывод на индикацию, во 2-ю строку, фиксированной надписи
; ""хх ПЕРЕГРЕВ хх" (х-колокольчики)".
;================================================================================
movlw b'11000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 2-й строки.
movlw .16 ;
25
movwf Count ;
movf Count,W ;
sublw .16 ; Аналогично, только
call TEXT_23 ; для TEXT_23.
bsf PortC,RS ;
call ENTER_BF ;
decfsz Count,F ;
goto $-6 ;
;================================================================================
; Формирование звукового сигнала срабатывания защиты от перегрева.
;================================================================================
movlw .10 ; Задание количества
movwf Temp ; "писков".

call PAUSE_UI ; Задержка.


;----> Возврат по стеку из ПП PAUSE_UI.

call MULTI ; Переход в ПП аварийной "пищалки".


;----> Возврат по стеку из ПП MULTI.
decfsz Temp,F ; "Постановка на счетчик"
goto $-3 ; количества "писков".
;================================================================================
; Вывод на индикацию, в 1-ю строку, фиксированной надписи " Ждите понижения".
;================================================================================
movlw b'10000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 1-й строки.
movlw .16 ;
movwf Count ;
movf Count,W ;
sublw .16 ; Аналогично, только
call TEXT_24 ; для TEXT_24.
bsf PortC,RS ;
call ENTER_BF ;
decfsz Count,F ;
goto $-6 ;
;================================================================================
; Вывод на индикацию, во 2-ю строку, фиксированной надписи " температуры ".
;================================================================================
movlw b'11000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 2-й строки.
movlw .16 ;
movwf Count ;
movf Count,W ;
sublw .16 ; Аналогично, только
call TEXT_25 ; для TEXT_25.
bsf PortC,RS ;
call ENTER_BF ;
decfsz Count,F ;
goto $-6 ;
;================================================================================
; Обеспечение необходимого времени "высвечивания" надписи.
;================================================================================
call PAUSE_S ; Задержка.
;----> Возврат по стеку из ПП PAUSE_S.
;================================================================================
; Вывод на индикацию, в 1-ю строку, фиксированной надписи "Тпорога= град.".
;================================================================================
movlw b'10000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 1-й строки.
movlw .16 ;
movwf Count ;
movf Count,W ;
sublw .16 ; Аналогично, только
call TEXT_26 ; для TEXT_26.
bsf PortC,RS ;
call ENTER_BF ;
26
decfsz Count,F ;
goto $-6 ;
;================================================================================
; Вывод на индикацию значения установленного температурного порога.
;================================================================================
; Задание адреса знакоместа, с которого начнется вывод на индикацию.
;--------------------------------------------------------------------------------
movlw b'10001000' ; Выбор ячейки DD RAM с адресом 08h, что
movwf PortB ; соответствует установке курсора в 9-е слева
; знакоместо 1-й строки.
call ENTER_BF ; "Плавающая" задержка со стробом
; под команду 10001000.
;----> Возврат по стеку из ПП ENTER_BF.
;================================================================================
; Вывод на индикацию числового значения верхнего Т-порога.
;================================================================================
call IND_TERMO ; Переход в ПП IND_TERMO.
;----> Возврат по стеку из ПП IND_TERMO.
;================================================================================
; Вывод на индикацию, во 2-ю строку, фиксированной надписи "Ттекущ.= град.".
;================================================================================
movlw b'11000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 2-й строки.
movlw .16 ;
movwf Count ;
movf Count,W ;
sublw .16 ; Аналогично, только
call TEXT_27 ; для TEXT_27.
bsf PortC,RS ;
call ENTER_BF ;
decfsz Count,F ;
goto $-6 ;
;-------------------------------------
; Деление содержимого Temp_LSB на 2.
;-------------------------------------
bcf Status,C ; C = 0.
rrf Temp_LSB,W ; Деление на 2. Результат --> W.
;================================================================================
; 2/10 преобразование (1х2) с перекодировкой результата.
;================================================================================
call BIN2_10_T ; Переход в ПП 2/10 преобразования.
;--->Возврат по стеку из ПП BIN2_10_T
;================================================================================
; Вывод на индикацию текущего значения температуры.
;================================================================================
; Задание адреса знакоместа, с которого начнется вывод на индикацию.
;--------------------------------------------------------------------------------
movlw b'11001000' ; Выбор ячейки DD RAM с адресом 08h, что
movwf PortB ; соответствует установке курсора в 9-е слева
; знакоместо 2-й строки.
call ENTER_BF ; "Плавающая" задержка со стробом
; под команду 11001000.
;----> Возврат по стеку из ПП ENTER_BF.
;================================================================================
; Вывод на индикацию числовых значений текущих значений температуры.
;================================================================================
call IND_TERMO ; Переход в ПП IND_TERMO.
;----> Возврат по стеку из ПП IND_TERMO.
;================================================================================
; Обеспечение необходимого времени "высвечивания" надписи.
;================================================================================
call PAUSE_S ; Задержка.
;----> Возврат по стеку из ПП PAUSE_S.
;================================================================================
bsf Flag_1,7 ; Флаг срабатывания термозащиты поднимается.
bcf PCLATH,1 ; Так как далее будет исполнен вычисляемый
27
bsf PCLATH,0 ; переход, лежащий во 2-м блоке PC.
;--------------------------------------------------
; Сравнение с температурным порогом.
;--------------------------------------------------
movlw .56 ;
subwf Temp_LSB,W ; Temp_LSB - .54 =... (результат -> W)
btfsc Status,C ; Результат "+/=0" или "-"
; (порог превышен или нет) ?
goto TERMO ; Если порог превышен, то ПП TERMO
; исполняется снова.
bcf Flag_1,7 ; Если не превышен, то флаг срабатывания
; термозащиты опускается.
bsf PCLATH,1 ; Так как далее будет исполнен вычисляемый
bcf PCLATH,0 ; переход, лежащий во 3-м блоке PC.
;================================================================================
; Вывод на индикацию, в 1-ю строку, фиксированной надписи " Автоматическая ".
;================================================================================
movlw b'10000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 1-й строки.
movlw .16 ;
movwf Count ;
movf Count,W ;
sublw .16 ; Аналогично, только
call TEXT_28 ; для TEXT_28.
bsf PortC,RS ;
call ENTER_BF ;
decfsz Count,F ;
goto $-6 ;
;================================================================================
; Вывод на индикацию, в 2-ю строку, фиксированной надписи " разблокировка ".
;================================================================================
movlw b'11000000' ; Установка курсора в крайнее
call ENTER_BF ; левое знакоместо 2-й строки.
movlw .16 ;
movwf Count ;
movf Count,W ;
sublw .16 ; Аналогично, только
call TEXT_29 ; для TEXT_29.
bsf PortC,RS ;
call ENTER_BF ;
decfsz Count,F ;
goto $-6 ;
;================================================================================
; Обеспечение необходимого времени "высвечивания" надписи.
;================================================================================
call PAUSE_S ; Задержка.
;----> Возврат по стеку из ПП PAUSE_S.
;================================================================================
clrf PCLATH ; Так как далее будет исполнен вычисляемый
; переход, лежащий во 1-м блоке PC.
return ; Возврат по стеку.
;================================================================================
; Инициализация термодатчика.
;================================================================================
; Установка на линии DQ 1.
;-----------------------------------
DQ_INIT call PIN_HI ; Установка вывода в высокоимпедансное
; состояние: за счет подтягивающего резистора,
; на линии устанавливается 1.
;----> Возврат по стеку из ПП PIN_HI.
;-----------------------------------
; Установка на линии DQ 0.
;-----------------------------------
call PIN_LO ; Установка на линии DQ нуля.
;----> Возврат по стеку из ПП PIN_LO.
;-----------------------------------
28
; Задержка 600 мкс.
;-----------------------------------
movlw .60 ; Установка количества проходов по 10мкс.
call PAUSE_X1 ; Переход в ПП задержки
; (задержка=60х10=600мкс.).
;----> Возврат по стеку из ПП PAUSE_X1.
;-----------------------------------
; Установка на линии DQ 1.
;-----------------------------------
call PIN_HI ; Установка вывода в высокоимпедансное
; состояние: за счет подтягивающего резистора,
; на линии устанавливается 1.
;----> Возврат по стеку из ПП PIN_HI.
;-----------------------------------
; Задержка 70 мкс.
;-----------------------------------
movlw .7 ; Установка количества проходов по 10мкс.
call PAUSE_X1 ; Переход в ПП задержки
; (задержка=7х10=70мкс.).
;----> Возврат по стеку из ПП PAUSE_X1.
;--------------------------------------------------------------------------------
; Определение наличия (или нет) отклика на импульс сброса.
;--------------------------------------------------------------------------------
btfsc PortC,DQ ; На линии DQ 0 или 1 (отклик есть или нет)?
bsf Flag,1 ; Если отклика нет (1), то флаг наличия
; термодатчика поднимается.
; Если отклик есть (0), то флаг наличия
; термодатчика остается опущенным и программа
; исполняется далее.
;-----------------------------------
; Задержка 500 мкс.
;-----------------------------------
movlw .50 ; Установка количества проходов по 10мкс.
call PAUSE_X1 ; Переход в ПП задержки
; (задержка=50х10=500мкс.).
;----> Возврат по стеку из ПП PAUSE_X1.
return ; Возврат по стеку.

;WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
; ПРОЦЕДУРА 1-WIRE ПРОТОКОЛА.
;WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
WIRE movwf Wire ; W --> Wire.
movlw 8 ; Задание количества
movwf Temp ; обрабатываемых битов.
;================================================================================
; Передача бита в линию DQ.
;================================================================================
; Установка на линии DQ уровня 0, то есть,
; формирование строба (перепад от 1 к 0).
;-----------------------------------------
METKA bcf PortC,DQ ; DQ=0.
nop ; Задержка 1 м.ц.
nop ; Задержка 1 м.ц.
;----------------------------------------
; Анализ состояния бита №0 регистра Wire.
;----------------------------------------
btfsc Wire,0 ; Wire,0 = 1 или 0 ?
bsf PortC,DQ ; Если Wire,0 = 1, то DQ=1.
rrf Wire,F ; Если Wire,0 = 0, а также после исполнения
; предыдущей команды, происходит сдвиг
; содержимого Wire вправо.
;------------------------------------------------
; Задержка на 11 м.ц. (от movlw 2 до bcf Wire,7).
;------------------------------------------------
movlw 2 ; Предустановка.
call PAUSE_X ; Переход в ПП PAUSE_X.
29
;--->Возврат по стеку из ПП PAUSE_X
;================================================================================
; Прием бита с линии DQ.
;================================================================================
; Подготовка 7-го бита регистра Wire к записи в него уровня DQ.
;--------------------------------------------------------------
bcf Wire,7 ; Wire,7=0.
;--------------------------------------------
; Перестройка направления работы ("на вход").
;--------------------------------------------
bsf Status,RP0 ; Выбор 1-го банка.
bsf TrisC,DQ ; RC0 работает "на вход".
bcf Status,RP0 ; Выбор 0-го банка.
;--------------------------------------------------------------
; Анализ состояния линии DQ.
; Если DQ=1, то в бит №7 регистра Wire записывается 1.
; Если DQ=0, то в бите №7 регистра Wire остается
; "лежать" ранее предустановленный 0.
;--------------------------------------------------------------
btfsc PortC,DQ ; На линии DQ 1 или 0 ?
goto $+2 ; Если DQ=1, то обход следующей команды.
goto $+2 ; Если DQ=0, то обход следующей команды.
bsf Wire,7 ; Wire,7=1.
;-------------------------------- ------------
; Перестройка направления работы ("на выход").
;--------------------------------------------
bsf Status,RP0 ; Выбор 1-го банка.
bcf TrisC,DQ ; RC0 работает "на выход".
bcf Status,RP0 ; Выбор 0-го банка.
;---------------------------------------------------
; Задержка на 59 м.ц. (от movlw .18 до bsf PortC,DQ).
;---------------------------------------------------
movlw .18 ; Предустановка.
call PAUSE_X ; Переход в ПП PAUSE_X.
;--->Возврат по стеку из ПП PAUSE_X
;---------------------------------------------------
; Установка на линии DQ уровня 1
; (подготовка к формированию следующего строба).
;---------------------------------------------------
bsf PortC,DQ ; DQ=1.
nop ; Задержка 1 м.ц.
nop ; Задержка 1 м.ц.
;----------------------------------------
; Счет битов.
;----------------------------------------
decfsz Temp,F ; Декремент счетчика битов.
goto METKA ; Если отработаны не все биты, то
; переход на обработку следующего бита.
; Если все, то программа исполняется далее.
;--------------------------------------------------------------------------------
; Опрос состояния флага исполнения/обхода "плавающей" задержки.
;--------------------------------------------------------------------------------
btfss Flag,0 ; Флаг исполнения/обхода "плавающей" задержки
; поднят или опущен ?
goto $+6 ; Если опущен, то обход "плавающей" задержки.
; Если поднят, то "плавающая" задержка
; отрабатывается.
;--------------------------------------------------------------------------------
; Ожидание завершения процесса преобразования температуры ("плавающая" задержка).
;--------------------------------------------------------------------------------
movlw b'11111111' ; Запись в W числа FFh.
subwf Wire,W ; Temp - FFh = ...
btfss Status,Z ; Z=0 или Z=1 (нулевой результат)?
goto WIRE ; Если Z=0, то ждем дальше.
; Если Z=1 (Temp заполнен единицами, то есть,
; на линии появился и надежно зафиксировался
30
; уровень 1), то программа исполняется далее.
return ; Возврат по стеку.
;----------------------------------------
; Завершающий этап.
;----------------------------------------
movf Wire,W ; Wire --> W.
return ; Возврат по стеку.
;WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW

;================================================================================
; Формирование на линии уровня "1" за счет подтягивающего резистора.
;================================================================================
PIN_HI bsf Status,RP0 ; Переход в банк 1.
bsf TrisC,DQ ; Настройка вывода RC0 на работу "на вход".
bcf Status,RP0 ; Переход в банк 0.
return ; Возврат по стеку.
;================================================================================
; Формирование на линии уровня "0" средствами микроконтроллера
;================================================================================
PIN_LO bcf PortC,DQ ; Установка 0 на выходе защелки вывода RA4.
bsf Status,RP0 ; Переход в банк 1.
bcf TrisC,DQ ; Настройка вывода RC0 на работу "на выход".
bcf Status,RP0 ; Переход в банк 0.
return ; Возврат по стеку.
;================================================================================
; ПП задержки, кратной 10 мкс.
;================================================================================
; Задание количества проходов по 10 мкс.
;----------------------------------------
PAUSE_X1 movwf Count ; W --> Count.
;----------------------------------------
; Задержка 10 мкс.
;----------------------------------------
PAUSE_10 nop ;
goto $+1 ; Одноразрядный,
goto $+1 ; вычитающий
goto $+1 ; счетчик
decfsz Count,F ; с "врезкой".
goto PAUSE_10 ;
return ; Возврат по стеку.
;================================================================================
; 2/10 преобразование (1х2) с перекодировкой результата.
;================================================================================
BIN2_10_T movwf Temp ; W -> Temp_1.
clrf Temp_1 ; Temp_1 = 0.
movlw .10 ;
subwf Temp,W ; Temp - .10 =... (результат -> W)
btfss Status,C ; Результат "+/=0" или "-" ?
goto $+4 ; Если "-", то обход следующих 3-х команд.
movwf Temp ; Если "+/=0", то W -> Temp.
incf Temp_1,F ; Temp_1 + 1 =... (результат -> Temp_1)
goto $-6 ; Переход на команду movlw .10
movf Temp,W ;
movwf LED0 ; Temp -> LED0.
movf Temp_1,W ;
movwf LED1 ; Temp_1 -> LED1.

movlw 30h ; W -> 30h


iorwf LED1,F ; Логическое "ИЛИ" содержимого W
iorwf LED0,F ; и содержимого регистров LED1 и LED0.
return ; Возврат по стеку.
;================================================================================
; Вывод на индикацию числовых значений верхнего Т-порога
; или текущих значений температуры.
;================================================================================
IND_TERMO movf LED1,W ; Вывод на индикацию
31
movwf PortB ; содержимого LED1.
bsf PortC,RS ;
call ENTER_BF ;
;----> Возврат по стеку из ПП ENTER_BF.
movf LED0,W ; Вывод на индикацию
movwf PortB ; содержимого LED0.
bsf PortC,RS ;
call ENTER_BF ;
;----> Возврат по стеку из ПП ENTER_BF.
return ; Возврат по стеку.
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
end ; Конец программы.

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


То, что относится к 2/10 преобразованию и перекодировке его результатов, выделено
темно-зеленым цветом.
То, что относится к сценарию-подсказке №3, выделено темно-красным цветом.
То, что относится к "пороговым делам" и "превращению" результата измерения
температуры в ШИМ-сигнал, выделено черным цветом.

Принципы работы всего того, что не относится к сценарию-подсказке №3, были


"расписаны" выше.
После того, как результат измерения температуры "осядет" в регистре Temp_LSB,
задается значение верхнего Т-порога.
В данном случае, я не стал его "задирать", а сделал равным 30-ти градусам.
Для удобства "экспериментов".
То есть, датчик не нужно будет греть паяльником (и т.п.).
Достаточно тепла руки (верхний Т-порог равен 30-ти градусам).
В будущем, значение верхнего Т-порога можно повысить.
В том числе, можно организовать и "пороговое меню", из которого можно будет
выбрать нужное значение верхнего Т-порога.
Так как в дальнейшем, нужно вывести числовое значение верхнего Т-порога на
индикацию, необходимо разделить числовое значение константы верхнего Т-порога на 2
(один сдвиг вправо).
Далее, для обеспечения вывода числового значения верхнего Т-порога на индикацию,
результат деления на 2 "протаскивается" через ПП 2/10 преобразования.
Я использовал ПП 2/10 преобразования программы DS18_20.asm из подраздела 4/38
"Обмена…" (автор статьи Сергей Рослик).
А так как эта ПП требуется более одного раза, то я вынес ее в "обслугу".
Далее, проверяется состояние флага срабатывания термозащиты.
Это нужно для организации температурного гистерезиса.
Принцип его организации такой:
Если обнаружено превышение верхнего Т-порога (термозащита сработала), то начнется
отработка сценария-подсказки №3, в "концовке" которого, флаг срабатывания
термозащиты поднимается.
На последующих циклах ПП TERMO, по факту поднятия этого флага, процедуры
сравнения с верхним Т-порогом и перевода числового значения младшего байта
температуры в ширину импульсов будут обойдены.
Транзистор закроется, вентиллятор будет переведен на максимальные обороты, и в
той же "концовке" сценария-подсказки №3, будет производиться сравнение текущей
температуры, но не с верхним Т-порогом, а с нижним Т-порогом.
Так будет продолжаться до тех пор, пока текущая температура не опустится ниже
нижнего Т-порога.
В этом случае, флаг срабатывания термозащиты опустится, транзистор откроется, и на
следующих циклах ПП TERMO, будут производиться сравнения текущей температуры
не с нижним Т-порогом, а с верхним Т-порогом, а заодно и переводы текущих,
числовых значениий младшего байта температуры в ширину импульсов.
В этом случае (верхний Т-порог не превышен), сценарий-подсказка №3 отрабатываться
не будет.
Предположим, что верхний Т-порог превышен.
32
В этом случае, процедуры сравнения с верхним Т-порогом и перевода числового
значения младшего байта температуры в ширину импульсов будут обойдены и
начнется отработка сценария-подсказки №3.
В части касающейся последовательного вывода на индикацию надписей, принцип их
вывода такой же, как и в сценарии-подсказке №2.
Разница только во "врезках".
В частности, после вывода на индикацию надписи Караул! Убивают! ПЕРЕГРЕВ,
организована "термоаварийная пищалка" с количеством "писков" = 10 (можно задать и
другое количество).
Основная "свистопляска" начинается после вывода на индикацию надписей
Тпорога=хх град. и Ттекущ.=хх град. (где хх - числовые значения "того-сего").
Что касается надписи Тпорога=хх град., то нужно только вывести на индикацию
содержимое LED1, LED0.
Почему?
Потому, что 2/10 преобразование числового значения верхнего Т-порога и его
перекодировка были произведены ранее (см. начало ПП TERMO).
А вот после вывода на индикацию надписи Ттекущ.=хх град., нужно "подсуетится" так:

;-------------------------------------
; Деление содержимого Temp_LSB на 2.
;-------------------------------------
bcf Status,C ; C = 0.
rrf Temp_LSB,W ; Деление на 2. Результат --> W.
;================================================================================
; 2/10 преобразование (1х2) с перекодировкой результата.
;================================================================================
call BIN2_10_T ; Переход в ПП 2/10 преобразования.
;--->Возврат по стеку из ПП BIN2_10_T

Перекодированный результат 2/10 преобразования будет "лежать" все в тех же


регистрах LED1, LED0, содержимое которых и выводится на индикацию.
А так как, при выводе на индикацию числовых значений верхнего Т-порога и текущих
значений температуры, применяется один и тот же "набор" команд, то я назвал этот
"набор" выводом на индикацию числовых значений верхнего Т-порога или
текущих значений температуры (ПП IND_TERMO) и вынес его в "обслугу".
После того, как указанная выше "цифирь" будет выведена на индикацию, флаг
срабатывания термозащиты поднимается (то, о чем говорилось выше) и задается
числовое значение нижнего Т-порога.
В данном случае, он равен 56/2=28 градусов.
Напоминаю, что верхний Т-порог = 30 градусов.
Температурный гистерезис = 30-28 = 2 градуса.
Нижний Т-порог вполне можно "привязать" к верхнему Т-порогу путем задания какой-то
конкретной "ширины" петли температурного гистерезиса.
В будущем, постараюсь "провернуть это дельце".
Числовое значение нижнего Т-порога делить на 2 не нужно, так как далее
производится сравнение с младшим байтом температуры.
В результате этого сравнения, возможны два сценария.

1. В том случае, если текущая температура находится в "зоне" петли


температурного гистерезиса, то ПП TERMO исполняется снова.
Причем, с поднятым флагом срабатывания термозащиты.
Таким образом, в дальнейшем, процедура сравнения текущей температуры, с верхним
Т-порогом, будет обойдена, а в еще более дальнейшем, снова будет произведено
сравнение текущей температуры с нижним Т-порогом.
И так будет продолжаться до тех пор, пока текущая температура не "покинет зону"
петли температурного гистерезиса.

2. В том случае, если текущая температура "покинула зону" петли температурного


гистерезиса, флаг срабатывания термозащиты опускается и на индикацию, примерно, в
течение 3-х секунд, выводится надпись Автоматическая разблокировка.
33
После этого, происходит возврат по стеку в то "место", из которого вызывалась ПП
TERMO.
В данном случае, этим "местом" будет процедура "рабочего" подрежима сценария
выключенной защиты.

Я организовал и ручную разблокировку при помощи кнопки "+/Да".


Смысл "жать" на нее имеется только тогда, когда нужно "принудительно" выйти из
термоблокировки, в интервале времени нахождения текущей температуры в "зоне"
петли температурного гистерезиса.
Обращаю Ваше внимание на то, что все табличные, вычисляемые переходы, к
которым происходит обращение из ПП TERMO, кроме первых двух, размещены в
начале 3-го блока памяти программ ПИКа.
Первая пара табличных, вычисляемых переходов размещена во 2-м блоке памяти
программ ПИКа.
После возврата из ПП TERMO, первый, отрабатываемый, вычисляемый переход
"лежит" в 1-м блоке памяти программ ПИКа.
В соответствии с этим "раскладом" и организованы числовые коррекции содержимого
регистра PCLATH.

Теперь посмотрите на это:


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

Команда clrf PortC заменена на то, что выделено красным цветом.


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

Лирическое отступление.
Вопрос: "Каково краткое определение понятия командир, в широком смысле этого
слова"?
Ответ: командир это специалист по наведению порядка. Не важно, какого именно.
Командир, это тот, кто, в своей "вотчине", догоняет проблемы, а не тот, кто от них
убегает.
Вывод: успешный конструктор должен быть командиром по определению.
Причем, командиром, "укомплектованным увесистой дубиной".
И чем "командиристее/задиристее", тем лучше.
И от этого никуда не денешься.
На мой взгляд, сей "перл" есть аксиома.

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

34