Как работает сдвиговый регистр 74HC595 и подключение к Arduino

Как работает сдвиговый регистр 74HC595 и подключение к Arduino

Одна из замечательных особенностей Arduino — это достаточное количество выводов ввода/вывода для ваших проектов. Вы можете подключать к ним различные компоненты: кнопки, датчики и двигатели. Однако по мере усложнения вашего проекта вы быстро обнаружите, что выводов не хватает.

Представьте, что вы создаёте проект, в котором нужно управлять 16 отдельными светодиодами. Обычно для этого потребовалось бы 16 отдельных выводов на Arduino. Проблема в том, что у большинства плат Arduino нет такого количества доступных выводов.

К счастью, есть хитрое решение этой проблемы! Вы можете использовать так называемый сдвиговый регистр, который позволяет добавить больше выводов ввода/вывода к вашему Arduino (или любому микроконтроллеру). Самый популярный и широко используемый сдвиговый регистр — 74HC595, часто называемый просто «595».

Что делает 74HC595 таким полезным — он может управлять восемью различными выходными выводами, используя при этом всего три входных вывода от Arduino. Ещё более впечатляет то, что если вам нужно более 8 дополнительных выводов, вы можете соединить несколько сдвиговых регистров в так называемую «гирляндную цепочку». Это позволяет создать столько выводов ввода/вывода, сколько вам нужно.

Для нашего примера с 16 светодиодами вы могли бы соединить два сдвиговых регистра последовательно и управлять всеми 16 светодиодами, используя всего три вывода Arduino. Это огромная экономия ресурсов!

Но как 74HC595 справляется с этим? Он использует технику, называемую «битовый сдвиг». Давайте узнаем больше о том, как это работает!

SIPO и PISO сдвиговые регистры

Существует два типа сдвиговых регистров: SIPO (вход последовательный — выход параллельный) и PISO (вход параллельный — выход последовательный).

Сдвиговые регистры SIPO отлично подходят для управления большим количеством выходов, таких как светодиоды, а регистры PISO идеальны для сбора большого количества входов, таких как кнопки.

Самая популярная микросхема SIPO — 74HC595, а для PISO — 74HC165.

Как работает сдвиговый регистр 74HC595?

Внутри микросхема 74HC595 содержит два 8-битных регистра:

  1. Сдвиговый регистр — задача этого регистра — принимать входные данные по одному биту за раз (последовательно).

  2. Регистр хранения — этот регистр хранит данные, а затем отправляет их все сразу (параллельно) на выходные выводы.

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

Каждый раз при подаче импульса на SRCLK все биты внутри сдвигаются на одну позицию вперёд, позволяя новому биту войти. После 8 импульсов все 8 бит будут загружены в сдвиговый регистр.

Но вот важный момент — хотя данные уже находятся внутри сдвигового регистра, они не появляются немедленно на выходных выводах. Это потому, что сдвиговый регистр и регистр хранения намеренно разделены. Это разделение позволяет загружать новые данные без немедленного изменения выходов.

Когда вы готовы обновить выходы, вы подаёте импульс на RCLK (тактовый вход регистра хранения, или вывод защёлки). Это копирует все данные из сдвигового регистра в регистр хранения, который затем обновляет все выходные выводы (обозначенные QA–QH) одновременно. Это одновременное обновление гарантирует стабильность выходов при загрузке новых данных.

Анимация ниже поможет вам лучше понять это.

Как работает сдвиговый регистр 74HC595 и подключение к Arduino

Микросхема также имеет вывод OE (Output Enable — разрешение выхода), который действует как выключатель для всех выходов. Этот вывод имеет «активный низкий» уровень, что означает: когда вы подключаете его к земле (устанавливаете «низкий» уровень), выходы показывают содержимое регистра хранения. Если вы установите этот вывод в «высокий» уровень, все выходы отключаются, независимо от содержимого регистров.

Наконец, есть вывод SRCLR (сброс сдвигового регистра), который позволяет сбросить сдвиговый регистр. При активации он устанавливает все хранящиеся биты в 0, фактически стирая все данные.

Распиновка сдвигового регистра 74HC595

Прежде чем перейти к деталям, важно знать, что микросхема 74HC595 производится несколькими компаниями. В этом руководстве мы сосредоточимся на SN74HC595N от Texas Instruments, которая является одной из самых распространённых версий. Если у вас другая версия, вам следует проверить её техническое описание на предмет отличий.

Теперь давайте рассмотрим, что делает каждый вывод этой микросхемы:

Как работает сдвиговый регистр 74HC595 и подключение к Arduino

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

VCC обеспечивает питание 74HC595 и должен быть подключён к 5V.

SER (вход последовательных данных) — сюда вы посылаете данные (биты) в сдвиговый регистр, по одному биту за раз. Данные начинаются с младшего значащего бита (LSB) и продвигаются с каждым тактовым импульсом.

SRCLK (тактовый вход сдвигового регистра) управляет перемещением данных в сдвиговый регистр. Он срабатывает по переднему фронту, что означает сдвиг данных при переходе тактового сигнала из LOW в HIGH.

RCLK (тактовый вход регистра хранения / вывод защёлки) управляет моментом передачи данных из сдвигового регистра в регистр хранения. Когда сигнал на этом выводе переходит из LOW в HIGH, данные сдвигового регистра копируются в регистр хранения и появляются на выходных выводах (QA–QH).

SRCLR (сброс сдвигового регистра) используется для сброса сдвигового регистра, обнуляя все биты. Этот вывод имеет активный низкий уровень, то есть для выполнения сброса его нужно подключить к земле (установить LOW). Для нормальной работы его следует держать в состоянии HIGH (подключённым к питанию).

OE (разрешение выхода) действует как переключатель вкл/выкл для всех выходов. Этот вывод также имеет активный низкий уровень, то есть когда вы подключаете его к земле (устанавливаете LOW), выходы (QA–QH) показывают содержимое регистра хранения. Если вы установите этот вывод в HIGH, все выходы отключаются, независимо от содержимого регистров.

QA–QH (параллельные выходы) — это восемь выходных выводов, к которым можно подключить светодиоды, двигатели или другие устройства.

QH“ (последовательный выход) выводит старший значащий бит (MSB) сдвигового регистра. Он в основном используется для соединения нескольких микросхем 74HC595 вместе. Если вы подключите QH“ одной микросхемы к выводу SER другой и используете общие тактовые сигналы, две микросхемы будут работать вместе как единое целое с 16 выходами. Вы можете продолжать подключать больше микросхем таким образом для получения ещё большего количества выходов!

Схема подключения сдвигового регистра 74HC595 к Arduino

Теперь, когда мы понимаем, как работает 74HC595, давайте подключим его к Arduino и начнём использовать!

Шаг 1: Размещение сдвигового регистра на макетной плате

  • Начните с размещения микросхемы 74HC595 на макетной плате. Убедитесь, что каждая сторона микросхемы находится на разных сторонах центрального разделителя макетной платы.

  • Для определения вывода 1 найдите маленькую U-образную выемку в верхней части микросхемы. Вывод 1 расположен слева от этой выемки.

Шаг 2: Подключение питания и земли

Теперь давайте подадим питание на сдвиговый регистр:

  • Подключите вывод 16 (VCC) и вывод 10 (SRCLR) к выходу 5V Arduino.

  • Подключите вывод 8 (GND) и вывод 13 (OE) к земле (GND).

Эти подключения обеспечат работу сдвигового регистра в нормальном режиме.

Шаг 3: Подключение управляющих выводов

Arduino будет управлять 74HC595 с помощью трёх выводов:

  • Подключите вывод 11 (SRCLK) сдвигового регистра к выводу 6 Arduino.

  • Подключите вывод 12 (RCLK) к выводу 5 Arduino.

  • Подключите вывод 14 (SER) к выводу 4 Arduino.

Шаг 4: Подключение светодиодов

Теперь давайте подключим светодиоды:

  • Подключите катод (короткая ножка) каждого светодиода к общей земле.

  • Подключите анод (длинная ножка) каждого светодиода к одному из выходных выводов сдвигового регистра (QA–QH).

  • Добавьте резистор 220 Ом последовательно с каждым светодиодом, чтобы предотвратить их перегорание.

Убедитесь, что QA подключён к первому светодиоду, а QH — к последнему; иначе светодиоды не будут загораться в правильном порядке!

Шаг 5: Краткая справка

Следующая схема поможет вам правильно всё подключить:

Как работает сдвиговый регистр 74HC595 и подключение к Arduino

Пример кода Arduino

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

Сначала загрузите код на Arduino и понаблюдайте, как загораются светодиоды. Затем мы разберём, как это работает.

int latchPin = 5;  // Latch pin of 74HC595 is connected to Digital pin 5
int clockPin = 6;  // Clock pin of 74HC595 is connected to Digital pin 6
int dataPin = 4;   // Data pin of 74HC595 is connected to Digital pin 4

byte leds = 0;  // Variable to hold the pattern of which LEDs are currently turned on or off

void setup() {
  // Set all the pins of 74HC595 as OUTPUT
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
}

void loop() {
  leds = 0;  // Initially turns all the LEDs off, by giving the variable 'leds' the value 0
  updateShiftRegister();
  delay(500);
  for (int i = 0; i < 8; i++)  // Turn all the LEDs ON one by one.
  {
    bitSet(leds, i);  // Set the bit that controls that LED in the variable 'leds'
    updateShiftRegister();
    delay(500);
  }
}

/*
 This function sets the latchPin to low, then calls the Arduino function 'shiftOut' to shift out contents of variable 'leds' in the shift register before putting the 'latchPin' high again.
 */
void updateShiftRegister() {
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, LSBFIRST, leds);
  digitalWrite(latchPin, HIGH);
}

После загрузки кода на Arduino вы должны увидеть следующий результат:

Как работает сдвиговый регистр 74HC595 и подключение к Arduino

Объяснение кода

В начале мы определяем три управляющих вывода — защёлки, тактирования и данных, — которые соединяют сдвиговый регистр 74HC595 с Arduino. Они назначены на цифровые выводы 5, 6 и 4 Arduino.

int latchPin = 5;
int clockPin = 6;
int dataPin = 4;

Далее мы создаём переменную leds, которая будет хранить состояние включения/выключения светодиодов. Поскольку тип данных byte состоит из 8 бит, он идеально подходит для хранения состояний 8 светодиодов, которыми мы управляем.

// Variable to hold the pattern of which LEDs are currently turned on or off
byte leds = 0;

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

void setup() {
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
}

Теперь в функции loop мы начинаем с выключения всех светодиодов. Это делается установкой leds = 0 (что означает, что все биты в байте равны 0). Затем мы вызываем пользовательскую функцию updateShiftRegister(), которая обновляет сдвиговый регистр для отражения этого изменения. После короткой задержки в 500 миллисекунд (полсекунды) мы переходим к следующей части.

Цикл for используется для включения светодиодов по одному. Цикл выполняется 8 раз, по одному для каждого светодиода. Внутри цикла функция bitSet() изменяет определённый бит в переменной leds с 0 на 1, фактически включая соответствующий светодиод. После каждого обновления мы вызываем updateShiftRegister() для применения изменения, ждём ещё 500 миллисекунд и переходим к следующему светодиоду.

void loop() {
  leds = 0;
  updateShiftRegister();
  delay(500);
  for (int i = 0; i < 8; i++) {
    bitSet(leds, i);
    updateShiftRegister();
    delay(500);
  }
}

Теперь поговорим о функции updateShiftRegister(), которая играет ключевую роль в управлении светодиодами.

Эта функция отвечает за отправку данных leds в сдвиговый регистр. Сначала она устанавливает вывод защёлки в LOW, что временно удерживает выходы для предотвращения мерцания при загрузке новых данных. Затем вызывается функция shiftOut(), которая отправляет данные leds по одному биту в сдвиговый регистр. Функция shiftOut() требует четыре параметра: вывод данных, вывод тактирования, порядок бит (LSBFIRST или MSBFIRST) и собственно данные для отправки (leds в данном случае). Наконец, вывод защёлки устанавливается обратно в HIGH, что передаёт данные в регистр хранения и обновляет выходные выводы, заставляя светодиоды изменять своё состояние.

Важная деталь: установка вывода защёлки в LOW перед сдвигом данных и в HIGH после сдвига обеспечивает плавное обновление. Если вы пропустите этот шаг, светодиоды могут мерцать во время передачи данных.

void updateShiftRegister() {
   digitalWrite(latchPin, LOW);
   shiftOut(dataPin, clockPin, LSBFIRST, leds);
   digitalWrite(latchPin, HIGH);
}

Пример Arduino 2: Управление яркостью с помощью ШИМ

Давайте продвинем нашу установку со сдвиговым регистром 74HC595 на шаг дальше! На этот раз, вместо простого включения и выключения светодиодов, мы будем управлять их яркостью с помощью вывода OE (Output Enable) на микросхеме.

Мы уже знаем, что вывод OE работает как переключатель вкл/выкл для всех выходных выводов. Когда OE в HIGH, выходные выводы отключены (помните, это вывод с активным низким уровнем). Когда OE в LOW, выходы работают нормально.

В предыдущем примере мы подключили OE напрямую к земле, что поддерживало выходы активными всё время. Но что произойдёт, если подключить OE к одному из цифровых выводов Arduino и запрограммировать его переключаться между включённым и выключённым состоянием? Мы получим эффект мигания, при котором все светодиоды включаются и выключаются одновременно!

Как работает сдвиговый регистр 74HC595 и подключение к Arduino

А вот ещё кое-что более интересное! Если подключить OE к одному из выводов ШИМ (широтно-импульсной модуляции) Arduino, мы можем регулировать яркость светодиодов, а не просто полностью включать или выключать их.

Это работает потому, что ШИМ быстро переключает вывод между HIGH и LOW состояниями много раз в секунду. Управляя тем, как долго вывод остаётся в HIGH по сравнению с LOW (так называемый «коэффициент заполнения»), мы можем контролировать, сколько мощности в среднем поступает на светодиоды. Когда вывод преимущественно в LOW, выходы остаются включёнными дольше, давая светодиодам больше мощности и заставляя их светить ярче. Когда вывод преимущественно в HIGH, выходы чаще отключаются, давая светодиодам меньше мощности и заставляя их светить тусклее.

Постепенно изменяя коэффициент заполнения ШИМ в коде Arduino, мы можем создавать плавные переходы между ярким и тусклым состоянием, создавая красивый эффект затухания для всех светодиодов одновременно.

Как работает сдвиговый регистр 74HC595 и подключение к Arduino

Схема подключения

Подключение остаётся почти таким же, как и раньше, но с одним небольшим изменением. Вместо подключения вывода 13 (OE) напрямую к земле, вы подключите его к выводу 3 Arduino, который поддерживает ШИМ.

Как работает сдвиговый регистр 74HC595 и подключение к Arduino

Пример кода

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

int latchPin = 5;         // Latch pin of 74HC595 is connected to Digital pin 5
int clockPin = 6;         // Clock pin of 74HC595 is connected to Digital pin 6
int dataPin = 4;          // Data pin of 74HC595 is connected to Digital pin 4
int outputEnablePin = 3;  // OE pin of 74HC595 is connected to PWM pin 3

byte leds = 0;  // Variable to hold the pattern of which LEDs are currently turned on or off

void setup() {
  // Set all the pins of 74HC595 as OUTPUT
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(outputEnablePin, OUTPUT);
}

void loop() {
  setBrightness(255);
  leds = 0;  // Initially turns all the LEDs off, by giving the variable 'leds' the value 0
  updateShiftRegister();
  delay(500);

  // Turn all the LEDs ON one by one.
  for (int i = 0; i < 8; i++) {
    bitSet(leds, i);  // Set the bit that controls that LED in the variable 'leds'
    updateShiftRegister();
    delay(500);
  }

  // Gradually fade all the LEDs back to off
  for (byte b = 255; b > 0; b--) {
    setBrightness(b);
    delay(50);
  }
}

/*
 This function sets the latchPin to low, then calls the Arduino function 'shiftOut' to shift out contents of variable 'leds' in the shift register before putting the 'latchPin' high again.
 */
void updateShiftRegister() {
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, LSBFIRST, leds);
  digitalWrite(latchPin, HIGH);
}

/*
 This function generates a PWM signal and writes it to the OE pin.
 */
void setBrightness(byte brightness)  // 0 to 255
{
  analogWrite(outputEnablePin, 255 - brightness);
}

Когда вы загрузите код на Arduino, вы должны увидеть следующий результат:

Как работает сдвиговый регистр 74HC595 и подключение к Arduino

Объяснение кода

Этот скетч похож на предыдущий. Однако есть несколько ключевых отличий.

В начале программы мы определяем и настраиваем outputEnablePin (вывод 3) как выход, так же как выводы защёлки, тактирования и данных.

int outputEnablePin = 3;
pinMode(outputEnablePin, OUTPUT);

Функция loop() по-прежнему следует той же логике — включает светодиоды по одному — но теперь, перед началом цикла, она вызывает setBrightness(255). Это гарантирует, что выходы полностью включены, то есть светодиоды загорятся на полной яркости.

setBrightness(255);

Сама функция setBrightness(byte brightness) — новая и отвечает за регулировку яркости. Эта функция принимает значение от 0 до 255, где 255 означает полную яркость, а 0 — полное выключение. Поскольку вывод OE имеет активный низкий уровень, мы фактически записываем 255 - brightness, то есть при brightness = 255 светодиоды полностью включены, а при brightness = 0 — полностью выключены.

void setBrightness(byte brightness)  // 0 to 255
{
  analogWrite(outputEnablePin, 255 - brightness);
}

Главное изменение происходит после включения всех светодиодов. Вместо мгновенного выключения программа теперь плавно уменьшает их яркость шаг за шагом. Это делается с помощью цикла for, который считает от 255 до 0, вызывая setBrightness(b) на каждом шаге. Эта функция использует analogWrite() для создания ШИМ-сигнала на выводе OE, позволяя светодиодам плавно затухать вместо резкого выключения.

// Gradually fade all the LEDs back to off
for (byte b = 255; b > 0; b--) {
  setBrightness(b);
  delay(50);
}