Часть 2. Размножение входов или shiftIn
(окончание, начало см. Часть 1. Размножение выходов или shiftOut)
(окончание, начало см. Часть 1. Размножение выходов или shiftOut)
Представим себе обратную ситуацию – есть много входов (например, от датчиков контактного типа или, попросту говоря - кнопок), которые надо считывать. И если универсальные пины Arduino легким движением руки при помощи оператора pinMode() превращаются в брюки во входы или выходы, то время вспомнить, что за такую универсальность приходится расплачиваться довольно сложной схемой пина, в которой, на самом-то деле, входная и выходная части отделены друг от друга.
Для рассмотренной в предыдущей части микросхемы 74HC595 существует "брат-близнец" 74HC597 - Serial-out Shift register w/Latches, который работает с точностью до наоборот: по команде "защелкивает" данные на входе, которые затем можно считать последовательно:
Работать с такой микросхемой надо аналогичным образом, учитывая назначение выводов:
Думаю, скетч напишется без труда, я же воздержусь от теоретических и потенциально неработоспособных примеров - этого чипа у меня под рукой не оказалось. Но не огорчайтесь, у меня в запасе есть и другие варианты ;)
Кстати, защелка по входу в нашем применении не нужна, можно использовать чип и без оной. Рассмотрим CD4021B, восьмибитный регистр с последовательным или параллельным входом и последовательным выходом:
PI-# - в данном случае расшифровывается как Parallel In, всего восемь входов.
CLOCK - вход тактовых импульсов, которые должен генерировать микроконтроллер, при каждом происходит сдвиг на один разряд.
PARALLEL/SERIAL CONTROL - официально управляет режимом по входу - единица соответствует параллельному входу, ноль - последовательному. На практике получается чуть интереснее: пока режим параллельный - по каждому фронту CLOCK происходит обновление состояния всех восьми бит регистра. Если мы хотим "зафиксировать" состояние всех восьми выводов в определенный момент времени, надо дать один CLOCK в параллельном режиме, а потом перейти в последовательный - и прочесть 8 бит - при этом счетчик заполнится тем, что поступит со входа SERIAL IN, а Arduino к этому моменту получит все 8 бит информации, записанной в режиме параллельного ввода. Поэтому, иногда этот вход на схемах маркируют как latch - по смыслу того, что он делает.
Q6, Q7, Q8 - это выходы соответствующих разрядов последовательного счетчика, для использования всех восьми разрядов надо считывать данные с Q8.
Вообще, серия 4000В - не очень скоростная (соответствует нашей 1561), максимальное быстродействие 90 нс. Учтите, что мы-то ее будем использовать не на предельном питании +15 В, так что готовьтесь к 160...320 нс, тактировать её можно с частотой 3..6 МГц. Немного, но для считывания, например, механических контактных групп - вполне подойдет.
Схема будет выглядеть очень похожим образом:
Номинал резисторов на этой схеме - 10К, смысл академический - нельзя "бросать" вход КМОП-схемы в плавающем состоянии, на нем должен быть устойчивый потенциал.
К сожалению, синтаксис Wiring не может нас порадовать отдельным оператором shiftIn, но при необходимости ее можно написать самостоятельно. Вот пример кода, считывающего значения кнопок с предыдущей схемы:
Прием с каскадированием для повышения разрядности:
Скетч при этом почти не изменится:
Разрядность переменной, в которую читается состояние увеличилась в два раза - с 8 до 16 бит, чтение выполняется за 16 тактов. В остальном - тоже самое.
Часто бывает так, что импортный чип достать сложнее, зато наш (советский или белорусский) валяется без дела, да так и просится в схему. Мне в свое время сильно помог К561ИР9 (функциональный аналог CD4035B):
RESET - сброс всех разрядов в ноль в произвольный момент времени.
PI1..PI4 - параллельные входы, как в CD4021.
Q1..Q4 - это параллельные выходы, как в 74HC595 (см. часть 1)
J/K - это последовательный вход. Замечу, что он выполнен в виде J/K триггера, и если J и К соединить, то получится D-триггер, как в CD4021.
P/S - управление режимом ввода, как в CD4021. По логической единице будут записаны данные с параллельных входов, по нулю - с последовательного входа J/K.
T/C - прямой/дополнение (true/complement). Микросхема универсальна до такой степени, что умеет менять знак у выводимого кода (т.е. выдавать не само число, а дополнение к нему). Нам это навряд ли понадобится, поэтому притянем этот вход к Vcc - это вечный true.
Как вы успели заметить, из-за обилия функциональности регистр получился всего в четыре разряда, но нас выручит старый трюк с каскадированим. Единственный существенный недостаток - это отсутствие отдельной защелки и третьего состояния на шине параллельного вывода, как в 595-ой микросхеме.
Можно использовать скетчи от предыдущих примеров практически без изменений:
Время взвешивать за и против.
Плюсы Arduino / Seeeduino Mega: компактность, гибкость, быстродействие, попутно получаем 128К памяти программ.
Плюсы логических микросхем: цена решения, на надо платить за лишнее/неиспользуемое, нагрузочная способность линии, доступность.
Казалось бы, на этом можно ставить точку, но... спустя какое-то время появилась и третья статья про увеличение числа пинов Arduino.
(в тексте использованы материалы статьи Parallel to Serial Shifting-In with a CD4021BE).
Для рассмотренной в предыдущей части микросхемы 74HC595 существует "брат-близнец" 74HC597 - Serial-out Shift register w/Latches, который работает с точностью до наоборот: по команде "защелкивает" данные на входе, которые затем можно считать последовательно:
Работать с такой микросхемой надо аналогичным образом, учитывая назначение выводов:
- D0-D7 - параллельные входы;
- Ds - последовательный вход от предыдущего чипа (для каскадирования);
- Q - последовательный выход;
- MR - инверсный сигнал сброса (активен в LOW);
- SHCP - синхронизация регистра
- STCP - синхронизация защелки
- PL - инверсный сигнал записи с параллельных входов (активен в LOW).
Схема:
Думаю, скетч напишется без труда, я же воздержусь от теоретических и потенциально неработоспособных примеров - этого чипа у меня под рукой не оказалось. Но не огорчайтесь, у меня в запасе есть и другие варианты ;)
Кстати, защелка по входу в нашем применении не нужна, можно использовать чип и без оной. Рассмотрим CD4021B, восьмибитный регистр с последовательным или параллельным входом и последовательным выходом:
PI-# - в данном случае расшифровывается как Parallel In, всего восемь входов.
CLOCK - вход тактовых импульсов, которые должен генерировать микроконтроллер, при каждом происходит сдвиг на один разряд.
PARALLEL/SERIAL CONTROL - официально управляет режимом по входу - единица соответствует параллельному входу, ноль - последовательному. На практике получается чуть интереснее: пока режим параллельный - по каждому фронту CLOCK происходит обновление состояния всех восьми бит регистра. Если мы хотим "зафиксировать" состояние всех восьми выводов в определенный момент времени, надо дать один CLOCK в параллельном режиме, а потом перейти в последовательный - и прочесть 8 бит - при этом счетчик заполнится тем, что поступит со входа SERIAL IN, а Arduino к этому моменту получит все 8 бит информации, записанной в режиме параллельного ввода. Поэтому, иногда этот вход на схемах маркируют как latch - по смыслу того, что он делает.
Q6, Q7, Q8 - это выходы соответствующих разрядов последовательного счетчика, для использования всех восьми разрядов надо считывать данные с Q8.
Вообще, серия 4000В - не очень скоростная (соответствует нашей 1561), максимальное быстродействие 90 нс. Учтите, что мы-то ее будем использовать не на предельном питании +15 В, так что готовьтесь к 160...320 нс, тактировать её можно с частотой 3..6 МГц. Немного, но для считывания, например, механических контактных групп - вполне подойдет.
Схема будет выглядеть очень похожим образом:
Номинал резисторов на этой схеме - 10К, смысл академический - нельзя "бросать" вход КМОП-схемы в плавающем состоянии, на нем должен быть устойчивый потенциал.
К сожалению, синтаксис Wiring не может нас порадовать отдельным оператором shiftIn, но при необходимости ее можно написать самостоятельно. Вот пример кода, считывающего значения кнопок с предыдущей схемы:
#define DATA 9 #define LATCH 8 #define CLOCK 7 #define CLKUS 1 byte dataInput; void setup() { pinMode(DATA,INPUT); pinMode(LATCH,OUTPUT); pinMode(CLOCK,OUTPUT); Serial.begin(9600); } void loop() { dataInput = 0; digitalWrite(LATCH,HIGH); // Parallel mode for (int i=7; i>=0; i--) { digitalWrite(CLOCK,HIGH); delayMicroseconds(CLKUS); dataInput |= (digitalRead(DATA) ? (1<<i) : 0); digitalWrite(CLOCK,LOW); delayMicroseconds(CLKUS); if (i==7) digitalWrite(LATCH,LOW); // Serial Mode } Serial.println(dataInput, BIN); delay(1000); }В основном теле loop() раз в секунду происходит считывание всех кнопок путем кратковременной подачи высокого уровня на пин LATCH. Дальше в цикле формируется восемь перепадов CLOCK и данные запишутся в соответствующие разряды переменной dataInput, после чего будут в двоичном формате выведены в последовательный порт (наблюдайте результаты в мониторе последовательного порта). Задержки умышленно даны с запасом, если есть желание - попробуйте их уменьшить до предела по документации.
Прием с каскадированием для повышения разрядности:
Скетч при этом почти не изменится:
#define DATA 9 #define LATCH 8 #define CLOCK 7 #define CLKUS 1 word dataInput; void setup() { pinMode(DATA,INPUT); pinMode(LATCH,OUTPUT); pinMode(CLOCK,OUTPUT); Serial.begin(9600); } void loop() { dataInput = 0; digitalWrite(LATCH,HIGH); // Parallel mode for (int i=15; i>=0; i--) { digitalWrite(CLOCK,HIGH); delayMicroseconds(CLKUS); dataInput |= (digitalRead(DATA) ? (1<<i) : 0); digitalWrite(CLOCK,LOW); delayMicroseconds(CLKUS); if (i==15) digitalWrite(LATCH,LOW); // Serial Mode } Serial.println(dataInput, BIN); delay(1000); }
Разрядность переменной, в которую читается состояние увеличилась в два раза - с 8 до 16 бит, чтение выполняется за 16 тактов. В остальном - тоже самое.
Часто бывает так, что импортный чип достать сложнее, зато наш (советский или белорусский) валяется без дела, да так и просится в схему. Мне в свое время сильно помог К561ИР9 (функциональный аналог CD4035B):
RESET - сброс всех разрядов в ноль в произвольный момент времени.
PI1..PI4 - параллельные входы, как в CD4021.
Q1..Q4 - это параллельные выходы, как в 74HC595 (см. часть 1)
J/K - это последовательный вход. Замечу, что он выполнен в виде J/K триггера, и если J и К соединить, то получится D-триггер, как в CD4021.
P/S - управление режимом ввода, как в CD4021. По логической единице будут записаны данные с параллельных входов, по нулю - с последовательного входа J/K.
T/C - прямой/дополнение (true/complement). Микросхема универсальна до такой степени, что умеет менять знак у выводимого кода (т.е. выдавать не само число, а дополнение к нему). Нам это навряд ли понадобится, поэтому притянем этот вход к Vcc - это вечный true.
Как вы успели заметить, из-за обилия функциональности регистр получился всего в четыре разряда, но нас выручит старый трюк с каскадированим. Единственный существенный недостаток - это отсутствие отдельной защелки и третьего состояния на шине параллельного вывода, как в 595-ой микросхеме.
Можно использовать скетчи от предыдущих примеров практически без изменений:
- в режиме ввода считывать данные последовательным кодом с digital9
- в режиме вывода подавать последовательный код через digital10.
Время взвешивать за и против.
Плюсы Arduino / Seeeduino Mega: компактность, гибкость, быстродействие, попутно получаем 128К памяти программ.
Плюсы логических микросхем: цена решения, на надо платить за лишнее/неиспользуемое, нагрузочная способность линии, доступность.
Казалось бы, на этом можно ставить точку, но... спустя какое-то время появилась и третья статья про увеличение числа пинов Arduino.
(в тексте использованы материалы статьи Parallel to Serial Shifting-In with a CD4021BE).
Большое спасибо за статьи!
ОтветитьУдалитьХотелос-бы еще услышать статью о расширении аналоговых входов, когда надо поставить не много кнопочек, а например много резисторов :)
И очень полезно, было-бы если вы выкладывали схемы из статей, в формате проэктов "Протеуса".
Не всегда хватает умения собрать обсуждаемую схему не только в железе но и в эмуляторе. А для вас я думаю это труда не составит.
Спасибо.
О, спасибо за отзыв! Просто даже силы появляются писать, когда знаешь, что кому-то это интересно ;)
ОтветитьУдалитьСхемы я рисую в Eagle, про Proteus много слышал - типа, что это такая сублимация для тех, кто ленится даже собрать на макетке ;)
Использовал PCF8574 для расширения выходов в свое время (LCD приделывал). На сколько знаю, данная микросхема I/O, т.е можно сразу и писать и читать (причем, согласно спецификации, даже в комбинации, т.е. часть портов читаем, а в часть пишем). Хотя, я еще не пробовал читать через нее.
ОтветитьУдалитьЯ пробовал читать/писать с PCF8574, проблем нет. Только про работу в комбинации первый раз слышу...
ОтветитьУдалить>> Например, от датчиков контактного типа или, попросту говоря - кнопок.
ОтветитьУдалитьНе совсем верно с кнопками сравнивать - кнопки аккордами редко когда надо читать. А без аккордов можно и без дополнительных микросхем увеличить разрядность.
Я ничего не сравнивал ;) Я привел пример ;)
ОтветитьУдалитьА как можно прицепить CD4021 или 74hc597(а лучше и то и то) напрямую к COM порту(или не напрямую, без контроллера)
ОтветитьУдалитьРискну предположить, что через согласующую схему. Например, через MAX232CPE.
ОтветитьУдалитьДопустим! Тгда вопрос как? Может есть где горовые рисунки...или нарисуте мне кто-нибудь пожалуйста..
ОтветитьУдалитьПочитайте даташит, там вполне доступно описано! В этом чипе два четыре конвертера - два перехода с COM на TTL и два - обратно. Подключите так, как требует Ваша задача. В качестве примера рекомендую изучить схему Freeduino MaxSerial.
ОтветитьУдалитьБлин, у меня не получиться... я в схемах дундук! Могу только спаять.
ОтветитьУдалитьИ наверно я очень нагло буду выглядеть... а как управлять этими регистраммичерез vb 6.0
хмм ... жуть какая
ОтветитьУдалитьнет ну можно конечно из VB через MSComm управлять CLOCK/LATCH модемными линиями DTR/RTS , а по линии DSR читать данные с регистра, но мягко говоря это как-то не выглядит разумным решением.
А сделать "честный" UART на регистре сдвига без микронтроллера затруднительно.
http://svetelektro.com/Pictures/PC_prislusenstvo/4021/obr1.png вот готовый вариант подцепления к com-порту.
ОтветитьУдалитьКто с исходниками на vb 6.0 может помоч?
Или есть еще регистр интересный 74hc597, суть впринцыпе аналогичная. И есть брат близнец, работает наоборот, вот у меня есть схема и исходники управления.. Может кто по аналогии на 74hc595 сможет перестроить?
У CD4021 разве не 8 - GND, 16 - VDD?
ОтветитьУдалитьИсправил, спасибо!
ОтветитьУдалитьЗдравствуйте Илья,
ОтветитьУдалитьспасибо за статью. У вас отсутствует код для записи в Q* К561ИР9 в явном виде. Вот он:
void put595(byte output) {
for (int i = 0; i < OUT_PINS; ++i) {
digitalWrite(OUTDATA, output & 1);
digitalWrite(CLOCK, HIGH);
delay(CLKUS);
digitalWrite(CLOCK, LOW);
delay(CLKUS);
output >>= 1;
}
}
Не могу сообразить какую роль в строке
ОтветитьУдалитьdataInput |= (digitalRead(DATA) ? (1<<i) : 0);
играют символы "?" и ":"
Объясните пожалуйста начинающему
Это условный оператор. Сначала вычисляется выражение до вопросительного знака, и если оно не равно нулю, возвращается результат выражения между вопросительным знаком и двоеточием, а если равно нулю - тогда возвращается то, что после двоеточия.
Удалить