Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Микроконтроллеры PIC фирмы Microchip для начинающих выпуск №5


РАССЫЛКА Микроконтроллеры PIC фирмы Microchip для начинающих
Ведущий: Алексей (wmstr@front.ru)


Доброго времени суток, дамы и господа!!

Сегодня в  выпуске мы продолжим рассмотрение инструкций ассемблерного кода микроконтроллеров серии PIC18!

С праздником Вас – днем Конституции Российской Федерации!

 

В прошлом выпуске мы остановились на байт-ориентированных командах. Сегодня завершим рассмотрение оставшихся команд! Потом, для закрепления этой темы, я дам несколько примеров!

Итак, продолжим:

Данная таблица с описанием параметров команд уже фигурировала в предыдущем выпуске, но, для вновь подписавшихся, она будет кстати.

Обозначение

Описание

FREG

любой регистр данных

d

указатель на регистр, куда будет записываться результат

0 – результат будет записываться в аккумулятор WREG

1 – результат будет записываться в регистр FREG

a

признак, использовать при вычислении адреса регистр BSR или нет

0 – FREG расположен в Access Bank или это специальный регистр

1 – вычислять адрес FREG, используя регистр  BSR

bit

номер бита в байте от 0 до 7

k

байтовая константа

kkk

абсолютный 20-ти битный адрес перехода

 
Открываем в datasheet пункт 20.0 INSTRUCTION SET SUMMARY и продолжаем по порядку рассмотрение инструкций. Следующими идут бит-ориентированные команды: 

Мнемоника и операнды

Описание команды

Кол-во циклов

Флаги

Бит-ориентированные команды

BCF FREG, bit, a

Сброс в ноль бита, задаваемого параметром bit, в регистре FREG.  Например: BCF temp,3,0 – сброс в ноль бита 3 в переменной temp, адрес переменной вычисляется без использования  BSR.

1

Не изменяет

BSF FREG, bit, a

Установка в единицу бита, задаваемого параметром bit, в регистре FREG.  Например: BSF temp,3,1 – установка в единицу бита 3 в переменной temp, адрес переменной вычисляется с использованием  BSR.

1

Не изменяет

BTFSC FREG, bit, a

Команда проверяет бит, заданный параметром bit, в регистре FREG. Если этот бит, равен нулю, то пропускается следующая по коду инструкция.

1 или 2,3

Не изменяет

BTFSS FREG, bit, a

Команда проверяет бит, заданный параметром bit, в регистре FREG. Если этот бит, равен единице, то пропускается следующая по коду инструкция.

1 или 2,3

Не изменяет

BTG FREG, bit, a

Инвертирование бита, задаваемого параметром bit, в регистре FREG.  Например: переменная temp до выполнения команды хранит значение 0x01. После команды BTG temp,0,0 – в переменной temp уже будет храниться значение 0x00. Мигать светодиодом этой командой – милое дело.

1

Не изменяет

Команды управления

BC n

Переход  на метку n, если установлен флаг переноса С.

Если бит переноса установлен, то производится переход на адрес PC+2+2n (это действие производится за два цикла). Если условие не выполняется, то исполняется следующая за инструкцией команда (1 цикл). Где: -128<=n<=127. Т.е. метка должна находиться не выше или не ниже по коду 128-ми инструкций размером в одно слово от этого перехода.   Иначе, компилятор выдаст ошибку.

PC – указатель команд в программной памяти.

1 или 2

Не изменяет

BN n

Переход  на метку n, если установлен флаг отрицательного результата N. Где: -128<=n<=127

1 или 2

Не изменяет

BNС n

Переход  на метку n, если не было переноса. Флаг переноса С не установлен.  Где: -128<=n<=127

1 или 2

Не изменяет

BNN n

Переход  на метку n, если  флаг отрицательного результата N не установлен.  Где: -128<=n<=127

1 или 2

Не изменяет

BNOV n

Переход  на метку n, если не было переполнения. Флаг переполнения результата OV не установлен.  Где: -128<=n<=127

1 или 2

Не изменяет

BNZ n

Переход  на метку n, если результат предыдущего вычисления не нулевой. Флаг нулевого результата Z не установлен.  

Где: -128<=n<=127

2

Не изменяет

BOV n

Переход  на метку n, если было переполнение. Флаг переполнения результата OV установлен.  Где: -128<=n<=127

1 или 2

Не изменяет

BRA n

Безусловный переход  на метку n. Производится переход на адрес PC+2+2n (это действие производится за два цикла).

 Где: -1024<=n<=1023. Т.е. метка должна находиться не выше или не ниже по коду 1024-х инструкций размером в одно слово от этого перехода.   Иначе, компилятор выдаст ошибку.

2

Не изменяет

BZ n

Переход  на метку n, если результат предыдущего вычисления равен нулю. Флаг нулевого результата Z установлен в 1.

Где: -128<=n<=127  

1 или 2

Не изменяет

CALL kkk, s

Вызов подпрограммы kkk. Подпрограмма может располагаться в любой области программной памяти. Сначала, сохраняется в стеке адрес возврата: PC+4. Затем, если s=1, сохраняется значение регистров WREG, STATUS, BSR в быстрый стек, если s=0 (по умолчанию), то регистры не сохраняются. Дальше, происходит переход на метку kkk. Инструкция занимает 2 слова программной памяти.    

2

Не изменяет

CLRWDT

Команда сбрасывает сторожевой таймер WDT и его предделитель. Биты регистра RCON, TO и PD, устанавливаются в единицу.  Более подробно, остановимся на сторожевом таймере при рассмотрении битов конфигурации.

1

TO, PD регистра RCON

DAW

Десятичная коррекция регистра WREG. Команда производит десятичную коррекцию упакованного результата сложения двух BCD-чисел в упакованном формате. Выполняет следующее действие: если [WREG<3:0> >9] или [DC=1] ,
то W
REG <3:0>= WREG<3:0>+6,
иначе, W
REG <3:0>= WREG <3:0>.
Если [W
REG <7:4> >9] или [C=1] ,
то W
REG <7:4>=WREG <7:4>+6,
иначе, W
REG <7:4>= WREG <7:4>

1

C

GOTO kkk

Безусловный переход на метку kkk. Метка kkk может располагаться в любой области программной памяти. Инструкция занимает 2 слова памяти программ.   

2

Не изменяет

NOP

Нет операции. Команда холостого кода.

1

Не изменяет

POP

Извлечение из стека. Перемещение всего содержимого стека на один уровень вверх. Предыдущее значение, находящееся на вершине стека утрачивается. Более подробно остановимся на этой команде в дальнейших выпусках, при работе с прерываниями.

1

Не изменяет

PUSH

Данная команда помещает на вершину стека (TOS) значение PC+2. Предыдущее значение, находящееся на вершине стека перемещается на один уровень вниз.

1

Не изменяет

RCALL n

Относительный вызов подпрограммы n.  В стеке сохраняется адрес возврата из подпрограммы PC+2. Дальше, производится переход на адрес PC+2+2n.  Где: -1024<=n<=1023. Т.е. метка должна находиться не выше или не ниже по коду 1024-х инструкций размером в одно слово от этого перехода.   Иначе, компилятор выдаст ошибку. 

2

Не изменяет

RESET

Программный сброс микроконтроллера. Следующей, исполниться команда, расположенная по адресу 0x000000.  Т.е., команда выполняет операцию, идентичную аппаратному сбросу по сигналу MCLR.  

1

Все флаги

RETFIE  s

Возврат из обработчика прерываний. Возврат осуществляется загрузкой из стека последнего сохраненного туда значения в счетчик команд (PC). Если s=1, то, автоматически, восстанавливаются значения регистров WREG, STATUS, BSR из быстрого стека, если s=0 (по умолчанию), то регистры не восстанавливаются и их надо сохранять и восстанавливать программно. Более подробно мы изучим этот механизм, когда будем рассматривать прерывания микроконтроллера.

2

GIE, PEIE

RETLW k

Возврат из подпрограммы с загрузкой в регистр-аккумулятор WREG константы k. Возврат осуществляется загрузкой из стека последнего сохраненного туда значения в счетчик команд (PC). Данная команда удобна для организации  выхода из подпрограммы с ошибкой.

2

Не изменяет

RETURN  s

Возврат из подпрограммы. Возврат осуществляется загрузкой из стека последнего сохраненного туда значения в счетчик команд (PC). Если s=1, то, автоматически, восстанавливаются значения регистров WREG, STATUS, BSR из быстрого стека, если s=0 (по умолчанию), то регистры не восстанавливаются. Данная команда часто используется в паре с командой:  CALL kkk, s

2

Не изменяет

SLEEP

 Переход в энергосберегающий режим. Производится сброс сторожевого таймера. Процессор переходит в режим SLEEP с остановкой тактового генератора. Изменяются биты регистра RCON: PD=0, TO=1

1

TO, PD регистра RCON

Символьные команды

ADDLW k

Команда выполняет операцию: WREG=WREG+k

1

C,DC,Z,OV,N

ANDLW k

Команда выполняет операцию: WREG = поразрядное И регистра WREG и константы k.

1

Z,N

IORLW k

Команда выполняет операцию: WREG = поразрядное ИЛИ регистра WREG и константы k.

1

Z,N

LFSR  x, kk

Команда для работы с косвенной адресацией. Загружает в пару регистров FSRxH,FSRxL 12-ти битную константу kk. Где: x=0,1,2.  Например: LFSR 1, 0x435. После выполнения этой команды: FSR1H=0x04, FSR1L=0x35. Т.е. данной командой мы можем напрямую адресоваться к переменной в любой области памяти данных. Инструкция занимает 2 слова памяти программ.

2

Не изменяет

MOVLB  k

Команда для работы с прямой адресацией. Загружает в BSR – регистр константу k. Где: k=0…15.  Т.е. этой командой мы выбираем банк памяти данных, в котором будем работать.

1

Не изменяет

MOVLW  k

Команда выполняет операцию: WREG=k.

1

Не изменяет

MULLW k

Умножение регистра WREG на константу k, результат помещается в пару регистров: PRODH, PRODL

1

Не изменяет

SUBLW k

Команда выполняет операцию: WREG=k-WREG

1

C,DC,Z,OV,N

XORLW k

Команда выполняет операцию: WREG = поразрядное исключающее ИЛИ регистра WREG и константы k.

1

Z,N

Команды для работы с программной памятью (табличные)

TBLRD*

Команда читает один байт из области программной памяти. Перед выполнением этой команды необходимо загрузить в TBLPTR адрес читаемого байта в программной памяти. TBLPTR состоит из трех регистров: TBLPTRU, TBLPTRH, TBLPTRL. После выполнения команды читаемый байт будет находиться в регистре TABLAT.

2

Не изменяет

TBLRD*+

Команда читает один байт из области программной памяти. И, автоматически, затем, инкрементирует TBLPTR. 

2

Не изменяет

TBLRD*-

Команда читает один байт из области программной памяти. И, автоматически, затем, декрементирует TBLPTR. 

2

Не изменяет

TBLRD+*

Команда, сначала, автоматически,  инкрементирует TBLPTR. А, затем, только читает один байт из программной памяти. 

2

Не изменяет

TBLWT*

Команда записывает байты в программную память. Перед выполнением этой команды необходимо загрузить в TBLPTR адрес программной памяти, куда будем писать. Записываемый байт необходимо положить в регистр TABLAT до выполнения данной команды.  Хотя, по одному байту в программную память не записывают. Более подробно, алгоритм записи в программную память мы изучим в дальнейших выпусках рассылки.

-

Не изменяет

TBLWT*+

Команда записывает байты в программную память. И, автоматически, затем, инкрементирует TBLPTR. 

-

Не изменяет

TBLWT*-

Команда записывает байты в программную память. И, автоматически, затем, декрементирует TBLPTR. 

-

Не изменяет

TBLWT+*

Команда, сначала, автоматически,  инкрементирует TBLPTR. А, затем, только записывает байты в программную память. 

-

Не изменяет

Микроконтроллер PIC18F452 не имеет расширенного ядра. Наиболее близки по структуре нашему, но с расширенным ядром, микроконтроллеры: PIC18F4620, PIC18F4520. Следующие команды поддерживаются только микроконтроллерами, у которых  расширенное (extended) ядро и оно разрешено в битах конфигурации:

Мнемоника и операнды

Описание команды

Кол-во циклов

Флаги

ADDFSR  x, kk

Команда для работы с косвенной адресацией. Выполняет операцию FSRx=FSRx + kk . Где: x=0,1,2, а kk=0..63.  Например: ADDFSR 1, 0x10.  До выполнения операции: FSR1H=0x04, FSR1L=0x35. После выполнения этой команды: FSR1H=0x04, FSR1L=0x45.

1

Не изменяет

ADDULNK  kk

Команда прибавляет к регистрам косвенной адресации FSR2 константу kk, а потом возвращается из подпрограммы.   Возврат осуществляется загрузкой из стека последнего сохраненного туда значения в счетчик команд (PC).  Где: kk=0..63. Т.е., FSR2=FSR2+kk; PC=(TOS).

2

Не изменяет

CALLW

Команда вызова подпрограммы с использованием регистра WREG. Перед выполнением этой команды необходимо загрузить регистры PCLATU и PCLATH. Эти регистры являются буфером для программного счетчика.  В итоге, адрес перехода на подпрограмму вычисляется следующим образом: PCU=PCLATU; PCH=PCLATH; PCL=WREG;

2

Не изменяет

MOVSF [z], FREG

Команда выполняет действие: FREG=[FSR2+z].  Используется для работы с косвенной адресацией. Т.е., сначала вычисляется адрес FSR2+z. Потом, по нему считывается значение и записывается в FREG. Здесь переменная FREG имеет абсолютный 12-ти битный адрес памяти данных. Где: z=0..127. Инструкция занимает 2 слова памяти программ.

2

Не изменяет

MOVSS [z], [n]

Команда выполняет действие: [FSR2+n]=[FSR2+z]. Используется для работы с косвенной адресацией.  Т.е., сначала вычисляется адрес FSR2+z. Потом, по нему считывается значение, потом вычисляется адрес FSR2+n. И по этому адресу записывается считанное ранее значение. Где: z,n=0..127. Инструкция занимает 2 слова памяти программ.

2

Не изменяет

PUSHL k

Команда сохраняет по адресу, выставленному в регистрах FSR2H, FSR2L, константу k=0..255. Затем, адрес в регистрах FSR2 уменьшается на 1.   

1

Не изменяет

SUBFSR  x, kk

Команда для работы с косвенной адресацией. Выполняет операцию FSRx=FSRx - kk . Где: x=0,1,2, а kk=0..63.  Например: SUBFSR 1, 0x10.  До выполнения операции: FSR1H=0x04, FSR1L=0x35. После выполнения этой команды: FSR1H=0x04, FSR1L=0x25.

1

Не изменяет

SUBULNK  kk

Команда вычитает из регистров косвенной адресации FSR2 константу kk, а потом возвращается из подпрограммы. Возврат осуществляется загрузкой из стека последнего сохраненного туда значения в счетчик команд (PC).  Где: kk=0..63. Т.е., FSR2=FSR2-kk; PC=(TOS).

2

Не изменяет

 На этом с описанием команд закончим! 

Теперь рассмотрим небольшие простые конструкции на языке ассемблера для закрепления материала!

Для начала запомним основные директивы ассемблера:

EQU – с помощью этой директивы объявляются константы и адреса переменных в памяти данных.

ORG – с помощью этой директивы указывается адрес программной памяти. Весь код, который расположен после этой инструкции, будет расположен с заданного директивой адреса.

END – директива, указывающая на конец кода.

Основное правило!  При объявлении переменных, констант, макросов, меток определитесь сразу, как их лучше Вам именовать. Т.е. необходимо выработать свой стиль. Иначе, потом, в больших программах будет путаница и потерянное впустую время на выяснение типа! Также, пытайтесь называть переменные, макросы, константы и метки в соответствии с их назначением. Например: uart_point – переменная,  указатель буфера приемника/передатчика периферийного модуля UART.

Например, я делаю так:

  • Переменные объявляю маленькими буквами (temp, count, data_ADC и т.п.);
  •  Макросы и константы большими буквами (SKIPZ, IO_PORTB и т.п.);
  • Метки и название подпрограмм с заглавной буквы (Loop_met, Send_data и т.п.);
  • Команды ассемблера пишу заглавными буквами (MOVLW, BSF и т.п.)  

 

Теперь примеры:

Объявим несколько переменных и констант.

tempa equ 0x00     ; переменная tempa расположена в access bank по адресу 0x00

tempb equ  0x80    ; переменная tempb расположена не в access  bank, все зависит от значения BSR 

IO_PORTB equ 0xFF     ; константа для определения направления пинов порта В

count equ 0x01      ; переменная count расположена в access bank по адресу 0x01

ab equ 0         ; признак, что переменная находиться в access bank                 

bb equ 1         ; признак, что адрес необходимо считать с использованием регистра BSR

rw equ ab      ; rw=0. Результат размещается в регистр-аккумулятор WREG

rf equ bb        ; rf=1.  Результат размещается в регистр FREG

 

Пример организации цикла:

   MOVLW         0x08                ; WREG=0x08, цикл будет выполняться 8 раз

   MOVWF          count, ab        ; count=WREG, адрес count вычисляется без регистра BSR

Loop_met:                             ; метка (адрес) перехода. После метки всегда ставится « : »

   ; тело цикла

  DECFSZ count, rf, ab ; count=count-1. если count=0, то пропускаем следующую команду 

  BRA Loop_met   ;  если count не 0, то переходим на метку

 

Пример чтения двух байт подряд  из программной памяти: 

Байты расположены по адресам: 0х002000, 0х002001

P_DATA  equ 0x2000  ; 3-ий старший байт всегда равен 0, т.к. у нас 0x8000 программной памяти        

 

Первый вариант:

CLRF   TBLPTRU, ab  ; TBLPTRU           - специальный регистр, поэтому BSR не используем

MOVLW HIGH(P_DATA) ; WREG=0x20

MOVWF TBLPTRH, ab      ; TBLPTRH=WREG

MOVLW LOW(P_DATA) ; WREG=0x00 

MOVWF TBLPTRL, ab       ; TBLPTRL=WREG

TBLRD*                                 ; читаем из FLASH байт по адресу 0x002000     

MOVFF TABLAT, temp      ; прочтенный байт помещаем в переменную temp

INCF TBLPTRL, rf, ab        ; переходим на адрес 0х002001, в флаг С заносится перенос.

CLRF WREG, ab                  ; WREG может адресоваться и как специальный регистр        

ADDWFC TBLPTRH, rf, ab  ; если был перенос, то прибавляем его к старшему регистру

TBLRD*                                 ; читаем из FLASH байт по адресу 0x002001     

MOVFF TABLAT, count     ; прочтенный байт помещаем в переменную count

 

Второй вариант (более оптимизированный):

CLRF   TBLPTRU, ab  ; TBLPTRU           - специальный регистр, поэтому BSR не используем

MOVLW HIGH(P_DATA) ; WREG=0x20

MOVWF TBLPTRH, ab      ; TBLPTRH=WREG

MOVLW LOW(P_DATA) ; WREG=0x00 

MOVWF TBLPTRL, ab       ; TBLPTRL=WREG

TBLRD*+                               ; читаем из FLASH байт по адресу 0x002000 TBLPTR++         

MOVFF TABLAT, temp      ; прочтенный байт помещаем в переменную temp

TBLRD*                                 ; читаем из FLASH байт по адресу 0x002001     

MOVFF TABLAT, count     ; прочтенный байт помещаем в переменную count


Думаю, на сегодня нам хватит информации!

В следующем выпуске будем рассматривать биты конфигурации! 


Большая просьба! Люди, кто подписался на текстовый вариант рассылки, прошу Вас, перерегистрируйтесь на HTML-версию. Прошу прощения, но у меня нет времени делать два разных выпуска! И без таблиц и рисунков, будет тяжело что-то показать и объяснить!

Полный архив рассылки Вы можете прочитать на нашем сайте!

Желаю Вам удачи! До скорой встречи!

 

 


С уважением, Алексей pont_a@mail.ru
Cайт разработчиков 2AplusA http://2aplusa.ru


В избранное