для чего используется регистры
Регистры и для чего они нужны
Регистрами называют устройства для хранения одного двоичного числа. Количество разрядов в регистрах, выпускаемых отдельно, обычно не превышает восьми, но в составе других микросхем могут быть и регистры с большей разрядностью— вплоть до 128 или 256 бит в «продвинутых» микропроцессорах. Большинство типов электронных запоминающих устройств, вообще говоря, можно рассматривать как совокупность регистров. Но собственно регистры, как входящие в состав процессоров, так и выпускаемые отдельно, отличаются тем, что позволяют не только записывать и считывать информацию, но и производить некоторые простейшие операции, например, сдвиг разрядов.
Простейший регистр — это упомянутый ранее статический D-триггер. Четыре таких триггера, входящих в микросхему 561ТМЗ, образуют четырехразрядный регистр с параллельной записью и считыванием, причем тактовый вход в этой микросхеме у всех четырех разрядов общий. Как и сам триггер, такой регистр называют «защелкой».
Если регистр-защелка позволяет осуществлять только параллельную запись, то последовательный регистр (пример— 561ИР2) наоборот, имеет возможность записи только через один вход, который является D-входом самого младшего разряда. Последовательный регистр является неким обобщением конструкции D-триггера. Работу динамического D-триггера можно рассматривать, как процесс сдвига информации от входа через первый триггер ко второму при поступлении соответствующих перепадов на тактовом входе. В последовательном регистре, который в простейшем случае представляет собой просто последовательное соединение таких триггеров, происходит нечто подобное — с каждым фронтом тактового импульса информация сдвигается от младшего разряда к старшему, при этом в младший разряд записывается состояние входа. Считывать информацию при этом можно из каждого разряда в отдельности, как и в случае регистра-защелки. Такие регистры получили еще название сдвиговых. Они широко используются для последовательного ввода и вывода информации — скажем, для вывода восьми бит через последовательный порт RS-232 достаточно записать их в такой регистр, а потом подать на него восемь тактовых импульсов с нужной частотой.
Сдвиговый регистр можно закольцевать — соединить выход старшего разряда со входом младшего и получить нечто подобное.слону из анекдота, который засунул хобот себе в известное место. Однако в случае одного сдвигового регистра такое соединение приведет к тому же результату, что и для слона, то есть довольно бесполезно практически, ибо мы без дополнительных ухищрений запись информации производить уже не сможем. Поэтому используют объединение параллельной и последовательной записи/считывания в одном устройстве (пример— четырехразрядный регистр 561ИР9 или восьмиразрядный 561ИР6).
Такие сдвиговые регистры с параллельной записью и последовательным считыванием информации — неотъемлемая часть устройств памяти большой емкости, без них чтение и запись в большие массивы запоминающих ячеек были бы невозможны. Имеются они, например, в матрицах цифровых камер. Интересное применение таких регистров — организация последовательного интерфейса SPI, широко используемого для скоростного обмена информацией ме>кду различными микросхемами (например, ме>кду энергонезависимой памятью, вроде флэш-карточек, и микроконтроллером). В SPI наличествуют два восьмибитовых регистра, соединенных в кольцо входами/выходами, но они разделены пространственно: один регистр находится в одном устройстве, другой — в другом. Если подавать тактовые импульсы на оба регистра одновременно (это осуществляет одно из устройств — ведущее), то после подачи ровно 8 импульсов устройства обменяются содержимым своих регистров.
Начинаем изучать STM32: Что такое регистры? Как с ними работать?
Продолжаем рассмотрение базовых вопросов
В предыдущем уроке мы рассмотрели работу с битовыми операциями и двоичными числами, тем самым заложив основу для рассмотрения новой темы. В этом уроке мы с Вами рассмотрим очередной вопрос: что такое регистры и как с ними работать?
Память и регистры
Одним из самых важных навыков необходимых при работе с микроконтроллерами является умение взаимодействовать с регистрами. Давайте для себя разберемся, что же это такое?
В целом, регистр — это особый вид памяти внутри микроконтроллера, который используется для управления процессором и периферийными устройствами. Каждый регистр в архитектуре ARM представляет собой ячейку памяти и имеет длину в 32 бита, где каждый бит можно представить в виде крошечного выключателя с помощью которого осуществляется управление тем или иным параметром микроконтроллера.
Каждый из регистров имеет свой порядковый номер – адрес. Адрес регистра обозначается 32-битным числом представленным в шестнадцатеричной системе счисления. Путём записи по адресу регистра определённой комбинации единиц и нулей, которые обычно представлены в шестнадцатеричном виде, осуществляется настройка и управление тем или иным узлом в МК. Вспомним, что в программе для работы с битовыми операциями, мы могли представить в виде шестнадцатеричного числа произвольный набор единиц и нулей. В целом стоит отметить, что существует два вида регистров: регистры общего назначения и специальные регистры. Первые расположены внутри ядра МК, а вторые являются частью RAM-памяти.
Так же стоит отметить, что Reference Manual, который мы скачивали в первом уроке, это один большой справочник по регистрам, содержащимся в целевом микроконтроллере, а библиотека CMSIS позволяет нам оперировать символьными именами регистров вместо числовых адресов. Например, к регистру 0x40011018 мы можем обратиться просто, используя символьное имя GPIOC_BSSR. Конкретные примеры конфигурирования мы рассмотрим в ходе разбора нашей программы из первого занятия.
Итак, обычно структура регистра описывается в виде небольшой таблицы с указанием:
Разбор кода из первого занятия
Итак, давайте вспомним задачу, которую мы решили на первом уроке используя готовый код примера: нам было необходимо написать программу, которая бы обеспечила попеременное включение двух светодиодов на плате Discovery (возможно и не двух, если у вас другая версия платы Discovery) с временным интервалом.
Давайте еще разок взглянем на код программы, которую мы использовали для того, чтобы заставить наш МК дрыгать двумя ногами на которых расположены наши светодиоды:
Первым делом, при работе с STM32, даже для такой простой задачи как включение и выключение светодиода нам необходимо предварительно ответить на ряд вопросов:
Куда подключены наши светодиоды? К какому выводу микроконтроллера?
Для того, чтобы посмотреть где что находится на плате Discovery, а в частности, нужные нам светодиоды — нужно открыть Schematic-файл, либо тот который мы скачали с сайта ST, либо прямо из Keil:
Открыв Schematic мы увидим схему всего того, что есть на плате — схему ST-Link, обвязку всей периферии и многое другое. На текущий момент нас интересуют два светодиода, ищем их обозначение:
Как мы видим, наши светодиоды подключены к порту GPIOC на 8 и 9 пин.
Как включить тактирование на нужный порт GPIO?
В целом, любая работа с периферией в микроконтроллерах STM32 сводится к стандартной последовательности действий:
Внимание! Вопрос касательно системы тактирования, её настройки и использования мы подробно рассмотрим в отдельной статье.
Найти к какой шине подключен наш порт GPIOC можно найти в Datasheet’е на наш МК в разделе Memory Mapping в Таблице 16. STM32F051xx peripheral register boundary addresses.
Как вы уже успели заметить, необходимая нам шина именуется как AHB2. Для того чтобы подробнее ознакомиться с регистром, в котором включается тактирование на нужный нам порт GPIO на шине AHB, надо перейти в соответствующий раздел в Reference Manual. По названию регистров мы можем определить тот, который нужен нам:
Переходим в этот пункт, и мы видим наш 32-битный регистр, его адрес смещения, значение по умолчанию, способ доступа к регистру и перечисление того, за что отвечает каждый бит в регистре.
Смотрим на таблицу и видим нечто напоминающее опции включения тактирования на портах GPIO. Переходим к описанию и находим нужную нам опцию:
Соответственно если мы установим 19 бит в значение «1» то это обеспечит включение тактирования на порт I/O C – то есть на наш GPIOC. К тому же — нам нужно включить отдельно один бит из группы, не затрагивая остальные т.к. мы не должны мешать и изменять без надобности другие настройки.
Основываясь на материалах прошлого урока, мы знаем что для того чтобы выставить определенный бит нужно используя логическую операцию «ИЛИ» сложить текущее значение регистра с маской которая содержит те биты которые необходимо включить. Например, сложим значение регистра RCC->AHBENR по умолчанию, т.е. 0x14 и число 0x80000 тем самым включим тактирование GPIOC путем установки 19 бита:
Каким образом мы можем это сделать из программы? Всё достаточно просто. В данном случае у нас два варианта:
То есть, мы могли бы обращаться к адресам регистров напрямую по адресу и написать так:
Второй вариант мне кажется наиболее привлекательным, т.к. библиотека CMSIS организована таким способом, что регистру можно обращаться, используя только его название. Препроцессор в ходе обработки текста программы перед компиляцией подставит все цифровые значения адреса регистра автоматически. Давайте разберем этот вопрос чуть подробнее.
Предлагаю открыть наш проект, который мы сделали в первом занятии, или скачайте предварительно подготовленый отсюда и удалите все содержимое программы оставив только подключенный заголовочный файл, функцию main() и инструкцию для включения тактирования (она нам понадобится для подробного разбора кода).
Наш код будет выглядеть следующим образом:
Давайте для ознакомления копнём вглубь библиотеки CMSIS.
Для того, чтобы быстро перейти к месту где объявлена та или иная константа или переменная в Keil реализована удобная функция. Кликаем правой кнопкой по необходимой нам константе, например, на RCC:
И мы переносимся в глубины библиотеки CMSIS, в которой увидим, что все регистры доступные для управления программным способом имеют вид TypeDef-структур, в том числе и наш RCC:
Провалившись подобным образом в RCC_TypeDef мы увидим структуру в которой описаны все поля нашего регистра:
Соответственно, мы можем спокойно обращаться к нужному нам регистру записью вида PERIPH_MODULE->REGISTER и присваивать ему определенное значение.
Помимо мнемонического обозначения регистров есть так же обозначения конкретных битов. Если мы провалимся к объявлению параметра RCC_AHBENR_GPIOCEN из нашей программы, то так же увидим объявление всех параметров:
Таким образом, используя библиотеку CMSIS у нас получается лаконичная читаемая запись нужного нам параметра в регистр, через установку которого мы запускаем тактирование на нужный нам порт:
В качестве задания: определите используя возможности Keil, каким образом получился адрес регистра RCC->AHBENR как 0x40021014.
Как настроить нужные нам пины GPIO для того чтобы можно было включить светодиод?
Итак, мы знаем что нужные нам светодиоды подключены к порту GPIOC к пинам PC8 и PC9. Нам нужно настроить их в такой режим, чтобы загорался светодиод. Хотелось бы сразу же сделать оговорку, что порты GPIO мы рассмотрим подробнее в другой статье и тут мы сконцентрируемся именно на работе с регистрами.
Первым делом нам нужно перевести режим работы пинов PC8 и PC9 в режим Output. Остальные параметры порта можно оставить по умолчанию. Переходим в Reference Manual в раздел 9. General-purpose I/Os (GPIO) и открываем пункт отвечающий за режим работы пинов порта GPIO и видим что за этот параметр отвечает регистр MODER:
Судя по описанию, для установки пинов PC8 и PC9 в режим Output мы должны записать 01 в соответствующие поля регистра GPIOC.
Это можно сделать через прямую установку с помощью числовых значений:
Или через использование определений из библиотеки:
После данной инструкции наши пины PC8 и PC9 перейдут в режим Output.
Как включить светодиод?
Если мы обратим внимание на список доступных регистров для управления портом GPIO то можем увидеть регистр ODR:
Каждый из соответствующих битов отвечает за один из пинов порта. Его структуру вы можете увидеть ниже:
Для того, чтобы обеспечить попеременную смену состояний светодиодов надо с определенным временным интервалом включать/выключать 8 и 9 биты. То есть попеременно присваивать регистру значение 0x100 и 0x200.
Сделать это мы можем через прямое присвоение значений регистру:
Можем через использование определений из библиотеки:
Но так как микроконтроллер работает очень быстро — мы не будем замечать смены состояний светодиодов и визуально будет казаться что они оба горят постоянно. Для того чтобы они действительно моргали попеременно мы внесем искусственную задержку в виде цикла который займет МК бесполезными вычислениями на некоторое время. Получится следующий код:
На этом первоначальное знакомство с регистрами и методами работы с ними мы можем закончить.
Проверка результатов работы нашего кода
Небольшое приятное дополнение в конце статьи: в Keil имеется отличный Debug-инструмент с помощью которого мы можем пошагово выполнить нашу программу и просмотреть текущее состояние любого периферийного блока. Для этого после загрузки прошивки после компиляции мы можем нажать кнопку Start Debug Session:
Рабочая среда Keil переключится в режим отладки. Мы можем управлять ходом программы с помощью данных кнопок:
И есть еще одна удобная функция работы с периферией в режиме отладки, она позволяет просматривать текущее состояние регистров и менять их состояние простым кликом мышкой.
Для того чтобы ей воспользоваться — нужно перейти в соответствующий периферийный блок и справа откроется окно с указанием регистров и их значением.
Если вы кликните по одному из пунктов данного меню, вы увидите адрес регистра и его краткое описание. Так же можно просмотреть описание к каждому отдельному параметру регистра:
Попробуйте самостоятельно пошагово выполнить программу, включить/выключить светодиоды не используя программу, а используя данный режим работы с микроконтроллером. Простор для фантазии тут обширный. Так же попробуйте поиграться с длительностями задержек, сделайте одновременное моргание обоими светодиодами. В общем экспериментируйте! )
Регистры микропроцессоров, их виды и назначение

При составлении программ в первую очередь необходимо
знать, какие из регистров микропроцессора являются программно–доступными регистрами, в которых можно хранить подлежащие обработке данные (операнды), адреса и управляющие сигналы (команды). Совокупность программно–доступных регистров образуют регистровую модель микропроцессора. Адресация регистровой области процессора и быстрый доступ к ней обеспечивают создание эффективно исполняемых программ.
В регистровой модели современных процессоров обычно выделяют следующие группы регистров:
● регистры, используемые при выполнении прикладных программ. К ним относят:
• основные функциональные регистры (регистры общего назначения; указатель команд, или программный счетчик; сегментные регистры; регистр флагов, или слова состояния);
обработки чисел с плавающей точкой (регистры данных, тегов, состояния, управления, регистры–указатели команды и операнда);
обработки пакетов чисел с плавающей точкой (регистры пакетов данных и регистр управления–состояния);
● системные регистры (регистры управления режимом, регистры системных адресов, регистры отладки);
● служебные (модельно–специфические) регистры, которые используются в процессе отладки систем, содержат информацию о процессе выполнения программы (число декодированных команд, полученных запросов прерывания, число загрузок в кэш–память и т. п.), обеспечивают различные режимы работы кэш–памяти при обращении к определенным областям основной памяти
О неоднородности регистров.
Регистровая область памяти микропроцессора (
— регистровый сегмент) представляет собой набор неоднородных по возможности доступа и по выполняемым функциям регистров. Например, в рассмотренном выше 8–разрядном процессоре:
● регистр команд является неадресуемым регистром и предназначен только для приема первого байта (кода команды) из памяти;
● адресуемые регистры В и С могут быть использованы для хранения одного байта данных или 16–разрядного адреса (в паре);
● указатель стека, представляющий собой 16–разрядный регистр, используется для доступа к стеку путем явной и неявной (с помощью специальных команд
● программный счетчик, или указатель команд, выполняет строго определенные функции и не может быть использован для хранения 16–разрядных операндов.
Функциональная неоднородность области
процессора проявляется в специализации регистров. В зависимости от выполняемых функций можно выделить три группы регистров:
● регистры данных, используемые в операциях АЛУ в качестве источника и приемника операндов;
● адресные регистры, или указатели, предназначенные для формирования адресов данных и команд;
● специальные регистры, служащие для индикации текущего состояния процессора и управления режимами его работы.
Функциональная специализация затрудняет программирование (из–за необходимости учета организации регистров), однако позволяет создать быстро исполняемую программу с меньшим требуемым объемом памяти для ее хранения.
Регистры обозначаются латинскими буквами, используемыми для символического кодирования и отражающими назначение регистра.
Среди регистров данных важное место занимает аккумулятор А (
), который выполняет функции временного хранения исходных операндов и результатов операций арифметическо–логических устройств (АЛУ). Интенсивное использование аккумулятора и связанное с ним большинство команд арифметической и логической обработки операндов способствует снижению загруженности шины данных, упрощению адресации, повышению быстродействия процессора. В системах команд микропроцессора выделяются операции с аккумулятором. Поэтому ссылка на аккумулятор при адресации, как правило, производится неявно с помощью кода операции. Неявная адресация позволяет не указывать в командах месторасположение одного из операндов и (или) результата операции, что уменьшает длину их кода. В составе микропроцессора может быть не один, а два аккумулятора (например, в МС6809). К регистрам данных относятся явно адресуемые рабочие регистры
1, …., используемые как сверхскоростные регистровые ОЗУ.
Рабочие регистры могут использоваться в операциях совместно с аккумулятором. Некоторые из них могут совмещать функцию хранения данных с функцией адресации. Для образования полноразмерного адреса регистры данных объединяются в пары.
В процессорах, предназначенных для работы в реальном времени, могут быть предусмотрены не один, а два или даже четыре (например, в некоторых микроконтроллерах) набора рабочих регистров. Один из регистров резервируется для системных целей или обработки прерываний, а остальные — для прикладных задач пользователя. В каждый момент времени доступен только один набор рабочих регистров, выбираемый специальным указателем.
К регистрам данных также относятся рассматриваемые ниже регистры общего назначения, которые совмещают функции хранения данных и адресов.
Среди регистров, на которые возложена функция адресации, следует выделить:
), или указатель инструкций–команд (
), хранящий адрес следующей команды выполняемой программы. Его разрядность обычно соответствует числу линий адресной шины. При выполнении программы с последовательно возрастающими адресами команд содержимое
увеличивается на 1 или 2 для указания следующего байта или слова. Увеличение содержимого счетчика происходит автоматически сразу после начала выполнения команды. Изменение последовательной выборки команд из ячеек памяти осуществляется путем загрузки программного счетчика адресом требуемой ячейки. Такая ситуация возникает, например:
• при выполнении команд условных и безусловных переходов;
• при инициализации микропроцессора путем сброса;
• при обслуживании запросов на прерывание;
используемый для обращений к системному стеку. Стек представляет собой область памяти, предназначенную для хранения адресов возврата и состояний процессора (содержимого регистров) при вызове подпрограмм и обслуживании прерываний. Доступ к стеку организован по принципу «последним пришел — первым ушел» (
т. е. в него можно только последовательно добавлять (вталкивать) или извлекать (выталкивать) элементы данных. Типовой стек, применяемый в большинстве процессоров, заполняется в сторону уменьшения адресов.
всегда показывает на последнюю заполненную ячейку, называемую вершиной стека (
Поэтому при операции записи (
) в стек элемента данных сначала содержимое указателя
уменьшается на 1 или 2 в зависимости от длины элемента (байт, два байта), формируя адрес ячейки, в которую затем помещается элемент. При операции считывания (
) сначала элемент данных извлекается из стека, после чего содержимое указателя
увеличивается на 1 или 2.
Принцип взаимодействия указателя
со стеком проиллюстрирован на примере записи в стек и считывания из него четырех однобайтных элементов (рис. 2.4.1, а).
При операциях со стеком значение указателя
непрерывно меняется, поэтому применять его в качестве точки отсчета при доступе к хранящимся в стеке данным вызывает определенные трудности. Поэтому в ряде случаев, например, при хранении в стеке локальных переменных или при обмене параметрами между вызываемой и вызывающей процедурой (подпрограммой), используется указатель кадра (
) — специально зарезервированный адресный регистр. Регистр
, указывающий на начало области параметров в стеке (рис. 2.4.1, б), принадлежит к классу базовых регистров. В 16–разрядных процессорах указателем кадра служит индексный регистр ВХ;
регистры, предназначенные для хранения адресов обращения к основной памяти. Такие регистры, называемые указательными или индексными, позволяют сократить размер кода (программы). К ним следует отнести:
• регистры косвенного адреса (
), содержащие непосредственно адрес операнда;
), хранящие начальные (базовые) адреса массивов и записей;
• индексные регистры I или X (
), содержимое которых является относительным (смещенным) адресом операнда;
• регистры автоинкрементной и автодекрементной адресации, автоматически увеличивающие или уменьшающие свое содержимое после выполнения операции;
• регистры расширения адресного пространства (до 1М байт).
К специальным регистрам следует отнести регистр флагов (
), или регистр слова состояния программы (
а также ряд регистров, используемых в сопроцессорах и микроконтроллерах.
На регистр флагов возлагается функция хранения признаков. С каждым признаком связывается одноразрядная переменная (бит), называемая флагом (флажком). Регистр флагов содержит:
● биты признаков состояния процессора. Обычно эти признаки формируются в АЛУ после выполнения операции и характеризуют ее результат;
● биты управления и системных признаков, которые устанавливаются операционной системой (некоторые пользователем) и задают режим процессора при организации ввода–вывода данных, обслуживании прерываний и исключений, решении последовательности вызываемых задач и реализации ряда других процедур.
Упаковка всех флагов в одно слово и хранение в регистре дает возможность их быстрой пересылки в память с последующим восстановлением, например, при обслуживании запросов на прерывание.
Ниже приведены обозначение, название и назначение флагов признаков состояния, а также показан принцип формирования некоторых флагов из отдельных бит
–разрядных операндов вида
, которые могут быть как исходным операндом, так и результатом выполненной операции:
