Во многих моделях объем памяти для хранения пользовательских данных больше, чем в микроконтроллере PIC16F84. И тем не менее даже в самой развитой модели среднего уровня объем памяти не превышает 368 байт. Это не так уж и много, поэтому программы должны использовать эту ограниченную емкость очень эффективно[72].
Возвращаясь к Рис. 3.5 (стр. 68), можно заметить, что из 14 бит, составляющих код команды, семь зарезервировано под адрес операнда в памяти данных. Семь битов дают нам всего 27 = 128 адресов, т. е. страницу или банк, вмещающий в себя 128 регистров. Для преодоления этого ограничения необходимо где-то взять дополнительные биты, чтобы расширить диапазон адресов. В микроконтроллере PIC16F84 для этой цели используется 5-й бит регистра STATUS, который называется RP0 (Register Page 0[73]). Этот бит выполняет роль 8-го бита адреса, позволяя использовать память данных, содержащую до 256 регистров. При RP0 = 0 (после сброса по питанию) обращения производятся к 0-му банку памяти данных (регистры h’00’…h’7F’). При RP0 = 1 разрешается доступ к 1-му банку, т. е. к регистрам h’80’…h’FF’.
Большинство моделей среднего уровня имеют 4 банка ОЗУ и используют уже два бита регистра STATUS — RP1:RP0 (6-й и 5-й биты соответственно); см. Рис. 5.5 на стр. 122. В результате формируется 9-битный адрес памяти данных. Более подробно этот вопрос будет рассмотрен в следующей главе.
Несмотря на то что использование банков памяти является довольно эффективным вариантом преодоления 7-битного ограничения на размер адреса, их использование может вызвать трудности у неопытных программистов. В качестве примера рассмотрим фрагмент кода, в котором осуществляется запись числа b’00001111’ в регистр h’86’. Для выполнения этой операции мы воспользуемся командой movlw, загружающей 8-битную константу в рабочий регистр:
movlw b’000011111; Загружаем константу h’0F’ в W
movwf h’86’; и копируем его в регистр с адресом h’86’
В коде ошибочно указан адрес h’86’, или b’10000110’, значение которого слишком велико для имеющегося размера поля. Большинство ассемблеров просто обрежут биты, выходящие за границы поля, в результате чего мы получим адрес h’06’, или Ь’0000110’. Таким образом, с точки зрения ассемблера адреса h’86’ и h’06’ являются одинаковыми, хотя большинство ассемблеров при этом выдадут программисту предупредительное сообщение. В частности, фирменный ассемблер Microchip (который мы будем рассматривать в главе 8) выдаст следующее сообщение:
Message[302] Register in operand not in bank 0.
Ensure that bank bits are correct.
Другими словами, именно программист должен позаботиться о корректной установке битов RPx перед обращением к таким адресам.
Чтобы понять, как это можно сделать, нам придется забежать немного вперед и рассмотреть команды манипуляций с битами, приведенные в Табл. 5.2 на стр. 131. Во всех микроконтроллерах требуется иметь возможность управления состоянием отдельных битов регистра как для задания опций в РСН, так и для «дрыгания» ножками портов ввода/вывода. В микроконтроллерах PIC для этих целей используются следующие команды[74].
∙ bcf
Команда сброса бита регистра данных (Bit Clear File) позволяет программисту сбросить любой бит в любом регистре. К примеру, команда bcf h’20’,7 сбрасывает 7-й бит регистра h’20’. Состояние остальных битов регистра при этом не изменяется.
∙ bsf
Команда установки бита регистра (Bit Set File) позволяет программисту установить любой бит в любом регистре. К примеру, команда bsf h131’,3 устанавливает 3-й бит регистра h’31’. Состояние остальных битов не изменяется.
Возвращаясь к нашему примеру, теперь мы можем написать:
bsf 3,5; Установка 5-го бита (RP0) регистра STATUS позволяет обращаться к 1-му банку памяти
movlw b100001111’; Загружаем константу h’0F’ в W
movwf h’86’; и копируем его в регистр с адресом h’86’
bcf 3,5; Сбрасываем RP0 для возврата к 0-му банку
На самом деле использование 1-го банка в микроконтроллере PIC16F84 сведено к минимуму. Все 68 РОН отображены на оба банка памяти, т. е. по адресу h’n’ и по адресу h’n+80’ расположен один и тот же регистр. Например, если программисту необходимо прочитать содержимое регистра h’20’, не имеет значения, какой из банков при этом используется процессором, поскольку в регистре h’A0’ находятся те же самые данные, а не просто их копия! Такое встречается достаточно редко, поскольку микроконтроллеры PIC с памятью данных большего объема «разбрасывают» свои уникальные РОН (и РСН) по всем имеющимся банкам памяти. Тем не менее в более новых моделях, таких как PIC16F628, имеется небольшая группа (обычно 16) РОН, отображенных на все банки памяти. Такое решение позволяет максимально быстро сохранять и восстанавливать критические данные независимо от того, с каким из банков процессор работает в данный момент времени (см. стр. 218).
73
Возможно, потому, что более очевидное название Register Bank О (RB0) используется для обозначения вывода, подключенного к 0-му биту порта В
74
В старшем семействе появилась еще одна команда — btg (переключить бит в регистре данных).