Найти тему
Разумный мир

Микроконтроллеры для начинающих. Часть 21. Команды манипуляции битами

Оглавление

Продолжаем наше краткое, обзорное, знакомство с системой команд процессоров микроконтроллеров. В предыдущей статье "Микроконтроллеры для начинающих. Часть 20. Команды логических операций" я рассказал о командах логических операций. В общем и целом, логических операций достаточно для работы с отдельными битами ячеек памяти.

Однако, это не очень удобно, так как приходится работать с битовыми масками. Кроме того, теоретически (именно теоретически!), битовые операции позволяют избежать последовательности чтение-модификация-запись для ячейки памяти в целом. А это может быть важно, если учесть, что ячейка памяти может быть аппаратным регистром управляющим каким-либо устройством. Этого вопроса мы будем еще не раз касаться при знакомстве с различными узлами и модулями микроконтроллеров. К сожалению, во многих (в большинстве) микроконтроллеров битовые команды все таки неявно воздействуют на ячейку памяти целиком.

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

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

Адрес бита

Бит является частью ячейки памяти. В нашем случае 8-битных микроконтроллеров, частью байта. При этом минимальной адресуемой порцией данных является байт, за редким исключением. Поэтому адресом бита является комбинация адреса байта, в котором этот бит и находится, и номера собственно бита в байте. Это очень похоже на адресацию база+смещение.

Это пример адресации бита в STM8 (команда установки бита), в других микроконтроллерах формат отличается, но принцип такой же. Биты обычно нумеруются начиная с младшего, от 0 до 7. Но бывают и исключения, особенно если говорить о процессорах в целом, включая специализированные.

При этом у нас возникает проблема, для рассматриваемых нами микроконтроллеров. Дело в том, что команды одноадресные. Поэтому номер бита задается в виде непосредственного операнда, в коде команды. Это может оказаться неудобным если номер бита должен изменяться. В таком случае приходится все таки пользоваться командами логических операций.

Неявная адресация бита

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

Например, команда CLC в микроконтроллерах AVR сбрасывает флаг переноса (бит 0) регистра SREG.

Прямой адрес бита

Я не рассматриваю в данном цикле статей микроконтроллеры архитектуры MCS-51. Однако, интересно продемонстрировать еще один, редко встречающийся, способ адресации бит. Я уже говорил в статьях и комментариях о нем, но немного напомню.

Дело в том, что в MCS-51 есть диапазон адресов байт от 20h до 2Fh, где каждый бит имеет и свой собственный адрес в диапазоне 00h - 7Fh.

-2

И этот адрес бита указывается в качестве операнда команды.

Многообразие и сложности

Я немного забегу вперед и при этом одновременно загляну в уже пройденное. Поговорим о том, что может вызвать затруднения у новичков. Здесь придется учитывать специфику микроконтроллеров, в большинстве случаев.

Рассмотрим задачу - установить бит номер 3 в ячейке памяти с адресом 70h. Это можно сделать несколькими способами. Рассмотрим на примере STM8

Пример установки бита для STM8
Пример установки бита для STM8

Наглядно видно преимущество битовой команды. Однако, давайте разберемся, почему потребовалось три логических команды. Во первых, команда OR применима только к аккумулятору и ячейке памяти. Значит, мы просто не можем указать маску бита непосредственно в коде команды. Что бы не использовать лишнюю ячейку памяти мы и загружаем маску в аккумулятор. А в качестве ячейки памяти для второго операнда указываем нужный нами адрес 70h. Во вторых, результат команды OR помещается в аккумулятор. Поэтому последней командой мы переносим его в нужную нам ячейку памяти.

В случае AVR все немного сложнее. Во первых, у нас нет команды подобной bset в STM8. Есть команда sbi, которая работает только с регистрами ввода-вывода("Микроконтроллеры для начинающих. Часть 12. Память и процессор в AVR"). Нам не повезло, адрес 70h не входит в эту область. Поэтому картинка будет не такая красивая

Пример установки бита для AVR
Пример установки бита для AVR

Здесь используется две битовые операции - set (устанавливает флаг Т) и bld (копирует флаг T в заданный бит заданного регистра). Логическую операцию ИЛИ использовать даже проще, только нужно учитывать, что команда ori работает с регистрами r16-r31. Вместо ori можно использовать команду sbr.

Однако, сбрасывать со счетов команду sbi не стоит. Если нужно установить бит в байте в диапазоне адресов 20h-51h (диапазон 00h-31h пространства ввода-вывода), это часть диапазона регистров ввода-вывода, то использование sbi позволит обойтись только одной командой.

Для PIC ситуация во многом похожа на STM8, так как есть команда bsf, но при этом может оказаться и сложнее. Дело в том, что для BaseLine микроконтроллеров адрес ячейки памяти лежит в диапазоне 0h-1Fh, а нам требуется 70h. Такого адреса просто не существует, например, в PIC12F510. А, например, в PIC12F506 он располагается в третьем банке памяти данных. А значит, нужно переключить банк установив соответствующие биты в регистре FSR. В более продвинутых PIC адрес 70h можно задать прямо в команде, что не исключает необходимости учитывать банковую организацию памяти. В иллюстрации я не буду учитывать этот момент.

Пример установки бита для PIC
Пример установки бита для PIC

Здесь я привел два варианта использования логической операции ИЛИ. Первый, полностью аналогичный предыдущим примерам. Второй, использующий возможность указать, куда помещать результат операции.

Флаги в регистре состояния процессора

Ранее рассмотренные примеры касались бит в ячейках памяти данных (и области ввода-вывода для AVR). А что можно сказать о флагах состояний?

Для PIC особых вариантов нет, используются обычные команды bsf и bcf. Для PIC18 доступна еще команда btg. Регистр STATUS, как вы уже знаете, имеет адрес 0x03, с которым и нужно работать.

Аналогичная ситуация и с STM8. Здесь регистр CC имеет адрес 0x0A. А для работы с флагами состояний используются обычные битовые команды bset, bres и bcpl.

С AVR ситуация более интересная. Здесь есть команды установки/сброса флагов состояния. Но при этом регистр SREG имеет адрес 3Fh в пространстве ввода-вывода (5Fh в пространстве данных). На первый взгляд, появляется возможность использовать команды sbi/cbi. Однако, это не возможно, так как максимальный адрес для sbi равен 31h. Таким образом, работа с флагами состояний возможна только специальными командами или обобщенными bset/bclr.

Краткий обзор команд работы с битами

Вот теперь, когда мы столько всего узнали, мы можем посмотреть, какие команды есть в различных микроконтроллерах

Установка бита

Как следует из названия операции, эта команда просто устанавливает бит, присваивает ему значение 1, вне зависимости от того, что с ним было ранее.

BSF - установка бита в ячейке с заданным адресом, включая регистр состояния процессора, в микроконтроллерах PIC.

BSET - аналогично, но для STM8.

SBI - установка бита в регистре ввода-вывода (не полное адресное пространство ввода-вывода) для AVR.

BSET - установка указанного бита в регистре SREG для AVR. Да, мнемоника похожа на команду для STM8, но применение команды в AVR специализированное.

SEC, SEN, SEZ, SEI, SES, SEV, SET, SEH - установка соответствующих флагов состояния для AVR. С каким именно флагом работает команда указывается последним символом в ее мнемонике. Так мы уже встречались с командой SET, которая устанавливает флаг Т. Команда SEI устанавливает флаг разрешения прерываний, то есть, разрешает собственно обработку прерываний.

SBR - специфичная для AVR команда групповой установки бит. Устанавливает указанные маской биты в регистрах r16-r31. Аналогична команде ORI.

Сброс бита

Как следует из названия операции, эта команда просто сбрасывает бит, присваивает ему значение 0, вне зависимости от того, что с ним было ранее.

BCF - сброс бита в ячейке с заданным адресом, включая регистр состояния процессора, в микроконтроллерах PIC.

BRES - аналогично, но для STM8.

CBI - сброс бита в регистре ввода-вывода (не полное адресное пространство ввода-вывода) для AVR.

BCLR - сброс указанного бита в регистре SREG для AVR.

CLC, CLN, CLZ, CLI, CLS, CLV, CLT, CLH - сброс соответствующих флагов состояния для AVR. С каким именно флагом работает команда указывается последним символом в ее мнемонике. Так команда CLT сбрасывает флаг Т.

CBR - специфичная для AVR команда группового сброса бит. Сбрасывает указанные маской биты в регистрах r16-r31. При этом, сбрасываются биты, которые установлены в маске. То есть, команда инвертирует маску, а потом выполняет ANDI.

Инверсия бита

Это более редкая команда. Из рассматриваемых в цикле статей микроконтроллеров эта операция доступна только в PIC18 и STM.

BTG - переключает заданный бит (меняет его значение на противоположное) в заданной ячейке памяти PIC18.

BCPL - аналогично, но для STM8.

Копирование (пересылка) бита

Тоже довольно редкая команда, хотя необходимость копирования битовой переменной иногда оказывается очень полезной.

BCCM - копирует флаг переноса в заданный бит заданной ячейки памяти STM8. Почему именно флаг переноса удостоился специальной команды? Дело в том, что этот флаг используется наиболее часто, причем не только как результат арифметических операций. Поэтому, особенно для программ на языках высокого уровня, не редко требуется сохранять его для последующего анализа.

BST - копирует заданный бит заданного регистра (r0-r31) в флаг Т SREG AVR. Я уже упоминал этот флаг, не только в данной статье, но и в "Микроконтроллеры для начинающих. Часть 14. Начинаем знакомство в системой команд. Флаги и статусы".

BLD - обратна команде BST, то есть, копирует флаг Т в заданный бит заданного регистра AVR.

Заключение

На этом мы заканчиваем знакомство с битовыми командами. Как я уже говорил ранее, эти команды не являются такими уж необходимыми, во многих случаях, так как заменяются обычными логическими командами. Это я проиллюстрировал на примерах, где задача решается двумя способами.

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

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

До новых встреч!