II
"РЛ" - НАЧИНАЮ Щ ИМ
1
}
На рис. 4 прямоугольниками по-
казаны команды основной про-
граммы, а кружочками - слева уча-
стки кода, реализующие задержку,
а справа - подпрограмма, выпол-
няющая ту же функцию. Получает-
ся, что команда вызова подпрог-
раммы как бы заменяется соответ-
ствующим участком кода.
Оформление участков кода, вы-
полняющих многократно однотип-
ные функции в виде подпрограмм
позволяет существенно сократить
объем программы. Более того, в та-
кой программе гораздо легче разоб-
раться спустя некоторое время, так
как встретив
в те к с т е
LC A LL
Zaderzhka все будет понятно сразу,
Podprogramma:
DJNZ
RET
Как вы думаете, какую задерж-
ку обеспечит эта подпрограмма?
Длительность задержки составит
2+2+R0*2 машинных цикла (для R0 >0,
если R0=0, то в формулу надо под-
ставить число 256 вместо R0), т.е.
меняя значение R0 перед вызовом
подпрограммы, мы обеспечим при
помощи одного и того же кода раз-
ные длительности задержки! Две
двойки в формуле - это число ма-
шинных циклов на вызов подпрог-
раммы и возврат из нее.
Остается только разобраться с
одной важной особенностью под-
программ. Когда вы пишите ее код,
вы не всегда можете представлять,
когда и из каких мест вашей про-
граммы вы будете осуществлять ее
вызов, ведь часто требования к
программе меняются прямо по ходу
ее разработки. Но любая подпрог-
рамма, если она не
состоит йз од-
них команд NO P,
использует для
своей работы какие-либо ресурсы
микроконтроллера-ячейки памяти,
регистры, биты. А ведь какие-то из
этих ресурсов могут быть заняты в
основной программе, т.е. их измене-
ние в подпрограмме может привес-
ти к непредсказуемым последстви-
ям. Как же быть? Постоянно пере-
делывать подпрограмму, используя
в ней только свободные ресурсы?
Или наоборот, менять основ«ую
а вот с многочисленными циклами
придется разбираться долго.
Н ебольш ое прим ечание. С ре-
да M CStudio позволяет использо-
вать вместо команд LCALL и ACALL
псевдокоманду CALL. Встретив та-
кую псевдокоманду, компилятор
автоматически вычислит значение
адреса вызываемой подпрограммы
и подставит наиболее “короткую"
команду: если вызываемая под-
программа располагается по адре-
су не д ал е е чём на 1024 байта
“выше" или “ниже" текущего адре-
са, будет использована команда
ACALL, а иначе - LCALL. Дело в
трм, что первая команда занимает
в памяти 2 байта, а вторая - три. В
программу, подгоняя ее под вызы-
ваемую процедуру? В принципе,
оба подхода имеют право на суще-
ствование, но лучш е поступить
прощ е © . Помните о стеке? Это
ведь область памяти (мы надеем-
ся, что она относительно велика),
которая
не должна
использовать-
ся в программе иначе, чем через
команды работы со стеком? Так
вот, в своей подпрограмме вы все-
гда можете сохранить в стеке нуж-
ные вам регистры и ячейки памяти
командами PUSH, после чего их
значения можно менять, как вам
угодно, а перед выходом из под-
программы надо восстановить зна-
чения задействованных ресурсов
при помощи команд POP. При этом
есть 2 важнейших правила: во-пер-
вых, число сохраненных в стеке
значений всегда должно быть рав-
ным числу извлекаемых из стека,
а во-вторых, извлекаются из стека
ресурсы всегда в обратном поряд-
ке. То есть если мы сохраняем ак-
кумулятор и регистр В в стеке так
PUSH
ACC
PUSH
В
то восстанавливать(извлекать) их
из стека нужно только в такой пос-
ледовательности
POP
В
POP
ACC
и никак иначе!
большинстве случаев можно не за-
думы ваясь всегда использовать
псевдокоманду CALL.
При
п о м о щ и
подпрограм м
оформляются часто требуемые в
програм м е действия. Это м огут
быть задержки, заполнение обла-
стей памяти значениями, формиро-
вание одинаковых последователь-
ностей сигналов и т.п. Чтобы ещ е
больше увеличить гибкость меха-
низма подпрограмм, в них исполь-
зуют передачу параметров, т.е. в
зависимости от значения опреде-
ленных ячеек памяти одна и та же
подпрограм м а м ожет выполнять
н еско л ь ко о тл и чаю щ иеся д е й -
ствия. Рассмотрим пример:
В а ж н о е прим ечание. Если вы
попробуете сохранить в стек зна-
чение аккумулятора так: P U S H А,
то вы получите со о б щ ен и е об
ошибке. Дело в том, что команды
сохранения аккумулятора
в
стеке
(как и извлечения из него) нет, есть
только команда сохранения (и из-
влечения) ячейки памяти. Для обо-
значения адреса этой ячейки мо-
жет использоваться ее символьное
имя (или, что то ж е самое, метка),
поэтому для аккумулятора надо ис-
пользовать символьное имя соот-
ветствующей ячейки памяти, т.е.
А С С . Это касается и регистров.
Попытка занести в стек содержи-
мое регистра PU S H R0 обречена на
провал
-
следует использовать ад-
рес соответствующей ячейки, т.е.
P U S H 00h.
Использовать стек для сохране-
ния значений ячеек памяти можно
и не только в подпрограммах - вез-
де, где требуется, но правила р а-
боты со стеком остаю тся те же.
Кстати, сохранять значения в сте-
ке можно не только внутри вызван-
ной подпрограммы (хотя так более
логично и экономно), но и перед ее
вызовом (разумеется, восстанав-
ливать значения надо там же, где
и сохраняли).
; наша подпрограмма получает R0 в качестве параметра
R 0,
$
Радиолюбитель - 0 4 /2 0 0 7 [|
предыдущая страница 57 Радиолюбитель 2007-05 читать онлайн следующая страница 59 Радиолюбитель 2007-05 читать онлайн Домой Выключить/включить текст