Добавляя подобным образом команды пор, можно создавать подпрограммы задержки, работающие при различных тактовых частотах. Например, при частоте кварцевого резонатора 8 МГц подпрограмма из Программы 6.2 сформирует задержку длительностью 1 мс. Так что вставка соответствующего количества команд пор позволит программисту «подстроить» нашу подпрограмму для использования совместно с резонаторами частотой от 4 до 20 МГц (см. также Программу 12.8 на стр. 401). Подумайте, сколько потребуется команд пор для получения 1-мс задержки при резонаторе на частоту 20 МГц?
Этот метод не очень подходит в тех случаях, когда необходимы достаточно большие задержки. Для их реализации можно использовать дополнительный цикл, в теле которого будет выполняться наш базовый цикл, формирующий 1-мс задержку (выделено на Рис. 6.6 серым цветом). Если этот базовый цикл будет выполнен 100 раз, то мы получим 100-мс задержку.
Рис. 6.6.
Код подпрограммы, реализующей 100-мс задержку, приведен в Программе 6.3. При входе в подпрограмму регистр, называемый COUNT1, инициализируется значением d’100’. Затем выполняется внутренний цикл формирования 1-мс задержки. Когда W становится равным нулю и внутренний цикл завершается, регистр COUNT1 декрементируется при помощи команды decfsz COUNT1,f. Выход из внешнего цикла произойдет только при достижении нуля в счетном регистре, т. е. после выполнения 100 внутренних циклов. Пока содержимое этого счетного регистра не равно нулю, внутренний цикл выполняется вновь и вновь.
;************************
; * ФУНКЦИЯ: Формирует задержку длительностью 100 мс *
; * при частоте резонатора 4 МГц *
; * ВХОД: Нет *
; * ВЫХОД: Изменяются флаги и W. Регистр h’30’ обнуляется *
;*************************
COUNT1 equ h’30’; Регистр h’30’ — счетчик цикла
N equ d’249’; — Параметр задержки, см. текст
DELAY_100MS
movlw d’100’; Инициализируем счетчик внешнего цикла
movwf COUNT1;
; Внешний цикл ---------------
DELAY_1MS
movlw N; Инициализируем внутренний цикл
; Внутренний цикл ------------
D_LOOP
addlw -1; Декрементируем счетчик внутреннего цикла
btfss STATUS,Z; Проверяем: равен нулю?
goto D_LOOP; ЕСЛИ нет, ТО повторяем
; ----------------------------------
decfsz COUNT1,f; Декрементируем счетчик внешнего цикла
goto DELAY_1MS; и повторяем до достижения им нуля
; ----------------------------------
return
Разумеется, отсчет заданного времени в Программе 6.3 осуществляется не очень точно, поскольку мы игнорируем время, которое занимают команды внешнего цикла, такие как decfsz. Отчасти это компенсируется тем, что количество машинных циклов, затрачиваемых при одном проходе внутреннего цикла, уменьшилось до 4 х
Максимальная задержка, формируемая этой подпрограммой, составляет 256 000 машинных циклов, что соответствует длительности 100 мс при использовании резонатора 10 МГц или 256 мс при использовании резонатора 4 МГц. Для формирования задержек большей длительности нам потребуется три вложенных цикла, что позволит получать задержки более одной минуты (см. Пример 6.3).
Наша процедура формирования 100-мс задержки является примером подпрограммы, у которой отсутствуют входные параметры (аппаратным аналогом которых являются входные сигналы карты расширения) и которая ничего не возвращает. Эта подпрограмма просто выполняет свою задачу, заключающуюся в формировании задержки (а также изменяет регистры данных, рабочий регистр и некоторые флаги регистра STATUS). Однако большинство подпрограмм используют данные, передаваемые им при вызове, а также предоставляют некоторые данные при возврате.