Перейти к содержанию

Код Грея: калькулятор и таблица

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

Исходные данные

Направление

от 0 до 15

Результат

Код Грея
0101
5 = 0x5
Вычисление g = b ⊕ (b >> 1)
0110 ⊕ 0011 = 0101
Следующая позиция
01007, меняется бит 0
Предыдущая позиция
01115, меняется бит 1

Кодовый диск

Кольцо на бит: старший внутри, младший снаружи; закрашено — 1. Соседние секторы отличаются одним кольцом.

6

Таблица 4-битного кода

Выделен бит, который изменился по сравнению с предыдущей строкой. Щёлкните по номеру, чтобы выбрать позицию.

ПозицияДвоичныйКод ГреяМеняется
00000000—
00010001бит 0
00100011бит 1
00110010бит 0
01000110бит 2
01010111бит 0
01100101бит 1
01110100бит 0
10001100бит 3
10011101бит 0
10101111бит 1
10111110бит 0
11001010бит 2
11011011бит 0
11101001бит 1
11111000бит 0

Код на C

Обратный перевод 4-битного кода — сдвиги на 2, 1: каждый удваивает число уже сложенных по XOR разрядов.

#include <stdint.h>

/* 4-bit reflected binary (Gray) code in the low bits of uint8_t */
static inline uint8_t bin_to_gray(uint8_t b)
{
    return (uint8_t)(b ^ (b >> 1));
}

static inline uint8_t gray_to_bin(uint8_t g)
{
    g ^= g >> 2;
    g ^= g >> 1;
    return g;
}

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

Код Грея (отражённый двоичный код) — способ записи чисел, при котором два соседних числа отличаются ровно одним разрядом. Его запатентовал инженер Bell Labs Фрэнк Грей: заявка подана в 1947 году, патент US 2 632 058 выдан в 1953-м. Сегодня код Грея стоит на дисках абсолютных энкодеров и в указателях асинхронных FIFO.

Как пользоваться

  1. Выберите разрядность кода — от 1 до 32 бит — и запись числа: двоичную, десятичную или шестнадцатеричную.
  2. Выберите направление: двоичный → Грей, если известно число (номер положения), или Грей → двоичный, если известен прочитанный код.
  3. Введите число. При переключении направления результат переносится в поле ввода — так удобно проверять перевод в обе стороны.

Калькулятор показывает результат в двоичном, десятичном и шестнадцатеричном виде, вычисление через XOR, коды соседних позиций и номер бита, который при переходе к ним меняется. Для кода до 8 бит рисуется кодовый диск, до 6 бит — полная таблица; при большей разрядности — 8 позиций до и после выбранной.

Формулы перевода

Пусть bn−1…b1b0 — разряды двоичного числа, gn−1…g0 — разряды кода Грея, разряд 0 младший. Прямой перевод — XOR соседних разрядов:

gn−1=bn−1,gk=bk+1⊕bk⟺g=b⊕(b≫1).g_{n-1} = b_{n-1}, \qquad g_k = b_{k+1} \oplus b_k \quad\Longleftrightarrow\quad g = b \oplus (b \gg 1).

Обратный перевод идёт от старшего разряда: каждый двоичный разряд — XOR всех разрядов кода от старшего до него самого:

bn−1=gn−1,bk=bk+1⊕gk=gn−1⊕gn−2⊕…⊕gk.b_{n-1} = g_{n-1}, \qquad b_k = b_{k+1} \oplus g_k = g_{n-1} \oplus g_{n-2} \oplus \ldots \oplus g_k.

Обе формулы — это формулы (1) и (2) из патента Грея, записанные через XOR вместо сложения по модулю 2. Поразрядный обратный перевод требует n − 1 шагов, но его можно ускорить: после g ^= g >> 1 каждый разряд содержит XOR двух соседних, после g ^= g >> 2 — четырёх, и так далее. Поэтому для 32-битного кода хватает пяти сдвигов, для 8-битного — трёх.

Таблица кода Грея на 4 бита

ЧислоДвоичныйГрейЧислоДвоичныйГрей
000000000810001100
100010001910011101
2001000111010101111
3001100101110111110
4010001101211001010
5010101111311011011
6011001011411101001
7011101001511111000

Видно, откуда название «отражённый»: младшие три разряда второй половины таблицы повторяют первую половину в обратном порядке, а старший разряд становится единицей. Так Грей и строил код — из одноразрядного двухразрядный, из него трёхразрядный и далее. Переход от 15 к 0 тоже меняет один разряд — старший, поэтому код замкнут в кольцо.

Где применяется

Абсолютные энкодеры

Абсолютный энкодер выдаёт код угла сразу, без подсчёта импульсов, и помнит положение после выключения питания. Каждый разряд кода снимается с отдельной дорожки диска. Если бы дорожки несли обычный двоичный код, на границе секторов 7 и 8 одновременно переключались бы четыре контакта, а из-за разброса их срабатывания энкодер на мгновение выдавал бы случайные значения — например, 15 или 0. С кодом Грея на каждой границе переключается одна дорожка.

Пример — механический энкодер TT Electronics EN16AB на 16 положений. В даташите приведены состояния четырёх выводов для трёх вариантов: положения в нём пронумерованы с 1, и в варианте 0 выводы 1–4 дают четырёхразрядный код Грея числа «номер положения − 1»: положение 1 — 0000, положение 16 — 1000 (вывод 1 — младший разряд). В варианте 1 — тот же код с обратным порядком выводов, в варианте 2 — обычный двоичный код того же числа. Функция gray_to_bin() вернёт число от 0 до 15; чтобы получить номер по даташиту, прибавьте 1.

Не все абсолютные энкодеры используют именно отражённый двоичный код. Bourns ACE-128 размещает 128 положений на одной кодовой дорожке: соседние состояния у него тоже различаются одним битом, но это другой код, и номер положения получают по таблице на 256 байт из даташита. Как устроены энкодеры, их сигналы и подключение, разобрано в статье «Энкодеры».

Указатели асинхронного FIFO

В FIFO между двумя тактовыми доменами указатель записи нужно передать в домен чтения, а указатель чтения — в домен записи. Многоразрядный двоичный счётчик для этого не годится: если синхронизатор защёлкнет его как раз во время перехода 0111 → 1000, получится произвольное число. Клиффорд Каммингс в статье для SNUG 2002 разбирает решение, ставшее стандартным: счётчик считает в двоичном коде, а в регистр указателя пишется (bin >> 1) ^ bin, который за такт меняет один бит.

У указателей на один бит больше, чем нужно для адреса памяти. FIFO пуст, когда указатели в коде Грея совпадают полностью. FIFO полон, когда у них различаются два старших бита, а остальные совпадают: из-за отражения код позиции k + 2ⁿ⁻¹ отличается от кода позиции k именно двумя старшими разрядами. Калькулятор это наглядно показывает: в таблице 4-битного кода строки 0 и 8, 1 и 9 и так далее отличаются только двумя старшими разрядами.

Код на C

Функции для кода до 32 бит, лежащего в младших разрядах слова:

#include <stdint.h>

static inline uint32_t bin_to_gray(uint32_t b)
{
    return b ^ (b >> 1);
}

static inline uint32_t gray_to_bin(uint32_t g)
{
    g ^= g >> 16;
    g ^= g >> 8;
    g ^= g >> 4;
    g ^= g >> 2;
    g ^= g >> 1;
    return g;
}

Калькулятор выдаёт эти функции под выбранную разрядность: для 8-битного кода — с типом uint8_t и тремя сдвигами. Для энкодера на выводах порта сначала соберите биты в число в правильном порядке (у EN16AB варианта 0 вывод 1 — младший), затем вызовите gray_to_bin() и, если положения в даташите нумеруются с 1, прибавьте единицу. Сами операции XOR и сдвиги разобраны в статье «Битовые операции в C».

Ограничения и типичные ошибки

  • Порядок разрядов. Перепутанные выводы энкодера дают не код Грея, а перестановку его разрядов, и переход между соседними положениями уже может менять несколько бит. Сверяйте порядок выводов с таблицей в даташите.
  • Арифметика. Коды Грея нельзя складывать и сравнивать как числа: код позиции 7 — 0100 — как число меньше кода позиции 6 — 0101. Для счёта, сравнения и вычисления разности положений переведите код в двоичный — в FIFO так и делают: счётчик двоичный, в код Грея переводится только передаваемое значение.
  • Длина цикла. Отражённый код замыкается в кольцо только при числе позиций 2ⁿ. Если сбросить счётчик Грея раньше — например, после 9 для десяти позиций, — переход 9 → 0 изменит больше одного разряда.
  • Код Грея не исправляет ошибки. Он гарантирует только, что при правильном переходе меняется один бит; искажённый разряд он не обнаружит. Для защиты данных служат контрольные биты — например, код Хэмминга.

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

Частые вопросы

Как перевести двоичное число в код Грея?

Сложить число по модулю 2 (XOR) с ним же, сдвинутым вправо на один разряд: g = b ⊕ (b >> 1). Старший разряд кода Грея равен старшему разряду числа, каждый следующий — XOR соседних разрядов числа. Например, 6 = 0110: 0110 ⊕ 0011 = 0101. Пример из патента Грея: 38 = 0100110₂ в семиразрядном коде Грея записывается как 0110101.

Как перевести код Грея обратно в двоичный?

Старший двоичный разряд равен старшему разряду кода, а каждый следующий двоичный разряд — XOR предыдущего двоичного разряда и очередного разряда кода. Иначе говоря, разряд номер k — XOR всех разрядов кода от старшего до k-го. В программе это несколько сдвигов: g ^= g >> 16; g ^= g >> 8; g ^= g >> 4; g ^= g >> 2; g ^= g >> 1 для 32 бит, для более коротких слов хватает меньшего числа сдвигов.

Зачем абсолютным энкодерам код Грея?

Контакты или оптические датчики разных дорожек переключаются не строго одновременно. В двоичном коде при переходе 0111 → 1000 меняются все четыре разряда, и в момент перехода можно прочитать любое из 16 значений. В коде Грея соседние положения отличаются одним разрядом, поэтому на границе читается либо старое, либо новое положение. Например, у абсолютного энкодера TT Electronics EN16AB на 16 положений вариант 0 выдаёт четырёхразрядный код Грея числа «номер положения − 1» (положения в даташите нумеруются с 1).

Почему в асинхронном FIFO указатели передают в коде Грея?

Указатель записи читается в домене другой тактовой частоты через синхронизатор из двух триггеров. Если при этом меняются сразу несколько бит двоичного счётчика, синхронизатор может защёлкнуть часть старых и часть новых бит и получить значение, которого никогда не было. Указатель в коде Грея за такт меняет один бит, поэтому после синхронизации получается либо старое, либо новое значение — так устроен FIFO в статье К. Каммингса (SNUG 2002).

Бывает ли код Грея на 10 или 12 положений?

Отражённый двоичный код из этого калькулятора замыкается в кольцо только при числе положений, равном степени двойки: 2, 4, 8, 16 и так далее. Каммингс отмечает, что последовательности нечётной длины с изменением одного бита не бывает, а счётчики Грея на чётное число шагов, не равное степени двойки, сделать можно, но перевод для них уже не так прост. Энкодеры на другое число положений используют собственные таблицы: у EN16AB на 12 положений своя таблица выходов, а Bourns ACE-128 выдаёт 8-битный код на 128 положений, который переводят в номер положения по таблице на 256 байт.

Источники

  1. Gray F. Pulse Code Communication. US Patent 2,632,058, подан 13.11.1947, выдан 17.03.1953 — с. 6 PDF — определение: соседние числа отличаются одной позицией, название «reflected binary code»; с. 7 — построение отражением, трёхразрядная таблица и пример: 38 = 0110101; с. 8 — формулы (1) и (2) перевода между кодами по модулю 2 — эталоны тестов
  2. Cummings C. E. Simulation and Synthesis Techniques for Asynchronous FIFO Design. SNUG San Jose 2002, Rev 1.2 — разд. 2.3 и 3.2 — указатели FIFO в коде Грея меняют один бит за такт; 3.3 — (n − 1)-битный код из n-битного; 5.1 и 5.2 — условия «пусто» и «полно» на указателях с лишним старшим битом; примеры 6 и 7 — (bin >> 1) ^ bin
  3. TT Electronics / BI Technologies. EN16AB Series 16 mm Absolute Encoder, Rev A 02/2022 — с. 6, «Output Signal Format» — состояния выводов 1–4 по 16 позициям: вариант 0 — четырёхразрядный код Грея, вариант 1 — он же с обратным порядком выводов, вариант 2 — обычный двоичный (эталоны тестов)
  4. Bourns. EAW — Absolute Contacting Encoder (ACE), K2540 05/26R — с. 1–2 — 128 положений одной кодовой дорожкой, выход — 8-битный код, для перевода в номер положения нужна таблица на 256 байт

Где пригодится

Встроить калькулятор на свой сайт

Скопируйте код и вставьте его в HTML страницы, статьи или вики. Виджет бесплатный, без рекламы, счётчиков и cookie. Условие одно — ссылка на GAW под рамкой остаётся на месте. Подробнее о виджетах

<iframe src="https://gaw.ru/embed/gray-code/" title="Код Грея: калькулятор и таблица" width="100%" height="640" style="border:1px solid #e3e5e9;border-radius:8px" loading="lazy" allow="clipboard-write"></iframe>
<p style="margin:6px 0 0;font-size:14px">Калькулятор: <a href="https://gaw.ru/tools/gray-code/">Код Грея: калькулятор и таблица</a> — GAW.ru</p>
Автоподстройка высоты рамки

Если сайт разрешает скрипты, добавьте этот код один раз в любом месте страницы: рамка будет менять высоту вместе с результатом расчёта.

<script>window.addEventListener("message",function(e){if(e.origin!=="https://gaw.ru"||!e.data||e.data.type!=="gaw:embed-height")return;var f=document.querySelectorAll('iframe[src^="https://gaw.ru/embed/"]');for(var i=0;i<f.length;i++)if(f[i].contentWindow===e.source)f[i].style.height=e.data.height+"px"})</script>

Обновлено .

Нашли ошибку в расчёте?