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

5/9.

Гашение незначащих нулей в показаниях


термометра.

Прежде чем “снимать сливки” (для того, чтобы “счастье” было всеобъемлющим), нужно
ликвидировать один “пупырышек”.
Суть: при наличии показаний менее 10 градусов, ноль в десятичном разряде десятков
градусов, “лишний на этом празднике жизни”.
Буду называть его левым незначащим нулем.
Кроме того, при замерах температуры свыше +100,0 градусов и последующем “остывании”
датчика, после перехода от +100,0 градусов к +99,9 градусам, “в наследство достается”
ноль в крайнем правом разряде показаний, то есть, показания будут выглядеть не так,
как, например, +99,9 градуса (и т.д.), а как +99,90 градуса, причем, в зависимости от
скорости “остывания” датчика (если она высокая), на месте нуля может оказаться любая
другая цифра из диапазона 1 … 9.
И эта “паразитная” цифра “заторчит” в показаниях термометра вплоть до выключения
питания.
Буду называть эту цифру правым незначащим нулем (хотя, она может быть и не нулем).
Это “торчание” объясняется тем, что, после замера и вывода на индикацию значения
температуры от +100,0 градусов и выше, “паразитный” символ сохраняется в оперативной
памяти ЖКИ модуля, и после перехода от +100,0 градусов к +99,9 градусам, он, при
данном “раскладе”, не может быть “уничтожен, так как, для температур до +99,9
градусов включительно, количество знаков, выводимых во 2-ю строку, на каждом цикле
измерения и индикации, составляет 5 знаков, а для того чтобы “уничтожить”
“паразитный” символ, нужно выводить 6 знаков (как в случае измерения температуры от
+100,0 градусов и выше).
Вот и будет эта “фигня” “глаз мозолить” и портить нервную систему.
Таким образом, левый и правый незначащие нули нужно “убивать”, но это нужно
сделать по-умному.
И в самом деле, если “убить” левый незначащий ноль путем обхода процедуры его
вывода на индикацию, то произойдет смещение показаний влево, после чего нужно
“биться” уже не с одним, а с двумя правыми незначащими нулями.
Можно сделать и так, но лично меня, это как-то не прельщает. Я не люблю, когда
показания, без особой на то необходимости, “скачут”. Это раздражает.
Следовательно, при гашении левого незначащего нуля, нужно не допустить смещения
показания влево.
Как это сделать?
А очень просто: нужно заменить левый незначащий ноль на символ “пусто”.
Как, после этого, “убить” правый незначащий ноль?
А это еще проще: в конце процедуры вывода на индикацию результата замера
температуры, нужно вывести на индикацию все тот же символ “пусто”.
Он-то и отправит правый незначащий ноль “к праотцам”.
Остался последний вопрос: “Как быть в случае измерения температуры от +100,0
градусов и выше, ведь в этом случае ничего гасить не нужно”?
Ответ: нужно организовать банальный обход процедуры гашения левого незначащего
нуля.
Вопрос: “А как быть с символом “пусто”, который гасит правый незначащий ноль? Не
может ли, при переходах от +99,9 к 100,0 градусам (и наоборот), символ “пусто” “убить”
цифру десятых долей градуса”?

1
Ответ: в любом случае, символ “пусто” выводится на индикацию только после вывода на
индикацию символа десятых долей градуса и поэтому, по определению, не сможет его
“убить”.
Теперь нужно все это “добро” “запустить в эксплуатацию”.
Как это сделать? А легко, так как на форуме этим вопросом уже озаботились и
придумывать мне особо нечего.
Я просто “сваял гибрид” из предложений Шевченко Ивана (RW1ZK) и Сахненко Андрея
(vintik), и “влепил” его туда, куда нужно.
Люди работают на опережение. “Зер гут”!
Для начала, процедуру гашения незначащих нулей я “врезал” в относительно простую
программу однодатчикового термометра 0_1grad1.asm, плюс, перевел ее на “паразитное”
питание.
Вот что из этого получилось (программа работает в “железе”):

;********************************************************************************
; 0_1grad2.asm ЭЛЕКТРОННЫЙ ТЕРМОМЕТР НА ОСНОВЕ ДАТЧИКА ТЕМПЕРАТУРЫ DS1820
; М/контроллер и DS1820 работают по интерфейсу 1-Wire.
; Работа с одним датчиком, "паразитным" питанием и гашением
; незначащих нулей. Разрешение 0,1 градус.
;********************************************************************************
; "Практикум по конструированию устройств на 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 и 3 соединяются - общий провод,
; вывод 2 - сигнальный провод.
; Информация выводится в русифицированный ЖКИ модуль 16х2 на
; основе м/к HD44780 (по 4-разрядному интерфейсу).
; Функции выводов порта А:
; RA0 - RW (ЖКИ),
; RA1 - RS (ЖКИ),
; RA2 - E (ЖКИ),
; RA4 - вывод DQ датчика DS1820.
;-------------------------------
; Объем программы: 274 команды.
;================================================================================
LIST p=16F84a ; Используется м/контроллер PIC16F84A.
__CONFIG 03FF1H ; Бит защиты выключен, WDT выключен,
; XT-генератор.
;================================================================================
; Определение положения регистров специального назначения.
;================================================================================
IndF equ 00h ; Доступ к памяти через FSR.
PC equ 02h ; Счетчик команд.
Status equ 03h ; Регистр Status.
FSR equ 04h ; Регистр косвенной адресации.
PortA equ 05h ; Регистр Port A.

2
TrisA equ 05h ; Регистр Tris A-банк1.
PortB equ 06h ; Регистр Port B.
TrisB equ 06h ; Регистр Tris B-банк1.
;================================================================================
; Определение названия и положения регистров общего назачения.
;================================================================================
N equ 0Ch ; Счетчик битов.
Temp equ 0Dh ; Многофункциональный регистр временного
; хранения.
Temp_MSB equ 0Eh ; Байт знака температуры (старший байт).
Temp_LSB equ 0Fh ; Байт значения температуры (младший байт).
Flag equ 10h ; Регистр флагов.
Count equ 11h ; Многофункциональный счетчик.
LED0 equ 12h ; Регистры двоично-десятичного
LED1 equ 14h ; преобразования.
Reg_1 equ 15h ; Регистр младшего разряда счетчика.
Reg_2 equ 16h ; Регистр среднего разряда счетчика.
Reg_3 equ 17h ; Регистр старшего разряда счетчика.
Count_REM equ 18h ; Регистр хранения остатка измерения.
;================================================================================
; Определение места размещения результатов операций.
;================================================================================
W equ 0 ; Результат направить в аккумулятор.
F equ 1 ; Результат направить в регистр.
;================================================================================
; Присваивание битам названий.
;================================================================================
Z equ 2 ; Флаг нулевого результата.
C equ 0 ; Флаг переноса-заема.
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.
;----> Возврат по стеку из ПП ENTER_BF.
movlw b'00101000' ; Установка: 4-разрядный интерфейс, 2 строки,
; 5х7 точек.
call ENTER_BF ; "Плавающая" задержка со стробом под команду
; 00101000.

3
;----> Возврат по стеку из ПП 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 м.ц.
;-----------------------

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

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


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

;************************************************************************
; Подпрограмма вывода на индикацию.
;************************************************************************
; Выбор 6-го слева знакоместа 2-й строки.
;----------------------------------------------------------
DISPLAY movlw b'11000101' ; Выбор ячейки DD RAM с адресом 45h, что
; соответствует установке курсора в 6-е слева
; знакоместо 2-й строки.
call ENTER_BF ; "Плавающая" задержка со стробом под команду
; 11000101.
;----> Возврат по стеку из ПП ENTER_BF.
;----------------------------------------------------------
; Определение и вывод на индикацию знака температуры (+/-).
;----------------------------------------------------------
btfsc Temp_MSB,0 ; В бите №0 старшего байта температуры 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 ; символ "-".
call ENTER_BF ; "Плавающая" задержка со стробом под вывод
; данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.
;----------------------------------------------------------
; Перевод двоичного числа младшего байта температуры
; из отрицательной области температур в положительную.
;----------------------------------------------------------
comf Temp_LSB,F ; После вывода на индикацию символа "-", все
incf Temp_LSB,F ; биты младшего байта температуры
; инвертируются и к результату прибавляется 1.
;================================================================================

5
; Подпрограмма обработки содержимого младшего байта температуры.
;================================================================================
; Деление числа, записанного в младшем байте температуры, на 2.
;--------------------------------------------------------------------------------
SDVIG clrf Flag ; Flag=0 (подготовка к работе).
rrf Temp_LSB,F ; Деление на 2.
;--------------------------------------------------------------------------------
; Установка (или нет) признака добавления (к показаниям) символа "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 ;

goto ASC ; Переход в ПП ASC.


;--------------------------------------------------------------------------------
; Запись в регистр FSR адреса регистра LED0 для дальнейшей косвенной адресации
; к нему в ПП adjBCD.
;--------------------------------------------------------------------------------
adjDEC movlw LED0 ; Запись в регистр FSR адреса регистра LED0
movwf FSR ; с дальнейшим переходом в ПП adjBCD.
call adjBCD ;

6
;---> Возврат по стеку из ПП 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 градусов и выше).
;================================================================================
clrwdt ; Сброс WDT.
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.
goto OBHOD_1 ; Если температура 100 и более, то обход
; гашения левого незначащего нуля.
;========================================================================
; Гашение левого незначащего нуля.
;========================================================================
C_00_99 movlw 30h ; В LED1 "лежит"
xorwf LED1,W ; символ "0" или
btfss Status,Z ; другой символ?
goto OBHOD_1 ; Если не "0", то незначащий ноль не гасится.

7
movlw 20h ; Если "0", то он заменяется на символ "пусто"
bsf PortA,RS ; (20h), т.е. гасится без смещения показания.
call ENTER_BF ; "Плавающая" задержка со стробом
; под вывод данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.
goto $+4 ; Обход следующих трех команд.
;================================================================================
; Вывод на индикацию двух символов результата измерения
; (в диапазоне от 00 до 99 градусов).
;================================================================================
; Вывод цифры десятков градусов (левой).
;----------------------------------------
OBHOD_1 movf LED1,W ; Вывод на индикацию байта,
bsf PortA,RS ; записанного в регистре LED1.
call ENTER_BF ; "Плавающая" задержка со стробом
; под вывод данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.
;----------------------------------------
; Вывод цифры единиц градусов (правой).
;----------------------------------------
;----> Возврат по стеку из ПП ENTER_BF.
movf LED0,W ; Вывод на индикацию байта,
bsf PortA,RS ; записанного в регистре LED0.
call ENTER_BF ; "Плавающая" задержка со стробом
; под вывод данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.
;-------------------------------------
; Формирование символа "запятая".
;-------------------------------------
movlw 2Ch ; Вывод на индикацию
bsf PortA,RS ; символа "," (2Ch).
call ENTER_BF ; "Плавающая" задержка со стробом под вывод
; данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.
;-------------------------------------
; Формирование символов после запятой.
;-------------------------------------
movf Count_REM,W ; Копирование содержимого Count_REM в W.
sublw .16 ; .16 - Count_REM (от .1 до .16) = от .0 до
; .15 (W).
call TEXT_1 ; Переход в перекодировщик 16/10.
bsf PortA,RS ; "Плавающая" задержка со стробом под вывод
call ENTER_BF ; данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.
;========================================================================
; Гашение правого незначащего ("паразитного") нуля.
;========================================================================
movlw 20h ; Гашение (символом "пусто") правого
bsf PortA,RS ; "паразитного" нуля, возникающего в случае
; перехода от 100,0 к 99,9 градусам.
call ENTER_BF ; "Плавающая" задержка со стробом
; под вывод данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.

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

8
;********************************************************************************

;================================================================================
; Подпрограммы табличного вычисляемого перехода.
;================================================================================
; Вычисляемый переход под тестовую надпись.
;----------------------------------------------------------------------
TEXT addwf PC,F ; Приращение PC на величину содержимого W.
retlw 0x20 ; "пусто"
retlw 0x20 ; "пусто"
retlw 0x54 ; "T"
retlw 0x45 ; "E"
retlw 0x4D ; "M"
retlw 0xA8 ; "П"
retlw 0x45 ; "E"
retlw 0x50 ; "P"
retlw 0x41 ; "A"
retlw 0x54 ; "T"
retlw 0xA9 ; "У"
retlw 0x50 ; "P"
retlw 0x41 ; "A"
retlw 0x3A ; ":"
retlw 0x20 ; "пусто"
retlw 0x20 ; "пусто"
;================================================================================
; Перекодировщик 16/10.
;================================================================================
; Вычисляемый переход под табл. 3 п/раздела 5/8 "Практикума...".
;--------------------------------------------------------------------------------
TEXT_1 addwf PC,F ; Приращение PC на величину содержимого W.
retlw 0x30 ; "0"
retlw 0x30 ; "0"
retlw 0x31 ; "1"
retlw 0x32 ; "2"
retlw 0x32 ; "2"
retlw 0x33 ; "3"
retlw 0x34 ; "4"
retlw 0x34 ; "4"
retlw 0x35 ; "5"
retlw 0x35 ; "5"
retlw 0x36 ; "6"
retlw 0x37 ; "7"
retlw 0x37 ; "7"
retlw 0x38 ; "8"
retlw 0x39 ; "9"
retlw 0x39 ; "9"
;--------------------------------------------------------------------------------
; Вычисляемый переход под табл. 4 п/раздела 5/8 "Практикума...".
;--------------------------------------------------------------------------------
;;;TEXT_1 addwf PC,F ; Приращение PC на величину содержимого W.
;;; retlw 0x30 ; "0"
;;; retlw 0x31 ; "1"
;;; retlw 0x32 ; "2"
;;; retlw 0x32 ; "2"
;;; retlw 0x33 ; "3"
;;; retlw 0x33 ; "3"

9
;;; retlw 0x34 ; "4"
;;; retlw 0x34 ; "4"
;;; retlw 0x35 ; "5"
;;; retlw 0x35 ; "5"
;;; retlw 0x36 ; "6"
;;; retlw 0x36 ; "6"
;;; retlw 0x37 ; "7"
;;; retlw 0x37 ; "7"
;;; retlw 0x38 ; "8"
;;; retlw 0x39 ; "9"
;================================================================================

;************************************************************************
; НАЧАЛО ПРОГРАММЫ
;************************************************************************
START clrf PortA ; Сброс всех защелок порта А.
clrf PortB ; Сброс всех защелок порта В.
bsf Status,RP0 ; Переход в 1-й банк.
clrf TrisA ; Все выводы портов А и В
clrf TrisB ; работают на выход.
bcf Status,RP0 ; Переход в 0-й банк.

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


; инициализации.
;----> Возврат по стеку из ПП LCD_INIT.
;------------------------------
; Вывод символов в 1-ю строку.
;------------------------------
movlw .16 ; Запись числа .16 (количества выводимых в
movwf Count ; строку символов) в регистр Count.
WR_1 movf Count,W ; Копирование содержимого регистра Count в W.
sublw .16 ; .16-Count=... (результат записывается в W).
call TEXT ; Условный переход в ПП TEXT.
;----> Возврат по стеку из ПП TEXT.
bsf PortA,RS ; Вывод на индикацию текущего символа.
call ENTER_BF ; "Плавающая" задержка со стробом под вывод
; данных на индикацию.
;----> Возврат по стеку из ПП ENTER_BF.
decfsz Count,F ; Подготовка к выводу на индикацию
; следующего символа таблицы.
goto WR_1 ; Если результат декремента не=0, то переход
; в ПП WR_1.
; Если результат декремента =0, то программа
; исполняется далее.
;########################################################################
; Начало работы с датчиком DS1820.
;########################################################################
; Инициализация DS1820.
;--------------------------------------------------------------------------------
SNOVA call DQ_INIT ; Инициализация DS1820.
;----> Возврат по стеку из ПП DQ_INIT.
;--------------------------------------------------------------------------------
; Команда Skip ROM (CCh).
; Команда пропуска процедуры сравнения серийного номера. Применяется в случае
; использования одного датчика (как в данном случае).

10
;--------------------------------------------------------------------------------
movlw 0CCh ; Запись команды CCh
movwf Temp ; в регистр Temp.
call OUT_BYTE ; Переход в ПП передачи байта OUT_BYTE.
;----> Возврат по стеку из ПП OUT_BYTE.
;--------------------------------------------------------------------------------
; Команда Convert T (44h).
; Эта команда запускает процесс преобразования температуры. В течение времени ее
; исполнения, DS1820 не реагирует на команды "мастера".
; Это время нужно просто переждать.
;--------------------------------------------------------------------------------
movlw 44h ; Запись команды 44h
movwf Temp ; в регистр Temp.
call OUT_BYTE ; Переход в ПП передачи байта OUT_BYTE.
;----> Возврат по стеку из ПП OUT_BYTE.
;================================================================================
; Ожидание завершения процесса преобразования температуры: задержка 700 мс.
;================================================================================
movlw .18 ;
movwf Reg_1 ;
movlw .142 ;
movwf Reg_2 ;
movlw .4 ;
movwf Reg_3 ;

WR decfsz Reg_1,F ;
goto WR ; Стандартный,
decfsz Reg_2,F ; 3-разрядный,
goto WR ; вычитающий
decfsz Reg_3,F ; счетчик.
goto WR ;
;--------------------------------------------------------------------------------
; Инициализация DS1820.
;--------------------------------------------------------------------------------
call DQ_INIT ; Инициализация DS1820.
;----> Возврат по стеку из ПП DQ_INIT.
;--------------------------------------------------------------------------------
; Еще одна команда Skip ROM (CCh).
;--------------------------------------------------------------------------------
movlw 0CCh ; Запись команды CCh
movwf Temp ; в регистр Temp.
call OUT_BYTE ; Переход в ПП передачи байта OUT_BYTE.
;----> Возврат по стеку из ПП OUT_BYTE.
;--------------------------------------------------------------------------------
; Команда Read Scratchpad (BEh).
; Чтение содержимого блокнотной памяти.
;--------------------------------------------------------------------------------
movlw 0BEh ; Запись команды BEh
movwf Temp ; в регистр Temp.
call OUT_BYTE ; Переход в ПП передачи байта OUT_BYTE.
;----> Возврат по стеку из ПП OUT_BYTE.
;----------------------------------------
; Само чтение.
;----------------------------------------
call IN_BYTE ; Чтение младшего байта температуры.
;----> Возврат по стеку из ПП IN_BYTE.

11
movwf Temp_LSB ; Запись принятого байта в регистр Temp_LSB.

call IN_BYTE ; Чтение старшего байта температуры.


;----> Возврат по стеку из ПП IN_BYTE.
movwf Temp_MSB ; Запись принятого байта в регистр Temp_MSB.
;----------------------------------------
; Формальное считывание байтов.
;----------------------------------------
call IN_BYTE ; Формальное считывание байта верхнего
; предела температуры.
;----> Возврат по стеку из ПП IN_BYTE.
call IN_BYTE ; Формальное считывание байта нижнего
; предела температуры.
;----> Возврат по стеку из ПП IN_BYTE.
call IN_BYTE ; Формальное считывание 1-го резервного байта.
;----> Возврат по стеку из ПП IN_BYTE.
call IN_BYTE ; Формальное считывание 2-го резервного байта.
;----> Возврат по стеку из ПП IN_BYTE.
;----------------------------------------
call IN_BYTE ; ПРИЕМ БАЙТА ОСТАТКА ИЗМЕРЕНИЯ.
;----> Возврат по стеку из ПП IN_BYTE.
movwf Count_REM ; Запись принятого байта в регистр Count_REM.
;---------------------------------------------------
; Итог; в Temp_MSB записан старший байт температуры,
; в Temp_LSB записан младший байт температуры,
; в Count_REM записан байт остатка измерения.
;---------------------------------------------------
call DISPLAY ; Переход в ПП вывода результата измерения
; на индикацию.
;----> Возврат по стеку из ПП DISPLAY.
goto SNOVA ; Переход на новый цикл измерения.
;********************************************************************************

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

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

12
;********************************************************************************
; Подпрограмма задержки.
;================================================================================
; Задание количества проходов по 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 мкс.
;================================================================================
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.

13
;-------------------------------------------------------------------
; Запись, в бит С, уровня текущего бита, выдаваемого 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.
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 ; Переход на новый цикл передачи бита.

14
;--------------------------------------------------------------------------------
; Формирование на линии уровня "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 ; Конец программы.

В “рабочей” части программы, предмет разговора выделен черным цветом.


Принцип гашения сформирован выше.
Левый незначащий ноль гасится путем его замены на символ “пусто”.
Если температура “зашкалила” за +100,0 градусов, то процедура гашения левого
незначащего нуля обходится (goto OBHOD_1).
Команду xorwf LED1,W можно заменить на команду subwf LED1,W. Результат один и
тот же.
По поводу команды xorwf (операция “исключающее ИЛИ”): на ней реализован сумматор
по модулю 2, работающий с двумя байтами.
Особенностью сумматора по модулю 2 является то, что нулевой результат на его выходе
(числовое значение байта результата суммирования равно нулю) будет только в случае
равенства числовых значений байтов, поданных на его входы, причем, конкретные их
числовые значения не важны. Важно их равенство (или нет).
Правый незначащий ноль гасится всегда: и в случае его наличия, и в случае его
отсутствия.
То есть, после формирования последнего символа измерения, на индикацию всегда
“тупо” выводится символ “пусто”.
Конечно же, можно сделать и поинтеллектуальнее, но какого-то особого практического
смысла, лично я, в этом не вижу.
На фоне большой инерционности работы датчика, выигрыш по скорости будет
минимален, а текст программы усложнится.
Итак, поставленная задача решена “малой кровью” и тем самым преодолена последняя
преграда на том “тернистом пути”, по которому Вы прошли вместе со мной.
Пришла приятная пора “снятия сливок” и “получения девидендов от трудов праведных”.
В следующем подразделе Вам будут предоставлены две базовые программы (работа с
одним датчиком и работа с двумя датчиками, с возможностью наращивания их
количества), “укомплектованные” всеми возможными “наворотами”, а это уже серьезно,
так как, на их основе, заменив “обслугу” (под конкретную задумку), можно решать очень
не слабые задачи, связанные не только с моральным, но и с материальным
удовлетворением, так как разработка высокоточностных устройств автоматического
контроля и регулировки температуры, которые расчитаны на большое количество
вынесенных (2-проводная линия !!! “Паразитное” питание !!!), помехоустойчивых
(контрольная сумма !!!) датчиков, есть занятие далеко не низкооплачиваемое, да и сами
эти устройства стоят совсем не дешево.

15
Если сделать такое устройство самому, то это обойдется гораздо дешевле, чем покупка
готового, промышленного аналога.
Датчики DS… это современные, достаточно высокоточностные и надежные устройства
вполне соответствующие времени.
Не смотря на изначальные “оргнеувязки”, связанные с их использованием в
м/контроллерном приложении, лично мне, они, в “русифицированном” виде, очень
понравились.
По большому счету, в ходе “разборок”, эти “оргнеувязки” полностью ликвидированы и
теперь ничто не мешает использовать DS… по максимуму.
Советую Вам, также по максимуму, использовать ту информацию, которую Вы получили.

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

16