Перейти к содержанию

Опрос Клавиатуры 3х4


miksergei

Рекомендуемые сообщения

Всем доброе время суток! Только начинаю писать программы для МК.

Цель устройства - кодовый замок, но сложность заключается в опросе клавиатура из 12 кнопок, т.е. матрица 4х3. В последствии нужно преобразовать номер кнопки в двоичный код этой кнопки. Схемку уже начертил, нужно написать прошивку. Принцип сам понял, но перед тем как писать программу хотел бы посмотреть другие идеи и советы. Возможно кто-нибудь уже делал подобное. Если не трудно пришлите куски программ, схемы, идеи по теме.

Заранее всем благодарен.

post-12842-1213961792_thumb.jpg

Ссылка на комментарий
Поделиться на другие сайты

  • 4 месяца спустя...

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Можно повесит кнопки на вход АЦП, применив делитель из сопротивлений

Так можно кучу кнопок повесить - при одном задействованном выводе..

пардон, не заметил

у тани2313 нет ацп :(

такой вопрос, а куда этот код с кнопок предполагается дальше подавать?

Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

все очень просто! У тебя 4 строки и 3 столбца Строки инициализируеш как выходы а столбцы как входы потом в подпрограмме опроса клавиш выводиш единицу в первую строку и проверяеш поочереди столбцы, потом выводиш единицу во вторую строку и снова проверяеш и тд. по окончанию опроса делаеш задержку допустим на 0.1 сек для защиты от дребезга контактов и выводиш код клавишы из регистра в порт В. Причем после опроса каждой клавиши если нажата - занести код клавиши в регистр!

Вот пример:

;Подпрограмма опроса клавиатуры 3*5

;Опрашываем первый столбец

Klava:

ldi temp,0b11110111 ;код столбца 1

out PortB,temp ;

sbis PinB,0 ;Проверяем клавишу 1

ldi sklav,1 ;Если нажата сохраняем код клавишы в регистре состояния клавиатуры

sbis PinB,1 ;Проверяем клавишу 6

ldi sklav,6 ;Если нажата сохраняем код клавишы в регистре состояния клавиатуры

sbis PinB,2 ;Проверяем клавишу 11

ldi sklav,11 ;Если нажата сохраняем код клавишы в регистре состояния клавиатуры

;Опрашиваем второй столбец

ldi temp,0b11101111 ;код столбца 2

out PortB,temp ;

sbis PinB,0 ;Проверяем клавишу 2

ldi sklav,2 ;Если нажата сохраняем код клавишы в регистре состояния клавиатуры

sbis PinB,1 ;Проверяем клавишу 7

ldi sklav,7 ;Если нажата сохраняем код клавишы в регистре состояния клавиатуры

sbis PinB,2 ;Проверяем клавишу 12

ldi sklav,12 ;Если нажата сохраняем код клавишы в регистре состояния клавиатуры

;Опрашиваем третий столбец

ldi temp,0b11011111 ;код столбца 3

out PortB,temp ;

sbis PinB,0 ;Проверяем клавишу 3

ldi sklav,3 ;Если нажата сохраняем код клавишы в регистре состояния клавиатуры

sbis PinB,1 ;Проверяем клавишу 8

ldi sklav,8 ;Если нажата сохраняем код клавишы в регистре состояния клавиатуры

sbis PinB,2 ;Проверяем клавишу 13

ldi sklav,13 ;Если нажата сохраняем код клавишы в регистре состояния клавиатуры

;Опрашиваем четвертый столбец

ldi temp,0b10111111 ;код столбца 4

out PortB,temp ;

sbis PinB,0 ;Проверяем клавишу 4

ldi sklav,4 ;Если нажата сохраняем код клавишы в регистре состояния клавиатуры

sbis PinB,1 ;Проверяем клавишу 9

ldi sklav,9 ;Если нажата сохраняем код клавишы в регистре состояния клавиатуры

sbis PinB,2 ;Проверяем клавишу 14

ldi sklav,14 ;Если нажата сохраняем код клавишы в регистре состояния клавиатуры

;Опрашиваем пятый столбец

ldi temp,0b01111111 ;код столбца 5

out PortB,temp ;

sbis PinB,0 ;Проверяем клавишу 5

ldi sklav,5 ;Если нажата сохраняем код клавишы в регистре состояния клавиатуры

sbis PinB,1 ;Проверяем клавишу 10

ldi sklav,10 ;Если нажата сохраняем код клавишы в регистре состояния клавиатуры

sbis PinB,2 ;Проверяем клавишу 15

ldi sklav,15 ;Если нажата сохраняем код клавишы в регистре состояния клавиатуры

rcall drebezg ;Вызов подпрограммы защиты от дребезга

ret ;Выход из падпрограммы

проверял етот пример в протеусе - в нем работает ;) но на железке непроверял

Забанен за рекламу

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Да с цыклами размер программы уменьшится но тогда я не совсем понимаю как узнать какая клавиша была нажата

можеш привести пример кода на асемблере :rolleyes:

Забанен за рекламу

Ссылка на комментарий
Поделиться на другие сайты

Да хоть многократное нажатие!!!! Всё зависит от того на что и как вы будете использовать данные.. Я лично всегда писал приментельно к нужной схеме... Так что у меня всё было заточено на железо... Главное сначала составте алгоритм на бумаге а потом переведите его на програму. Научитель использовать подпрограмы - в разы упрощает програмирование... Имеется ввиду розделять подпрограму на подпрограмы...

Ссылка на комментарий
Поделиться на другие сайты

Ребята, давайте базовые вопросы обсуждать в специальных темах МК для начинающих или Алгоритмы.

Теперь по теме клавиатуры.

В свое время была книжка "Проектирование ццифровых устройств на однокристальных микроконтроллерах"

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

Так-что книга будет полезна всем новичкам, а не только тем, кто изучает 51 ядро.

Конкретно клавиатура там описана начиная со 156 страницы.

Как советовать, так все чатлане ...

Ссылка на комментарий
Поделиться на другие сайты

  • 1 месяц спустя...

<OFFTOP>

Migray

Большое спасибо, что разшариваешь литературу, но это не оч. информативно;)

</OFFTOP>

Как по мне то неплохо реализовывать клавиатуру так:

Инициализация:

1. Пины линии, например, X делаем выходами;

2. Пины линии, например, Y делаем входами;

3. На линии X выводим лог. 1;

4. На линиях Y включаем подтягивающие резисторы;

5. Инициализируем один из таймеров, в последтвии в нем будем обрабатывать события клавиатуры;

6. Разрешаем прерывания по переполнению таймера.

Работа:

1. По прерыванию считываем состояние порта Y;

2. Записываем текущее значение во временную переменную;

3а. Сравниваем полученное значение и предыдущее, если значения не совпадают: обнуляем счетчик повторов и записываем новое значение в переменную хранящую предыдущее значение;

3б. Сравниваем полученное значение и предыдущее, если значения совпадают - инкрементируем значение счетчика повторений. Если счетчик повторений совпадает с доверительным значение, выставляем соответствующий флаг и обнуляем счетчик;

4. Устанавливаем лог. 1 на текущей ноге линии X и лог. 0 на следующей;

5. Выходим из прерывания;

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

Ссылка на комментарий
Поделиться на другие сайты

Инициализация:

1. Пины линии, например, X делаем выходами;

2. Пины линии, например, Y делаем входами;

3. На линии X выводим лог. 1;

4. На линиях Y включаем подтягивающие резисторы;

5. Инициализируем один из таймеров, в последтвии в нем будем обрабатывать события клавиатуры;

6. Разрешаем прерывания по переполнению таймера.

Работа:

1. По прерыванию считываем состояние порта Y;

Которое всегда будет одинаковым, т.к. X все = "1", а Y подтянуты :(

По прерыванию мы запускаем цикл, число повторений = числу линий порта X.

В цикле:

1. Сбрасываем соответствующую линию порта в "0"

2. Читаем состояние порта Y

3. Записываем (и в случае необходимости сдвигаем) информацию в переменную. Переменная - часть массива.

4. Возвращаем соответствующую линию порта в "1"

5. Переходим к следующему шагу цикла.

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

При длительном нажатии можно и автоповтор включить :)

Автоповтор конечно в книжке не описан, но там ничего сложного нет, если подумать.

Изменено пользователем Migray

Как советовать, так все чатлане ...

Ссылка на комментарий
Поделиться на другие сайты

Которое всегда будет одинаковым, т.к. X все = "1", а Y подтянуты :(

...

"4. Устанавливаем лог. 1 на текущей ноге линии X и лог. 0 на следующей;"

Которое будет изменяться;)

Ссылка на комментарий
Поделиться на другие сайты

Т.е. состояние первой линии тебе не интересно?

Она-же не прочитается.

Сбрасываем, читаем, выставляем обратно.

Все в одном цикле, тогда все гарантировано работает.

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

Как советовать, так все чатлане ...

Ссылка на комментарий
Поделиться на другие сайты

Т.е. состояние первой линии тебе не интересно?

Она-же не прочитается.

Интересно! И оно прочитается;) Так как там реализован цикл например: X = 0x0F (значение после инициализации), 0x0E, 0x0D ... 0x07

Например:

...
#define GOOD_COUNT 50

typedef struct {
U8 NewKey;
U16 KeyCode;
} TKeyBoard;

...
TKeyBoard gKeyBoard

#pragma vector = TIMER0_OVF_vect
__interrupt void TIMER0_OVF_ISR(void) 
{
static U8 LineX = 0x01;
U8 LineY = 0;
static U16 LastKeyCode = 0;
static U8 KeyCounter;

if (gKeyBoard.NewKey)
	return;

LineX <<= 1;
if (!LineX)
	LineX = 0x01;

PORTA = ~LineX;

LineY = PORTC;

if (LineY = 0xFF)
	return;

gKeyBoard.KeyCode = (LineX << 8) + LineY;

if (LastKeyCode == gKeyBoard.KeyCode)
{
	KeyCounter++;
	if (KeyCounter < GOOD_COUNT)
		return;
	else
	{
		KeyCounter = 0;
		gKeyBoard.NewKey = 1;
	}
}
else
{
	LastKeyCode = gKeyBoard.KeyCode;
	KeyCounter = 0;
}
} 

...
void InitMCU(void)
{
DDRA = 0xFF;
PORTA = 0xFF;
PORTC = 0xFF;

// Инициализация таймеров
TCCR0 = 0x01;	   // Запуск таймера 0 без пред. делителя
TIMSK = (1<<TOIE0); // Разрешим прерывание от переполнения счетчика TMR0
}

...
void main(void)
{
while(1)
{
	if (gKeyBoard.NewKey)
	{
		switch (gKeyBoard.KeyCode)
		{
			case KB_LED_ON:
				func_LED_ON();
				gKeyBoard.NewKey = 0;
				break;
			case KB_LED_OFF:
				func_LED_OFF();
				gKeyBoard.NewKey = 0;
				break;
			default: break;
		}
	}
}
}

Этот пример написан на скорую руку, но должен работать! Краткое описание:

Матрица 8*8, порт А сигнальный, порт С приемный. Есть глобальная переменная хранящая состояние клавиатуры. В основном цикле программы обслуживаются события, чтение состояния клавиатуры происходит по прерыванию. Таким образом, что можно запрограммировать комманду на нажатие на две кнопки одного ряда, что иногда очень удобно!

Сбрасываем, читаем, выставляем обратно.

Все в одном цикле, тогда все гарантировано работает.

Т.е. клавиатуру вы опрашиваете не в прерывание а в основном цикле? :o

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

Только давайте, мы не будем друг друга учить как правильно коды писать для МК;) Как насчет ассемблерных вставок? Или вы их не используете для повышения производительности?

Изменено пользователем ss85
Ссылка на комментарий
Поделиться на другие сайты

1. Сбрасываем соответствующую линию порта в "0"

......

4. Возвращаем соответствующую линию порта в "1"

А если вместо этого вывести на все линии порта "0" и

1. Переключаем соответствующую линию порта (DDRn) как выход

.....

4. Возвращаем соответствующую линию порта в режим входа.

Тогда можно будет не ставить защитные диоды на линии

Изменено пользователем YurkaM
Ссылка на комментарий
Поделиться на другие сайты

Т.е. состояние первой линии тебе не интересно?

Она-же не прочитается.

Интересно! И оно прочитается;) Так как там реализован цикл например: X = 0x0F (значение после инициализации), 0x0E, 0x0D ... 0x07

Было заявлено "3. На линии X выводим лог. 1;" соответственно начальное значение - все линии неактивны.

При последующих циклах естественно все прочитается, но не в первый раз.

Именно так можно понять из описания алгоритма.

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

Сбрасываем, читаем, выставляем обратно.

Все в одном цикле, тогда все гарантировано работает.

Т.е. клавиатуру вы опрашиваете не в прерывание а в основном цикле? :o

Нет конечно. Еще раз читаем:

По прерыванию мы запускаем цикл, число повторений = числу линий порта X.

В цикле:

...

Цикл сканирования клавиатуры запускается в прерывании по таймеру.

Хотя в тех МК, которые я использую, я могу среагировать и на прерывание клавиатуры, при необходимости.

Но таймер - универсальнее, есть у всех.

Только давайте, мы не будем друг друга учить как правильно коды писать для МК;) Как насчет ассемблерных вставок? Или вы их не используете для повышения производительности?
В 1995 году нормальных Си-компиляторов было не достать, приходилось ес-но все писать на АСМе.

Сейчас на АСМе только критические блоки.

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

Как советовать, так все чатлане ...

Ссылка на комментарий
Поделиться на другие сайты

...

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

...

Да, возможно я сильно упростил описание алгоритма, но ведь никто не мешает попросить более детальных объяснений!

...

Хотя в тех МК, которые я использую, я могу среагировать и на прерывание клавиатуры, при необходимости.

Но таймер - универсальнее, есть у всех.

...

Таймер универсальнее, спору нет!

...

Сейчас на АСМе только критические блоки.

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

Да, на сегодня IAR и WinAVR очень хорошо компилируют.

Ссылка на комментарий
Поделиться на другие сайты

  • 1 месяц спустя...

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...