CraftDuino v2.0
  • - это CraftDuino - наш вариант полностью Arduino-совместимой платы.
  • CraftDuino - настоящий конструктор, для очень быстрого прототипирования и реализации идей.
  • Любая возможность автоматизировать что-то с лёгкостью реализуется с CraftDuino!
Просто добавьте CraftDuino!

SPI и Arduino: плодим входы

SPI и Arduino:
  1. Теория
  2. Вывод
  3. Ввод

Теперь попробуем считать состояние нескольких кнопок через другой сдвиговый регистр, предназначенный для ввода — 74HC165, модель SN74HC165N от Texas Instruments. Этот регистр, в отличие от рассмотренного ранее 74HC595, работает наоборот — преобразует параллельный интерфейс в последовательный. Но порядок работы немного другой: сначала дёргается линия SS вниз-вверх — состояния входов «защёлкиваются» во внутренний регистр, а уже потом идёт тактирование по SCLK и передача данных по MISO.

Чтобы понять, как работает регистр, взглянем на его схему:



Вход SH/L͞D (сдвиг/загрузка) управляет занесением состояний входов в триггеры — так называемой параллельной загрузкой: стоит прижать его к «земле», как состояние входов регистра будет подано на S-входы триггеров. Чтобы отключить триггеры от входов регистра и иметь возможность читать из регистра, нужно установить SH/L͞D в 1. Тактирование происходит при переходе CLK из 0 в 1 при условии, что SH/L͞D = 1 (параллельная загрузка отключена), а CLK INH = 0 (тактирование включено). При каждом «тике» CLK каждый триггер проталкивает бит в следующий триггер, захватывая бит со своего 1D-входа. Так как к 1D-входу первого триггера подключен вход SER, то подаваемые на него биты проталкиваются в регистр, позволяя соединять регистры в цепочки. В конечном итоге проталкиваемые биты достигают выхода последнего регистра, где подаются сразу на два вывода — на QH и, через инвертор, на Q͞H.

А вот и сам регистр в DIP-корпусе:



Назначение выводов:
  • Vcc — питание
  • GND — земля
  • SH/L͞D — защёлка, SS (SPI)
  • CLK — тактовый вход, SCLK (SPI)
  • A-H — входы, состояние которых считывается в регистр
  • QH — последовательный вывод, MISO (SPI)
  • Q͞H — инверсный вывод, на нём идут биты с QH, но инвертированные
  • SER — последовательный ввод; к нему можно подсоединить вывод QH второго регистра, получив каскадное подключение
  • CLK INH — Clock Inhibit, или инвертированный Clock Enable; когда на нём 1, тактирование выключено
Попробуем считать состояние 8 кнопок, подключенных к выводам A-H регистра. Для этого подключим выводы следующим образом:
  • Vcc ⇨ +5 В
  • GND ⇨ GND
  • SH/L͞D ⇨ пин 8
  • CLK ⇨ пин 13
  • QH ⇨ пин 12
  • Q͞H оставим неподключенным
  • SER ⇨ GND
  • CLK INH ⇨ GND
Кнопки сажаем на выводы A-H, подтягивая к питанию резисторами на 10 кОм, и на землю:



Получилась такая каша из проводов, что мои mad skillz в делах рисовальных не помогли, так что постарайтесь как-нибудь догадаться, что куда идёт (:



Лепить на макетку ещё и светодиоды было бы слишком, поэтому состояния кнопок будем слать по UART и смотреть через Serial Monitor. Поехали:

#include <SPI.h>

enum { REG_LATCH = 8 };


void setup()
{
  /* Включаем UART и SPI */
  Serial.begin(9600);
  SPI.begin();
  /* Включаем защёлку */
  pinMode(REG_LATCH, OUTPUT);
  digitalWrite(REG_LATCH, HIGH);
}


void loop()
{
  static uint8_t last_input_states = 0;

  /* Выставим на защёлке сначала низкий, потом - высокий уровни.
   * Сдвиговый регистр запомнит уровни сигналов на входах и сможет
   * их нам потом отдать бит за битом.
   */
  digitalWrite(REG_LATCH, LOW);
  digitalWrite(REG_LATCH, HIGH);
  /* Читаем запомненные состояния входов. Ноль шлём просто потому,
   * что transfer() одновременно и шлёт, и принимает. Да и вообще,
   * MOSI не подключена (:
   */
  uint8_t states = SPI.transfer(0);

  /* Если состояние любого входа изменилось, расскажем по UART */
  if (states != last_input_states)
  {
    /* Старый добрый XOR даст нам битовую разницу между старым и новым состояниями. */
    uint8_t changed = states ^ last_input_states;
    last_input_states = states; // запоминаем текущие состояния

    for (int i = 0; i < 8; ++i)
    {
      if (changed & 1) // если состояние кнопки изменилось…
      {
        Serial.print("#");
        Serial.print(i); // шлём номер кнопки
        Serial.print(" -> ");
        Serial.println(states & 1); // … и новое состояние
      }

      /* Сдвигаем биты вправо. Теперь первый бит
       * будет указывать состояние следующей кнопки.
       */
      changed >>= 1;
      states >>= 1;
    }
  }
}




С каскадным подключением история такая же, как и с 74HC595, только здесь вывод QH второго регистра подключается к выводу SER первого и т.п. Или, как вариант, использовать выводы Q͞H вместо QH, если нужно считать много кнопок, подтянутых к питанию.

Исходник примера доступен для скачивания напрямую и на GitHub в репозитории.

Картинки из статьи лежат в альбоме на Яндекс.Фотках.

Использовалось железо:
  • +1
  • 12 мая 2011, 14:20
  • burjui

Комментарии (33)

RSS свернуть / развернуть
+
0
если в программе есть задержки вроде delay(1000) (вне цикла проверки состояни), будут ли корректно считаны состояния регистра?
avatar

lehha

  • 12 мая 2011, 20:19
+
0
Да, всё считается нормально: задержки никак не повлияют на считывание. Тут могут быть только проблемы с дребезгом контактов у кнопок.
avatar

burjui

  • 13 мая 2011, 02:34
+
0
угу, только если кто-то успеет нажать-отпусть кнопку в течении этой (односекундной)задержки нажатие потеряется=)
avatar

Zoltberg

  • 13 мая 2011, 09:23
+
+1
поэтому в любом коде больше чем на 3 строки задержки лучше делать через конечный автомат, а не через delay()
avatar

xtile

  • 23 мая 2011, 14:34
+
+1
Конечные автоматы рулят: мы с коллегой на прошлой работе на КА весь «AI» в игрульке делали (казуальная, стиль time-management). Если приправить random()'ом, получается почти живое существо (:
avatar

burjui

  • 23 мая 2011, 14:38
+
+1
думаю, живое существо — это и есть конечный автомат с random()-ом :)))
avatar

noonv

  • 23 мая 2011, 15:35
+
+2
ИИ — рекурсивный рандом(с)
avatar

Zoltberg

  • 23 мая 2011, 19:51
+
0
а чем можно увеличить число входов на которые можно повесить прерывание?
Ну что бы например понять какая из кнопок была нажата первой.
avatar

nubas

  • 24 мая 2011, 12:39
+
0
Для таких задач вам нужен мультиплексор прерываний вроде PCA9544A, но это дорогие микросхемы: минимальная цена, которую я видел — 3$.
avatar

burjui

  • 24 мая 2011, 18:16
+
0
У меня в местном магазине нет «74HC165, модель SN74HC165N от Texas Instruments»
Можете посоветовать близкий аналог?
avatar

Sicness

  • 27 июня 2011, 17:13
+
0
SN54HC166/SN74HC166, CD4014B, SN74LS647, 74F676, SL74HC597, SN74LS395A/SN54ALS299/SN74ALS299 (универсальные сдвиговые регистры). У них ещё бывают всякие модификации с другими буквами — типа 74LS165 вместо 74HC165. Даже если ничего этого в вашем магазине нет, можете попросить у них на заказ, ну или заказать у нас, если не ломает доставка robocraft.ru/store/catalog/16 (:
avatar

burjui

  • 27 июня 2011, 19:45
+
0
Ребята, спасайте всю голову затуркал не как не получается подрубить каскад из 4х HC165, пробовал и через SPI_Bus библеотеку из соседнего поста, помогите, подскажите плиз как это реализовать?
ЗЫ. заранее благодарен.
avatar

michaeltex

  • 19 октября 2011, 15:35
+
0
Завтра протестирую каскад и отпишусь.
avatar

burjui

  • 20 октября 2011, 18:01
+
0
Заранее благодарен))))
avatar

michaeltex

  • 21 октября 2011, 01:33
+
+1
Извини за задержку, решил ответить так, чтобы всем было хорошо (:
Читай robocraft.ru/blog/arduino/618.html
avatar

burjui

  • 22 октября 2011, 18:18
+
0
Ё маё спасибо Огромное черезмерно благодарен!!!;)
avatar

michaeltex

  • 22 октября 2011, 23:27
+
+1
На схеме распиновка регистра неправильная — Vcc и GND. Поправьте…
avatar

GraninDm

  • 1 ноября 2011, 08:52
+
0
Поправил, спасибо (:
avatar

burjui

  • 1 ноября 2011, 10:53
+
0
Как можно расширить аналоговые порты!? Какие микрухи юзать :) Заранее спасибо!
avatar

Makep

  • 2 ноября 2011, 08:43
+
+1
robocraft.ru/forum/viewtopic.php?f=14&t=72&hilit=%D0%BA%D0%BF2
там схема есть, + немного почитать что такое мультиплексор.
ну или подождать немного -может мы скоро статьей разродимся на эту тему.
avatar

Zoltberg

  • 2 ноября 2011, 10:18
+
0
Благодарю! Почитаем.
avatar

Makep

  • 2 ноября 2011, 10:20
+
0
Использовалось железо:
здесь указано что использовались резисторы 510 Ом, а по тексту написано что 10 кОм.
avatar

BasiC

  • 8 июля 2012, 23:31
+
0
Использую в своем проекте M74HC595N. Прототип собран, работает отлично. Но! Их у меня там 18! Подскажите, какой-нить 16-битный регист, а еще лучше 32-битный, чтоб сократить кол-во элементов.
Спасибо!
avatar

BBird

  • 15 октября 2012, 09:32
+
0
Нагугливаются только 16-битные 74F676, но они везде дорогие. Можно на alibaba.com посмотреть (там цены гуманные), но я сам оттуда не заказывал ничего, так что больше помочь ничем, увы, не могу.
avatar

burjui

  • 16 октября 2012, 18:37
+
0
Купил STP16CP05 — работают прекрасно.
Но мне в итоге нужно в итоге нужно построить матрицу 3*60 и я решил еще сократить кол-во элементов. Хочу 1-им регистром (4-бит.) переключать строки и 4-мя регистрами (16-бит.) мигать светодиодами в этой строке.
Нашел в инете инфу о 4-бит. регистре STP04CM05, того же производителя и из той же серии что и STP16CP05, но нигде не могу его купить.

Соответственно вопрос: как вообще грамотно подобрать компоненты чтоб они без проблем работалм друг с другом, есть ли какие-то критерии, на какие параметры обращать внимание?
avatar

BBird

  • 24 октября 2012, 10:14
+
0
Тут я небольшой помощник — сам в электронике разбираюсь слабо: ничего, кроме описанного в моих статьях, толком не знаю (:
avatar

burjui

  • 24 октября 2012, 10:27
+
0
Обычно, достаточно посмотреть только напряжения питания и логические уровни. В случае ардуины — чтобы могли питаться от 5В, за лог. ноль понимали 0В за лог.еденицу 5В.
avatar

Zoltberg

  • 24 октября 2012, 13:35
+
0
Спасибо.
Я так и подбираю, но подумал вдруг еще есть какие-то важные параметры.
avatar

BBird

  • 25 октября 2012, 04:47
+
0
подскажите на сколько принципиально будет отличаться схема при использовании hc166? и можно ли реализовать работу с ним не через spi или на ногах отличных от дефолтовых spi?
avatar

deathbel

  • 28 марта 2013, 21:10
+
0
разобрался я со своим вопросом, что называется RTFM.
avatar

deathbel

  • 28 марта 2013, 21:57
+
0
Можно ли подключить к ардуине одновременно сдвиговый регистр ввода и вывода — и если да, то как правильно это сделать имея 74HC165 и 74HC595?

Спасибо за ответ.
avatar

rashn

  • 25 декабря 2013, 18:43
+
0
avatar

Zoltberg

  • 26 декабря 2013, 21:36
+
0
Подскажите, пожалуйста, как в данном скетче обработать нажатие кнопки? То есть, как при нажатии на одну кнопку включить, например, светодиод?
avatar

Blidge

  • 16 июня 2015, 02:22

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