; *******************************
; * Сюда попадаем при сбросе по тайм-ауту сторожевого таймера *
; *******************************
READING btfsc GPIO,0; Новое значение при низкой температуре?
goto NEW_LO; ЕСЛИ да, ТО переходим на эту секцию!
btfsc GPIO,1; Новое значение при низкой температуре?
goto NEW_HI; ЕСЛИ да, ТО переходим на эту секцию!
btfsc GPIO,2; Обновление среднего для низкой температуры?
goto UPDATE_LO; ЕСЛИ да, ТО переходим на эту секцию!
btfsc GPIO,3; Обновление разности для высокой температуры?
goto UPDATE_HI; ЕСЛИ да, ТО переходим на эту секцию!
goto READING_EXIT; ИНАЧЕ ничего не делаем
NEW_LO movf ROLL_OVER+1,w; Берем младший байт текущего числа переполнений
addwf LO_TEMP+1,f; и прибавляем его к младшему байту накопленного значения
btfsc STATUS,С; Проверяем перенос
incf LO_TEMP,f; ЕСЛИ был, ТО учитываем его
movf ROLL_OVER,w; Берем старший байт текущего числа переполнений
addwf LO_TEMP,f; и прибавляем его к старшему байту накопленного значения
movf FIRST_LO,f; Это был 1-й отсчет?
btfsc STATUS,Z
goto FIRST_TIME_LO; ЕСЛИ да, ТО отметим это!
rrf LO_TEMP,f; ИНАЧЕ делим сумму на два
rrf LO_TEMP+1,f
goto READING_EXIT; и выходим
FIRST_TIME_LO; При первом отсчете ничего не делаем
incf FIRST_LO,f; Первый отсчет уже был
goto READING_EXIT
NEW_HI movf ROLL_OVER+1,w; Берем младший байт текущего числа переполнений
addwf HI_TEMP+1,f; и прибавляем его к младшему байту накопленного значения
btfsc STATUS,С; Проверяем перенос
incf HI_TEMP,f; ЕСЛИ был, ТО учитываем его
movf ROLL_OVER,w; Берем старший байт текущего числа переполнений
addwf HI_TEMP,f; и прибавляем его к старшему байту накопленного значения
movf FIRST_HI,f; Это был 1-й отсчет?
btfsc STATUS,Z
goto FIRST_TIME_HI; ЕСЛИ да, ТО отметим это!
rrf HI_TEMP,f; ИНАЧЕ делим сумму на два
rrf HI_TEMP+1,f
goto READING_EXIT; и выходим
FIRST_TIME_HI; При первом отсчете ничего не делаем
incf FIRST_HI,f; Первый отсчет уже был
READING_EXIT; Сбрасываем Таймер 0
clrf TMR0; Перезапускаем сторожевой таймер
clrwdt
clrf ROLL_OVER+1; Обнуляем число переполнений
clrf ROLL_OVER
goto $; Ждем следующего сброса от сторожевого таймера
Также в Программе 15.10 приведены секции кода, соответствующие первым двум задачам. В этих секциях 2-байтное количество переполнений Таймера 0 прибавляется к значению, хранящемуся в регистрах LO_TEMO: LO_TEMP+1 или Н1_ТЕМР:Н1_ТЕМР+1 соответственно, после чего для усреднения результат делится на два сдвигом на один бит вправо. Поскольку суммарное число переполнений достаточно скромное, двух байтов вполне достаточно, чтобы избежать переполнения. Если мы будем в течение нескольких минут многократно выполнять указанные операции, то в результате получим усредненное значение.
Если считывание результата производится в первый раз, то операция деления на два пропускается, а в соответствующую переменную-флаг FIRST_LO или FIRST_HI заносится ненулевое значение.