Тема сдвиговых регистров довольно часто поднимается, но все не было подходящего повода. Настал момент — пополнить каталог статей.

Пример. Вам понадобилось 8 семисегментных индикаторов. Допустим, на четырех из них выводится время, на четырех выводится некая информация, пусть температура или еще что либо, не важно. Даже если мы будем использовать динамическую индикацию, то понадобится 7 общих ножек для вывода данных и еще 8 для переключения между индикаторами, итого 15 ножек и достаточно загруженный микроконтроллер.

Одним из решений подобной проблемы, может быть использование сдвигового регистра.
hc595

Если в кратце описать, то работает эта микросхема так: есть вход DS на который подается сигнал, либо логическая единица, либо логический ноль. Также имеется восемь выходов Q0-Q7. В первый момент времени, данные со входа, окажутся на выходе Q0. В следующий момент времени, данные со входа снова окажутся на выходе Q0. Но предыдущие данные переместятся на выход Q1. В следующий момент времени, данные «сдвинутся» с Q1 на Q2, c Q0 на Q1, со входа на Q0. Поэтому и называется сдвиговый.

Временные интервалы сдвига задаются импульсом на ножке SH_CP, не хочешь сдвигать сейчас — не надо, можешь сделать это хоть через час 🙂 В общем из описания работы, сразу понятно что работает эта штука медленно, т.е. чтобы зажечь светодиод только на выходе Q7 на нужно:
1. выставить единицу на ножке данных,
2. послать импульс,
3. выставить ноль на ножке данных,
4. послать 7 импульсов
Получается некисло, но скорость не всегда важна. Для всяких светодиодных мигалок, свистелок и перделок этого может быть более чем достаточно.

Но обзор на этом заканчивать рано, так как плюшки еще не окончены. Из необычных есть еще ножка ST_CP, так называемая защелка. Допустим нужно чтобы загорелся светодиод на выходе Q7, но при этом нельзя чтобы логическая единица появилась на выходах Q0-Q6. С защелкой этот вопрос решается легко — пока данные подаются на вход и сдвигаются, на выходах Q0-Q7 состояние не изменяется, но как только придет импульс на ножку ST_CP, данные появятся на выходе.

Еще одной вкусной плюшкой является возможностью каскадного подключения. Вы возможно уже заметили подозрительную ножку Q7′, так вот, если эту ножку у первой микросхемы подключить на вход DS второй микросхемы, то после сдвига данных с ножки Q7 первой микросхемы, окажутся на выходе Q0 второй микросхемы. Таким образом, используя всего 3 ножки микроконтроллера, можно подключать сколько угодно выходов.
ds_595
Ножка /OE — запрет работы (разрешение — низкий уровень), /MR — сброс (по низкому уровню).

Теперь должно быть понятно, что восемь семисегментников спокойно рулятся всего тремя ножками, вместо 15, в случае статической индикации, и 7 ножек для динамической. В добавок ко всему, очень хорошо с этим справляется интерфейс SPI, где ножка сдвига SH_CP подключается к SCK, данные DS к MOSI и произвольную ножку можно заюзать для защелки.

При отсутствии аппаратного SPI можно заюзать программный.

 
#define _soft_data  PORTA.0
#define _soft_shift PORTA.1
#define _soft_latch PORTA.2
 
void write(char a)
{    
       unsigned char i;
       for(i=0;i<8;i++)
       {        
       if(a & 0x80)
       {
       _soft_data = 1;
       }
       else
       {
       _soft_data = 0;
       }
         #asm("nop") //shift
         _soft_shift=1;
         #asm("nop")
         _soft_shift=0;  
         a <<= 1;   
       }
 
       #asm("nop") //latch
       _soft_latch=1; 
       #asm("nop")
       _soft_latch=0;       
}

7seg_595

Для желающих можно поковырять заготовки

40 комментариев: 74HC595

  • Знаете Админ, вот я использовал эти регистры, для реализации бегущей строки, 16×16, т.е. подключил 2 регистра по горизонтали, два по вертикали, и взял 8×8 матрицы 4 штуки, ну и итого у меня получилось 16×16, написал код, на атмеге 16, с частотой 16МГЦ, ща не хватает частоты))) сильно мерцает и тускло горят светодиоды)) Вот ща надумываю о STM32, как вы думаете? может ли быть что частоты в 16 мгц для 256 лампочек не хватать?

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

  • Так именно что наверное Не в ногодрыге дело, я вот пару for(){}; расписал обычным образом, ну повтори столько сколько надо, потом пару операции по другому сделал, ща перестало мерцать, но так же тускло горят. У меня в коде было for(){for(){for(){}for(){}}} и еще пару фор было внутри)) :mrgreen: , пару сократил и стало ему легче, ведь это же не дергание ножек виноваты да? просто он не успевает обрабаывать код…?

  • может наоборот слишком быстро

  • to cas2010
    Светодиоды у тебя тускло горят из-за герцовки
    Рекомендую ознакомиться с принципом широтно импульсной модуляции

  • Админ Шим я знаю, получается как бы вольтажа мало. Но если я дам не большую задержку то у меня получается прорисовка уже идет по строчно… чет с этими регистрами не получается, я до этого делал без регистров, брал 8×8, соединял прям на ножки контроллера мега 8, через резисторы, там так же было, но я задержку давал, и яркость увеличивалась, а здесь, яркость никак)) может быть регистры мало току пропускают? через регистры контроллировать транзисторами, а транзисторы подсоединить на ножки матрицы?

  • Да 74HC595 вещь, что на ней народ не делал на нём, вот и хочу замутить строку ,8х8 12 модулей. Зачёт Админу

  • Подключайте по SPI, так в разы проще, не будет никакой ногодрыг забирать ресурсы процессора, ну и, у SPI скорость может достигать половины тактовой процессора.
    Т.е. целых 10 Мбит, когда МК тактируется от 20 МГц кварца. 😆

    Еще, если вам не нужно преобразовывать последовательную шину в параллельную- можете взять более простой регистр, а именно 74HC164, у него нету защелки, что в него задвинул- то и будет на выходе. Если задвигать с большой скоростью- задвиг будет практически незаметен человеческому глазу. Можно будет драйвить кучи 7-сегментников малой кровью, просто поцепив к SPI, без ножек управления. 😉

  • to iEugene0x7CA
    А по мне именно в 74hc595 приколв, в защелке, без него будет мутина… и еще у меня получилось нормальная индикация 16×16 бегущая строка. :mrgreen:

  • Для скорости, предполагаю, надо делать программный SPI, а каждый регистр 74hс595 управлять разными ножками МК

  • Жандос, скорость от этого не вырастет, мк выполняет инструкции последовательно

  • Передавая сигналы на регистры мы передаем некоторое число, например 0110 1100. Это число может быть длиннее. Надо разделить их на несколько частей(на сколько надо), и передавать через разные ножки к которым подключены разные регистры, инструкция выполняется последовательно,но одновременно на всех ножках МК.

  • cas2010, понапрягай поиск на тему «чарлиплексинга» — на ту же мегу8 влёт вешал 210 диодов (21х10 панель) без дополнительных чипов вообще и то не все ноги забил!

  • admin, скажи пожалуйста, как считать данные с регистра? хочу 6 кнопок

  • все, разобрался использую сдвиговый регистр 74198N

  • Помогите плиз надо написать библу на сдвиговый регистр, чтобы можно было простыми командами вывести на выходы любое состояние.
    Например, пишем out_reg=0b01001011;
    а получаем единицу на выходах Q0, Q1, Q3, Q6

  • Здравствуйте, имеется платка индикации на 4-ёх 74HC595, но подвох там в том, что нет соответствия «одина микросхема регистр-одно знакоместо». Выходы там раскиданы по-разному. Вопрос собственно в том, как организовать перестановку битов в байтах,
    чтобы выводить не абракадабру, а нормальные числа ?

  • скорее всего они подключены каскадом, поэтому менять один бит и смотреть куда он приходит

  • Да, составлен порядок соответствия. А так как выходы одного регистра захватывают по 2 соседних знакоместа( там статическая индикация на одноразрядных индикаторах), то проще наверное представить последовательность для вывода на регистры в виде 32-ух битного числа. Последователбность у него будет 31…0, а нужен порядок (я точно не помню) вразнобой… Так как лучше реализовать перестановку битов в этом числе ? 🙄

  • Без схемы обсуждение бессмысленно

  • Здравствуйте, решение составлено в виде функции. Если кому интересно.

    unsigned long int bit_kak_nado(unsigned long int temp32)
    {
    unsigned char i;
    unsigned long int st_bit; // Базовый байт
    unsigned long int led = 0x00000000; // Последовательность для вывода на регистры
    unsigned char shift_reg[28]={26,19,28,27,25,17,18,22,23,31,30,29,20,21,14,5,12,13,15,7,6,2,1,9,10,11,4,3}; // Количество сдвигов влево в базовом байте

    for(i=0;i<28;i++) // В этом цикле реализуем перестановку бит в нужный нам порядок
    {
    st_bit = 0x00000001;
    if(temp32 & st_bit)
    {
    led = (led|(st_bit <>1;
    }
    return led;
    }

  • Странно… копи-паст неправильно отобразился…

  • Здраствуйте, а зачем в коде нужны искуственные задержки на АСМе(#asm ‘nop’)?

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

  • Доброго времени суток admin on!
    Прошу помощи нигде, конкретно на просторах иннета не нашёл
    Задача состоит в передачи числа в семисегментный индикатор
    Ниже код который может отображать как сделать что бы в copy_temp
    можно было записать число и это же число отобразилость на индикаторе

    while (1)
    {
    copy_temp = 109;
    ST_CP=0;
    MR=1;

    for (counter = 0; counter < 16; counter++)
    {
    if (copy_temp & 0x80)
    {
    DS = 1;
    }
    else
    {
    DS = 0;
    }

    SH_CP = 1;
    SH_CP = 0;
    copy_temp = copy_temp << 1;
    }
    ST_CP = 1;
    MR=0;
    }

  • вы кажется перепутали ку 1 с ку 0 )

    В первый момент времени, данные со входа, окажутся на выходе Q0. В следующий момент времени, данные со входа снова окажутся на выходе Q0. Но предыдущие данные переместятся на выход Q1.

  • а не это я тупанул сорри)

  • Всем привет.С 4 понятно регистрами а добавляю 5 всё сдохло и не хочет ничего выводить.
    ВОТ ФУНКЦИЯ ВЫВОДА .МОЖЕТ ЧТО-ТО НЕ ТАК??????????
    void send_data (long int data){
    unsigned char i;
    for (i=0;i<40;i++){
    if ((data&0x8000000000)==0x00) PORTD&=~(1<<DATA); //Выставляем данные на PD0
    else PORTD|=(1<<DATA);
    #asm("sei")
    PORTD|=(1<<CLK); //Импульс на CLK
    #asm("sei")
    PORTD&=~(1<<CLK);
    #asm("sei")
    data=(data<<1);
    }
    PORTD|=(1<<Latch); // Импульс на Latch
    #asm("sei")
    PORTD&=~(1<<Latch);
    }

  • cavr не умеет работать с 64 битными значениями

  • Всем привет вот сбросили мне код сделаный наверно а AVR STUDIO .Пытаюсь адаптировать его по визард компилятор выдаёт ошибки в первой строке

    void send_data_block (byte* DATA, byte LEN)
    {
    byte i,DD;
    while (LEN) // пока есть данные для передачи
    {
    DD = DATA[—LEN]; // очередной байт данных, из конца вх.массива
    for (i=0;i<8;i++) // делаем 8 раз
    {
    if (DD & 0x80) // копирование ст.бита данных
    PORT.DBIT = 1; // в выходной бит порта
    else PORT.DBIT = 0;
    DD <<= 1; // сдвигаем обработанный бит
    SHIFT_strobe(); // стробируем сдвиг данных в регистрах
    }
    }
    LATCH_strobe(); // импульс защелки данных на выходах регистров
    }

    byte DATA[BUFSIZE] = {1,2,3,4,5}; // буфер экранных данных, любого размера

    main{}
    {
    send_data_block(DATA,BUFSIZE); // функции передаем адрес массива, и его длину
    }

  • Пишу вот так
    void send_data_block (unsigned char* DATA, unsigned char LEN)
    тоже ругается???

  • ошибка была в #define DATA 2 // Подключаем к порту PD0 ножку данных сдвигового регистра

  • TM74HC595 и 74HC595 -одна и та же микросхема или нет ?Можете ответить?заранее говорю спасибо.

  • по всей видимости да.

  • Значит эти библиотеки подключения подходят и к ней?

  • должны

  • я хочу сделать часы на динамической индикации на 74hc595 проблема в секундах.точька как секунда в этом же разряде в 3 я не могу сделать.мне наверное нужно индикатор с отдельным разрядом ? Дайте совет? я не прошу код.Спасибо заранее.

  • если вы используете 595, то там уже динамическая индикация не нужна. на точку заводите отдельный разряд и все

  • Добрый день.Помогите разобраться подключаю через регистр драйвер шагового движка

    send_data(0x08);
    delay_us(speed);
    send_data(0x02);
    delay_us(speed);
    send_data(0x04);
    delay_us(speed);
    send_data(0x01);
    delay_us(speed);
    send_data(0x00);
    delay_us(speed);//500

    РАБОТАЕТ МЕДЛЕННО

    когда от контроллера на 500us то замечательно работает а вот от регистров нет ?

  • А есть что то подобное для LCD 7-сегменнтников а то я уже запутался с CD4543? 😐

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

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

Последние комментарии
  • Загрузка...
Счетчик
Яндекс.Метрика