За исключением операции записи адреса возврата (стадии 1 и 2), команда call функционирует точно также, как и команда goto. Соответственно, она тоже выполняется за два машинных цикла в связи с необходимостью сброса стека для удаления команды, расположенной вслед за командой call и уже загруженной на вершину конвейера. Схожи эти команды и тем, что абсолютный 11-битный адрес в коде команды call расширяется в 13-битный адрес памяти программ с помощью 3-го и 4-го битов регистра PCLATH, как показано на Рис. 5.17 (стр. 153). Дальние вызовы подпрограмм, расположенных в диапазоне адресов h’07FF’…h’1FFF’, требуются только в тех микроконтроллерах с 14-битным ядром, размер памяти программ которых составляет более 2048 слов, например в PIC16F877.
Командой, завершающей подпрограмму, должна быть команда return. Эта команда извлекает адрес возврата из стека и помещает его в счетчик команд, как показано на Рис. 6.3, в. Исполнение команды return происходит следующим образом:
1. Декрементируется указатель стека.
2. 13-битный адрес, адресуемый указателем стека, копируется из стека в счетчик команд.
Таким образом, независимо от того, откуда была вызвана подпрограмма, сразу же после ее завершения выполнение вернется к команде, следующей за командой call.
Команда retlw[93] похожа на обычную команду return, за исключением того, что помещает заданное число в рабочий регистр. Так, чтобы после возврата из подпрограммы в W оказалось число h’FF’ (-1), скажем, для индикации ошибки, можно использовать команду retlw -1. Обе команды возврата сбрасывают конвейер и соответственно выполняются за два машинных цикла.
Прелесть стекового механизма в том, что он поддерживает
Рис. 6.4.
Поскольку стек совместно со своим указателем является частью «железа» микроконтроллера и не требует инициализации, программист должен учитывать только следующие моменты:
• Вызов подпрограмм должен осуществляться с помощью команды call.
• Точка входа в подпрограмму должна быть помечена (эта метка станет именем подпрограммы).
• Последней командой в подпрограмме должна быть команда return или retlw, причем последняя используется для загрузки в рабочий регистр заданной константы при возврате из подпрограммы (см. Программу 6.6).
В качестве упражнения давайте напишем подпрограмму формирования задержки длительностью 1 мс, которая указывалась на Рис. 6.2. Программное формирование задержки заключается в простом «ничегонеделании» в течение требуемого времени. Обычно это реализуется с помощью цикла, в котором заданная константа декрементируется до нуля, как показано на Рис. 6.5. Выбирая соответствующее значение константы, можно сформировать задержку требуемой длительности. Понятно, что эта задержка будет зависеть от частоты тактового сигнала микроконтроллера. В примерах данной главы предполагается, что тактовая частота равна 4 МГц, что соответствует длительности машинного цикла 1 мкс (см. также Программу 12.8 на стр. 401).
Рис. 6.5.
Рассмотрим подпрограмму, блок-схема которой приведена на Рис. 6.5. В данной подпрограмме в рабочий регистр помещается константа