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

5/6.

Работа с температурными порогами: засылка “шпиона” на “вражескую


территорию” и операция по “вырезанию аппендицита”. Конструирование
“безаппендицитного” устройства.

Вашему вниманию предлагается цепочка логических рассуждений, которая, в очередной


раз (сознательно “долблю в одну точку”, так как это очень важно), иллюстрирует
процесс разбирательств с “мутной” темой.
В м/процессорном секторе электроники, подобного рода “мути” - пруд пруди, и если
человек не “хулиган”, то проблемы просто - напросто “забъют его насмерть”.
Если “добрый дядя” перекрывает “кислородный шланг”, то у “предмета такого
бесчеловечного эксперимента” есть 2 пути: либо “сложить лапки” и смириться с этой
данностью, либо, не мудрствуя лукаво, отправить “дядю” в “нокдаун” и после этого,
получить контроль над “кислородным шлангом”.
Итак, прежде чем что-то “ваять”, с использованием температурных порогов, нужно
разобраться с сутью алгоритма работы DS1820, который предлагается разработчиками,
в части касающейся этих самых температурных порогов.
Разбираюсь.
Просмотрел всю имеющуюся у меня информацию, залез в Интернет.
Мать честная …, да тут “Макар вообще телят не гонял”. Как все запущено …
В приложении к м/контроллерам, все попавшиеся на глаза авторы русскоязычной
информации по DS1820 (и по другим типам аналогичных датчиков) старательно и
бережно обходят эту “муть” при помощи примерно таких высказываний: “Команда Alarm
Search (EСh). На эту команду “откликаться” будут только те термометры, у которых
результат последнего измерения температуры выходит за предустановленные пределы
TH и TL”.
Пути к дальнейшему “счастью” не указаны и теряются в “туманной дали”.
Из этого высказывания понятно только то, что существует команда Alarm Search (EСh)
(сигнальный или аварийный поиск), после исполнения которой, датчики, у которых
результат последнего измерения температуры выходит за предустановленные пределы
TH и TL, что-то выдают, в линию DQ, со своей стороны (“отклик”), и “мастер” должен
это “что-то” принять, проанализировать, обработать и после этого, предпринять какие-то
действия.
Совсем не густо и очень туманно.
Это “жу-жу” неспроста… Чего это так испугались авторы русскоязычной информации по
DS1820?
Хотя с английским я и в больших неладах, но, поневоле, пришлось “лезть” в
фирменную, техническую документацию.
Переводчик добросовестно выдал соответствующую “абракадабру”, процедура
приведения которой к потребному виду и разбирательств с ней, нанесли довольно-таки
приличный урон моей нервной системе.
Без “хулиганства” никак не обойтись.
Главный вопрос, на который нужно ответить: “Что такое есть отклик на команду Alarm
Search (EСh) и с чем его едят”?
Не буду утомлять Вас описанием процедуры этого достаточно запутанного (в основном,
из-за скудности информации) “детективного расследования” (с засылкой “шпиона” и
хитроумными интригами), а сразу выдам “сухой осадок”.
Итак, имеет место быть команда Alarm Search (EСh), после выдачи которой
(“мастером”) в линию DQ, датчики, последние результаты измерений которых выходят
за температурные пороги TH и TL, “обязаны” (в соответствии с заданным алгоритмом)
что-то ответить (откликнуться).
Обратите внимание на множественное число слова “датчики”.
Например, откликнулись 2 датчика и выдали в линию DQ соответствующие биты.
А если, например, один датчик выдаст бит с уровнем 1, а второй выдаст бит с
уровнем 0?
В результате накладки (во времени) уровней битов друг на друга (откликнулись оба
датчика), 0 “задавит” 1, и в конечном итоге, на линии DQ будет выставлен 0.
Короче, единица “даст дуба” (“уйдет в небытие”).
А если откликнулось большее количество датчиков?

1
Стоит только одному биту иметь уровень 0, как он “задавит” все остальные биты с
уровнем 1.
А ведь, при таком способе обмена данными, отклик должен состоять не из одного
бита (он для этого слишком малоинформативен), а из нескольких.
Если, например, откликнулись 10 датчиков, то “мастер”, прежде чем работать с
температурными порогами, должен абсолютно точно идентифицировать каждый из этих
датчиков.
Только после этого он сможет адресно обратиться к конкретному датчику и сделать
свои “пороговотемпературные дела”.
Вывод: отклик датчика есть не что иное, как его уникальный, идентификационный
признак, хранящийся в ПЗУ.
Соответственно, “масса” отклика одного датчика составляет 8 байтов (64 бита).
Все это, конечно, прекрасно, но как быть с упомянутыми выше накладками, ведь на
команду Alarm Search (EСh) могут ответить не только один, а сразу несколько
датчиков?
Существует ли какой-то способ обработки сигнала, в результате применения которого
можно было бы последовательно “выудить”, из этого “безобразия”, полные, 64-битные
идентификационные признаки всех откликнувшихся датчиков?
Существует. Иначе и не стоило бы “огород городить”.
Применяется специальный, математический алгоритм, в основе которого лежит анализ
состояний линии DQ при “непосредственном отклике” и при “вторичном отклике”.
Например, если откликнулось 4 датчика и “непосредственный отклик” представляет
собой накладку друг на друга битов с уровнями 1, 0, 0, 1, то “вторичный отклик”
будет представлять собой накладку друг на друга инвертированных уровней тех же
битов, то есть, 0, 1, 1, 0.
В обеих случаях, в результате накладок уровней, на линии DQ будет выставлен 0, но
“мастер”, в своих дебрях, инвертирует 0 “вторичного отклика”.
Получается то, что, в результате двухшаговой обработки одного (текущего) бита
отклика, “мастер, в данном случае, создал” 2-разрядную комбинацию 01, и 0 “на ум
пошел”.
По этому же принципу, в результате двухшаговой обработки следующего бита отклика,
“мастер создаст” еще одну комбинацию и т.д.
Между этими “кирпичиками” организуется, достаточно “массивная” и по времени (13160
мкс. на определение содержимого ПЗУ одного датчика), и по количеству команд,
математическая “круговерть”, лезть в которую, лично я, с учетом тех задач, которые
передо мной стоят, не вижу никакого практического смысла.
Подпрограмму, в которой имеет место быть такая “круговерть”, “сваяли” разработчики.
Она однозначна (“железобетонный” алгоритм) и свои порядки в ней навести и не
получится, и не нужно.
Предположим, что в результате всей этой “свистопляски”, “мастер” определил адреса
всех датчиков, откликнувшихся на команду Alarm Search (EСh) (вернее, на целую “кучу”
таких команд).
Только после этого он может адресоваться к конкретному датчику (из числа
откликнувшихся), и, соответственно, после этого, определить величину превышения
температурного порога, его знак (и т.д.).
Кульминация - вывод во внешние устройства “координат” тех датчиков, в которых
допущено превышение температурных порогов, а также величин и знаков этих
превышений (или просто их показаний).
Можно и еще что-нибудь полезное создать и вывести “наружу”, это уже “дело техники”.
А теперь представьте себе суммарную сложность (в том числе и понятийную) всей
этой процедуры.
Прочитав это, Вы должны понять, что речь идет о достаточно “крутой” и
“навороченной” программе.
Обычно, после подобного рода осознаний, в голову приходят грустные мысли о
высоком, которые (мысли), в простейшем случае, приводят к “метаниям” и “прыжкам в
сторону” (вот Вам и причина испуга авторов).
Не знаю как другие, но лично я 30 лет “кровь на фронте проливал” вовсе не для
того, чтобы сигать, как заяц, от каждого чиха.
Какой – никакой, а опыт по “выдвиганию челюсти” имеется.
2
Да и о легендарной кузькиной матери вспомнить самый раз, так как зад проблемы
настолько оголился, что это выглядит очень похабно и вызывающе.
Итак, если перефразировать, то есть 2 пути: либо идти по пути, предложенному
разработчиками, либо идти по своему пути.
По поводу первого, мой здравый смысл “выдал на гора” такое огромное количество
всяких нелицеприятных слов, что сие, во-первых, очень впечатляет (в смысле гордости
за богатство русского языка), а во-вторых, открывает глаза на то, что, в контексте
поставленных задач, “король-то голый”.
Это чем-то смахивает на ту колбасу, которую продают в наших магазинах: фирменная
упаковка, содержимое заманивающего цвета, но есть ее нельзя (даже моя собака не
ест, а она несусветная обжора).
В части касающейся “мощного, голого зада”, главный вопрос можно сформулировать
так: “Существует ли на нем некая “болевая точка”, слабенько вдарив по которой,
можно было бы его “завалить”? Ведь если бить куда попало, то только ногу отобъешь,
а толка не будет”.
Так или иначе, но это коварство, в конечном итоге, сводится к поиску ответа на
очередной вопрос: “Существует или нет более простой и не менее эффективный
способ работы с температурными порогами (в приложении к небольшому количеству
датчиков, которые зафиксировали “переход границы”), чем способ, предложенный
разработчиками”?
Сначала “засылаю шпиона” и ищу “лазейку” в том, что есть.
Выясняется, что внутри DS1820 есть некий флаг, который поднимается в случае
превышения температурного порога и остается опущенным, если этого превышения
нет, но это внутренний флаг и напрямую считать его состояния нельзя.
Так что “номер не удался”…
Ставлю большой и жирный крест на стратегическом замысле разработчиков (в части
касающейся работы с температурными порогами) и “ваяю” свой стратегический
замысел.
“Привязываюсь” к программе DS1820_1.asm, так как в ней происходит работа с
несколькими датчиками (с двумя, но их количество можно увеличить).
“Камнем преткновения”, в “штатной” процедуре работы с температурными порогами,
является вопрос адресации к тому или иному датчику.
Именно на обеспечение этой возможности и тратится почти весь “порох”.
А в программе-то DS1820_1.asm этот вопрос решен, причем, “малой кровью”!
И в самом деле, на каждом “витке” полного цикла программы, в соответствии с
числовым значением байта регистра Mem, адресно выбирается только один, вполне
конкретный датчик (остальные - “в отключке”), и не нужно никаких дополнительных,
заумных считываний и вычислений, связанных с определением того, что уже
определено в ходе решения предыдущих задач (от добра, добра не ищут).
На практике это означает то, что, после копирования содержимого области
оперативной памяти DS1820 в соответствующие девять регистров общего назначения
(или после окончания процедуры работы с контрольной суммой), можно просто-
напросто произвести сверку текущего результата измерения с температурными
порогами.
Если все в норме, то “сигнал SOS” не выдается, а если не в норме, то “сигнал SOS”
выдается.
Кстати, там же, можно определить знак и величину превышения температурного
порога, а также сформировать внешний сигнал управления (если в этом есть
необходимость) и т.д.
Мало того, обеспечивается шаг установки температурного порога величиной 0,5
градуса, тогда как, при “штатном раскладе”, он составляет 1 градус.
Это обусловлено тем, что в последнем случае, в ходе сравнения текущих результатов
измерения с температурными порогами (внутри DS1820), младшие биты сравниваемых
байтов всегда читаются как нули (пол-градуса “погибли”).
Осталось только определиться с “привязкой” температурных порогов к конкретному
датчику.
А они уже “привязаны”!
Даром я что ли “кровь проливал” в предыдущем подразделе?
Работа проделана совсем не зря.
3
Какие значения температурных порогов будут предварительно записаны (в область
EEPROM памяти DS1820) во вспомогательном устройстве, такие их значения и будут
“железобетонно привязаны” к конкретному датчику.
В ходе отработки полного цикла программы, их байты, точно таким же способом, как и
все остальные байты регистров области оперативной памяти DS1820, “осядут” в
регистрах общего назначения TH и TL.
И никаких лишних “телодвижений” делать не нужно, кроме как считать их оттуда
(примитивное действие) и сравнить с этими “эталонами” значение текущего замера
температуры (содержимое регистра Temp_LSB), что немногим сложнее первого.
Все это делается “с реактивным свистом” (быстро).
Обработку результатов этого сравнения можно произвести несколькими способами.
Это уже “дело техники”.
Вывод: в контексте поставленной задачи, гораздо эффективнее, на каждом “витке”
полного цикла программы, организовать простую и быструю проверку текущего
результата замера температуры на предмет ее выхода (или нет) за температурные
пороги (плюс, имеется “простор для маневра”), чем заниматься тем же самым,
“череззаборногузадерещенским” способом, предлагаемым разработчиками.
В данном случае, последнее, это даже не поездка из Москвы в Питер через
Владивосток, а то же самое, но через Луну.
Но ведь должна же существовать какая-то разумная мотивация этого
“череззаборногузадирания”?
А она и существует, только направлена эта мотивация на интересы тех людей,
которые могут себе позволить раскошелиться на достаточно дорогой, самодостаточный
(автономный) комплекс устройств, имеющий в своем составе большое количество
датчиков и который управляется с помощью компьютера (а в нем “дури не меряно”, и
он “перемелет” любую “неудобоваримость”).
И готовая программа под это дело предоставляется.
Под словом “самодостаточный” подразумевается то, что, в этом случае, нет
необходимости в применении каких-то вспомогательных устройств (типа описанного), так
как их функции “ушли внутрь” этой “самодостаточности”.
Соответственно, сложность программы возрастает в разы.
В этом случае, и особенно с учетом большого количества датчиков, аварийный поиск,
спора нет, является полезным “наворотом”, так как, для определения фактов выходов
результатов замеров температуры (ограниченным, по сравнению с общим количеством,
количеством датчиков) за температурные пороги, не нужно производить
последовательный опрос всего “огроменного” количества датчиков (выигрыш по
времени).
А если речь идет о желании конструктора минимизировать материальные затраты и
“сваять” нечто попроще на основе, например, PIC16F84A?
Если при этом слепо руководствоваться “правилами игры”, заданными разработчиками
(в части касающейся температурных порогов), то в лучшем случае, потратив кучу
времени и сил, можно “родить” достаточно “тормозную” и необоснованно
“навороченную” “каракатицу” (если объем памяти программ позволит), а в худшем
случае, если “мозги заклинило”, можно “намыливать веревку и вешаться”.
Вот вам и насущная, жизненная необходимость наличия, в “биокомпьютере”
конструктора, некоего “разведуправления” со своей “агентурной сетью” и “шпионами”.
По большому счету, лично меня, как “заземленного работника паяльника и пинцета”, в
данном случае, интересуют не безальтернативные “продукты” чьей-то изощренной,
мозговой деятельности, ориентированные на решение “суперзадач”, а только наиболее
простые, понятные и эффективные способы достижения желаемого, комфортно
укладывающиеся в сознании.
В моем понимании, добротная работа это не решение конкретной задачи каким угодно
способом, а решение конкретной задачи самым простым и оптимальным способом.
Вот и получается, что при решении задач, связанных с применением м/контроллера и
с относительно малым количеством датчиков, во всех отношениях выгоднее и проще
произвести банальные сравнения значений текущих замеров температуры, с
температурными порогами, в конце каждого цикла замера температуры, чем
“связываться” с тем, что предлагают разработчики.
Пусть уж все датчики “тупо”, последовательно опрашиваются по кольцу.
4
В данном случае, это гораздо лучше, чем “увязание в сервисе”, который ориентирован
на значительно большее количество датчиков и на совсем не слабого “рулевого”.
В связи с этим, лично у меня, имеется упрек, направленный в сторону разработчиков.
Его можно выразить примерно так: “Вы сваяли очень перспективное устройство
(особенно при большом количестве 1-Wire устройств и наличии тугого кошелька),
соответствующее времени, но дали бы хоть пол-намека на возможность обхода Вашего
“сервиса”, ведь далеко не всем людям, по совокупности причин, нужен весь комплекс
предоставляемых Вами возможностей. Это понятно, что толку от них мало (в смысле
денег), но и о них тоже нужно не забывать”.
Подвинусь ближе к практике.
В части касающейся группы команд, обращающихся к содержимому ПЗУ DS1820,
можно сделать следующие, радостные, практические выводы:
Команду Alarm Search (EСh) можно “забыть как кошмарный сон”.
Кроме того, то же самое можно сделать и с командой Search ROM (F0h).
Это “одного поля ягоды”, так как команда Search ROM (F0h) делает то же самое, но
только без “привязки” к температурным порогам (откликаться будут все датчики,
подключенные к линии).
Таким образом, группа команд работы с ПЗУ сокращается с 5-ти до 3-х команд:

Read ROM (33h)


Match ROM (55h)
Skip ROM (CCh)
Рис. 1
А вот без этих 3-х команд, и в самом деле нельзя обойтись (все они уже были
применены ранее).
Перехожу от слов к делу.
Вашему вниманию предлагается устройство, работающее с температурными порогами.
Это все тот же “двухдатчиковый” термометр (возможность наращивания количества
датчиков сохраняется), о котором ранее шла речь, только с дополнительной функцией
визуального контроля выхода температуры за заданные пороги.
Принципиальная схема - без изменений. Меняете прошивку и все.
Естественно, предварительно нужно будет поработать со вспомогательным устройством.
Рекомендации на этот счет будут даны.
Это выглядит примерно так:

Примечание: можно установить любые величины температурных порогов (в пределах


дозволенного).
В левом показании, надпись “АВАРИЯ” сменится на надпись “НОРМА:” сразу же после
понижения температуры, в месте размещения этого датчика, до величины менее 30-ти
градусов.
В правом показании, надпись “НОРМА:” сменится на надпись “АВАРИЯ” сразу же после
повышения температуры, в месте размещения этого датчика, до величины 31 градус и
более.

5
Если будут превышены температурные пороги обеих датчиков, то на индикацию будут
выведены две надписи “АВАРИЯ”.
Одновременно можно проконтролировать величины температур в местах размещения
обеих датчиков.
Разрабатывая это устройство, я исходил из того, что в большинстве случаев, в
пределах одного датчика, требуется назначение только одного температурного порога,
а не двух.
Если в одной точке замера температуры нужно обеспечить ее контроль в каком-то
диапазоне температур, то нужно записать (при помощи вспомогательного устройства), в
область EEPROM памяти конкретного DS1820, два соответствующих температурных
порога (нижний и верхний). Проблемы в этом нет.
Естественно, после этого нужно скорректировать текст программы под эту доработку.
С учетом того, что Вы прочтете и увидите, ничего особо сложного в этом нет (есть от
чего “оттолкнуться”).
По сравнению с указанным выше “адресным геморроем”, это “мелочь пузатая”.
Вернусь к своим “котлетам”.
Итак, один разъединственный температурный порог я записываю в ячейку области
EEPROM памяти DS1820, с названием TH.
Вопрос: “А какова участь ячейки с названием TL? Неужели добру пропадать? Жалко”.
Вопрос резонный. И мне тоже жалко.
После выполнения необходимой, в этом случае, процедуры “чесания за ухом”, я
придумал следующее полезное применение этой ячейки.
Суть: в программе DS1820_1.asm имеется следующая группа команд:

;--------------------------------------------------------
; Подготовка к выводу результата измерения из следующего
; датчика (на следующем цикле измерения).
;--------------------------------------------------------
movlw 2 ; Запись в W "порога" сравнения (количества
; датчиков).
incf Mem,F ; Mem + 1 = ?
subwf Mem,W ; ? - .2 = ...
btfsc Status,C ; Результат вычитания положительный или
; отрицательный?
clrf Mem ; Если "+", то в Mem записывается .0.
; Если "-", то программа исполняется далее.
bcf Status,C ; Подготовка бита С к дальнейшей работе (С=0).
call DISPLAY ; Переход в ПП вывода результата измерения
; на индикацию.
;----> Возврат по стеку из ПП DISPLAY.
goto SNOVA ; Переход на новый цикл измерения.
;********************************************************************************

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


обеспечить адресацию к следующему датчику.
После опроса всех датчиков, происходит “закольцовка”, в результате которой
происходит переход на следующий цикл опроса и т.д., “до посинения”.
Например, имеется 10 датчиков.
Опрос происходит в следующей последовательности: №1, №2, №3, … №10, №1, №2,
№3 …
Один цикл опроса выделен синим цветом.
Для того чтобы это обеспечить, нужно 6 команд (я их выделил красным цветом).
Хотя эта группа команд и достаточно хороша (причин жаловаться на нее нет), но, для
разнообразия, можно “провернуть следующую комбинацию”.
Для случая наличия 10-ти датчиков: в ячейку области EEPROM памяти, с названием
TL, первого DS1820, с помощью вспомогательного устройства, записывается число .1.
В ячейку области EEPROM памяти, с названием TL, второго DS1820, с помощью
вспомогательного устройства, записывается число .2.
И т.д.
В ячейку области EEPROM памяти, с названием TL, десятого DS1820, с помощью
вспомогательного устройства, записывается число .0.
6
Напоминание: не забывайте про вычисляемый переход, под который все это “ваяется”.
Получается вот что:
Номер датчика: №1 №2 №3 №4 №5 №6 №7 №8 №9 №10
Число в ячейке TL: .1 .2 .3 .4 .5 .6 .7 .8 .9 .0
Для двух датчиков это будет выглядеть так:
Номер датчика: №1 №2
Число в ячейке TL: .1 .0

Это есть не что иное, как один из способов организации цикла опроса датчиков.
В этом случае, указанные выше 6 команд, заменяются на 2 команды:

movf TL,W ; Перезапись признака следующего датчика


movwf Mem ; из регистра TL (через W) в регистр Mem.

Причем, кроме малого числа команд, положительной особенностью такого способа


организации цикла опроса датчиков является то, что число, “лежащее” в регистре
общего назначения TL, перепишется в регистр Mem только после успешного
завершения процедуры проверки контрольной суммы (см. текст программы
DS1820_2.asm), а это есть гарантия того, что, даже в условиях сильных помех,
заданный порядок последовательного опроса датчиков нарушен не будет.
По-моему, это большой плюс и просто грешно не воспользоваться такой возможностью.
Итак, в ячейку области EEPROM памяти DS1820, с названием TH, записываю один
разъединственный температурный порог, а в ячейку области EEPROM памяти DS1820,
с названием TL, записываю:
для датчика №1 - .1,
для датчика №2 - .0.
В принципе, название ячейки TL (а также и название регистра общего назначения TL)
можно было бы сменить на что-то более “удобоваримое”, но я этого делать не стал.
Пусть будет то, к чему люди (и я в том числе) уже привыкли.
Просто, в данном случае, нужно иметь ввиду, что за названием TL “скрывается” не
нижний температурный порог, а “указивка” на следующий датчик.
Что касается сравнения текущего замера температуры с температурным порогом, то
это достаточно простая процедура:

;================================================================================
; Работа с температурными порогами.
;================================================================================
bcf Flag,5 ; Подготовка к работе бита №5 регистра Flag.
;------------------------------------------------------
; Сравнение результата замера с температурным порогом
; (работа с регистром TH).
;------------------------------------------------------
movf TH,W ; Копирование температурного порога в W.
subwf Temp_LSB,W ; Temp_LSB - TH = ?
btfss Status,C ; Результат вычитания положительный или
; отрицательный?
goto $+2 ; Если "-", то 1 в бит №5 регистра Flag
; не записывается (обход команды bsf Flag,5).
; Если "+" (превышение порога), то программа
; исполняется далее.
bsf Flag,5 ; В бит №5 регистра Flag записывается 1
; (признак превышения порога).
call DISPLAY ; Переход в ПП вывода результата измерения
; на индикацию.

В качестве указателя выхода (или нет) значения текущего замера температуры за


“границу” заданного температурного порога, я использовал бит №5 регистра Flag.
В начале процедуры работы с температурными порогами, его содержимое
сбрасывается в ноль (подготовка к работе).

7
Далее, из содержимого регистра Temp_LSB (значение текущего замера температуры)
вычитается содержимое регистра TH (заданный температурный порог), после чего
следует стандартная проверка на знак результата этой операции (вычитания).
Если результат отрицательный, то считается, что температурный порог не превышен и,
к моменту входа в ПП DISPLAY, в бите №5 регистра Flag, как был ранее
установленный ноль, так от им и останется.
Если результат положительный, то, перед входом в ПП DISPLAY, в бит №5 регистра
Flag, записывается 1.
Вот и вся премудрость.
Далее, 0 или 1, записанная в бите №5 регистра Flag, будет определять содержание
надписи, выводимой на индикацию (“НОРМА:” или “АВАРИЯ” соответственно).
А от содержимого регистра Mem будет зависеть то, над каким из двух показаний
будет “высвечиваться” та или иная из этих надписей.
Так как замеры датчиками температуры происходят последовательно, а ЖКИ модуль
имеет оперативную память показаний, то одновременно будут “высвечиваться” и
результаты обеих замеров, и сопровождающие их надписи.
Визуально будут ощущаться только смены величин показаний и смены одной надписи
на другую.
И самое главное, Вы можете своими глазами убедиться, что датчики, образно
выражаясь, “живут отдельной друг от друга, независимой жизнью”.
Именно за это и “пролито море крови”.
В принципе, датчик DS1820, с поправкой на “вырезанный аппендицит”, это хорошая,
удобная “машина”, и ругать его совсем не стоит (“сын не в ответе за своего отца”).
А вот и практический результат “воплощения в жизнь” приведенных выше
“словоблудий”, который убеждает лучше десятка докторских диссертаций (работа
программы проверена в “железе”. “Мин нет”):

;********************************************************************************
; DS1820_2.asm ЭЛЕКТРОННЫЙ ТЕРМОМЕТР НА ОСНОВЕ ДАТЧИКОВ ТЕМПЕРАТУРЫ DS1820
; М/контроллер и DS1820 работают по интерфейсу 1-Wire.
; Работа с двумя датчиками, вычислением контрольной суммы,
; температурными порогами и учетом импульса присутствия.
; Количество датчиков можно увеличить.
;********************************************************************************
; "Практикум по конструированию устройств на PIC контроллерах".
; Эта программа входит в состав 5-го раздела.
; Авторы: Alberto Rolando Senelyuk (Argentina),
; Корабельников Евгений Александрович (Русь-матушка)
; http://ikarab.narod.ru karabea@lipetsk.ru
;********************************************************************************
; Используется м/контроллер PIC16F84A. Частота кварца 4 Мгц.
; Сигнальный вывод (DQ) датчика DS1820 подключается к выводу RA4.
; Между выводом RA4 и шиной питания подключается подтягивающий резистор
; номиналом 4,7-5,1 кОм.
; DS1820 включается по схеме с активным питанием, т.е.: вывод 1 - общий,
; вывод 2 - сигнальный,
; вывод 3 - питание (+5в).
; Информация выводится в русифицированный ЖКИ модуль 16х2 на
; основе м/к HD44780 (по 4-разрядному интерфейсу).
; Функции выводов порта А:
; RA0 - RW (ЖКИ),
; RA1 - RS (ЖКИ),
; RA2 - E (ЖКИ),
; RA4 - вывод DQ датчика DS1820.
;-------------------------------
; Объем программы: 385 команд.
;================================================================================
LIST p=16F84a ; Используется м/контроллер PIC16F84A.
__CONFIG 03FF1H ; Бит защиты выключен, WDT выключен,
; XT-генератор.
;================================================================================
; Определение положения регистров специального назначения.

8
;================================================================================
IndF equ 00h ; Доступ к памяти через FSR.
PC equ 02h ; Счетчик команд.
Status equ 03h ; Регистр Status.
FSR equ 04h ; Регистр косвенной адресации.
PortA equ 05h ; Регистр Port A.
TrisA equ 05h ; Регистр Tris A-банк1.
PortB equ 06h ; Регистр Port B.
TrisB equ 06h ; Регистр Tris B-банк1.
IntCon equ 0Bh ; Регистр IntCon.
;================================================================================
; Определение названия и положения регистров общего назачения.
;================================================================================
N equ 0Ch ; Счетчик битов.
N1 equ 0Dh ; Счетчик байтов.
Temp equ 0Eh ; Многофункциональный регистр временного
; хранения.
Mem equ 0Fh ; Регистр оперативной памяти номеров датчиков.
Temp_LSB equ 10h ; Регистр младшего байта температуры.
Temp_MSB equ 11h ; Регистр старшего байта температуры.
TH equ 12h ; Регистр верхнего предела температуры.
TL equ 13h ; Регистр нижнего предела температуры.
NO_1 equ 14h ; Регистр резерва.
NO_2 equ 15h ; Регистр резерва.
Count_REM equ 16h ; Применяются при измерении температуры
Count_D_C equ 17h ; с более высоким разрешением.
CRC equ 18h ; Регистр хранения считанного байта
; контрольной суммы.
CRC_1 equ 19h ; Регистр хранения вычисленного байта
; контрольной суммы.
Flag equ 1Ah ; Регистр флагов.
Count equ 1Bh ; Многофункциональный счетчик.
LED0 equ 1Ch ; Регистры двоично-десятичного преобразования
LED1 equ 1Dh ; (плюс, LED0 используется при вычислении CRC)
;================================================================================
; Определение места размещения результатов операций.
;================================================================================
W equ 0 ; Результат направить в аккумулятор.
F equ 1 ; Результат направить в регистр.
;================================================================================
; Присваивание битам названий.
;================================================================================
C equ 0 ; Флаг переноса-заема.
Z equ 2 ; Флаг нулевого результата.
RP0 equ 5 ; Бит выбора банка.
DQ equ 4 ; Бит порта A для управления DS1820.
RW equ 0 ; Бит №0 регистра PortA (вывод RA0 – линия RW)
RS equ 1 ; Бит №1 регистра PortA (вывод RA1 - линия RS)
E equ 2 ; Бит №2 регистра PortA (вывод RA2 - линия E)
BF equ 7 ; Бит №7 регистра PortB.
;================================================================================
org 0 ; Начать выполнение программы
goto START ; с подпрограммы START.
;********************************************************************************

;************************************************************************
; ------------------- "РАБОЧАЯ" ЧАСТЬ ПРОГРАММЫ -------------------
;************************************************************************
; "Рабочая" инициализация ЖКИ модуля.
;================================================================================
LCD_INIT movlw b'00101000' ; Установка: 4-разрядный интерфейс, 2 строки,
; 5х7 точек.
call ENTER_BF ; "Плавающая" задержка со стробом под команду
; 00101000.

9
;----> Возврат по стеку из ПП ENTER_BF.
movlw b'00101000' ; Установка: 4-разрядный интерфейс, 2 строки,
; 5х7 точек.
call ENTER_BF ; "Плавающая" задержка со стробом под команду
; 00101000.
;----> Возврат по стеку из ПП ENTER_BF.
movlw b'00001100' ; Установка: дисплей включен, видимое
; отображение курсора выключено.
call ENTER_BF ; "Плавающая" задержка со стробом под команду
; 00001100.
;----> Возврат по стеку из ПП ENTER_BF.
movlw b'00000001' ; Установка: очистка дисплея со сбросом
; данных, установка курсора в начало
; 1-й строки.
call ENTER_BF ; "Плавающая" задержка со стробом под команду
; 00000001.
;----> Возврат по стеку из ПП ENTER_BF.
return ; Возврат по стеку на начало вывода символов
; в 1-ю строку.
;================================================================================
; ПП "плавающей" задержки на основе анализа состояния флага занятости BF
; (вариант для 4-разрядного интерфейса).
;================================================================================
ENTER_BF movwf Temp ; Переправка старшего п/байта регистра W на
movwf PortB ; линии RB4...7.
;------------------------------------------
; Запуск в работу старшего п/байта (строб).
;------------------------------------------
nop ; Задержка в 1 м.ц.
bsf PortA,E ; Установка на линии Е "1".
nop ; Задержка в 1 м.ц.
bcf PortA,E ; Установка на линии Е "0".
;------------------------------------------
swapf Temp,W ; Смена п/байтов с сохранением результата
; операции в W.
movwf PortB ; Переправка младшего п/байта регистра W на
; линии RB4...7.
;------------------------------------------
; Запуск в работу младшего п/байта (строб).
;------------------------------------------
nop ; Задержка в 1 м.ц.
bsf PortA,E ; Установка на линии Е "1".
nop ; Задержка в 1 м.ц.
bcf PortA,E ; Установка на линии Е "0".
;-------------------------------------------------
; Проверка состояния флага занятости BF.
;-------------------------------------------------
; Подготовка к проверке.
;------------------------
bsf Status,RP0 ; Переход в 1-й банк.
movlw b'11110000' ; Запись в W "11110000"
movwf TrisB ; RB4...7 работают на вход, а RB0...3 работают
; на выход.
bcf Status,RP0 ; Переход в 0-й банк.

bcf PortA,RS ; Установка на линии RS "0" (режим команд).


bsf PortA,RW ; Линия RW в "1" (режим чтения данных).
nop ; Задержка в 1 м.ц.
bsf PortA,E ; Установка на лини Е "1".
POVTOR nop ; Задержка в 1 м.ц.
;-----------------------
; Сама проверка.
;-----------------------
btfsc PortB,BF ; Проверка состояния флага занятости BF.
goto POVTOR ; Если BF=1, то продолжение задержки до тех
; пор, пока BF не установится в "0" (программа
10
; исполняется далее).
;-----------------------
; Завершение процедуры.
;-----------------------
clrf PortA ; Сброс в "0" всех защелок порта А
; (RW=0, RS=0, E=0).
bsf Status,RP0 ; Переход в 1-й банк.
clrf TrisB ; Все выводы порта В работают на выход.
bcf Status,RP0 ; Переход в 0-й банк.

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


;********************************************************************************

;================================================================================
; Подпрограмма вывода на индикацию надписи "АВАРИЯ".
;================================================================================
AVARIJA movlw 41h ; На индикацию выводится
bsf PortA,RS ; символ "А".
call ENTER_BF ; "Плавающая" задержка со стробом под вывод
; данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.
movlw 42h ; На индикацию выводится
bsf PortA,RS ; символ "В".
call ENTER_BF ; ------"------
;----> Возврат по стеку из ПП ENTER_BF.
movlw 41h ; На индикацию выводится
bsf PortA,RS ; символ "А".
call ENTER_BF ; ------"------
;----> Возврат по стеку из ПП ENTER_BF.
movlw 50h ; На индикацию выводится
bsf PortA,RS ; символ "Р".
call ENTER_BF ; ------"------
;----> Возврат по стеку из ПП ENTER_BF.
movlw 0A5h ; На индикацию выводится
bsf PortA,RS ; символ "И".
call ENTER_BF ; ------"------
;----> Возврат по стеку из ПП ENTER_BF.
movlw 0B1h ; На индикацию выводится
bsf PortA,RS ; символ "Я".
call ENTER_BF ; ------"------
;----> Возврат по стеку из ПП ENTER_BF.

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


;================================================================================
; Подпрограмма вывода на индикацию надписи "НОРМА:".
;================================================================================
NORMA movlw 48h ; На индикацию выводится
bsf PortA,RS ; символ "Н".
call ENTER_BF ; "Плавающая" задержка со стробом под вывод
; данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.
movlw 4Fh ; На индикацию выводится
bsf PortA,RS ; символ "О".
call ENTER_BF ; ------"------
;----> Возврат по стеку из ПП ENTER_BF.
movlw 50h ; На индикацию выводится
bsf PortA,RS ; символ "Р".
call ENTER_BF ; ------"------
;----> Возврат по стеку из ПП ENTER_BF.
movlw 4Dh ; На индикацию выводится
bsf PortA,RS ; символ "М".
call ENTER_BF ; ------"------
;----> Возврат по стеку из ПП ENTER_BF.
movlw 41h ; На индикацию выводится
bsf PortA,RS ; символ "А".
call ENTER_BF ; ------"------
11
;----> Возврат по стеку из ПП ENTER_BF.
movlw 3Ah ; На индикацию выводится
bsf PortA,RS ; символ ":".
call ENTER_BF ; ------"------
;----> Возврат по стеку из ПП ENTER_BF.

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


;================================================================================
;********************************************************************************
; ПОДПРОГРАММА ВЫВОДА НА ИНДИКАЦИЮ.
;********************************************************************************
; Работа в 1-й строке.
;********************************************************************************
; Анализ состояния аварийного флага.
;-----------------------------------------------
DISPLAY btfss Flag,5 ; Бит №5 регистра Flag =0 или =1 ?
goto OBHOD ; Если =0, то обход процедуры вывода
; надписи "АВАРИЯ".
movf Mem,W ; Если =1, то копирование содержимого регистра
; оперативной памяти номеров датчиков Mem
; в регистр W.
;=========================================================
; Определение датчика, показанию которого нужно
; поставить в соответствие надпись "АВАРИЯ".
;=========================================================
addwf PC,F ; Вычисляемый переход.
goto AVAR ; Если Mem=.0, то переход на метку AVAR.
; Если Mem=.1, то переход на команду
; movlw b'10001001'.
;-----------------------------------------------
; Вывод надписи "АВАРИЯ" для датчика №2.
;-----------------------------------------------
movlw b'10001001' ; Выбор ячейки DD RAM с адресом 09h, что
; соответствует установке курсора в 10-е слева
; знакоместо 1-й строки.
call ENTER_BF ; "Плавающая" задержка со стробом под команду
; 10001001.
;----> Возврат по стеку из ПП ENTER_BF.
call AVARIJA ; Переход в ПП вывода надписи "АВАРИЯ".
;----> Возврат по стеку из ПП AVARIJA.
goto DISPLAY_1 ; Переход в ПП DISPLAY_1.
;-----------------------------------------------
; Вывод надписи "АВАРИЯ" для датчика №1.
;-----------------------------------------------
AVAR movlw b'10000001' ; Выбор ячейки DD RAM с адресом 01h, что
; соответствует установке курсора в 2-е слева
; знакоместо 1-й строки.
call ENTER_BF ; "Плавающая" задержка со стробом под команду
; 10000001.
;----> Возврат по стеку из ПП ENTER_BF.
call AVARIJA ; Переход в ПП вывода надписи "АВАРИЯ".
;----> Возврат по стеку из ПП AVARIJA.
goto DISPLAY_1 ; Переход в ПП DISPLAY_1.
;=========================================================
; Определение датчика, показанию которого нужно
; поставить в соответствие надпись "НОРМА:".
;=========================================================
OBHOD movf Mem,W ; Копирование содержимого регистра оперативной
; памяти номеров датчиков Mem в регистр W.
addwf PC,F ; Вычисляемый переход.
goto NORMAL ; Если Mem=.0, то переход на метку NORMAL.
; Если Mem=.1, то переход на команду
; movlw b'10001001'.
;-----------------------------------------------
; Вывод надписи "НОРМА:" для датчика №2.
;-----------------------------------------------
12
movlw b'10001001' ; Выбор ячейки DD RAM с адресом 09h, что
; соответствует установке курсора в 10-е слева
; знакоместо 1-й строки.
call ENTER_BF ; "Плавающая" задержка со стробом под команду
; 10001001.
;----> Возврат по стеку из ПП ENTER_BF.
call NORMA ; Переход в ПП вывода надписи "НОРМА:".
;----> Возврат по стеку из ПП NORMA.
goto DISPLAY_1 ; Переход в ПП DISPLAY_1.
;-----------------------------------------------
; Вывод надписи "НОРМА:" для датчика №1.
;-----------------------------------------------
NORMAL movlw b'10000001' ; Выбор ячейки DD RAM с адресом 01h, что
; соответствует установке курсора в 2-е слева
; знакоместо 1-й строки.
call ENTER_BF ; "Плавающая" задержка со стробом под команду
; 10000001.
;----> Возврат по стеку из ПП ENTER_BF.
call NORMA ; Переход в ПП вывода надписи "НОРМА:".
;----> Возврат по стеку из ПП NORMA.

;********************************************************************************
; Работа во 2-й строке.
;********************************************************************************
; Выбор места начальной установки курсора во 2-й строке.
;----------------------------------------------------------
DISPLAY_1 movf Mem,W ; Копирование содержимого регистра оперативной
; памяти номеров датчиков Mem в регистр W.
addwf PC,F ; Вычисляемый переход.
goto DISPL ; Если Mem=.0, то переход на метку DISPL.
; Если Mem=.1, то переход на команду
; movlw b'11001001'.
;----------------------
; Для датчика №2.
;----------------------
movlw b'11001001' ; Выбор ячейки DD RAM с адресом 49h, что
; соответствует установке курсора в 10-е слева
; знакоместо 2-й строки.
call ENTER_BF ; "Плавающая" задержка со стробом под команду
; 11001001.
;----> Возврат по стеку из ПП ENTER_BF.
goto $+3 ; Обход последующих двух команд.
;----------------------
; Для датчика №1.
;----------------------
DISPL movlw b'11000001' ; Выбор ячейки DD RAM с адресом 41h, что
; соответствует установке курсора во 2-е слева
; знакоместо 2-й строки.
call ENTER_BF ; "Плавающая" задержка со стробом под команду
; 11000001.
;----> Возврат по стеку из ПП ENTER_BF.
;----------------------------------------------------------
; Определение и вывод на индикацию знака температуры (+/-).
;----------------------------------------------------------
btfsc Temp_MSB,0 ; В бите №0 регистра Temp_MSB 0 или 1 ?
goto MINUS ; Если 1, то переход в ПП MINUS.
movlw 2Bh ; Если 0, то на индикацию
bsf PortA,RS ; выводится символ "+".
call ENTER_BF ; "Плавающая" задержка со стробом под вывод
; данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.
goto SDVIG ; После вывода на индикацию символа "+",
; переход на обработку младшего байта
; температуры.
MINUS movlw 2Dh ; На индикацию выводится
bsf PortA,RS ; символ "-".
13
call ENTER_BF ; "Плавающая" задержка со стробом под вывод
; данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.
;----------------------------------------------------------
; Перевод двоичного числа младшего байта температуры
; из отрицательной области температур в положительную.
;----------------------------------------------------------
comf Temp_LSB,F ; После вывода на индикацию символа "-", все
incf Temp_LSB,F ; биты младшего байта температуры
; инвертируются и к результату прибавляется 1.
;================================================================================
; Подпрограмма обработки содержимого младшего байта температуры.
;================================================================================
; Деление числа, записанного в младшем байте температуры, на 2
; и запись, в бит №0 регистра Flag, признака символов "0" или "5".
;--------------------------------------------------------------------------------
SDVIG clrf Flag ; Flag=0 (подготовка к работе).
rrf Temp_LSB,F ; Деление на 2.
btfsc Status,C ; В бите С 0 или 1 ?
bsf Flag,0 ; Если С=1, то в бит №0 регистра Flag
; записывается 1 (признак символа "5").
; Если С=0, то в бите №0 регистра Flag так и
; останется "лежать" 0 (признак символа "0"),
; и программа будет исполняться далее.
;--------------------------------------------------------------------------------
; Установка (или нет) признака добавления (к показаниям) символа "1"
; (признак устанавливается при температуре от 100 градусов и выше).
;--------------------------------------------------------------------------------
movlw .100 ;
subwf Temp_LSB,W ; Temp_LSB - .100 = ? Результат - в W.
btfss Status,C ; Результат положительный или отрицательный?
goto BIN2_10 ; Если отрицательный, то признак добавления
; символа "1" не устанавливается
; (бит №7 регистра Flag=0).
bsf Flag,7 ; Если положительный, то устанавливается
; (бит №7 регистра Flag=1).
;********************************************************************************
; Подпрограмма двоично-десятичного преобразования (для двух десятичных чисел).
;********************************************************************************
BIN2_10 bcf Status,C ; Сброс флага переноса-заема.
movlw .8 ; Запись в регистр Count числа
movwf Count ; проходов преобразования.
clrf LED0 ; Сброс регистра LED0.
;--------------------------------------------------------------------------------
; Циклический сдвиг влево через бит С регистра Status.
;--------------------------------------------------------------------------------
LOOP_16 rlf Temp_LSB,F ; Циклический сдвиг влево содержимого регистра
; Temp_LSB.
rlf LED0,F ; Циклический сдвиг влево содержимого регистра
; LED0.
decfsz Count,F ; Декремент содержимого регистра Count,
; с сохранением результата в нем же.
goto adjDEC ; Если результат не = 0, то переход в ПП
; adjDEC, а если = 0, то программа
; исполняется далее.
;--------------------------------------------------------------------------------
; Порязрядное распределение полубайтов.
;--------------------------------------------------------------------------------
swapf LED0,W ; Запись старшего полубайта LED0
andlw 0Fh ; в младший полубайт LED1
movwf LED1 ;

movfw LED0 ; Запись младшего полубайта LED0


andlw 0Fh ; в младший полубайт LED0
movwf LED0 ;

14
goto ASC ; Переход в ПП ASC.
;--------------------------------------------------------------------------------
; Запись в регистр FSR адреса регистра LED0 для дальнейшей косвенной адресации
; к нему в ПП adjBCD.
;--------------------------------------------------------------------------------
adjDEC movlw LED0 ; Запись в регистр FSR адреса регистра LED0
movwf FSR ; с дальнейшим переходом в ПП adjBCD.
call adjBCD ;
;---> Возврат по стеку из ПП adjBCD.
goto LOOP_16 ; Переход на следующее кольцо числовых
; преобразований.
;--------------------------------------------------------------------------------
; Основные операции преобразования двоичных чисел в двоично-десятичные.
;--------------------------------------------------------------------------------
adjBCD clrwdt ; Сброс сторожевого таймера WDT.
movlw 3 ; Суммирование содержимого текущего LED
addwf 0,W ; (LED0...3) с числом 03h, с записью
movwf Temp ; результата операции, через регистр W, в
; регистр Temp.
btfsc Temp,3 ; Анализ состояния бита №3 регистра Temp.
movwf 0 ; Если бит №3 = 1, то содержимое регистра Temp
; копируется в текущий LED.
movlw 30 ; Если бит №3 = 0, то содержимое текущего LED
addwf 0,W ; складывается с константой 30h, с записью
movwf Temp ; результата операции, через регистр W, в
; регистр Temp.
btfsc Temp,7 ; Анализ состояние бита №7 регистра Temp.
movwf 0 ; Если бит №7 = 1, то содержимое регистра Temp
; копируется в текущий LED.
retlw 0 ; Если бит №7 = 0, то регистр W очищается и
; происходит возврат по стеку в ПП adjDEC.
;********************************************************************************
; Процедура преобразования кода.
;================================================================================
ASC movlw 30h ; Запись в регистр W числа 30h.
iorwf LED0,F ; Логическое "ИЛИ" содержимого регистра W и
; регистра LED0 с сохранением результата в
; LED0.
iorwf LED1,F ; То же самое для LED1.
;********************************************************************************
; Вывод на индикацию результата измерения.
;********************************************************************************
; Вывод (или нет) на индикацию символа "1" (выводится при Т=100 градусов и выше).
;================================================================================
btfss Flag,7 ; Бит №7 регистра Flag =0 или =1 ?
goto C_00_99 ; Если =0, то символ "1" на индикацию не
; выводится.
movlw 31h ; Если =1, то символ "1" (31h)
bsf PortA,RS ; на индикацию выводится.
call ENTER_BF ; "Плавающая" задержка со стробом под вывод
; данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.
;================================================================================
; Вывод на индикацию двух символов результата измерения
; (в диапазоне от 00 до 99 градусов).
;================================================================================
C_00_99 movf LED1,W ; Вывод на индикацию байта,
bsf PortA,RS ; записанного в регистре LED1.
call ENTER_BF ; "Плавающая" задержка со стробом под вывод
; данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.
movf LED0,W ; Вывод на индикацию байта,
bsf PortA,RS ; записанного в регистре LED0.
call ENTER_BF ; "Плавающая" задержка со стробом под вывод
; данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.
15
;================================================================================
; Вывод на индикацию пары символов ",0" или ",5".
;================================================================================
movlw 2Ch ; Вывод на индикацию
bsf PortA,RS ; символа "," (2Ch).
call ENTER_BF ; "Плавающая" задержка со стробом под вывод
; данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.
btfsc Flag,0 ; Бит №0 регистра Flag =0 или =1 ?
goto _5 ; Если =1, то далее (goto _5), на
; индикацию будет выведен символ "5".
movlw 30h ; Если =0, то на индикацию
bsf PortA,RS ; выводится символ "0" (30h).
call ENTER_BF ; "Плавающая" задержка со стробом под вывод
; данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.
return ; Возврат по стеку.

_5 movlw 35h ; Вывод на индикацию


bsf PortA,RS ; символа "5" (35h).
call ENTER_BF ; "Плавающая" задержка со стробом под вывод
; данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.

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


;********************************************************************************

;************************************************************************
; НАЧАЛО ПРОГРАММЫ
;************************************************************************
START clrf PortA ; Сброс всех защелок порта А.
clrf PortB ; Сброс всех защелок порта В.
clrf Mem ; Сброс регистра оперативной памяти
; номера датчика.
clrf IntCon ; Запрет всех прерываний.

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


clrf TrisA ; Все выводы портов А и В
clrf TrisB ; работают на выход.
bcf Status,RP0 ; Переход в 0-й банк.

call LCD_INIT ; Условный переход в процедуру "рабочей"


; инициализации.
;----> Возврат по стеку из ПП LCD_INIT.

;########################################################################
; Начало работы с датчиком DS1820.
;########################################################################
; Инициализация DS1820.
;================================================================================
SNOVA call DQ_INIT ; Переход в ПП нициализации DS1820.
;----> Возврат по стеку из ПП DQ_INIT.
;================================================================================
; Команда Skip_ROM (CCh).
; Необходима для запуска процедуры преобразования температуры сразу
; всеми датчиками.
;================================================================================
movlw 0CCh ; Запись команды CCh
movwf Temp ; в регистр Temp.
call OUT_BYTE ; Переход в ПП передачи байта OUT_BYTE.
;----> Возврат по стеку из ПП OUT_BYTE.
;================================================================================
; Команда Start_Conv (44h).
; Эта команда запускает процесс преобразования температуры. В течение времени ее
; исполнения, DS1820 не реагирует на команды "мастера".

16
; Это время нужно просто переждать.
;================================================================================
movlw 44h ; Запись команды 44h
movwf Temp ; в регистр Temp.
call OUT_BYTE ; Переход в ПП передачи байта OUT_BYTE.
;----> Возврат по стеку из ПП OUT_BYTE.
;================================================================================
; Ожидание завершения процесса преобразования температуры.
; То что Вы видите ниже, есть один из способов реализации "плавающей" (следящей)
; задержки (можно применить фиксированную задержку).
;================================================================================
WAIT call IN_BYTE ; Переход в ПП приема байта IN_BYTE.
;----> Возврат по стеку из ПП IN_BYTE.
movlw b'11111111' ; Запись в W числа FFh.
subwf Temp,W ; Temp - FFh = ...
btfss Status,Z ; Z=0 или Z=1 (нулевой результат)?
goto WAIT ; Если Z=0, то ждем дальше.
; Если Z=1 (Temp заполнен единицами, то есть,
; на линии появился и надежно зафиксировался
; уровень 1), то программа исполняется далее.
;================================================================================
; Инициализация DS1820.
;================================================================================
RE_START call DQ_INIT ; Переход в ПП нициализации DS1820.
;----> Возврат по стеку из ПП DQ_INIT.
;================================================================================
; Команда Match ROM (55h).
; Эта команда разрешает адресацию к конкретному датчику, с целью
; дальнейшего считывания данных из области его оперативной памяти.
;================================================================================
movlw 055h ; Запись команды Match ROM.
movwf Temp ; в регистр Temp.
call OUT_BYTE ; Переход в ПП передачи байта.
;----> Возврат по стеку из ПП OUT_BYTE.
;----------------------------------------
; Подготовка к процедуре адресации.
;----------------------------------------
movlw 10h ; Вывод типа прибора (для DS1820 - 10h, для
movwf Temp ; DS1990A - 01h, для DS18B20 - 28h, для
call OUT_BYTE ; DS2415(часы реального времени) - 24h и
; т.д.).
;--------------------------------------------------------------------------------
; Выбор того датчика, из которого будет считано содержимое области
; оперативной памяти.
;--------------------------------------------------------------------------------
movf Mem,W ; Копирование содержимого регистра оперативной
; памяти номеров датчиков Mem, в регистр W.
addwf PC,F ; Вычисляемый переход.
goto NOMER ; Если Mem=.0, то переход на метку NOMER.
; Если Mem=.1, то переход на команду
; movlw 3Fh.
;--------------------------------------------------------------------------------
; Процедура адресации к датчику №2 (адрес: 57 00 08 00 DC 00 3F 10)
; В ячейку TH записано 3Eh (порог 31 градус), в ячейку TL записано 00h.
;--------------------------------------------------------------------------------
movlw 3Fh ; Передача первого байта серийного номера.
movwf Temp ;
call OUT_BYTE ;
;----> Возврат по стеку из ПП OUT_BYTE.
movlw 0 ; Передача второго байта серийного номера.
movwf Temp ;
call OUT_BYTE ;
;----> Возврат по стеку из ПП OUT_BYTE.
movlw 0DCh ; Передача третьего байта серийного номера.
movwf Temp ;
call OUT_BYTE ;
17
;----> Возврат по стеку из ПП OUT_BYTE.
movlw 0 ; Передача четвертого байта серийного номера.
movwf Temp ;
call OUT_BYTE ;
;----> Возврат по стеку из ПП OUT_BYTE.
movlw 8 ; Передача пятого байта серийного номера.
movwf Temp ;
call OUT_BYTE ;
;----> Возврат по стеку из ПП OUT_BYTE.
movlw 0 ; Передача шестого байта серийного номера.
movwf Temp ;
call OUT_BYTE ;
;----> Возврат по стеку из ПП OUT_BYTE.
movlw 57h ; Передача байта контрольной суммы
movwf Temp ; предыдущих семи байтов.
call OUT_BYTE ;
;----> Возврат по стеку из ПП OUT_BYTE.
goto BLOKNOT ; Переход в ПП BLOKNOT.
;--------------------------------------------------------------------------------
; Процедура адресации к датчику №1 (адрес: A1 00 08 00 E5 31 62 10)
; В ячейку TH записано 3Ch (порог 30 градусов), в ячейку TL записано 01h.
;--------------------------------------------------------------------------------
NOMER movlw 62h ; Передача первого байта серийного номера.
movwf Temp ;
call OUT_BYTE ;
;----> Возврат по стеку из ПП OUT_BYTE.
movlw 31h ; Передача второго байта серийного номера.
movwf Temp ;
call OUT_BYTE ;
;----> Возврат по стеку из ПП OUT_BYTE.
movlw 0E5h ; Передача третьего байта серийного номера.
movwf Temp ;
call OUT_BYTE ;
;----> Возврат по стеку из ПП OUT_BYTE.
movlw 0 ; Передача четвертого байта серийного номера.
movwf Temp ;
call OUT_BYTE ;
;----> Возврат по стеку из ПП OUT_BYTE.
movlw 8 ; Передача пятого байта серийного номера.
movwf Temp ;
call OUT_BYTE ;
;----> Возврат по стеку из ПП OUT_BYTE.
movlw 0 ; Передача шестого байта серийного номера.
movwf Temp ;
call OUT_BYTE ;
;----> Возврат по стеку из ПП OUT_BYTE.
movlw 0A1h ; Передача байта контрольной суммы
movwf Temp ; предыдущих семи байтов.
call OUT_BYTE ;
;----> Возврат по стеку из ПП OUT_BYTE.
;================================================================================
; Команда Read Scratchpad (BEh).
; Разрешение чтения из области оперативной памяти DS1820.
;================================================================================
BLOKNOT movlw 0BEh ; Запись команды BEh
movwf Temp ; в регистр Temp.
call OUT_BYTE ; Переход в ПП передачи байта OUT_BYTE.
;----> Возврат по стеку из ПП OUT_BYTE.
;--------------------------------------------------------------------------------
; Чтение содержимого области оперативной памяти DS1820
; (в полном объеме - 9 байтов).
;--------------------------------------------------------------------------------
call IN_BYTE ; Прием младшего байта температуры.
;----> Возврат по стеку из ПП IN_BYTE.
movwf Temp_LSB ; Запись принятого байта в регистр Temp_LSB.

18
call IN_BYTE ; Прием старшего байта температуры.
;----> Возврат по стеку из ПП IN_BYTE.
movwf Temp_MSB ; Запись принятого байта в регистр Temp_MSB.

call IN_BYTE ; Прием байта верхнего предела температуры.


;----> Возврат по стеку из ПП IN_BYTE.
movwf TH ; Запись принятого байта в регистр TH.

call IN_BYTE ; Прием байта нижнего предела температуры.


;----> Возврат по стеку из ПП IN_BYTE.
movwf TL ; Запись принятого байта в регистр TL.

call IN_BYTE ; Прием резервного байта (по умолчанию


; записано FFh).
;----> Возврат по стеку из ПП IN_BYTE.
movwf NO_1 ; Запись принятого байта в регистр NO_1.

call IN_BYTE ; Прием резервного байта (по умолчанию


; записано FFh).
;----> Возврат по стеку из ПП IN_BYTE.
movwf NO_2 ; Запись принятого байта в регистр NO_2.

call IN_BYTE ; Count_REM применяется при измерении


;----> Возврат по стеку из ПП IN_BYTE. ; температуры с более высоким разрешением.
movwf Count_REM ; Запись принятого байта в регистр Count_REM.

call IN_BYTE ; Count_D_C применяется при измерении


;----> Возврат по стеку из ПП IN_BYTE. ; температуры с более высоким разрешением.
movwf Count_D_C ; Запись принятого байта в регистр Count_D_C.

call IN_BYTE ; Прием байта контрольной суммы (CRC).


;----> Возврат по стеку из ПП IN_BYTE.
movwf CRC ; Запись принятого байта в регистр CRC.
;================================================================================
; Вычисление контрольной суммы (CRC) первых 8-ми, считанных
; из области оперативной памяти DS1820, байтов.
;================================================================================
clrf CRC_1 ; Подготовка регистра CRC_1 к вычислению.
movlw 8 ; Запись количества обрабатываемых байтов (.8)
movwf N1 ; в регистр счетчика байтов N1.

movlw Temp_LSB ; Запись адреса регистра хранения 1-го


movwf FSR ; принятого байта в регистр косвенной
; адресации FSR.
SNOVA_2 movlw 8 ; Запись количества обрабатываемых битов (.8)
movwf N ; в регистр счетчика битов N.
movf IndF,W ; Копирование текущего байта (через W)
movwf LED0 ; в регистр LED0.
;------------------------------------
SNOVA_1 xorwf CRC_1,W ;
movwf Temp ;
rrf Temp,W ;
movf CRC_1,W ;
btfsc Status,C ;
xorlw b'00011000' ; Процедура вычисления
movwf Temp ; контрольной суммы.
rrf Temp,W ;
movwf CRC_1 ;
bcf Status,C ;
rrf LED0,F ;
movf LED0,W ;
;------------------------------------
decfsz N,F ; Декремент содержимого счетчика битов N.
goto SNOVA_1 ; Если результат не=0, то переход на обработку
; следующего бита.
incf FSR,F ; Если результат =0, то подготовка к обработке
19
; следующего байта (FSR+1=...).
decfsz N1,F ; Декремент содержимого счетчика байтов N_1.
goto SNOVA_2 ; Если результат не=0, то переход на обработку
; следующего байта.
; Если результат =0, то программа
; исполняется далее.
;******************************************************
; После вычисления, результат вычисления контрольной
; суммы первых 8-ми байтов "осядет" в регистре CRC_1.
;******************************************************
;--------------------------------------------------------------------------------
; Анализ совпадения или не совпадения числовых значений байтов
; регистров CRC и CRC_1.
;--------------------------------------------------------------------------------
movf CRC,W ; Вычитание содержимого регистра CRC из
subwf CRC_1,W ; содержимого регистра CRC_1. Результат - в W.
btfss Status,Z ; Результат вычитания =0 или не=0 ?
goto RE_START ; Если не=0, то процедура адресации
; повторяется.
; Если =0, то программа исполняется далее.
;========================================================================
; Работа с температурными порогами.
;========================================================================
bcf Flag,5 ; Подготовка к работе бита №5 регистра Flag.
;------------------------------------------------------
; Сравнение результата замера с температурным порогом
; (работа с регистром TH).
;------------------------------------------------------
movf TH,W ; Копирование температурного порога в W.
subwf Temp_LSB,W ; Temp_LSB - TH = ?
btfss Status,C ; Результат вычитания положительный или
; отрицательный?
goto $+2 ; Если "-", то 1 в бит №5 регистра Flag
; не записывается (обход).
; Если "+" (превышение порога), то программа
; исполняется далее.
bsf Flag,5 ; В бит №5 регистра Flag записывается 1
; (признак превышения порога).
call DISPLAY ; Переход в ПП вывода результата измерения
; на индикацию.
;----> Возврат по стеку из ПП DISPLAY.
;------------------------------------------------------
; Подготовка к работе со следующим датчиком
; (работа с регистром TL).
;------------------------------------------------------
movf TL,W ; Перезапись признака следующего датчика
movwf Mem ; из регистра TL (через W) в регистр Mem.

goto SNOVA ; Переход на новый цикл измерения.


;************************************************************************

;================================================================================
; Подпрограмма нициализации 1-Wire устройства (DS1820).
;================================================================================
; Установка на линии DQ 1.
;-----------------------------------
DQ_INIT call PIN_HI ; Установка вывода в высокоимпедансное
; состояние: за счет подтягивающего резистора,
; на линии устанавливается 1.
;----> Возврат по стеку из ПП PIN_HI.
;-----------------------------------
; Установка на линии DQ 0.
;-----------------------------------
call PIN_LO ; Установка на линии нуля.
;----> Возврат по стеку из ПП PIN_LO.

20
;-----------------------------------
; Задержка 600 мкс.
;-----------------------------------
movlw .60 ; Установка количества проходов по 10мкс.
call PAUSE_X ; Переход в ПП задержки
; (задержка=60х10=600мкс.).
;----> Возврат по стеку из ПП PAUSE_X.
;-----------------------------------
; Установка на линии DQ 1.
;-----------------------------------
call PIN_HI ; Установка вывода в высокоимпедансное
; состояние: за счет подтягивающего резистора,
; на линии устанавливается 1.
;----> Возврат по стеку из ПП PIN_HI.
;-----------------------------------
; Задержка 70 мкс.
;-----------------------------------
movlw .7 ; Установка количества проходов по 10мкс.
call PAUSE_X ; Переход в ПП задержки
; (задержка=7х10=70мкс.).
;----> Возврат по стеку из ПП PAUSE_X.
;--------------------------------------------------------------------------------
; Определение наличия (или нет) отклика на импульс сброса.
;--------------------------------------------------------------------------------
btfsc PortA,DQ ; На линии DQ 0 или 1 (отклик есть или нет)?
goto DQ_INIT ; Если отклика нет (1), то снова начинается
; исполнение процедуры инициализации.
; Если отклик есть (0), то программа
; исполняется далее.
;-----------------------------------
; Задержка 500 мкс.
;-----------------------------------
movlw .50 ; Установка количества проходов по 10мкс.
call PAUSE_X ; Переход в ПП задержки
; (задержка=50х10=500мкс.).
;----> Возврат по стеку из ПП PAUSE_X.

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


;********************************************************************************
; Подпрограмма задержки.
;================================================================================
; Задание количества проходов по 10 мкс.
;----------------------------------------
PAUSE_X movwf Count ; Копирование количества проходов
; из W в Count.
;----------------------------------------
; Пауза в 10 мкс.
;----------------------------------------
PAUSE_10 nop ;
goto $+1 ; Одноразрядный,
goto $+1 ; вычитающий
goto $+1 ; счетчик
decfsz Count,F ; с "врезкой".
goto PAUSE_10 ;

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


;================================================================================

;************************************************************************
; Базовые процедуры чтения/записи по 1-Wire протоколу.
;************************************************************************
; Подпрограмма передачи "мастером" байта: цикл передачи бита начинается импульсом
; низкого уровня длительностью 1...15 мкс, далее следует передаваемый бит.
; Цикл завершается импульсом высокого уровня длительностью не менее 1 мкс.

21
;================================================================================
OUT_BYTE movlw .8 ; Запись количества бит передаваемого
movwf N ; байта в регистр N.

METKA_1 rrf Temp,F ; Сдвиг вправо содержимого передаваемого


; байта.
btfss Status,C ; В бите С "лежит" 0 или 1 ?
goto OUT_0 ; Если С=0, то переход в ПП передачи нуля.
goto OUT_1 ; Если С=1, то переход в ПП передачи единицы.

METKA_2 decfsz N,F ; Уменьшение на 1 содержимого счетчика битов.


goto METKA_1 ; Если результат не =0, то переход
; на метку METKA_1.
return ; Если результат =0, то возврат по стеку.
;================================================================================
; Подпрограмма приема "мастером" байта: цикл приема бита начинается импульсом
; низкого уровня длительностью 1...15 мкс, после чего DS1820 выставляет на линии
; бит. Цикл завершается импульсом высокого уровня длительностью не менее 1 мкс.
;================================================================================
IN_BYTE movlw .8 ; Запись количества бит принимаемого
movwf N ; байта в регистр N.
clrf Temp ; Очистка регистра принимаемого байта.

IN_BYTE_1 call PIN_LO ; Формирование на линии уровня 0.


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

call PIN_HI ; Формирование на линии уровня 1.


;----> Возврат по стеку из ПП PIN_HI.
nop ; Калибровочный NOP.
;-------------------------------------------------------------------
; Запись, в бит С, уровня текущего бита, выдаваемого DS1820 в линию.
;-------------------------------------------------------------------
btfss PortA,DQ ; На линии 0 или 1 ?
bcf Status,C ; Если на линии 0, то в бите С выставляется 0
btfsc PortA,DQ ; Если на линии 1 (а также после исполнения
; предыдущей команды), то еще одна проверка
; состояния линии.
bsf Status,C ; Если на линии 1, то в бите С выставляется 1
; Если на линии 0 (а также после исполнения
; предыдущей команды), то программа
; исполняется далее.
;-------------------------------------------------------------------
; Последовательное заполнение битами регистра Temp.
;-------------------------------------------------------------------
rrf Temp,F ; Сдвиг содержимого регистра Temp вправо
; (через C).
movlw .4 ; Установка количества проходов по 10мкс.
call PAUSE_X ; Переход в ПП задержки
; (задержка=4х10=40мкс.).
;----> Возврат по стеку из ПП PAUSE_X.
decfsz N,F ; Уменьшение на 1 содержимого счетчика битов.
goto IN_BYTE_1 ; Если результат не=0, то переход
; на прием следующего бита.
movf Temp,W ; Если =0, то копирование принятого байта
; в регистр W.
return ; Возврат по стеку.
;================================================================================
; Подпрограмма передачи бита с уровнем "0".
;================================================================================
OUT_0 call PIN_LO ; Переход в ПП установки уровня 0.
; Начало передачи.
;----> Возврат по стеку из ПП PIN_LO.
movlw .6 ; Установка количества проходов по 10мкс.
call PAUSE_X ; Переход в ПП задержки
; (задержка=6х10=60мкс.).
;----> Возврат по стеку из ПП PAUSE_X.
22
call PIN_HI ; Переход в ПП установки уровня 1.
; Конец передачи.
;----> Возврат по стеку из ПП PIN_HI.
goto METKA_2 ; Переход на исполнение процедуры декремента
; и анализа содержимого счетчика битов.
;================================================================================
; Подпрограмма передачи бита с уровнем "1".
;================================================================================
OUT_1 call PIN_LO ; Переход в ПП установки уровня 0.
; Начало передачи.
;----> Возврат по стеку из ПП PIN_LO.
call PIN_HI ; Переход в ПП установки уровня 1.
; (передача 1).
;----> Возврат по стеку из ПП PIN_HI.
movlw .6 ; Установка количества проходов по 10мкс.
call PAUSE_X ; Переход в ПП задержки
; (задержка=6х10=60мкс.).
;----> Возврат по стеку из ПП PAUSE_X.
goto METKA_2 ; Переход на новый цикл передачи бита.
;--------------------------------------------------------------------------------
; Формирование на линии уровня "1" за счет подтягивающего резистора
;--------------------------------------------------------------------------------
PIN_HI bsf Status,RP0 ; Переход в банк 1.
bsf TrisA,DQ ; Настройка вывода RA4 на работу "на вход".
bcf Status,RP0 ; Переход в банк 0.
return ; Возврат по стеку.
;--------------------------------------------------------------------------------
; Формирование на линии уровня "0" средствами микроконтроллера
;--------------------------------------------------------------------------------
PIN_LO bcf PortA,DQ ; Установка 0 на выходе защелки вывода RA4.
bsf Status,RP0 ; Переход в банк 1.
bcf TrisA,DQ ; Настройка вывода RA4 на работу "на выход".
bcf Status,RP0 ; Переход в банк 0.
return ; Возврат по стеку.
;********************************************************************************
end ; Конец программы.

Программа DS1820_2.asm “родилась” из программы DS1820_1.asm.


Темно – синим цветом выделено то, с чем “разборки” были ранее.
Красным цветом выделено то, что, в данном случае, записано в область EEPROM
памяти конкретного DS1820.
Черным цветом выделен предмет разговора.
Произведенные изменения
1. Группа команд вывода тестовой надписи “ТЕМПЕРАТУРА:”, вместе с ПП TEXT
(работают в “связке”), удалены.
2. После окончания процедуры анализа совпадения или не совпадения числовых
значений байтов регистров CRC и CRC_1, в текст программы “врезана” группа
команд работы с температурными порогами, о работе которой говорилось выше.
Это всего – навсего 10 команд (а без учета команд переходов - 8).
В части касающейся той замены, о которой идет речь, по сравнению с программой
DS1820_1.asm, объем программы DS1820_2.asm увеличился всего на 2 команды (8
убыло, 10 прибыло), и это особенно отрадно.
Плюс, ясность в мозгах и полная определенность.
А теперь прикиньте “массу” и “крутизну” предлагаемого разработчиками “адресного
счастья”.
То-то и оно …
И самое главное: в приложении к небольшому количеству датчиков, задача решена
качественно и без “надрыва пупка”.
3. После окончания работы с температурными порогами, ее результатами занимается
“обслуга”.
“Обслуга” может быть разной (той или иной степени “крутизны”).
В простейшем случае, это может быть банальный светодиод или “пищалка”.

23
В данном же случае, имеет место быть “обслуга средней крутизны”, а за “сервис”, как
известно, нужно и соответственно платить.
Сколько “отстегивать”?
Считаю: 385 (количество команд программы DS1820_2.asm) минус 348 (количество
команд программы DS1820_1.asm) минус 2 (см. пункт 2) = 35 команд.
При этом нужно учитывать то, что процедура вывода на индикацию тестовой надписи
“ТЕМПЕРАТУРА:” “убита”.
С учетом этого, а также и уровня “сервиса”, “плата”, величиной в 35 команд, вполне
приемлема.
Проще и понятнее всего, начать ПП DISPLAY с вывода на индикацию, в 1-ю строку,
сопровождающих надписей (“НОРМА:” или “АВАРИЯ”).
Так я и сделал (см. текст программы DS1820_2.asm).
ПП DISPLAY начинается с анализа состояния аварийного флага (бит №5 регистра
Flag).
1. Если бит №5=1 (“Караул! Убивают!”), то рабочая точка программы попадает в
группу команд вычисляемого перехода, при помощи которого происходит выбор
знакоместа (одного из двух), с которого начнется вывод на индикацию надписи
“АВАРИЯ”.
После этого, на индикацию выводится надпись “АВАРИЯ”.
Выбор того или иного сценария вычисляемого перехода зависит от числового значения
байта регистра Mem (в данном случае, .0 или .1), “заложенного” в него ранее.
Еще раз напоминаю то, что все вычисляемые переходы “привязаны” к регистру Mem, и
я их “сваял” с “прицелом” на большее количество датчиков (можно было бы обойтись
и проверкой на четность).
После вывода на индикацию надписи “АВАРИЯ”, происходит обход группы команд,
работающих с надписью “НОРМА:”, и рабочая точка программы “сигает” на начало
группы команд работающих со 2-й строкой ЖКИ модуля.
2. Если бит №5=0, то происходит то же самое, только на индикацию выводится
надпись “НОРМА:”, а процедура вывода на индикацию надписи “АВАРИЯ” обходится.
Что касается деталей, то они достаточно подробно расписаны в тексте программы.
Общее замечание: разрабатывая это устройство, я не ставил себе целью “сваять”
нечто позарез нужное и полезное.
Если бы эта цель передо мной стояла, то я разработал бы что-то более солидное.
Моя задача гораздо скромнее - практический показ “базы”, от которой можно
“оттолкнуться”, а в этом случае, излишние “навороты” не желательны.
Вот Вам и “карты в руки”.
“Детородные функции” программы DS1820_2.asm “находятся на должном уровне”, и
если добиться ее взаимности, то можно “нарожать и воспитать” много “румяных
детишек”.

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

25