Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

README.md

2026-01-02

Youtube-запись от 2026-01-02: https://youtu.be/lzsZ56mmu54

Сдвиговый регистр

Конкретные железки: 74HC595 (золотой стандарт, дальше всё про него) — 74HCT595 — 74HC164 (без LATCH) — 74HC165 — TPIC6B595 / TPIC6C595 (высоковольтные) — MAX7219 / MAX7221 (скорее драйвер светодиодной матрицы) — MCP23S17 (фактически уже GPIO-микроконтроллер)


Что такое сдвиговый регистр? Это микросхема. Она раскидывает сигналы из одного входа на разные выходы.

Принимает один за другим сигналы с одного своего входящего пина — и одновременно выставляет значение этой последовательности на всех своих исходящих пинах.

flowchart LR

subgraph Отправитель
pin_out{{DATA}}:::red
end

one((1)):::white
two((2)):::white
three((3)):::white
four((4)):::white

subgraph Регистр
in{{•}}:::black
one_{{1}}:::yellow
two_{{2}}:::yellow
three_{{3}}:::yellow
four_{{4}}:::yellow
end

subgraph Получатель
one__{{A}}:::green
two__{{B}}:::green
three__{{C}}:::green
four__{{D}}:::green
end

pin_out --> four
four -.-> three -.-> two -.-> one --> in
in --> one_
in --> two_
in --> three_
in --> four_

one_ ==> one__
two_ ==> two__
three_ ==> three__
four_ ==> four__

classDef red fill:#D65D0E,stroke:#D65D0E,color:#F6F0D8;
classDef green fill:#9A9A00,stroke:#9A9A00,color:#F6F0D8;
classDef yellow fill:#CC9105,stroke:#CC9105,color:#F6F0D8;
classDef black fill:#272727,stroke:#272727,color:#FBFAF3;
classDef white fill:#FBFAF3,stroke:#F6F0D8,color:#272727;


Loading

Если коротко, это такая «анти-шина1»: на вход сигналы поступают по одному проводу, а на выходе уходят уже по нескольким. Или, если угодно, «анти-[[UART]]»: был провод — стала шина.

Зачем нужно такое устройство? Чтобы экономить пины отправителя. Ведь так один пин (DATA) может отправлять данные на несколько устройств. И, значит, управлять ими.

Один?! Нет, конечно. Ещё нужны как минимум два служебных пина: «Считай очередной бит» (CLOCK) и «Всё, набор готов, отправляй» (LATCH).

Caution

LATCH есть не на всех сдвиговых регистрах Есть модели попроще, и там «защёлки» вообще нет. Это то же самое, что нет внутреннего регистра, только внешний. Используются редко.

flowchart LR

subgraph Отправитель
pin_data{{DATA}}:::red
pin_clock{{CLOCK}}:::red
pin_latch{{LAUCH}}:::red
end

subgraph Регистр
data{{SER}}:::red
clock{{SRCLK}}:::red
latch{{RCLK}}:::red
end


pin_data ==>|вот тебе бит| data
pin_clock --> |забирай его| clock
pin_latch -.-> |отправляй пачку| latch

classDef red fill:#D65D0E,stroke:#D65D0E,color:#F6F0D8;


Loading

Warning

В документации по регистрам нет названий DATA, CLOCK и LATCH. Там — SER, SRCLK и RCLK соответственно.

Тогда использование сдвигового регистра выглядит так.

  1. Решаем, какие 0 и 1 должны быть выставлены на пинах устройств-получателей.
  2. Собираем из этих 0 и 1 последовательность, которую регистр должен разложить по своим пинам выхода. Длина последовательности == количество пинов выхода регистра (иначе в каких-то пинах будет мусор, а нам такое не нужно). Где-то всегда будет одно и то же значение — например, ноль.
  3. Отправляем первый бит последовательности в свой регистр DATA.
  4. И как выставили один — поднимаем2 CLOCK — мол, забирай значение бита в DATA. Как только регистр видит подъём CLOCK — он забирает DATA. Это называется «срабатывать по фронту3».
  5. Потом сбрасываем CLOCK — всё, не забирай, жди новое значение. Точнее, жди появления нового фронта, чтобы сработать.
  6. П. 3 и следующие — для следующих бит последовательности. Проходим полный цикл по последовательности.
  7. Когда вся последовательность отправлена в регистр — поднимаем LAUCH. И снова срабатывание по фронту. Так регистр отправит последовательность дальше. Сразу всю. Не по очереди.
  8. Потом не забываем сбросить LAUCH — чтобы позже можно было снова его поднять для «срабатывания по фронту».
  9. И всё по новой.

Tip

Выглядит длинным и непонятным На самом деле просто: «Забирай, забирай, забирай… Отправляй!».

Как часто запускать такой цикл? Зависит от того, как часто мы хотим обновлять значения пинов на принимающих устройствах. Конечно, это будет медленней, чем можно было бы сделать, используя связку «Один пин выхода — один пин входа». Но если скорости не так уж важны — схема работает.

Так мы можем на отправляющем устройстве использовать 3 пина вместо, например, 8 (если в регистре восемь исходящих пинов). Экономия!

Для упрощения работы есть ещё два входящих пина регистра.

  1. «Ничего не отправляй на выход» (OE, output enable). Заставляет регистр игнорировать LAUCH. По умолчанию равен нулю — то есть ничего не блокируется, данные проходят.
  2. «Очисти регистр» (MR, master reset). Пин обнуляется — весь регистр обнуляется. В стандартных сборках всегда устанавливают4 в 1 — то есть ничего никогда не обнуляется.

И для сложных ситуацией с выстраиванием цепочки регистров есть пин QH' (QH-prime). Он содержит предыдущее значение старшего регистра. То есть это как бы «регистр переполнения» Если подключить его как DATA к следующему регистру, а команды фиксации отдавать синхронно — очевидно, получим шину шире. Но это уже реально следующий уровень, не сейчас.

Как подключаться? Вот стандартная распиновка стандартной микросхемы сдвигового регистра [[74HC595]]:

flowchart LR

OUT_B{{выход B}}:::green
OUT_C{{выход C}}:::green
OUT_D{{выход D}}:::green
OUT_E{{выход E}}:::green
OUT_F{{выход F}}:::green
OUT_G{{выход G}}:::green
OUT_H{{выход H}}:::green
GND{{земля}}:::blue

subgraph 74HC595
subgraph left
1{{QB}}:::green
2{{QC}}:::green
3{{QD}}:::green
4{{QE}}:::green
5{{QF}}:::green
6{{QG}}:::green
7{{QH}}:::green
8{{GND}}:::blue
end
subgraph right
1_16{{16 • VCC}}:::blue
2_15{{15 • QA}}:::green
3_14{{14 • SER}}:::red
4_13{{13 • OE}}:::blue
5_12{{12 • RCLK}}:::red
6_11{{11 • SRCLK}}:::red
7_10{{10 • SRCLR}}:::blue
8_9{{9 • QH'}}:::green
end

left ~~~ right
end

5V{{+5V}}:::blue
OUT_A{{выход A}}:::green
DATA{{DATA}}:::red
CLOCK{{CLOCK}}:::red
OE{{OE}}:::blue
LATCH{{LATCH}}:::red
MR{{MR}}:::blue
SER2{{SER 2 == DATA 2}}:::green

OUT_B <==> 1
OUT_C <==> 2
OUT_D <==> 3
OUT_E <==> 4
OUT_F <==> 5
OUT_G <==> 6
OUT_H <==> 7
GND <--> |0| 8

1_16 <--> 5V
2_15 <==> OUT_A
3_14 <-.-> DATA
4_13 <--> |0| OE
5_12 <-.-> LATCH
6_11 <-.-> CLOCK
7_10 <--> |5V| MR
8_9 <==> SER2

classDef red fill:#D65D0E,stroke:#D65D0E,color:#F6F0D8;
classDef green fill:#9A9A00,stroke:#9A9A00,color:#F6F0D8;
classDef yellow fill:#CC9105,stroke:#CC9105,color:#F6F0D8;
classDef blue fill:#0077BB,stroke:#0077BB,color:#F6F0D8;
classDef black fill:#272727,stroke:#272727,color:#FBFAF3;
classDef white fill:#FBFAF3,stroke:#F6F0D8,color:#272727;


Loading

Как видно, у нас 8 «нормальных» исходящих пинов и один для того, чтобы сделать регистр подлинней. Ну или его ещё как-то можно использовать, но это уже вопрос фантазии.

Главное, что происходит в регистре — это сдвиг. Вот как он устроен.

flowchart TB

SER{{SER}}:::red
subgraph prev
QA{{QA}}:::white
QB{{QB}}:::white
QC{{QC}}:::white
QD{{QD}}:::white
QE{{QE}}:::white
QF{{QF}}:::white
QG{{QG}}:::white
QH{{QH}}:::white
QHprime{{QH'}}:::white
end

subgraph next
QA_{{QA}}:::white
QB_{{QB}}:::white
QC_{{QC}}:::white
QD_{{QD}}:::white
QE_{{QE}}:::white
QF_{{QF}}:::white
QG_{{QG}}:::white
QH_{{QG}}:::white
QHprime_{{QH'}}:::white
end

NULL{{/dev/null}}:::black

SER ==> QA_
QA --> QB_
QB --> QC_
QC --> QD_
QD --> QE_
QE --> QF_
QF --> QG_
QG --> QH_
QH ==> QHprime_
QHprime ==> NULL

classDef red fill:#D65D0E,stroke:#D65D0E,color:#F6F0D8;
classDef white fill:#FBFAF3,stroke:#F6F0D8,color:#272727;
classDef black fill:#272727,stroke:#272727,color:#FBFAF3;

Loading

Из схемы сдвига очевидно, что отправлять последовательность бит нужно, начиная с того бита, который в итоге должен попасть в QH (или в QH' и дальше, если у нас цепочка регистров). А заканчивать — тем, который должен в итоге попасть в QA). То есть «чем дальше идти, тем раньше выходим».

Важно: сначала сдвигается так называемый «внутренний регистр». То есть то, что мы не видим. На выходах микросхемы ничего не меняется до особого распоряжения — команды LATCH. Если команды не было — сколько угодно двигай внутренний регистр, снаружи не поменяется ничего.

Кое-что про электричество

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

Caution

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

Caution

Для управления светодиодами — своё семейство И там свои особенности и возможности.

Подключать к выходам сдвигового регистра напрямую можно только слаботочные устройства. Ток одного выхода должен быть меньше 5 мА, при том что суммарный ток по всем выходам тоже ограничен — обычно не больше 20 мА.

Если этого мало — включать через транзистор. Так сигнал становится чисто логическим, а не силовым — для того транзисторы и нужны.

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

Где часто применяют?

  1. Управление шаговыми двигателями. Например, для биполярного шагового двигателя нужны четыре логических сигнала — чтобы менять в определённой последовательности напряжения на четырёх контактах обмотки. Если вот это вот «менять в определённой последовательности» не удастся организовать — мотор не закрутится. Но тратить на логику мотора четыре пина — слишком расточительно: ведь обычно мотор нужен не один. Используют 8-битовый сдвиговый регистр — и через него управляют сразу двумя моторами (каждому достаётся по 4 бита, как раз хватит на 4 логических сигнала). Сигналы потом уходят в драйвер мотора, но это совсем другая история.
  2. Крохотные микроконтроллеры. Например, ATtiny. У них очень мало пинов. А вычислительной дури много. Почему бы не подключить малютку к большому количеству устройств вывода — зуммеры, светодиоды, моторы и т. п. — через сдвиговый регистр?

Задачи для первого знакомства

Скорее всего, лучше собрать какой-то демо-стенд — и уже дальше его программировать.

  1. Модуль на C для управления регистром.
  2. Какой-нибудь эксперимент для сравнения регистров с/без LATCH.
  3. Железка для лабы: сдвоенный регистр + два цвета светодиодов + кнопка. Случайные числа (одно по факту, два видны из-за двух цветов). Задача — либо кто быстрей назовёт числа, либо кто быстрей сложит. Вариант для одного регистра — умножение. Кнопка перезапускает игру.
  4. Бегущий огонёк.
  5. Бросаем кубик (вывод регистра в момент нажатия кнопки, а так он там фоном пусть ползёт-сдвигается сколько угодно).
  6. Демо-стенд «Число и его двоичное представление» (нужен экран?).
  7. Тренажёр чтения двоичных чисел.
  8. Порядок зажжения ханукальных свечей (следующий день по кнопке).
  9. Запуск шагового двигателя.
  10. Сдвоенный регистр.
  11. Наглядное умножение двоичного числа на -1.
  12. Бегущая строка (нужны доп. железки?).

Footnotes

  1. Так обычно называют несколько параллельных проводов. Ожидается, что имеет смысл сигнал, принятый со всех проводов одновременно. То есть, например, 8 проводов передадут нам аж целый байт сразу. И работают все провода сразу — то есть отдельный провод шины ценности не представляет. Да даже и механизма «Передай значение по одному проводу, а остальные не трогай» часто не существует.

  2. «Поднимать» пин — это значит поднимать напряжение на нём. То есть в случае с микроконтроллером — отправлять туда значение 1.

  3. Термин из электричества. Суть простая: график сигнала на осциллографе «поднимается» от 0 к 1 — это и есть фронт. Схема срабатывает, когда обнаруживает такой подъём.

  4. Устанавливают без логики, просто подачей питания +5 вольт (или какое на конкретной схеме питание считается за логическую единицу). Если сами собираете схему, а не используете готовую плату — не забудьте подать сюда +5 вольт. Иначе ничего не заработает вообще.