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

Когда необходимо подключить к контроллеру два десятка светодиодов или еще чего на помощь приходят сдвиговые регистры. Ну не тратить же драгоценные пины микроконтроллера на это дело :-) Для эксперимента купил сдвиговый регистр 74HC595 и в этой небольшой статье покажу как с ним работать при помощи самого крохотного контроллера Tiny13.


Посмотрим что из себя представляет эта микруха. Распиновка на рисунке ниже:

74HC595 распиновка

С первого взгляда кажется немного запутано, будем разбираться. Начнем с назначения выводов:

  • Q0…Q7 — выходы которыми будем управлять. Могут находится в трёх состояниях: логическая единица, логический ноль и  высокоомное Hi-Z состояние
  • GND — земля
  • Q7′ — выход предназначенный для последовательного соединения регистров.
  • MR — сброс регистра.
  • SH_CP — вход для тактовых импульсов
  • ST_CP — вход «защёлкивающий» данные
  • OE — вход переводящий выходы из HI-Z в рабочее состояние
  • DS — вход данных
  • VCC — питание 5 вольт

Для управления нам вполне достаточно всего лишь трёх  выводов а именно: SH_CPST_CP, DS.

Как работает регистр
Все не так сложно, как кажется на первый взгляд.  Когда на тактовом входе SH_CP появляется логическая единица, регистр считывает бит со входа данных DS и записывает его в самый младший разряд. При поступлении на тактовый вход следующего импульса, всё повторяется, только бит записанный ранее сдвигается на один разряд, а его место занимает вновь пришедший бит. Когда все восемь бит заполнились и приходит девятый тактовый импульс то регистр снова начинает заполнятся с младшего разряда  и всё повторятся вновь. Что бы данные появились на выходах Q0…Q7 нужно их «защёлкнуть». Для этого необходимо подать логическую единицу на вход ST_CP. Что бы мы не делали с регистром, данные на выходах не изменятся пока мы вновь не «защёлкнем» их. Отсюда кстати пошло название «регистр-защёлка». Теперь пару слов о других выводах микросхемы. Когда на входе OE лог 1 то выходы находятся в высокоомном состоянии. Когда подаем на этот вход логический 0, тогда выходы работают в нормальном режиме. MR — сбрасывает регистр устанавливая все выходы Q0…Q7 в состояние логического нуля. Для осуществления сброса нужно подать логический ноль на этот вход. После этого «защёлкнуть» данные. В нормальном состоянии на этом выводе должна находится логическая единица. Q7′ предназначен для последовательного соединения сдвиговых регистров. Можно соединить хоть десяток штук!

Программное обеспечение
Для того чтоб управлять этим регистром была написана небольшая библиотека. Вы без труда сможете использовать её в любом своем проекте. Состоит она всего навсего из одной процедуры ShiftRegOut перед вызовом которой нужно загрузить в регистр temp то что должно быть записано в сдвиговый регистр. Код неплохо прокомментирован, поэтому вопросов я думаю не будет. Если будут то прошу задавать их в комментариях. Если паять совсем лениво то можно собрать тестовую схемку в симуляторе Proteus. Файл симуляции прилагается. Если же хочется попробовать в настоящем железе то вот сама схема:

74HC595 схема

Кстати существуют регистры работающие на вход с параллельной загрузкой и последовательным выводом. Если требуется чтобы в ходе работы программы  назначение пина можно было менять, (делать входом или выходом) то применяют так называемые расширители портов. Они обычно имеют интерфейс i2c но слишком дороги и малораспространенны во всяком случае у нас. Так что сдвиговые регистры наше все =)
Ну и напоследок фото того на чем это всё проверялось и отлаживалось:

74HC595 отладка

Кстати очень удобно для отладки использовать мини макетки для SOIC корпусов. Рекомендую взять на заметку =). Все вопросы складываем в комментарии.

Файл симуляции + исходник
Чисто по приколу записал видео всего этого безобразия

Сдвиговый регистр 74HC595: 56 комментариев

  1. Существуют и так называемые регистры-защелки (параллельный ввод- параллельный вывод). Например, SN74LS374 и их разновидности. Эти микросхемы особенно удобно использовать в том случае, если у микроконтроллера есть хотя бы один свободный полноценный 8-разрядный порт (та же tiny2313) и обрезаный. Через обрезаный порт осуществляется выбор и/или тактирование микросхемы, состояние выводов которой нужно изменить, полноценный порт выставляет необходимые данные и, пока не выбран регистр-защелка, этот порт может использоваться разработчиком по своему усмотрению. До тех пор, пока на тактовый вход не поступил импульс и микросхема не выбрана, состояние на выходах регистра не меняется. В принципе, ничего не мешает использовать для работы с этими регистрами и пины контроллера, расположенные на разных портах и в разнобой. Выходы SN74LS374 могут быть переведены в Z-состояние, например, если на используемый порт повешены 2 регистра- защелки так, что один работает на ввод данных, другой на вывод. Понятно, что при использовании более трех регистров-защелок целесообразнее обратиться к регистрам типа 595, однако, чтобы загрузить три сдвиговых регистра потребуется больше машинного времени, да и не так много задач, где это нужно.

  2. 595 идеальная микруха для создания информационных панелей на светодиодах. Строки цепляем через транзистор на лапы МК, а столбики подключаем к куче последовательно зацепленных 595. Благодаря защелке все работает без морганий и артефактов.

  3. Для светодиодных панелей лучше использовать специализированные для этого микросхемы-драйверы. Я делал панель на MBI5027. Принцип управления такой же как и у 595 регистров, однако ток светодиодов можно регулировать всего лишь одним токозадающим резистором. При этом имеем 16 выходных линий.

  4. Medved,а зачем вот это: L0010:
    inc r16 //Увеличиваем содержимое temp на единицу -?
    Без этой строчки все работает нормально. Я симулировал в Алгоритм Билдере. И еще вопрос-как сделать,чтобы сдвигающиеся биты заполнялись
    не нулями, а единицами ? Мне нухно перемещение темного участка по горящему ряду

    1. ну смотри этот демонстрационный пример занимается тем что выводит в сдвиговый регистр числа от 0 до 255. Чтоб выводить число за числом достаточно прибалять по единичке к регистру R16. Этим и занимается строчка inc r16. после того как единичка прибавлена содержимое R16 выводит в сдвиговый регистр. Для перемещения тёмного участка просто загружай нужное чилсо в R16 вызывай процедуру ShiftRegOut
      Например можно вот так

      ldi r16,0b01111111
      rcall ShiftRegOut
      rcall Delay
      ldi r16,0b10111111
      rcall ShiftRegOut
      rcall Delay
      ldi r16,0b11011111
      rcall ShiftRegOut
      rcall Delay
      …. итд

  5. Здравствуйте! Я начинающий в этом деле и начал программировать на языке С++, отелось бы увидить код сдвигового регистра 74HC595 на языке С++. Зарание благодарен.

    1. К сожалению кода на Си нет, я на асме пишу. Но ты сможешь написать его сам я думаю. Тут главное только понять алгоритм работы сдвигового регистра. а тут он описан.

  6. Для этой микросхемы ток через VCC/GND ограничен на уровне 70 мА, поэтому токоограничительные резисторы я бы побольше поставил. Соглашусь с владимиром, что например для динамической индикации лучше использовать драйверы, т.к. импульсный ток в этом случае больше в [количество индикаторов] раз, а для 595 этот ток в худшем случае будет постоянным.

  7. #include
    #include

    #define SH_CP PORTB.0
    #define DS PORTB.1
    #define ST_CP PORTB.2

    void main(void)
    {
    unsigned char temp=0;
    unsigned char copy_temp=0;
    unsigned char counter;

    PORTB=0x00;
    DDRB=0x07; // Пины 0,1,2 на выход

    // Analog Comparator initialization
    // Analog Comparator: Off
    ACSR=0x80;
    ADCSRB=0x00;

    while (1)
    {
    for (counter = 0; counter < 8; counter++){ // цикл для 8 битов
    // Проверяем крайний левый бит если он равен 1 то записываем в линию данных 1
    if (copy_temp & 0x80){ DS = 1;
    }else {DS = 0;} // иначе записываем 0
    //Дергаем ногой чтоб пропихнуть бит в регистр
    SH_CP = 1;
    SH_CP = 0;
    copy_temp = copy_temp << 1; // Сдвигаем все биты переменной темp влево на один бит
    }
    //Дергаем ногой и защёлкиваем данные.
    ST_CP = 1;
    //Возможно вместо этого комментария придёца вставить задержку…а может и нет..
    ST_CP = 0;
    DS = 0;
    delay_ms(300);

    ++temp; // увеличиваем переменную
    copy_temp = temp;
    }
    }

  8. И ещё в догонку к коду на С
    mmi спрашивал как перемещать темный участок
    для перемещения тёмного участка достаточно в цикле for поменять вывод в линию данных вот так:
    if (copy_temp & 0×80){ DS = 0; // здесь поменяли на 0
    }else {DS = 1;} // а здесь на 1
    теперь будет перемещаться темный участок

  9. Hi,
    А про последовательное соединение можно было и подробнее написать. Как с ним работать? Куда будет записан бит со входа?
    И сколько так можно последовательно соединить? =)

    1. Да тут всё просто! :-)
      У примеру надо соединить два регистра. Выводы ST_CP соединяем между собой. SH_CP тоже соединяем.
      Ногу Q7′ одного регистра соединяем с ногой DS другого. Данные будут поступать на свободную ногу DS одного из регистров. Вот и вся схемотехника! Работать с этими двумя регистрами так же как и с одним. только считай что теперь там вместо 8 бит стало 16. Теоретически так можно навешать сколько угодно регистров.

  10. добрый день, не полуается найти 595 в чистом виде в дип корпусе, подскажите, какие его аналоги можно использовать?
    ниже приведены микросхемы, похожие по номерам, но я не уверен, что они одинаковые, так же приведены цены на них:)

    STM74HC590B1(dip16) 25
    SN74HC594N(dip16) 47
    SN74HC594(smd16) 34
    STM74HC595B1(dip16) 10
    74HC595D(smd16) 10
    74HC597N(dip16) 27

    читал даташиты, но плохо знаю англ и не очень понял, что там в них различного. так что прошу подсказать:)

  11. купил я этот M74HC595B1, подключил по схеме, представленной тут, но использую в качестве контроллера ATMega8 и у меня ничего путного не выходит.
    есть минимум 2 варианта:
    1 — не правильные входы задействую (склоняюсь к этому)
    2 — не так программирую девайс

    пока писал — попробовал еще раз его «оживить».. в общем при касании провода ST_CP рукой через изоляцию — сигнал пошел.. я не понял что это было:(

    1. Что бы данные появились на выходах Q0…Q7 нужно их «защёлкнуть». Для этого необходимо подать логическую единицу на вход ST_CP. Что бы мы не делали с регистром, данные на выходах не изменятся пока мы вновь не «защёлкнем» их. Отсюда кстати пошло название «регистр-защёлка»

  12. Автор раз уж зашел вопрос о всякого рода ЛОГИКА/Регистр
    расскажите про такую штуку SN74LS161N точнее про
    ее русский аналог К555ИЕ10 что сней делать.
    У меня ее залежи. Хотел бы как то вставить в проекты.
    И вообще предложение: по больше бы инфы о всякой логике.

    Р.S. Регистрация на сайт не высылает пароль на мыло.

  13. Здравствуйте! хочу повесить 4 шт 595, подскажите как дописать код для передачи байтов в остальные сдвиговые регистры. Я новичек в программирование, этот пример очень помог. заранее спасибо

  14. Как соеденять я понял, я не знаю как мне загружать регистр, он восьмибитный, а у меня 4шт 595. Тобишь cpi counter,32
    А вот как эти 32 бита в temp загрузить пока не понимаю.
    Искал примеры, но они на СИ или на Васике
    Ели не трудно разжуйте подробнее. Спасибо

    1. Самый простой способ:
      Из процедуры ShiftRegOut исключить строчки
      //Дергаем ногой и защёлкиваем данные.
      sbi ShiftRegPort,ST_CP
      ///Возможно вместо этого комментария придёца вставить задержку.... а может и нет..
      cbi ShiftRegPort,ST_CP

      Потом просто вызываем процедуру ShiftRegOut 4 раза (8 * 4=32) и после вызова защёлкиваем данные (вставляем строчки которые вырезали выше) В результате


      Begin:
      inc temp //Увеличиваем содержимое на единицу
      rcall ShiftRegOut //записываем в регистр сдвига (первые 8 бит)
      inc temp //Увеличиваем содержимое на единицу
      rcall ShiftRegOut //записываем в регистр сдвига (вторые 8 бит)
      inc temp //Увеличиваем содержимое на единицу
      rcall ShiftRegOut //записываем в регистр сдвига (третьи 8 бит)
      inc temp //Увеличиваем содержимое на единицу
      rcall ShiftRegOut //записываем в регистр сдвига (последние 8 бит)
      rcall Delay // делаем небольшую паузу

      //Дергаем ногой и защёлкиваем данные.
      sbi ShiftRegPort,ST_CP
      ///Возможно вместо этого комментария придёца вставить задержку.... а может и нет..
      cbi ShiftRegPort,ST_CP

      rjmp begin // И так до конца времен

  15. Ох спасибо огромное, очень оперативно. Буду сегодня вкуривать всю эту музыку. Супер!
    Ещё раз огромное спасибо за асм, примеры на нём найти трудно.

  16. А как реализовать равномерную, частоту мерцания диодов? Т.е. что бы загорался только 1-й, потом только 2-й, потом только 3-й…только 8-й и по новой..?

  17. загружаем в регистр темп число 0b00000001
    Вызываем ShiftRegOut
    загружаем в регистр темп число 0b00000010
    Вызываем ShiftRegOut
    загружаем в регистр темп число 0b00000100
    Вызываем ShiftRegOut
    загружаем в регистр темп число 0b00001000
    Вызываем ShiftRegOut
    итд…

  18. Ув. автор, у Вас в исходнике есть строка
    sbi ShiftRegPort-1,SH_CP
    никак не могу понять как это так происходит настройка порта на вывод… разве что PORTB-1=DDRB ?

  19. Здравствуйте, а кто подскажет как правильно подключить 74HC595 и pic16f628 уже два дня маюсь и не работает ни как.. даташит читал. Если не сложно подскажите или просто накидайте в протеусе, буду очень благодарен. Могу на сотик немного денег подкинуть

  20. Много времени потратил, на то, что бы понять: MR со значком инверсии сверху говорит о том, что не подключенный вывод означает сброс и подключенный в плюс(единицу) — означает выводить данные.

  21. Если паять совсем лениво то можно собрать тестовую схемку в симуляторе Proteus.
    У меня с PIC16F84A данный регистр 74HC595 в Proteus работает, но в железе отказался. Не понимаю по чему. Но очень уж понравилась идея и я применил регистр CD74HC4094E. В Proteusе и в железе работает на ура.

      1. мы же передаем по одному биту,нельзя же передать целое число например 010101010, нам нужно что бы оно выглядело вот так 0 1 0 1 0 1 0 1 ,что то типа разложения числа 8965 на тысячи ,сотни,десятки и единицы.

        1. Это можно реализовать при помощи битового сдвига.
          если писать на си то выглядит как-то так (не проверял ничего):

          unsigned char b0,b1,b2,b3,b4,b5,b6,b7;
          unsigned char some_byte=0xD9 // 11011001

          b0=0x01 & some_byte // теперь в b0 значение нулевого бита (1)
          some_byte>>=1; //сдвигаем биты вправо на 1 разряд.

          b1=0x01 & some_byte // теперь в b1 значение первого бита (0)
          some_byte>>=1; //сдвигаем биты вправо на 1 разряд.

          b2=0x01 & some_byte // теперь в b2 значение второго бита (0)
          some_byte>>=1; //сдвигаем биты влево на 1 разряд.

          b3=0x01 & some_byte // теперь в b3 значение третьего бита (1)
          some_byte>>=1; //сдвигаем биты влево на 1 разряд.

          b4=0x01 & some_byte // теперь в b4 значение четвертого бита (1)
          some_byte>>=1; //сдвигаем биты вправо на 1 разряд.

          b5=0x01 & some_byte // теперь в b5 значение пятого бита (0)
          some_byte>>=1; //сдвигаем биты вправо на 1 разряд.

          b6=0x01 & some_byte // теперь в b6 значение шестого бита (1)
          some_byte>>=1; //сдвигаем биты вправо на 1 разряд.

          b7=0x01 & some_byte // теперь в b7 значение седьмого бита (1)

  22. Скажите, когда подаешь питание на регистр какие у него состояния на выходах Q0-Q7 без подавания каких-либо сигналов? Схема такая же как в теме.

  23. вот функция для отправки байта в регистр,проверял в протеусе на PIC16f628a:
    void sdvig_reg (unsigned char input)
    {
    unsigned char cicle;
    unsigned char doobleinput;
    for(cicle = 0; cicle > cicle;//сдвигаем вправо
    Ds = doobleinput & 0b00000001;//накладываем маску
    Sh_cp = 0;
    Sh_cp = 1; //даем импульс на тактовый выход
    St_cp = 1; //защелкиваем введенные данные
    }
    }

  24. чет криво пост прорисовался
    void sdvig_reg (unsigned char input)
    {
    unsigned char cicle;
    unsigned char doobleinput;
    for(cicle = 0; cicle > cicle;//сдвигаем вправо
    Ds = doobleinput & 0b00000001;//накладываем маску
    Sh_cp = 0;
    Sh_cp = 1; //даем импульс на тактовый выход
    St_cp = 1; //защелкиваем введенные данные
    }
    }

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