→ Пленочная клавиатура подключение к микроконтроллеру. Подключение к микроконтроллеру клавиатуры матричного типа. Схема с дисплеем и матричной клавиатурой

Пленочная клавиатура подключение к микроконтроллеру. Подключение к микроконтроллеру клавиатуры матричного типа. Схема с дисплеем и матричной клавиатурой

Зачастую свободных выводов микроконтроллера не хватает для подключения необходимого количества кнопок. При непосредственном соединении для n кнопок надо выделить столько же линий ввода-вывода, что не всегда возможно. Для более рационального использования линий портов можно воспользоваться матричной схемой подключения на рис.1. В данном случае матрица, подключённая к порту D, имеет размер 4*4=16 кнопок (4 строки r0…r3 и 4 столбца с0…с3). Линии PD0…PD3, являющиеся строками r0…r3, всегда настроены на ввод, и подтянуты к шине питания резисторами R (типичный номинал 4,7…10 кОм). С них и производится считывание состояния кнопок SB1-SB16. На линиях PD4…PD7 (столбцы с0…с3) поочерёдно формируется сигнал логического нуля. Первоначально низкий уровень устанавливается на столбце с0, а на всех остальных столбцах при этом Z-состояние. Теперь только при нажатии кнопок этого столбца (SB1…SB4) на линиях строк r0…r3 может возникнуть низкий логический уровень. Далее логический 0 выставляется на столбце с1 и сканируются группа кнопок SB5…SB8 и т.д. Точно такой же алгоритм опроса кнопок применяется и для любой другой матричной клавиатуры не зависимо от числа строк и столбцов. В общем случае количество кнопок n является произведением числа строк и столбцов. Так, например, матрица 2*2 (4 линии) будет содержать 4 кнопки. Но с другой стороны столько же линий ввода-вывода понадобится и для непосредственного подключения того же числа кнопок. Таким образом, экономия выводов начинает проявляться при числе кнопок, превышающем 4…6, и становится ещё более существенной с ростом их количества.

Рис.1 Матричная схема подключения кнопок

Элементы VD1…VD4, и R1…R4 не являются обязательными на схеме. Диоды служат для защиты от короткого замыкания между линиями строк и столбцов. Если, например, при нажатии на кнопку SB1 (в момент сканирования столбца c0) линия строки r0 вдруг окажется настроенной на вывод и на ней будет высокий логический уровень, то по цепи c0r0 начнет протекать недопустимо большой ток. Хотя логика программы не допускает такого режима работы, по разным причинам это все-таки может произойти. Поэтому, по крайней мере, при отладке программы диоды не будут лишними. Если емкость монтажа, приведенная к выводам PD3…PD0, не слишком велика, то сопротивления подтяжки к шине питания, вполне можно заменить внутренними “pull-up” резисторами. Для этого необходимо установить соответствующие разряды в регистре PORTD, когда линии настроены на ввод.

Пример подпрограммы сканирования матричной клавиатуры

Def button = R16 ;регистр с кодом нажатой кнопки.def temp = R17 ;регистр для промежуточных операций ldi temp,high(RAMEND) ;инициализация стека out SPH,temp ldi temp,low(RAMEND) out SPL,temp . clr temp ;настраиваем линии порта D на ввод out DDRD,temp ldi temp, (1 << PD0)|(1 << PD1)|(1 << PD2)|(1 << PD3) out PORTD,temp . rcall btn_pol . ; Подпрограмма опроса матричной клавиатуры; R16 – номер нажатой кнопки на выходе из подпрограммы, ; если ни одна кнопка не нажата, то R16=0; ; если нажаты две и более кнопок, то R16=0xFF ; R17 – регистр для определения номера строки; R18 – регистр для задания номера столбца; R19 – счётчик столбцов; R20 – регистр для промежуточных операций btn_pol: clr R16 ;обнуляем регистры с кодом нажатой clr R19 ;кнопки и номером столбца ldi R18,0x0F ;очищаем регистр данных PORTD порта D out PORTD,R18 ldi R18,0x00010000 bp1: out DDRD,R18 ;настраиваем на вывод линию соответствующего nop ;столбца через регистр DDRD порта D in R17,PIND ;считываем состояние строк из регистра PIND com R17 andi R17,0x0F ;выделяем значение 4-х строк ldi R20,0 ;если ни одна кнопка в столбце не нажата, breq bp5 ;перемещаемся на следующий столбец cpi R17,0x01 ;если нажата кнопка в строке c0, ldi R20,1 ;то вычисляем её номер breq bp2 cpi R17,0x02 ;если нажата кнопка в строке c1, ldi R20,2 ;то вычисляем её номер breq bp2 cpi R17,0x04 ;если нажата кнопка в строке c2, ldi R20,3 ;то вычисляем её номер breq bp2 cpi R17,0x08 ;если нажата кнопка в строке c3, ldi R20,4 ;то вычисляем её номер brne bp3 ;если нажато более одной кнопки, завершаем опрос bp2: tst R16 ;если в предыдущих столбцах были нажаты breq bp4 bp3: ldi R16,0xFF ;кнопки, то завершаем опрос с кодом 0xFF ret bp4: push R19 ;иначе вычисляем номер кнопки, как lsl R19 ;N = 4*column + row + 1 = 4*R19 + R20 + 1 lsl R19 add R20,R19 mov R16,R20 pop R19 bp5: inc R19 lsl R18 cpi R19,4 ;повторяем цикл опроса пока не будут brne bp1 ;опрошены все 4 столбца ret

При всех преимуществах матричная схема подключения обладает и одним недостатком. С её помощью тяжело реализовать чтение комбинаций кнопок. В случае, когда на такой клавиатуре будут нажаты любые три кнопки, образующие между собой прямой угол (например, SB1,SB2,SB5), то программой опроса будет зафиксировано ложное нажатие кнопки, лежащей в свободном углу прямоугольника (в данном случае SB6). При определённом раскладе такой “фантомной” кнопкой может оказаться любая кнопка на клавиатуре.

Список радиоэлементов

Обозначение Тип Номинал Количество Примечание Магазин Мой блокнот
DD1 МК AVR 8-бит

ATmega8

1 В блокнот
VD1-VD4 Диод 4 В блокнот
R, R, R, R Резистор 4

При необходимости использования в устройстве клавиатуры с большим количеством кнопок, например в кодовом замке, очень часто применяют матричную клавиатуру. Если подключить 12 кнопок обычным способом потребуется 12 выводов микроконтроллера плюс общий провод, в матрице же используется всего один порт контроллера, что способствует экономии выводов контроллера. Кнопки в такой клавиатуре подключаются к общим столбцам и к общим строкам, линии порта микроконтроллера разделяются на ввод PB7-PB4 и вывод PB3-PB0. В каждый момент времени сигнал низкого уровня (логический ноль) подается только на одну строку кнопок, на остальные должна подаваться логическая единица. Это исключит неоднозначность определения номера нажатой кнопки. Двоичные сигналы, присутствующие при этом на столбцах клавиатуры, считываются через порт ввода микроконтроллера.

В программе обязательно организовываем бесконечный цикл. В специальной функции производим опрос клавиатуры, анализируем полученные данные и выводим результата на индикатор. Опрос клавиатуры заключается в последовательном сканировании каждой строки, для этого на соответствующую линию порта вывода подается логический ноль (эквивалент общего провода), на остальных строках должен быть высокий уровень, после чего с порта ввода, к которому подключены столбцы, считывается код. Если считаны все единицы, то ни одна из клавиш не нажата, в противном случае код содержит информацию о нажатых клавишах. Стоит заметить, что считанный код содержит не только номер замкнутого контакта, но и информацию о нажатии нескольких кнопок одновременно, поэтому лучше хранить в памяти контроллера непосредственно считанный код, а не готовый номер кнопки. Для хранения считанного кода следует ввести специальный алгоритм и переменные.

Ниже показан пример программы в которой при нажатии определенной клавиши ее значение высвечивается на семисегментном индикаторе. Микроконтроллер Atmega8 работает от внутреннего генератора частотой 8MHz.

/*** Подключение матричной клавиатуры к микроконтроллерам AVR ***/ #include #include // Массив значений для порта вывода unsigned char key_tab = {0b11111110, 0b11111101, 0b11111011, 0b11110111}; // Функция опроса клавиатуры unsigned char scan_key(void) { unsigned char key_value = 0; unsigned char i; for(i = 0;i < 4;i++) { PORTB = key_tab[i]; // выводим лог. 0 в порт вывода _delay_us(10); switch (PINB & 0xF0) { case 0b11100000: key_value = 1 + i * 3; return (key_value); case 0b11010000: key_value = 2 + i * 3; return (key_value); case 0b10110000: key_value = 3 + i * 3; return (key_value); default: break; } } return (key_value); } int main(void) { // массив цифр для индикатора unsigned char num = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F}; DDRB |= (1 << PB3)|(1 << PB2)|(1 << PB1)|(1 << PB0); // Порт вывода DDRB &= ~(1 << PB7)|(1 << PB6)|(1 << PB5)|(1 << PB4); // Порт ввода PORTB = 0xF0; // Устанавливаем лог. 1 в порт ввода DDRD = 0xFF; // Выход на индикатор PORTD = 0x00; _delay_ms(10); while(1) { // Выводим значение нажатой кнопки на индикатор if(scan_key()==1) PORTD = num; if(scan_key()==2) PORTD = num; if(scan_key()==3) PORTD = num; if(scan_key()==4) PORTD = num; if(scan_key()==5) PORTD = num; if(scan_key()==6) PORTD = num; if(scan_key()==7) PORTD = num; if(scan_key()==8) PORTD = num; if(scan_key()==9) PORTD = num; if(scan_key()==11) PORTD = num; } }

Архив для статьи "Подключение матричной клавиатуры к микроконтроллерам AVR"
Описание: Проект AVRStudio и Proteus
Размер файла: 37.33 KB Количество загрузок: 1 905

Иногда мы сталкиваемся с проблемой нехватки портов на Arduino. Чаще всего это относится к моделям с небольшим количеством выводов. Для этого была придумана матричная клавиатура. Такая система работает в компьютерных клавиатурах, калькуляторах, телефонах и других устройств, в которых используется большое количество кнопок.

Для Arduino чаще всего используются такие клавиатуры:

Самыми распространенными являются 16 кнопочные клавиатуры 4x4. Принцип их работы достаточно прост, Arduino поочередно подает логическую единицу на каждый 4 столбцов, в этот момент 4 входа Arduino считывают значения, и только на один вход подается высокий уровень. Это довольно просто, если знать возможности управления портами вывода в Arduino , а так же портами входа/ввода.

Для программирования можно использовать специализированную библиотеку Keypad, но в этой статье мы не будем её использовать для большего понимания работы с матричной клавиатуры.

Подключаем клавиатуру в любые порты ввода/вывода.

На красные порты будем подавать сигналы, а с синих будем их принимать. Зачастую на синие провода подводят подтягивающие резисторы, но мы их подключим внутри микроконтроллера Arduino .

В программе будем вычислять нажатую кнопку и записывать её в Serial порт.
В данном методе есть один значительный недостаток: контроллер уже не может выполнять других задач стандартными методами. Эта проблем решается подключением матричной клавиатуры с использованием прерываний .

Int PinOut {5, 4, 3, 2}; // пины выходы int PinIn {9, 8, 7, 6}; // пины входа int val = 0; const char value { {"1", "4", "7", "*"}, {"2", "5", "8", "0" }, {"3", "6", "9", "#"}, {"A", "B", "C", "D"} }; // двойной массив, обозначающий кнопку int b = 0; // переменная, куда кладется число из массива(номер кнопки) void setup() { pinMode (2, OUTPUT); // инициализируем порты на выход (подают нули на столбцы) pinMode (3, OUTPUT); pinMode (4, OUTPUT); pinMode (5, OUTPUT); pinMode (6, INPUT); // инициализируем порты на вход с подтяжкой к плюсу (принимают нули на строках) digitalWrite(6, HIGH); pinMode (7, INPUT); digitalWrite(7, HIGH); pinMode (8, INPUT); digitalWrite(8, HIGH); pinMode (9, INPUT); digitalWrite(9, HIGH); Serial.begin(9600); // открываем Serial порт } void matrix () // создаем функцию для чтения кнопок { for (int i = 1; i <= 4; i++) // цикл, передающий 0 по всем столбцам { digitalWrite(PinOut, LOW); // если i меньше 4 , то отправляем 0 на ножку for (int j = 1; j <= 4; j++) // цикл, принимающих 0 по строкам { if (digitalRead(PinIn) == LOW) // если один из указанных портов входа равен 0, то.. { Serial.println(value); // то b равно значению из двойного массива delay(175); } } digitalWrite(PinOut, HIGH); // подаём обратно высокий уровень } } void loop() { matrix(); // используем функцию опроса матричной клавиатуры }

С использованием библиотеки считывание данных с цифровой клавиатуры упрощается.

#include const byte ROWS = 4; const byte COLS = 3; char keys = { {"1","2","3"}, {"4","5","6"}, {"7","8","9"}, {"#","0","*"} }; byte rowPins = {5, 4, 3, 2}; byte colPins = {8, 7, 6}; Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS); void setup(){ Serial.begin(9600); } void loop(){ char key = keypad.getKey(); if (key != NO_KEY){ Serial.println(key); } }

Резисторы R2 – R4, R8 – R11 предназначены для ограничения входного/выходного тока в случае неправильной настройки портов или одновременного нажатия нескольких кнопок. Выводы PD0(RXD), PD1(TXD) подключены к преобразователю UART-RS232, который на схеме не отображен. Обмен по USART`у используется для отладки программы.

Алгоритм опроса матричной клавиатуры

Строки клавиатуры подключены к выводам PD4, PD5, PD6, PD7. Они настроены на выход и в начальном состоянии на этих выводах напряжение логического нуля. Столбцы подключены к выводам PC0, PC1, PC2. Они настроены на вход, внутренние подтягивающие резисторы отключены и эти линии “придавлены к нулю питания” с помощью внешних резисторов номиналом в 10 КОм.

Процедура сканирования клавиатуры выглядит следующим образом. Выставляем 1 на выводе PD4 и проверяем состояние выводов PC0, PC1, PC2 (то есть считываем содержимое регистра PINC). Если на каком-то из выводов установлена 1, значит, на клавиатуре в данный момент нажата кнопка, подключенная к первой строке. Сохраняем биты PD4, PD5, PD6, PD7 и PC0, PC1, PC2 в одной переменной – по этому коды мы будем определять номер нажатой кнопки. Если ни одна из кнопок не нажата, продолжаем процедуру сканирования.

Сбрасываем 1 на выводе PD4 и устанавливаем 1 на выводе PD5. Снова проверяем состояние выводов PC0, PC1, PC2, и в случае нажатия кнопки сохраняем биты PD4, PD5, PD6, PD7 и PC0, PC1, PC2 в переменной.

Повторяем описанную последовательность для двух оставшихся строк.

Переключения кнопок клавиатуры сопровождаются дребезгом контактов, который микроконтроллер может “воспринимать” как многократные нажатия. В приложениях, использующих клавиатуры, это нежелательное явление, поэтому в программе опроса клавиатуры обязательно должна быть какая-нибудь защита. Обычно делают так - факт нажатия кнопки регистрируется, если она удерживается в течение нескольких циклов опроса.

Код, получаемый в процессе сканирования клавиатуры, часто требуется преобразовать в символьное значение номера/буквы кнопки (например, для передачи по USART`у). Для этого можно создать таблицу перекодировки - двумерный массив. В первом столбце таблицы будут храниться коды кнопок, а во втором соответствующие символьные значения. Методом последовательного перебора в таблице можно находить нужное значение.

Алгоритм опроса матричной клавиатуры можно реализовать в виде конечного автомата (State Machine) – функции, которая в зависимости от своего состояния (значения определенной переменной) и входного воздействия, выполняет разную работу. На рисунке ниже представлена диаграмма подобного автомат.

Начальное состояние автомата - 0. В этом состоянии автомат находится, пока не будет нажата какая-нибудь кнопка. Когда зафиксировано нажатие на кнопку, запускается функция сканирования клавиатуры ScanKey(), запоминается код нажатой кнопки и автомат переходит в состояние 1.

В состоянии 1 автомат проверяет, нажата ли в данный момент та же кнопка, что и в состоянии 0 или нет. Если коды кнопок не совпадают, автомат возвращается в состояние 0, если совпадают, запускается функция FindKey(), которая находит символьное значение номера кнопки и устанавливает флаги, сигнализирующие системе о нажатой кнопке. По завершению функции автомат переходит в состояние 2.

Пока удерживается одна и та же кнопка, автомат находится в состоянии 2. Если произошли какие-то изменения, он переходит в состояние 3.

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

Программная реализация автомата

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

//хранит текущее состояние автомата
unsigned char keyState;

//прототипы функций используемых автоматом
unsigned char AnyKey(void );
unsigned char SameKey(void );
void ScanKey(void );
unsigned char FindKey(void );
void ClearKey(void );

void ScanKeyboard(void )
{
switch (keyState){
case 0:
if (AnyKey()) {
ScanKey();
keyState = 1;
}
break;

case 1:
if (SameKey()) {
FindKey();
keyState = 2;
}
else keyState = 0;
break;

case 2:
if (SameKey()){}
else keyState = 3;
break;

case 3:
if (SameKey()) {
keyState = 2;
}
else {
ClearKey();
keyState = 0;
}
break;

Default:
break;
}

Довольно наглядная запись. Теперь все, что нам остается, это написать/разобрать реализации недостающих функций. Чтобы код программы был максимально понятным, давайте обойдемся без макроопределений. Итак, по порядку.


unsigned char AnyKey(void )
{
PORTD |= 0xf0;
return (PINC & 0x07);
}

Устанавливаем на выводах PD7 – PD4 единицы, возвращаем состояния выводов PC2 – PC0. Если какая-нибудь из кнопок клавиатуры в этот момент нажата, функция вернет значение отличное от нуля, то есть true.

//хранит код нажатой кнопки
unsigned char keyCode;

void ScanKey(void )
{
unsigned char activeRow = (1<<4);
while (activeRow) {
PORTD = (PORTD & 0x0f)|activeRow;
if (PINC & 0x07) {
keyCode = (PINC & 0x07);
keyCode |= (PORTD & 0xf0);
}
activeRow <<= 1;
}
}

Устанавливаем в 1 четвертый бит переменной activeRow (активизируем первую строку). Обнулив биты PD7 – PD4, записываем переменную в PORTD. Если какой-нибудь из трех младших разрядов регистра PINC установлен в единицу, значит в данный момент нажата кнопка, относящаяся к первой строке. Сохраняем биты PD7 – PD4 и PC2 - PC0 в переменную keyCode. Сдвигаем влево значение переменной activeRow на один разряд и повторяем цикл еще три раза.


unsigned char SameKey(void )
{
PORTD = (PORTD & 0x0f) | (keyCode & 0xf0);
return ((PINC & keyCode) & 0x07);
}

Функция проверяет, совпадает ли код нажатой в данный момент кнопки с кодом, полученным в предыдущем цикле опроса. Для этого на нужной строке устанавливается 1 – в PORTD записываются старшие 4 бита keyCode. Затем считывается регистр PINC, на него накладывается маска в виде переменной keyCode и выделяются 3 младших разряда. Полученное значение возвращается. Если коды кнопок совпадут, значение будет отлично от нуля, то есть true.


//хранит символьное значение нажатой кнопки
unsigned char keyValue;
//флаговая переменная - устанавливается, если кнопка удерживается
unsigned char keyDown;
//флаговая переменная - устанавливается, когда нажата новая кнопка
unsigned char keyNew;

//таблица перекодировки
__flash unsigned cha r keyTable = {
{ 0x11, "1"},
{ 0x12, "2"},
{ 0x14, "3"},
{ 0x21, "4"},
{ 0x22, "5"},
{ 0x24, "6"},
{ 0x41, "7"},
{ 0x42, "8"},
{ 0x44, "9"},
{ 0x81, "*"},
{ 0x82, "0"},
{ 0x84, "#"}
};

unsigned char FindKey(void )
{
unsigned char index;
for (index = 0; index < 12; index++) {
if (keyTable == keyCode) {
keyValue = keyTable ;
keyDown = 1;
keyNew = 1;
return 1;
}
}
return 0;

Aruna Rubasinghe

Матричные клавиатуры до сих пор еще применяются в качестве устройств ввода информации в проектах на микроконтроллерах. Обычный способ подключения такой клавиатуры к микроконтроллеру заключается в использовании нескольких портов ввода/вывода. В свою очередь, микроконтроллер выполняет алгоритм сканирования, чтобы определить, какая кнопка была нажата пользователем. Недостаток такого способа - необходимость использования достаточно большого количества портов микроконтроллера для обслуживания клавиатуры. Например, для подключения клавиатуры 4×3 потребуется семь свободных линий ввода/вывода. Это становится проблемой, когда в проекте планируется использование микроконтроллера с малым количеством выводов, или когда микроконтроллер не имеет свободных портов.

Для решения этой проблемы можно использовать специализированные микросхемы расширителей портов или цепочки резисторов для подачи определенного напряжения на каждую кнопку совместно с АЦП микроконтроллера для определения нажатия конкретной кнопки. Каждое решение имеет свои недостатки.

Многие расширители портов для обмена данными требуют коммуникации по специальным протоколам (например, I 2 C или SPI), потому в этом случае микроконтроллер должен иметь встроенные коммуникационные интерфейсы, или пользователь должен реализовать их программно, что повысит нагрузку на ядро. С другой стороны, назначение каждой кнопке определенного напряжения с помощью резисторов может быть затруднительным при большом количестве кнопок и приводит к сужению диапазона напряжений для каждой кнопки. Кроме того, сопротивление резисторов может изменяться с температурой, что совместно с узким диапазоном напряжений приведет к неправильному определению нажатий. Другой существенный недостаток этого способа - обязательное наличие в микроконтроллере аналогового входа (АЦП).

В статье мы рассмотрим способ подключения клавиатуры, который эффективно решает все вышеуказанные проблемы и имеет несколько преимуществ: требуются только две линии ввода/вывода независимо от числа используемых кнопок, не используются специальные коммуникационные протоколы, не нужен АЦП. Идея заключается в использовании двух доступных микросхем (десятичный счетчик-делитель).

На Рисунке 1 изображена схема модуля матричной клавиатуры 4×3. Резисторы R 1 , R 4 , R 5 и R 6 используются для ограничения тока; резистор R 7 , диоды D 4 , D 5 и D 6 образуют логический элемент ИЛИ.

Далее мы рассмотрим, как реализовать этот метод для сканирования кнопок матричной клавиатуры 4×3. Одна микросхема счетчика CD4017 используется для контроля строк (IC 2), другая - для контроля столбцов клавиатуры (IC 1).

Микроконтроллер генерирует тактовый сигнал и подает его на вход CLK счетчика, контролирующего столбцы. Первоначально выходы Q0 двух счетчиков находятся в состоянии лог. 1 и значение счетчика IC 1 инкрементируется на 1 с каждым тактовым импульсом. На четвертый импульс счетчик IC 1 сбрасывается и одновременно инкрементирует значение счетчика IC 2 , управляющего строками клавиатуры. Счетчик IC 2 сбросится через пять импульсов, поступающих от счетчика IC 1 , обслуживающего столбцы. При генерировании одного тактового импульса микроконтроллер должен инкрементировать значение переменной COUNT (Рисунок 2) и сбрасывать ее в 1 на пятом тактовом импульсе для счетчика IC 2 . Выход матричной клавиатуры через логический элемент ИЛИ подключается в выводу внешнего прерывания микроконтроллера.

Сигнал прерывания вырабатывается только в том случае, когда нажатой кнопке соответствует лог. 1 одновременно в строке и столбце. В обработчике прерывания микроконтроллер считывает значение переменной в момент, соответствующий нажатию кнопки.

Счетчик тактовых импульсов, реализованный в микроконтроллере, инкрементируется в моменты их генерирования. Значение в этом счетчике соответствует номеру нажатой кнопки на клавиатуре. Блок-схема программы микроконтроллера на Рисунке 2 наглядно демонстрирует этот алгоритм.

Обратите внимание, несмотря на то, что в примере мы рассматриваем клавиатуру 4×3, при данном способе можно управлять клавиатурой 10×10, задействовав оставшиеся выходы обеих микросхем CD4017. Кроме того, применив каскадное включение счетчиков, количество кнопок можно увеличить, если в этом есть необходимость.

Дополнительные материалы

Чтение состояния 10 и более кнопок с использованием двух линий ввода/вывода микроконтроллера - Журнал Радиолоцман (еще не публиковался) .

  • Первая же импульсная помеха от бритвы соседа - и кнопки меняются местами:)
  • Купи соседу бритву Жилет с антистатикой:-) По твоему, например, если сосед электросваркой дуговой увлекается, вокруг никто цифровой техникой не пользуется??? Судя по схеме - один через 3, другой через 4 такта ресетятся, что в динамике почти мгновенно, а про МК ты вообще забываешь при этом, хотя он на несколько порядков сложнее. На крайняк, хотя и существуют фильтры по питанию, но ManualReset никто не запрещал
  • Две микросхемы, пять резисторов и 10 диодов большая "цена" за экономию пяти выводов микроконтроллера за 12 кнопок. Конечно, можно сказать и за 100 кнопок эта плата. Но можно ли придумать такое устройство на 100 кнопок на микроконтроллере с 8 выводами? Такие устройства, как правило, используют отдельный микропроцессор, обслуживающий клавиатуру и соединяются с основным процессором интерфейсом, используя небольшое количество выводов, минимум один. Для познавательных целей схема интересна, для практического применения - не уверен.
  • Похоже, никто не понял непостижимой глубины моей эпической сентенции. Схема имеет 12 устойчивых состояний, в каждое из которых может перейти под управлением МК, или под действием помехи. Каждому состоянию будет соответствовать индивидуальная раскладка клавиш. В схеме отсутствуют средства сброса в начальное состояние! Даже после подачи питания!
  • Теоретически возможно, значит - желательно предусмотреть, а т.к. аппаратный сброс задействован в схеме, то монтажное ИЛИ +RC-цепочку для питания, но на практике что-то не сталкивался с хаосом в работе ИЕ8 и ещё раз повторю, как бы не встали триггеры, первый счётчик сбросится, за ним - второй, и всё хоккей...Прошла помеха...Да, есть маловероятный шанс, что ты успеешь нажать кнопку до сброса(который есть!) и с такой быстротой...Ну тогда ты -Шаман:-) Да, а по поводу цены вопроса...Разумеется, в проммасштабе, т.е. если всё покупать+монтаж+габариты+и т.д. - то на то и выйдет, но если в загашнике мешок старых микрух, то почему бы на МК не съэкономить?
  • Нет, не "теоретически возможно", а практически и принципиально эта схема не будет работать. Всё будет ОК, только если сброс триггеров произойдет вместе с подачей питания. Тогда после 12 импульсов опроса они вернутся в исходное состояние и синхронизм между схемой и программой сохранится. Но, во-первых, триггеры не обязаны сбрасываться по подаче питания (и на практике встают как попало). И во-вторых, любая помеха изменяет состояние триггеров в одно из 12-ти возможных. В итоге: в схеме не предусмотрена начальная установка состояния и у МК нет какого-либо способа прочитать текущее состояние или установить любое известное состояние. Поэтому синхронизм между программой и схемой будет наступать с вероятностью 8%. Неплохо для игрового автомата:)
  • Что-то кто-то где-то недоперепонял:-) Внутри 4017 все пять тригеров объединены по входу Reset, который выведен наружу, в данном варианте под именем MR, (куда можно вставить простейший Reset через кондёр(+) и резистор(-) Проц постоянно выдаёт такт (CLOCK), 4-й импульс положительным перепадом ресетит до нуля счётчик1 с выхода дешифратора1(Q3) и одновременно выдаёт первый такт на счётчик2, который через 4 на пятый обнулится всё по тому же входуMR с выхода дешифратора2(Q4), в наихудшем варианте счётчик2 по помехе станет в состояние дешифратора Q5=1, то ему придётся пройти почти полный круг, но так как всё это происходит постоянно и циклически, а внешнее прерывание происходит не по помехе, а по совпадению в момент нажатия единиц и там и там, то очень затруднительно нажать кнопку за время первого цикла после включения или помехи...Наверно ты имел ввиду возможность сдвига значений внутри МК и снаружи, но ведь и внутрений счётчик сбрасывается внешним прерыванием... Так что работать будет...
  • Это ещё надо подумать, как его туда прицепить, чтоб не было конфликта с синалами на других выводах, куда подключен этот сброс...
  • Но мы обсуждаем приведенную схему, и именно про нее я сказал, что она нерабочая. Ты начинаешь понимать, что косяк есть, и предлагаешь ее изменить, чтобы этот косяк исправить. Эти подробности рассматривать нет необходимости. Счетчик работает по кругу, проходя 12 равноценных состояний под управлением одного внешнего сигнала. Смотрите в общем. Между двумя схемами, между которыми происходит обмен, теоретически и практически возможна рассинхронизация, которая нарушит ее работу, и нет средств приведения частей в соответствие. Когда-нибудь ремонтировал видик Панасоник? Вынул шестеренки, вставил обратно - и привет. Меток на них не ставят, а стоять должны строго в определенном положении, о котором знает только Панасоник и управляющий процессор. Только схема об этом не может узнать, вот ведь засада какая. Исправить схему можно тремя способами. 1. Добавить линию из клавы в проц, означающую "начальное состояние". Тогда проц обязан долбить клоки до тех пор, пока на этой линии не появится сигнал - вот тогда можно начинать сканирование. 2. Добавить линию от проца в клаву и организовать по ней сброс в начальное состояние - тут всё очевидно. 3. Добавить одновибратор, который бы разрешал счет. После первого обращения он запускается и во время импульса можно произвести опрос. После окончания импульса счетчики сбрасываются в исходное. Все три способа будут работать. PS. Видоизменение 1-го способа без кардинальных изменений. Пожертвовать одной кнопкой, замкнув ее на постоянно. Тогда проц будет знать (в большинстве случаев), откуда начать сканирование. Так никто не делает и это лажа и моветон, но если будет стоять задача "ничего не менять, но чтобы работало", то так сделать можно.
  • Автору исходной схемы пользователи задают тот же самый вопрос - как насчет синхронизации? http://www.edn.com/design/power-mana...g-two-I-O-pins На что он советует применить линию с тремя состояниями:) То есть, автор косвенно признает, что есть проблема, но, желая оставаться в рамках идеи минимизации количества проводов, вынужден увеличивать число состояний одной линии с 2 до 3, что равносильно увеличению количества самих линий. http://www.edn.com/design/components...icrocontroller
  • Ну вот и добрались до сути, ты говоришь вообще не будет работать, я говорю будет, но с минимальными переделками (у журнала Радио научился не верить в то что видишь) и без использования 3-го порта...
  • Внутренняя схема счетчика CD4017 построена таким образом, что после прохождения 10, максимум, счетных импульсов он установится в одно из 10 разрешенных состояний, включая и нулевое. Произойдет это потому, что внутри счетчика присутствуют обратные связи, исключающие запрещенные состояния. Ну а дальше все будет синхронизироваться как пишет автор. Схема рабочая, кто не уверен может собрать и проверить, хотя и имеется одно "скользкое" место - схема сброса самого себя, работающая на задержках переключения. При таком построении импульс сброса будет очень коротким и теоретически возможен сброс не всех триггеров в ноль.
  • Вы меня не слышите. Я не говорил о кривых состояниях, которые теоретически возможны в триггерах без сброса. Я говорил о принципиальном отсутствии средств синхронизации между МК и схемой. Ну, тогда "на пальцах". Предположим, триггеры встали в состояние 5. МК об этом не знает и узнать не может - нет такого проводка. МК может только прогнать весь цикл сканирования, состоящий из 12 импульсов тактирования, и прочувствовать, на каком из импульсов на выходе появится логический уровень, соответствующий нажатой кнопке. ОК. После всего цикла сканирования триггеры окажутся опять в состоянии 5. Понимаете? Ну и что, что они во время сканирования прошли через сброс? МК об этом не знает! Нужен не сам сброс, а нужно четкое соответствие начала цикла сканирования и состояния внутреннего счетчика тактов в МК, как это обеспечивается в предложенной схеме? Покажите.
  • Да все всё слышат! Очень мало схем сразу начинают работать или работают нормально в одних условиях и совершенно не хотят(не могут) в других... Может, действительно, у автора нет вредных соседей.. ИМХО, приведённая схемка, приведёт к небольшому удорожанию, но позволит разрешить некоторые разногласия, хотя и не является вершиной конструкторской мысли:-))) PS. А если, вообще, Начинать отсчёт тактов с момента появления сигнала Interrupt, который одновременно коротким импульсом обнулит и счётчики, то за время нажатия вполне можно определить кнопку(не в этой схемке) PPS. Меня терзают смутные сомнения...А зачем вообще считать всё время? Или я не доглядел? Кстати, что это за ФункшнБаттон у автора? в левой ветке алгоритма, если это и есть инициализация счётчика тактов от нажатия любой кнопки, то весь наш спор почти бред, если нет, то так и надо сделать програмно, заменив счётчики на обычные, с предустановкой в 1111 и 1111 ну и используя только однозначные пересечения.
  • Вы все правильно говорите, но мы обсуждаем конкретную схему, а синхронизация это задача проца и программиста. Самое простое договориться (написать в эксплуатационной документации), что после включения питания нажимается конкретная любая кнопка, от которой проц начинает отсчет.
  • Ну слава б-гу. Нет, мои схемы я буду делать так, чтобы они работали всегда. Представьте, вы сделали разработку, всё готово, можно показывать шефу. Шеф включает прибор, нажимает кнопку 5, на табло вылетает цифра 9. Шеф смотрит на табло, на вас и говорит - "а чё за х-нь?" И вы начинаете объяснять, что мы, мол, напишем инструкцию, как правильно включать прибор:) Ладно, написали, запустили. Потом прибегает операторша и говорит: "Здесь клавиатура постоянно глючит! Работает 5 минут, а потом вместо одной цифры бьётся другая!" - а вы ей терпеливо начинаете объяснять, что состояние регистров процессора не обязано соответствовать актуальному состоянию счетчиков в клавиатуре и что синхронизация - это дело программиста:) А может, лучше не экономить проводок, а сделать сразу, чтобы работало?
  • В первом своем посте в теме я об этом и писал.
  • Ребята, давайте жить дружно! И не путать работу с хобби, ведь не управление реактором и не постройка храма обсуждается, а всего лишь какая-то хренотень(Прим. Тень, отбрасываемая кустом Хрена на близко расположенные предметы), которая якобы чем-то управляет, и дружно последуем совету из темы про клеточные автоматы, не дадим победить Матрице!!!, и будем держать в кармане кнопку "MasterReset"...

 

 

Это интересно: