Малаток-меню
Авторизация

Наш опрос
Сколько ВАМ лет?

Всего ответов: 92
Мини-чат
200
Статистика


Наш линк
Malatok.at.ua
Полезные ссылки
Это может быть интересно
[
Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Модератор форума: Викр, Дмытрохан  
Сдвиговый регистр 74HC595
Викр Дата: Понедельник, 21.09.2015, 10:06 | Сообщение # 1
Админ
Группа: Администраторы
Сообщений: 71
Награды: 6
Репутация: 100
Статус: Офлайн
Сдвиговый регистр - это набор последовательно соединённых триггеров (обычно их 8 штук). В
отличии от стандартных регистров, сдвиговые поддерживают функцию сдвига
вправо и влево. (т. е. переписывание данных с каждого предыдущего
триггера на следующий по счёту).


Функционал и назначение у сдвиговых регистров довольно велик. Сегодня мы познакомим одного из них с Arduino  (Отличный способ множить выходы у
Arduino: занимаем 3, получаем 8).
Наверное самая популярная микросхема, представляющая собой такой регистр - это 74HC595.



- Работает на интерфейсе SPI: ноги DS, ST_CP, SH_CP - это шины управления. Соответственно: шина данных(MOSI), защёлка(SS) и тактовая
линия(SCK). Подключаем на любые 3 контакта Arduino (библиотека SPI в
коде не будет задействована). У меня это 12, 10, 13 выходы
Arduino (стандарт).
- Ноги Q0, Q1, ..., Q7 - это выходы регистра (разряды). Для того,
чтобы следить за состоянием каждого из них, повесим на каждый вывод по
светодиоду (с последовательно соединённым резистором. Номинал от 150 до
330 Ом)
- VCC и GND - это питание. Подключаем к +5v и GND.
- выход Q7` не трогаем (предназначен для последовательного соединения таких регистров)
- MR - это сброс. Подключаем к +5v (сброс не активен).
- ну и OE притягиваем к земле (подключаем к контакту GND).
Получается вот, такая схема:

Теперь к коду:
- как говорилось ранее, библиотека SPI использоваться не будет. Есть удобная функция shiftOut().
для начала именуем наши пины (тактовая линия - clock, данные - data, защёлка - latch):
Код
#define clock 13
#define data 12
#define latch 10


потом в void setup() обозначаем их как выходы и сразу ставим защёлке высокий уровень, чтобы регистр не принимал сигналов:
Код
void setup()
{     
     pinMode(clock, OUTPUT);
     pinMode(data, OUTPUT);
     pinMode(latch, OUTPUT);
     digitalWrite(latch, HIGH);
}


теперь давайте попробуем что-нибудь отправить на регистр:
- для начала ставим LOW на защёлку (начинаем передачу данных. Теперь регистр принимает сигналы с Arduino).
digitalWrite(latch, LOW);

- потом отправляем данные (т. е. отправляем байт в цифровом или
двоичном виде. В двоичном проще, т. к. каждый из 8 битов отвечает за
свой разряд в регистре. Проще сориентироваться глазами):


Для начала отправим байт 0b10000000; (должен будет загореться первый светодиод):
shiftOut(data, clock, LSBFIRST,0b10000000);

- и в конце выставляем HIGH на защёлку (заканчиваем передавать данные).
digitalWrite(latch, HIGH);

В итоге весь наш код:
Код
#define clock 13
#define data 12
#define latch 10

void setup()
  {
     pinMode(clock, OUTPUT);
     pinMode(data, OUTPUT);
     pinMode(latch, OUTPUT);
     digitalWrite(latch, HIGH);
}

void loop()
  {
     digitalWrite(latch, LOW);
     shiftOut(data, clock, LSBFIRST, 0b10000000);
     digitalWrite(latch, HIGH);
}


Теперь вгружаем в ардуину. Результат должен быть таким (зажёгся первый светодиод):

(если у вас зажёгся не первый, а последний светодиод, то в функции shiftOut поменяйте LSBFIRST на MSBFIRST и всё станет на свои места).
Итак, получилось! Предлагаю создать функцию для того, чтобы каждый раз не писать эти 3 СТРОЧКИ:
Я назову её: sendbyte;
Код
void sendbyte(byte value)
{    
    digitalWrite(latch, LOW);    
    shiftOut(data, clock, LSBFIRST, value);    
    digitalWrite(latch, HIGH);
}
Эта функция отправляет регистру состояние всех разрядов сразу. Это пригодится для управления семисегментом (например). Но, чтобы использовать регистр как расширитель портов,
нужно управлять каждым разрядом по-отдельности (аналогично функции
digitalWrite()):
- Мы можем отправлять регистру только полный байты (8 бит - 0b00000000). Если отправить не 8, а 5 бит (например: 0b00000000), то регистр будет ждать недостающие 3 бита. Значит, что когда мы хотим
изменить состояние одного разряда регистра (включить его, или
выключить) мы должны, по сути, послать ранее отправленный байт, с
изменением на один бит.
(P. S.: Сейчас долгое и нудное объяснение (новичкам), кому не интересно, спуститесь чуть ниже :);
- Итак, сначала создаём, так называемую (мною), базу данных, в
которой будет храниться состояние каждого разряда (включен(HIGH) или
выключен(LOW)). тип: boolean:
boolean states[8];

Только что у нас появился массив переменных;
Каждая переменная в данном массиве обозначает свой разряд (в нулевой
(по счёту) будет храниться состояние 1 разряда, второй - 3-го, и т. д.)
- Теперь напишем функцию (я назову её: sendpin). Она будет
принимать 2 значения: номер разряда, и уровень, который нам надо этому
разряду приписать: высокий(HIGH) или низкий(LOW).
Код
void sendpin(int pin, boolean state)
{
      pin--;
      
     states[pin]=state;
        
    byte value = 0;
      byte add = 1;
     for(int i=0; i<8; i++)
      {
         if(states[i]==HIGH)   
           value+=add;    add*=2;
      
       }
     digitalWrite(latch, LOW);    
     shiftOut(data, clock, LSBFIRST, value);    
     digitalWrite(latch, HIGH);
    }
 Из-за того, что счёт начинается с нуля, нам придётся называть первый пин нулевым. Чтобы это исправить (мы будем писать как
есть(первый, значит первый), а Arduino будет сама отбавлять один), Я
написал:
pin--;

- Затем отмечаем изменения в базе данных:
states[pin]=state;

Теперь надо сформировать из 8 битов байт и отправить его на регистр.
- для начала создаём переменные:
value - тот байт, который будем отправлять. (по умолчанию его нужно сделать нулём):
byte value = 0;

add - это переменная, которая будет хранить в себе байт текущего разряда. для первого разряда это байт 1 (0b10000000);
byte add = 1;

теперь нам нужно прокрутить в базе данных все 8 переменных и сформировать байт (делать это будем с помощью цикла for():
Код
for(int i=0; i<8; i++){      
}
Итак, каждый раз мы проверяем очередной разряд в базе данных.
Если он должен иметь высокий уровень, то мы прибавляем к value add и
переходим на следующий разряд в цепочке (как бы сдвигаемся на разряд
выше (левее). Т. е., в двоичном коде всё просто: было так: 0b01000000;
сдвинули единичку влево и получилось так: 0b10000000. А вот в цифровом
виде всё по-другому. Сдвиг влево аналогичен умножению на 2 (а вправо,
кстати, - делению на 2)). Получается примерно так:
Код
if(states[i]==HIGH) value+=add;add*=2;
Теперь остаётся только послать value на регистр:
Код
digitalWrite(latch, LOW);
shiftOut(data, clock, LSBFIRST, value);
digitalWrite(latch, HIGH);
В принципе, если понять, то всё очень просто.
Итак, давайте попробуем включить 2, 4, 6, и 8 разряды отдельно (4 раза напишем в цикле нашу функцию):
Код
sendpin(2, HIGH);
sendpin(4, HIGH);
sendpin(6, HIGH);

sendpin(8, HIGH);
И кстати, в setup-e нужно очистить регистр (послать 0).
Можно даже такую функцию создать:
Код
void cleanreg()
{    
     for(int i=0; i<8; i++)   
       states[i]=LOW;    
    digitalWrite(latch, LOW);    
    shiftOut(data, clock, LSBFIRST, 0);    
    digitalWrite(latch, HIGH);
   }

В общем результат таков:


И оставлю от себя, как репостера несколько слов. В этом примере все сделано с минимальной сложностью, т.е. с максимальной понятностью, можно оптимизировать и сделать меньше кода и больше эффективности. Материал взят с сайта "Паяльник"
Прикрепленные файлы:



 
Skalkin Дата: Четверг, 21.01.2016, 10:24 | Сообщение # 2
Группа: Гости





Доброго времени суток. Подскажите уважаемые знатоки, а можно ли, и как, при использовании сдвигового ригистра, байт (0b00000000) отправляемый на него формировать с переменных, значение которых изменяется в результате нажатия кнопки, т.е. 1 или 0.
 
Дмытрохан Дата: Пятница, 22.01.2016, 13:09 | Сообщение # 3
Создатель сайта
Группа: Администраторы
Сообщений: 178
Награды: 7
Репутация: 103
Статус: Офлайн
Цитата Skalkin ()
Доброго времени суток. Подскажите уважаемые знатоки, а можно ли, и как, при использовании сдвигового ригистра, байт (0b00000000) отправляемый на него формировать с переменных, значение которых изменяется в результате нажатия кнопки, т.е. 1 или 0.
Здравствуйте! Конечно можно))

Код
void sendbyte(byte value) 
{    
    digitalWrite(latch, LOW);    
    shiftOut(data, clock, LSBFIRST, value);    
    digitalWrite(latch, HIGH); 
}
Значение в параметре этой функции и будет записано в регистр.
А если конкретно, то  можно так:

Код
#define clock 13 
#define data 12 
#define latch 10 
#define Btn 8 

void setup() 
  { 
     pinMode(clock, OUTPUT); 
     pinMode(data, OUTPUT); 
     pinMode(latch, OUTPUT); 
     pinMode(Btn, INPUT); 
     digitalWrite(Btn, LOW); // pulldown resistor fo button
     digitalWrite(latch, HIGH); 

byte val = 0;
void loop() 
  { 
     

  if (digitalRead(Btn) == HIGH)
  val++;
    
  delay(500);  //delay for debounce

  digitalWrite(latch, LOW); 
  shiftOut(data, clock, LSBFIRST, val); 
  digitalWrite(latch, HIGH); 
}


Нет человека-которого нельзя научить...
Есть человек-который не хочет учиться!!!
 
bumrik Дата: Четверг, 10.03.2016, 11:27 | Сообщение # 4
Группа: Гости





Добрый день!
А как сюда еще потенциометр приделать можно?
К примеру сюда чтобы цифры переключались при вращении!?

const byte latchPin = 4; // 11 пин на 74HC595 
const byte clockPin = 7; // 12 пин на 74HC595 SRCLR
const byte dataPin = 5; // 14 пин на 74HC595 SER
byte number[] = {0b01000001, 0b11011011, 0b10100001, 0b10010001, 0b00011011, 0b00010101, 0b00000101, 0b11011001, 0b00000001, 0b00010001, 0b01000001}; // Таблица цифр от 1-0
                 

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

void loop() {
for (int i = 0; i<10; i++){
    digitalWrite(latchPin, LOW);
//    shiftOut(dataPin, clockPin, MSBFIRST,0b11111101); // без использования массива вывести данные
 shiftOut(dataPin, clockPin, MSBFIRST, number); //С масивом
    digitalWrite(latchPin, HIGH);
     delay(500);
}
  }

Добавлено (10.03.2016, 11:27)
---------------------------------------------
Всем спасибо!
Уже не актуально код будет такой
const byte latchPin = 4; // 11 пин на 74HC595 
const byte clockPin = 7; // 12 пин на 74HC595 SRCLR
const byte dataPin = 5; // 14 пин на 74HC595 SER
int sensorPin=A0;

byte number[10] = {0b01000001, 0b11011011, 0b10100001, 0b10010001, 0b00011011,
                 0b00010101, 0b00000101, 0b11011001, 0b00000001, 0b00010001}; // Таблица цифр от 0-9
                 

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

void loop() {
int analogueValue = analogRead(sensorPin); // читаем аналоговый пин A0
analogueValue = map(analogueValue, 0, 1023, 0, 9); //преобразуем диапазон с А0 (0-1023) в нужный нам (0-9)

  digitalWrite(latchPin, LOW); 
  shiftOut(dataPin, clockPin, MSBFIRST, number[analogueValue]);
  digitalWrite(latchPin, HIGH);
}

 
Гость Дата: Вторник, 05.07.2016, 17:22 | Сообщение # 5
Группа: Гости





http://geekmatic.in.ua/Arduino_UNO_SMD_R3
 
Гость Дата: Четверг, 20.10.2016, 07:44 | Сообщение # 6
Группа: Гости





Зачем народу даете неверную информацию, отсчет байтов идет  справа налево
 
  • Страница 1 из 1
  • 1
Поиск:
Новый ответ
Имя:
Текст сообщения:
Опции сообщения:
Код безопасности:
Яндекс.Метрика
24 log 24 LOG statistick
счетчик посещений
Если вы видите это,
то ваш браузер устарел
и не поддерживает технологий
CSS 3.0