Матричная клавиатура 4х4

Когда писал об организации меню в МК использовал клавиатуру 2х2 и не описал какой принцип сканирования клавиатуры. Сейчас хочу исправить это упущение. 
Давайте подключим к МК клавиатуру 4х4. Каков же принцип работы такой клавиатуры? На самом деле все довольно просто:
  1. У нас есть биты порта настроенные на выход (в нашем случае будут биты 0-3 PORTD) и есть биты настроенные на вход (биты 4-7 PORTD).
  2. На выходах единица. На входах включен подтягивающие резисторы.
  3. Устанавливаем один из битов выхода в нуль и проверяем все входы порта на нуль. Если на входе везде единица, тогда устанавливаем следующий бит в нуль и снова проверяем входы на нуль и т.д. до последнего бита выхода, а затем начинаем заново. Если, например, мы установили бит 0 в нуль и при проверке входов на бите 4 обнаружен нуль, тогда мы считаем что была нажата кнопка и функция возвращает код кнопки. С которым мы дальше и работаем в основной программе.  
Короче говоря, мы этим сканированием клавиатуры, просто быстро проверяем нажата ли кнопка в данный момент или нет, если нет, тогда переходим к следующей.
Нарисуем схему подключения клавиатуры.
Подключение питания микроконтроллера не показано.
CLM1-CLM4 и есть выходы нашего порта, состояние которых мы будем менять. 
ROW1-ROW4 это входы порта, состояние которых будем смотреть.
Приведу здесь код функции сканирования клавиатуры с комментариями. Простой пример использования клавиатуры с проектом в Proteus можно скачать в конце статьи.

//функция сканирования клавиатуры
unsigned char fScanButtons()
{
unsigned char portd, clm, row;//объявляю переменные
for(unsigned int i=0; i<4; i++)//запускаю цикл для установки выходов в нуль
{
clm=(1<<i);//устанавливаем нужный выход
portd = PORTD;
portd = (clm ^ 0xFF);//исключающее или, т.е. там где соответствующие биты равны 1 будет 0. 
                //Например, clm = 0b00000001, тогда portd = 0b11111110;
PORTD = portd;//записываем в PORTD полученное значение
for(unsigned int j=4; j<8; j++)//цикл проверки входов 
{
row=(1<<j);//устанавливаем вход, который будем смотреть
portd = (clm | row)^0xFF;//получаем код конкретной кнопки
if(portd == PIND)//проверяем наличие этого кода 
return portd;//если код присутствует, возвращаем его значение
}
}
return 0;//если ничего не совпало, возвращаем 0
}
Казалось бы простая клавиатура, но даже ее можно использовать для радиоуправления моделями или сделать простой калькулятор.
Главное понять принцип работы, а потом можно обобщить на любое количество кнопок. Например, используя два порта - один на выход, другой на вход, можно подключить 64 кнопки (не знаю, пока, зачем это может понадобитьсяsmile) и код нажатой кнопки передавать по SPI на другое устройство, которое будет заниматься обработкой.

Комментариев: 8 RSS

1 Илья Владимирович 07-11-2011 00:38

Уважаемый Dmitry, давно хотел задать этот вопрос.

В интернете множество схем кодовых замков на микроконтроллерах, и почти во всех их используется строчно-столбцовая организация клавиатуры. Меня в них пугает следующая ситуация: допустим, человек, не знающий кода или просто хулиган попытается если не подобрать код, то просто поиграть с такой клавиатурой. И будет жать всё подряд. И наступит момент, когда он нажмёт хотя бы две кнопки в одной строке (если по Вашей схеме). Тогда два столбца (то есть выходы, на которых разные состояния) окажутся замкнуты на неопределённый промежуток времени, а это не есть гуд. Возникает вопрос - 1. можно ли конфигурировать DDRD прямо во время основного цикла, находу, чтобы в один момент времени только один вывод был выходом? 2. Или единственный выход из ситуации - использование "обычной" организации клавиатуры - то есть сколько кнопок, столько и входов, а все кнопки подключены к массе? Но ведь готовая клавиатура от профессионального номеронабирателя - просто загляденье, поэтому строка/столбец - предпочтительней.

3. - я не правильно понял и приведённая схема от данного недостатка свободна?

2 Dmitry 07-11-2011 15:42

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

3 Vacho 17-06-2013 22:35

Помогите пожалуйста...........как делать на codevision......заранее спасибо

5 Dmitry 18-06-2013 19:17

берете и делаете на codevision. функция сканирования есть, а в остальном обычные проект на CV

6 Vachagan 19-06-2013 04:50

if(portd == PIND)

return portd;

}

}

return 0;

оператор ретурн не делает пишет

помогите если не трудно

8 Dmitry 19-06-2013 13:57

ну у вас походу объявленная функция сканирования возвращает тип void. поменяйте на unsigned char как здесь

Оставьте комментарий!

grin LOL cheese smile wink smirk rolleyes confused surprised big surprise tongue laugh tongue rolleye tongue wink raspberry blank stare long face ohh grrr gulp oh oh downer red face sick shut eye hmmm mad angry zipper kiss shock cool smile cool smirk cool grin cool hmm cool mad cool cheese vampire snake excaim question

Используйте нормальные имена. Ваш комментарий будет опубликован после проверки.

Вы можете войти под своим логином или зарегистрироваться на сайте.

(обязательно)