Как работает регистр
Перейти к содержимому

Как работает регистр

  • автор:

Что такое регистр?

Регистр это устройство, выполненное на триггерах для выполнения ряда действий с двоичными числами. Для тех, кто не знает, что такое триггер, рекомендуем познакомиться с простейшим RS-триггером.

Наиболее простая функция регистров — это запоминание числа и его длительное хранение. Эти устройства так и называются – регистры хранения. Вот простейший пример.

На входы D0 – D2 подаётся число, которое необходимо сохранить. Как только на входе С появляется импульс синхронизации, число записывается в триггер, изменяя их состояние. На рисунке показан трёхразрядный регистр хранения. При подаче на входы числа 1112 оно же появится на прямых выходах триггеров (Q0Q2). На инверсных выходах (Q0Q2) будет, естественно 0002. Сигналом R (Reset) или сброс, триггеры устанавливаются в нулевое состояние.

Обычно используются регистры, состоящие из 4, 8, или 16 триггеров. Изображение четырёхразрядного регистра на принципиальных схемах может быть таким.

На рисунке не показаны инверсные выхода триггеров и сигнал R. Регистры всегда обозначаются латинскими буквами RG. Если регистр сдвигающий, то под обозначением рисуется стрелка направленная влево, вправо или двойная.

Сдвигающие регистры или регистры сдвига.

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

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

Рассмотрим четырёхразрядный регистр сдвига, преобразующий последовательный двоичный код в параллельный. Применение последовательного кода оправдано тем, что по одной линии можно передавать огромные массивы информации. Таким примером может служить универсальная последовательная шина — USB порт любого устройства. Число триггеров в данном регистре может быть любым. Достаточно соединить прямой выход Q3 с D входом следующего триггера и так далее до достижения необходимой разрядности.

Регистр работает следующим образом. Первый информационный бит поступает на вход D0. Одновременно с этим битом приходит тактовый синхроимпульс на вход С. Входы С всех триггеров входящих в регистр, объединены между собой. С приходом первого тактового импульса уровень, находящийся на входе D0 записывается в первый триггер и с выхода Q0 приходит на вход следующего триггера, но записи во второй триггер не происходит, так как синхроимпульс уже закончился.

При поступлении следующего тактового импульса уровень, присутствующий на входе второго триггера запоминается в нём и поступает на вход третьего триггера. Одновременно следующий информационный бит запоминается в первом триггере. После прихода четвёртого тактового импульса в четырёх триггерах регистра будут записаны логические уровни, которые последовательно поступали на вход D0.

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

Видно, что на условном изображении присутствует стрелка — указатель того, что это сдвиговый регистр.

Рассмотрим, как работает четырёх разрядный универсальный регистр сдвига К155ИР1 (аналог — SN7495N). Вот его внутреннее устройство.

Регистр содержит четыре D-триггера, которые соединены между собой с помощью дополнительных логических элементов И – ИЛИ, которые позволяют реализовать различные функции. На схеме:

  • V2 – вход управления. С его помощью выбирается режим работы регистра.
  • Q1 – Q4 выходы триггеров с которых снимается параллельный код.
  • V1 – вход для подачи последовательного кода.
  • C1, C2 – тактовые синхроимпульсы.
  • D1 – D4 – входы для записи параллельного кода.

Алгоритм работы регистра следующий. Если на вход V2 подать низкий потенциал, тактовые импульсы на C1, а на вход V1 подавать информационные биты, то регистр осуществляет сдвиг вправо. После приёма четырёх разрядов на выходах триггеров Q1 – Q4 мы получаем параллельный код. Таким образом осуществляется преобразование последовательного кода в параллельный.

Для обратного преобразования параллельный код записывается по входам D1 – D4, с подачей на вход V2 высокого потенциала и тактовых импульсов на вход С2. Затем подавая на вход V2 низкий потенциал, а тактовые импульсы на вход С1 мы сдвигаем записанный код, а с выхода последнего триггера снимается последовательный код.

По своей структуре это один из самых простых регистров сдвига.

Регистры сдвига в цифровой технике могут послужить основой, на которой собираются узлы с интересными свойствами. Это, например, кольцевые счётчики, которые называются счётчики Джонсона. Такой счётчик имеет количество состояний вдвое большее, чем число составляющих его триггеров. Например, если кольцевой счётчик состоит из трёх триггеров, то он будет иметь шесть устойчивых состояний. На вход счётчика ничего не подаётся кроме синхроимпульсов. В первоначальном состоянии все триггеры «сброшены», то есть на прямых выходах триггеров логические нули, а вот на входе D первого триггера с инверсного выхода третьего триггера находится логическая единица. Начнём подавать тактовые импульсы и процесс пошёл.

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

N Q2 Q1 Q0
1 0 0 1
2 0 1 1
3 1 1 1
4 1 1 0
5 1 0 0
6 0 0 0

Теперь вы знаете, что такое регистр и как он может использоваться на практике. Основа любого регистра — это триггер. Число триггеров в регистре определяет его разрядность. Те, кто увлекается микроконтроллерами знает, что важнейший элемент любого микроконтроллера, будь то PIC, AVR, STM или MSP, это регистр.

Регистры и их работа

Регистры — это цифровые устройства, осуществляющие функции приема, хранения и передачи информации в виде двоичных числовых последовательностей.

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

Что такое регистр. Основой функциональной единицей построения регистров являются RS-триггеры или Д-триггеры.

Параллельный регистр

В этой схеме цифровой код поступает на D-вход триггеров. Запись возможна при наличии логической единицы на вход С. Записанная числовая последовательность снимается с выходов Q. Параллельные регистры используются для хранения цифровых данных в виде параллельного двоичного кода, а также для преобразования прямого в обратный код или наоборот.

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

Последовательный регистр

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

При поступлении тактового импульса код, находящийся в регистре, сдвигается на один разряд. Т.е для нашей схемы, сдвиг кода идет вправо (в направлении младших разрядов).

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

Рассмотрим, работу четырёх разрядного универсальный регистра на микросборке К155ИР1 (SN7495N), который может работать как со сдвигом вправо так и влево.

К155ИР1 несет в себе четыре D-триггера, связанные дополнительно между собой с помощью логических элементов И – ИЛИ, позволяюших расширить базовые функции:

V2 – вход управления через него задается режим работы регистра
Q1 – Q4 выходы с которых снимается параллельный код. V1 – вход для подачи последовательного йифрового кода. C1, C2 – тактовые синхроимпульсы. D1 – D4 – для записи параллельного кода

Алгоритм работы следующий. Если на V2 подать низкий уровень, тактовые импульсы на первый вход синхронизации C1, а на V1 подавать биты информации, то регистр работает со сдвигом вправо и после приёма четырех разрядов на выходах Q1 – Q4 мы получим параллельный код.

Для обратного преобразования данных параллельный код записывается на D1 – D4, на V2 подают высокий уровень, а тактовых импульсы следуют уже на второй вход С2. Затем подавая на V2 низкий уровень, а синхроимпульсы на С1 мы сдвигаем записанный код, а с выхода последнего триггера идет последовательный код.

Условно-графическое обозначение параллельного, сдвигового и реверсивного регистров на схемах рассмотрено ниже:

D1-DN — входы D-триггеров соответствующих разрядов при записи информации в параллельном коде; Q1-QN — прямые выходы Q-триггеров; С — вход тактовых импульсов; R — вход сброса; S0,S1 — входы управления сдвигом вправо или влево; VR — вход последовательного кода при сдвиге вправо, при сдвиге кода влево применяется обозначение VL

Помимо уже перечисленных функций, регистры могут выполнять арифметические и логические операции, временную задержку и даже деление частоты. Сдвиговые регистры в отечественном варианте представлены микросборками: 133ИР1, К155ИР1, КМ155ИР1, 134ИР1

Справочник по регистрам

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

Если использовать дополнительно элемент «НЕ», можно сделать делитель частоты. На схеме ниже приведены делители частоты на 2, 3, 4, 5, 6, 7. При этом сигнал на L=0.

Импульсы следуют на вход синхронизации С1, а выходные импульсы идут с выхода Q старшего разряда, включенные через инвертор ОС со входом VR.

Отечественная микросборка К134ИР2 испоьзуется для хранения восьмиразрядного кода, который записывается последовательно через инверсный вход V. Для считывания кода в прямом виде используют инверсный выход, для считывания в инверсии — прямой. Считывани и запись, осуществляются поразрядно с поступлением фронта каждого последующего тактового импульса на тактовый вход С. Обнуление происходит за счет подачи напряжения логического 0 на вход сброса.

Микросхема 134ИР8, КР134ИР8, 533ИР8, КМ555ИР8, КР1533ИР8 для хранения восьмиразрядных данных и преобразования их из последовательного в параллельный вид. Запись осуществляется через любой из входов VR по тактовому импольсу. Считывание идет с выходов Q1-Q8 или поразрядно с выхода Q8.

533ИР9, К555ИР9, КМ555ИР9, КР1533ИР9 используется для хранения восьмиразрядного кода и преобразования его из параллельного в последовательный. Входная информация, представленная на входах D1 — D8, записывается асинхронно. При этом на инверсном входе L должно быть напряжение логического нуля, а состояния других входов могут быть различными. После записи на выходе Q8 появится сигнал. Для сдвига вправо на С1 или С2 идут тактовые импульсы. Микросхема может принимать информацию и в последовательном виде, для чего задействуется вход VR и один из синхровходов. На свободном синхровходе устанавливается логический ноль, как и на входе L.

Генератор белого шума схема на регистрах

Цифровой генератор белого шума это временной случайный процесс, близкий по своим свойствам к процессу физических шумов и его называют псевдослучайным процессом. Цифровой последовательностью двоичных символов в цифровых акустических генераторах шума называют псевдослучайной последовательностью, которая представляет собой последовательность прямоугольных импульсов с псевдослучайной длительностью и интервалами между ними. Генератор шума выполнен на цифровых микросхемах: восьмиразрядный регистр сдвига на микросхеме К561ИР2, сумматор по модулю 2 (DD2.1), тактовый генератор (DD2.3, DD2.4) и цепь запуска (DD2.2), на микросхеме К561ЛП2.

Тахометр автомобильный

Конструкция тахометра использует 8-разрядный сдвиговый регистр 74HC595 с ЖК дисплеем 16х2.

Исследование регистров

Лабораторная работа выполняется с помощью учебного лабораторного стенда LESO2.

Лаборатория с удаленным доступом. ПЛИС1 Цель работы

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

2 Краткие теоретические сведения

Регистры предназначены для хранения и преобразования многоразрядных двоичных чисел. Для запоминания отдельных разрядов числа могут применяться триггеры различных типов. Одиночный триггер можно считать одноразрядным регистром.

Занесение информации в регистр называется операцией записи. Операция выдачи информации из регистра – считывание.

Перед записью информации в регистр, его необходимо обнулить.

Классификация регистров:

  1. по способу ввода/вывода информации:
  • параллельные (регистры хранения) – информация вводится и выводится одновременно по всем разрядам;
  • последовательные (регистры сдвига) – информация бит за битом «проталкивается» через регистр и выводится также последовательно;
  • комбинированные – параллельный ввод и последовательный вывод (и наоборот).
  1. по способу представления информации:
  • однофазные – информация представляется в прямом или обратном (инверсном) виде;
  • парафазные – информация представляется и в прямом, и в обратном виде.

2.1 Параллельный регистр

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

Для записи информации в регистр на его входных выводах (D0-D3) нужно установить логические уровни, после чего на вход синхронизации (C) подать разрешающий импульс — логическую единицу. После этого на выходах Q0-Q3 появится записанное слово. Регистры запоминают входные сигналы только в момент времени, определяемый сигналом синхронизации.

Условно-графическое обозначение параллельного регистраРисунок 2.1 – Условно-графическое обозначение параллельного регистра Схема параллельного регистраРисунок 2.2 – Схема параллельного регистра

2.1 Последовательные регистры

Кроме параллельного соединения триггеров для построения регистров используется последовательное соединение этих элементов.

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

Принципиальная схема последовательного регистра, собранного на основе D-триггеров и позволяющего осуществить преобразование последовательного кода в параллельный, приведена на рисунке 2.3.

Рассмотрим работу этого регистра. Можно предположить, что в начале все триггеры регистра находятся в состоянии логического нуля, т.е. Q0=0, Q1=0, Q2=0, Q3=0. Если на входе D-триггера Т1 имеет место логический 0, то поступление синхроимпульсов на входы «С» триггеров не меняет их состояния.

Схема последовательного регистра

Рисунок 2.3 – Схема последовательного регистра

Как следует из рисунка 2.3, синхроимпульсы поступают на соответствующие входы всех триггеров регистра одновременно и записывают в них то, что имеет место на их информационных входах. На информационных входах триггеров Т2, Т3, Т4 – уровни логического «0», т.к. информационные входы последующих триггеров соединены с выходами предыдущих триггеров, находящихся в состоянии логического «0», а на вход «D» первого триггера, по условию примера, подается «0» из внешнего источника информации. При подаче на вход «D» первого триггера «1», с приходом первого синхроимпульса, в этот триггер запишется «1», а в остальные триггеры – «0», т.к. к моменту поступления фронта синхроимпульса на выходе триггера Т1 ещё присутствовал логический «0». Таким образом, в триггер Т1 записывается та информация (тот бит), которая была на его входе «D в момент поступления фронта синхроимпульса и т.д.

При поступлении второго синхроимпульса логическая «1» с выхода первого триггера, запишется во второй триггер, и в результате происходит сдвиг первоначально записанной «1» с триггера Т1 в триггер Т2, из триггера Т2 в триггер Т3 и т.д. Таким образом, производится последовательный сдвиг поступающей на вход регистра информации (в последовательном коде) на один разряд вправо в каждом такте синхроимпульсов.

После поступления четырёх синхроимпульсов регистр оказывается полностью заполненным разрядами числа, вводимого через последовательный ввод «D». В течение следующих четырёх синхроимпульсов производится последовательный поразрядный вывод из регистра записанного числа, после чего регистр оказывается полностью очищенным (регистр окажется полностью очищенным только при условии подачи на его вход уровня «0» в режиме вывода записанного числа).

Временные диаграммы, поясняющие работу регистра сдвига

Рисунок 2.4 – Временные диаграммы, поясняющие работу регистра сдвига

3 Задание к работе

3.1 Исследовать параллельный регистр

Сконфигурировать ПЛИС в соответствии с рисунком 3.1.

Схема 4-х битного параллельного регистра

Рисунок 3.1 – Схема 4-х битного параллельного регистра

Записать целые десятичные числа от 0 до 15 в двоичной системе счисления в регистр и считать их. Заполнить таблицу 3.1.

Таблица 3.1 – Коды, записанные в параллельный регистр

Записываемое десятичное число Считанное из регистра двоичное число
0
1
.
15

3.2 Исследовать последовательно-параллельный регистр

Сконфигурировать ПЛИС в соответствии с рисунком 3.2.

Схема последовательно-параллельного регистра

Рисунок 3.2 – Схема последовательно-параллельного регистра

Элемент 74164 – это последовательно-параллельный регистр.

ВНИМАНИЕ! Для того, что бы выполнить блок Antitinkling, прочтите инструкцию Борьба с дребезгом контактов.

Записать нечётное число в интервале от 32 до 56 в последовательном коде, поразрядно продвигая его влево путём нажатия кнопки Button. Записать результат в отчёт.

3.3 Исследовать параллельно-последовательный регистр

Сконфигурировать ПЛИС в соответствии с рисунком 3.3.

Схема параллельно-последовательного регистра

Рисунок 3.3 – Схема параллельно-последовательного регистра

Элемент 74166 представляет собой параллельно-последовательный регистр.

Чтобы записать на входе число необходимо установить на входе STLD логический 0 и подать синхроимпульс, чтобы начать считывать записанное число необходимо на вход STLD подать логическую 1 и подавать синхроимпульсы.

Записать число в интервале от 32 до 56 в параллельном коде и поразрядно считывать его на выходе. Записать результат в отчёт.

4 Содержание отчёта

  1. Цель работы.
  2. Схема исследования параллельного 4-х битного регистра с таблицей 3.1 .
  3. Схема последовательно-параллельного регистра с результатами исследований.
  4. Выводы по каждому заданию.

5 Контрольные вопросы

  1. Назначение регистров.
  2. По каким признакам классифицируются регистры?
  3. Чем определяется разрядность регистров?
  4. Назначение параллельного регистра.
  5. Объяснить принцип работы последовательного регистра.
  6. Объяснить принцип работы параллельного регистра.
  7. Объяснить принцип работы последовательно-параллельного регистра.
  8. Объяснить принцип работы параллельно-последовательного регистра.

Работа с регистрами

В прошлом уроке мы освоили битовые операции, а в этом – научимся работать напрямую с регистрами микроконтроллера. Зачем? Я думаю в первую очередь это нужно для того, чтобы понимать чужой код и переделывать его под себя, потому что прямая работа с регистрами в скетчах из Интернета встречается довольно часто.

Что такое регистр? Тут всё весьма просто: это сверхбыстрые блоки оперативной памяти объёмом 1 Байт, находящиеся рядом с ядром МК и периферией. На стороне программы это обычные глобальные переменные, которые можно читать и менять. В регистрах микроконтроллера хранятся “настройки” для различной его периферии: таймеры-счётчики, порты с пинами, АЦП, шина UART, I2C, SPI и прочее железо, встроенное в МК. Меняя регистр, мы даём практически прямую команду микроконтроллеру, что и как нужно сделать. Запись в регистр занимает около 1 такта МК (0.0625 мкс при частоте тактирования 16 МГц) – это ОЧЕНЬ быстро. Имена регистров фиксированные, полный перечень с подробным описанием можно найти в даташите на микроконтроллер (официальный даташит на ATmega328 – Arduino Nano/UNO/Mini).

Работа с регистрами очень непростая, если вы не выучили их все наизусть, потому что названия у них обычно нечитаемые, аббревиатуры. Так называемые “Ардуиновские” функции собственно и занимаются тем, что работают с регистрами, оставляя нам удобную, понятную и читаемую функцию, ничего сверхъестественного в этом нет. Зачем вообще работать с регистрами напрямую? Есть несколько больших преимуществ:

  • Скорость работы: чтение/запись регистра выполняется максимально быстро, что позволяет ускорить работу с МК (например дёргать пины вручную вместо digitalWrite() ). Максимальная скорость работы с периферией МК нужна далеко не всегда, поэтому если вам не нужно сэкономить несколько микросекунд – с регистрами можно даже не связываться.
  • Объём памяти: прямая работа с регистрами позволяет максимально компактно работать с периферией МК, читая и записывая только нужные биты, поэтому написанный под свои задачи конкретный код займёт меньше места, чем чьи-то готовые универсальные функции и библиотеки (например тот же digitalWrite или работа с Serial). При работе с Ардуино можно не заморачиваться по этому поводу практически никогда, а вот если делать проект на ATTiny – там придётся ужимать код вплоть до байта.
  • Гибкость настройки: работа с микроконтроллером напрямую при помощи регистров позволяет очень гибко настраивать периферию под свои задачи. Дело в том, что все существующие Ардуино-библиотеки охватывают чуть больше половины всех возможностей микроконтроллера! Огромное количество настроек и полезных трюков не описано нигде, кроме даташита, и для их использования нужно уметь читать этот самый даташит и работать с регистрами.

В микроконтроллерах серии ATmega/ATtiny регистры 8 битные, то есть регистр – это переменная типа byte . Насколько мы знаем, байт это число от 0 до 255, получается каждый регистр имеет 255 настроек? Нет, логика здесь совсем другая: байт это 8 бит, то есть один регистр хранит 8 настроек, которые можно включить/выключить. Давайте для примера рассмотрим один из регистров таймера 1, под названием TCCR1B . Картинка из даташита на ATmega328p:
Регистр TCCR1B , как и положено здоровому байту, состоит из 8 бит. Почти каждый его бит имеет имя (кроме 5-го, в этом МК он не используется). Что делает каждый бит и регистр – самым подробным образом расписано в даташите. Имена всех битов и регистров заданы в компиляторе, то есть создавать переменные с такими же именами нельзя. Изменять значения битов также нельзя, они являются константами:

int WGM12; // приведёт к ошибке CS11 = 5; // приведёт к ошибке

Но считать значение бита по его названию можно! Причём значение будет равно его номеру в регистре, считая справа. CS11 равен 1, WGM13 равен 4, ICNC1 равен 7 (см. таблицу выше).

Думаю здесь всё понятно: есть регистр (байт), имеющий уникальное имя и состоящий из 8 бит, каждый бит также имеет уникальное имя, по которому можно получить номер этого бита в байте его регистра. Осталось понять, как этим всем пользоваться.

Запись/чтение регистра

Существует несколько способов установки битов в регистрах. Мы рассмотрим их все, чтобы столкнувшись с одним из них вы знали, что это вообще такое и как работает данная строчка кода. В предыдущем уроке по битовым операциям мы подробно разобрали всё, что касается манипуляций с битами, поэтому если вы его прочитали и поняли – следующая информация не будет для вас новой.

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

TCCR1B = 0b01010101;

Таким образом мы включили и выключили нужные биты сразу, одним махом. Как вы помните из урока о типах данных и чисел, микроконтроллеру всё равно, в какой системе исчисления вы с ним работаете, то есть число 0b01010101 у нас в двоичной системе, в десятичной это будет 85 , а в шестнадцатеричной – 0x55 . И вот эти три варианта абсолютно одинаковы с точки зрения результата:

TCCR1B = 0b01010101; TCCR1B = 85; TCCR1B = 0x55;

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

Гораздо чаще бывает нужно “прицельно” изменить один бит в байте, и тут на помощь приходят логические (битовые) функции и макросы. Рассмотрим все варианты, во всех из них BYTE это байт-регистр, и BIT это номер бита, считая с правого края. То есть BIT это цифра от 0 до 7, либо название бита из даташита.

Установка бита в 1 Установка бита в 0 Описание
BYTE |= (1

BYTE &= ~(1

Битовый сдвиг
BYTE |= (2^BIT); BYTE &= ~(2^BIT); 2 в степени номер бита
BYTE |= bit(BIT); BYTE &= ~bit(BIT); Ардуиновский макрос bit(), заменяющий сдвиг
BYTE |= _BV(BIT); BYTE &= ~_BV(BIT); Встроенная функция _BV(), опять же сдвиг
sbi(BYTE, BIT); cbi(BYTE, BIT); Используем ассемблерные макросы sbi и cbi
bitSet(BYTE, BIT); bitClear(BYTE, BIT); Используем Ардуиновские функции bitSet() и bitClear()

Что хочу сказать по перечисленным вариантам: они все по сути являются одним и тем же, а именно – первым, просто обёрнуты в другие функции и макросы. Время выполнения всех вариантов одинаково, т.к. макро-функции не делают лишних действий, а приводят все способы к первому, со сдвигом и |= и &= . Все эти способы вы можете встретить в скетчах из интернета, это факт. Лично мне больше всего нравится ардуиновский bitSet и bitClear, потому что они имеют читаемое название и заранее сидят в библиотеке.

Что касается sbi() и cbi() – то для их использования где-то должны быть созданы макросы:

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

И после этого можно пользоваться sbi() и cbi() . Давайте рассмотрим пример, где просто подёргаем TCCR1B разными способами:

void setup() < TCCR1B = 0; // обнулили регистр bitSet(TCCR1B, CS11); // включили бит №1 TCCR1B |= _BV(4); // включили бит №4 TCCR1B |= (1 

Можно ещё добавить вариант, где в одной строчке можно “прицельно” установить несколько битов:

void setup() < TCCR1B = 0; // обнулили регистр // ставим бит 1, 3 и 4(WGM13) TCCR1B |= _BV(1) | _BV(3) | _BV(WGM13); >

Я думаю тут всё понятно, давайте теперь попробуем “прицельно” прочитать бит из регистра:

Чтение бита Описание
(BYTE >> BIT) & 1 Вручную через сдвиг
bitRead(BYTE, BIT) Ардуиновская макро-функция

Два рассмотренных способа возвращают 0 или 1 в зависимости от состояния бита. Пример:

void setup() < TCCR1B = 0; // обнулили регистр bitSet(TCCR1B, CS12); // включили бит №2 Serial.begin(9600); // открыли порт Serial.println(bitRead(TCCR1B, 2)); // получили 1 >

Ещё больше примеров работы с битами смотри в уроке по битовым операциям.

16-бит регистры

У Ардуинок (AVR) встречаются также сдвоенные 16-битные регистры, состоят из двух 8-битных, например “сдвоенный регистр” АЦП ADC состоит из ADCH и ADCL , или регистр таймера ICR1 состоит из ICR1H и ICR1L . АЦП у нас 10 битный, но регистры – 8 битные, поэтому часть (8 бит) хранится в одном регистре ( ADCL ), а остальное (2 бита) – в другом ( ADCH ). Смотрите, как это выглядит в виде таблицы:
Вопрос: как нам принять или изменить это самое 10 битное число, если оно разбито на два разных регистра? Очень просто: работа с такими сдвоенными регистрами встроена в компилятор и можно просто работать с ними напрямую как с обычной переменной, например:

int val = ADC; // читаем значение ICR1 = 1234; // записываем значение

Такую запись почему-то используют редко, возможно для совместимости с другими компиляторами. Чаще всего вы встретите вот такой вариант, в котором значения “склеиваются” через сдвиг:

int val = ADCL + (ADCH 

Читать нужно с младшего регистра. Как только мы читаем младший регистр (первый), у МК полностью блокируется доступ к всему регистру, пока не будет прочитан старший. Если прочитать сначала старший – значение младшего может быть утеряно.

Обратная задача: есть опять же мнимый 16-битный регистр (состоящий из двух 8-битных), в который нам нужно записать значение. Например сдвоенный регистр ICR1H и ICR1L , вот таблица:
Микроконтроллер может работать только с одним байтом, а как нам записать двухбайтное число? А вот так: разбить число на два байта при помощи ардуиновских функций highByte() и lowByte() , и уже эти байты записать в соответствующие регистры. Пример:

uint16_t val = 1500; // просто число типа int ICR1H = highByte(val); // пишем старший байт ICR1L = lowByte(val); // пишем младший байт // читаем байты обратно и "склеиваем" в int byte val_1 = ICR1L; byte val_2 = ICR1H; uint16_t value = val_1 + (val_2 

Записывать нужно со старшего байта. Как только мы записываем младший байт (последний) – МК “защелкивает” оба регистра в память, соответственно если сначала записать младший – в старшем будет 0, и последующая запись старшего будет проигнорирована.

ВАЖНО: запись в 16 бит регистры производится начиная со СТАРШЕГО байта, чтение – с МЛАДШЕГО

Полезные страницы

  • Набор GyverKIT – большой стартовый набор Arduino моей разработки, продаётся в России
  • Каталог ссылок на дешёвые Ардуины, датчики, модули и прочие железки с AliExpress у проверенных продавцов
  • Подборка библиотек для Arduino, самых интересных и полезных, официальных и не очень
  • Полная документация по языку Ардуино, все встроенные функции и макросы, все доступные типы данных
  • Сборник полезных алгоритмов для написания скетчей: структура кода, таймеры, фильтры, парсинг данных
  • Видео уроки по программированию Arduino с канала “Заметки Ардуинщика” – одни из самых подробных в рунете
  • Поддержать автора за работу над уроками
  • Обратная связь – сообщить об ошибке в уроке или предложить дополнение по тексту ([email protected])

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *