.
Немало проблем доставляет при разработке программы вычисляемые переходы, которыми пользуются обычно при работе с таблицами, вызовы подпрограмм и переходы на определенную метку в разных страницах памяти программ.
Покажу прием, как легко избежать этих проблем. Но для начала, давайте разберемся, как организована память программ среднего семейства.
Из самого названия следует, что в этой памяти хранится программа. Т.е. написанная программа, но уже в машинном коде.
1.Общие понятия
Каждая инструкция (команда) программы состоит из 14 разрядного слова. Чтобы обратится к ним, применяется адресный счетчик РС. У него 13 разрядов. В счетчике РС можно записать число 1FFFh (819110), т.е. 8Кслов.
Из этого и надо ориентироваться при определении объема будущей программы.
Напомню, что это максимально возможное число. И не у всех мк среднего семейства такой объем памяти программ.
На рис.1 изображена организация памяти программ.
РС – 13 разрядный счетчик команд, указывает адрес выбираемой команды.
Состоит из двух регистров PCL и PCH,
РСL доступен пользователю для записи и чтения.
PCH не доступен пользователю. Для обращения к нему используется дополнительный регистр PCLATH.
Вся память разбита на 4 страницы по 2К слова. Каждая страница разбита на блоки памяти. В каждом блоке памяти сохраняется значение PCL (256).
Вектор сброса – адрес 0000h. Сброс приводит к очистке счетчика PCL и установке на адресе 0000h . Также очищается PCLATH, устанавливая нулевую страницу памяти.
Вектор прерывания – адрес 0004h. При возникновении разрешенного прерывания в счетчике команд РС устанавливается адрес 0004h. При этом значение PCLATH не изменяется.
Аппаратный стек – это буфер из 8 уровней по 13 разрядов. В стек заносится значение счетчика команд PC при выполнении команды CALL (перехода на подпрограмму) или обработку прерываний. Значение PC заносится в верхний уровень, называемый вершиной стека. Следующее значение PC опять запишется в вершину стека, а предыдущее перепишется в следующий нижний уровень. При заполнении всех 8 уровней девятая запись заменит первую, десятая вторую и т.д.
Чтение из стека и последующая запись в PC происходит при выполнении выхода из подпрограммы или прерывания (RETURN, RETFIE, RETLU), при этом значение PCLATH не меняется.
Стек не доступен пользователю.
Вычисляемый переход – это операция, прибавляющая к младшему счетчику команд PCL определенное число. Например, командой ADDWF PCL. Единственное условие, чтобы значение PCL, не пересекло границу блока памяти. (256)
рисунок 1
Команды CALL и GOTO имеют 11 разрядную адресацию. Это позволяет непосредственно адресовать в пределах 1 страницы памяти программ (2К). Если необходимо адресовать из одной страницы в другую, то необходимо выбрать старшие биты регистра PCH (через PCLATH). Эти биты выбирают страницу памяти программ.
Простым языком. При выполнении CALL и GOTO не возможно обратится ко всей памяти программ (13 разрядов счетчика команд), т.к. данные команды имеют только 11 разрядов адреса. Два старших разряда адреса нужно установить пользователю в регистре PCLATH, если переход будет осуществлен на другую страницу. На первый взгляд, это проблематично, т.к нужно постоянно контролировать адрес вызываемой подпрограммы. Ниже, я расскажу и покажу на примере, как легко справится с этой проблемой, практически в автоматическом режиме.
Выход из подпрограммы по стеку не представляет проблем, т.к. стек 13 разрядный и попадаем на тот же адрес в РС, с которого исполнялась команда CALL.
На рис.2 показан процесс обращения и выхода из подпрограммы.
рисунок 2
Операторы Hign и Lov
Немного забежим вперед, но надо объяснить назначение этих операторов.
Операторы помогают при написании программы и являются, по сути, то же командами понятными компилятору. Они определены производителем. Рассмотрим только два, которые нам пригодятся в дальнейшей работе при изучении приемов работы с памятью программ.
High- возвращает старший байт слова. Означает, что при обращении, к какому то слову, в W (аккумулятор) запишется старший байт слова.
Lov - возвращает младший байт слова. Означает, что при обращении, к какому то слову в W (аккумулятор) запишется младший байт слова.
Мы знаем, что счетчик PC состоит из двух байт, т.е. используя данные операторы можно обращаться к каждому байту.
Начнем рассматривать правила и методы работы с памятью программ.
Обычно в программе мы обращаемся к каким то программным модулям (подпрограммам). Производитель определил для этого две команды: CALL и GOTO. Про них я выше писал.
Рассмотрим способы перехода между страницами при использовании этих команд.
1. Знать адрес метки ( страница, блок) и записать его в PCLATH. Это очень неудобный способ, любое изменение в программе до этой метки, приведет к сдвигу адреса и ошибки в обращении.
2. Воспользоваться оператором High. С его помощью указываем на адрес метки при компиляции. Адрес автоматически генерируется линкером и записывается в PCLATH . После этого выполняется переход на метку по адресу записанному в PCLATH.
movlw high metka
movwf PCLATH
call metka
.
.
.
movlw high metka
movwf PCLATH
goto metka
Практически тоже самое можно получить при использовании директивы Pageselw. Эта директива по сути является макросом приведенной выше записи.
pageselw metka
call metka
.
.
.
pageselw metka
goto metka
Особенностью является, некоторые считают недостатком, не сохранение данных аккумулятора при использовании оператора high или директивы pageselw.
3. Использовать директиву Pagesel. Эта директива представляет собой указание линкеру генерировать код устанавливающий биты выбора страницы в которой находится метка.
pagesel metka
call metka
.
.
.
pagesel metka
goto metka
Эта директива корректирует 3;4 бит PCLATH. Не использует W, т.е. если в аккумуляторе были данные, то они будут сохранены.
Например, если metka находится во 2 странице памяти программ после компиляции будет следующая запись.
bcf PCLATH,0x03
bsf PCLATH,0x04
call metka
Вычисляемый переход обычно используют для обращения к таблицам или массивам данных.
Мы определились, что вычисляемый переход, это прибавление к младшему регистру счетчику PCL какого-то числа. Что бы понять суть этого метода рассмотри одну страницу памяти программ. Рис.3
Одна страница (2К) на 8 блоков памяти по 256. Понятно, что значение в PCL это 8- битный регистр и записать в него больше 256 значений невозможно. Если больше, произойдет ошибка записи в регистр, просто переполнится и начнет новый отсчет с нуля.
Рассмотрим пример. Пусть командой addwf PCL нам надо переместиться на метку с адресом 0xFE в нулевом блоке. Значение PCL до этого 0xFA. Следовательно, надо прибавить к PCL число 0x04, пересечения границы блока (переполнение регистра не будет).
А если прибавим число 0x08 ? Произойдет переполнение регистра PCL (блока памяти). И определится новый ошибочный адрес в нулевом же блоке. Перехода на метку в первый блок не произойдет.
рисунок 3
Рассмотрим способы организации вычисляемых переходов.
1. Вычисляемые переходы располагают в нулевом блоке памяти и контролируют невозможность пересечения границы между нулевым и первым блоками. Также размещают вычисляемый переход в начале любого блока, привязывая к адресу PC директивой org.
Это простой, но неудобный метод.
2. Используя операторы High и Lov. При этом не следят за страницей и тем более границей блока страницы. Суть в том, что перед переходом проверяется значение PCL. Если оно больше 255, то к PCLATH прибавляется 1, таким образом выбирается следующий блок страницы.
movlw high metka ; записать PCH метки в W
movwf PCLATH ; проверка смещения блока памяти страницы (кратно 256 )
movf reg,w ; выч. переход на число в reg
addlw low metka ; cложить W и PCL метки
btfsc STATUS,C ; проверить бит С (переполнение)
incf PCLATH,f ; было, +1 к PCLATH
movf reg,w ; не было, просто выч. переход.
addwf PCL,F
metka
retlw 0x78
retlw 0x92
.
.
.
retlw 0xAA
3. Используя директиву pageselw
Напомню, что эта директива использует W и копирует в PCLATH старший байт счетчика РC (PCH)
pageselw metka ; в PCLATH записано страница и номер блока метки
; проверка смещения блока памяти страницы (кратно 256 )
movlw metka ; получаем адрес метки в блоке в W
addwf reg,w ; сложить адрес метки (W) и число выч. перехода
btfsc STATUS,C ; проверить бит С (переполнение)
incf PCLATH,f ; было, +1 к PCLATH
movwf PCL,F ; адрес метки (W) в PCL
metka
retlw 0x78
retlw 0x92
.
.
.
retlw 0xAA
Были приведены основные приемы работы со страницами и блоками памяти программ для контроллеров с 13 разрядным РС. На основании их можно довольно комфортно перемещаться в памяти программ. Существуют еще варианты, но все они основываются на именно этих приемах.
В качестве примера программы, где используются операторы HignиLov предлагаю разобрать программу "переход".
Обсуждение на форуме
Все права принадлежат ChipMK.ru. При копировании материала ссылка обязательна. 2011-2019 © ChipMK.ru
![]() |
|