Библиотека для опроса матричной клавиатуры 4x4 и 3х4
13/10/2011 - 05:03
Pavel Bobkov
Введение
Написал программный модуль для опроса матричной клавиатуры.
Особенности модуля:
- простая интеграция с готовым проектом
Особенности модуля:
- простая интеграция с готовым проектом
- поддержка всех микроконтроллеров семейства mega
- возможность использования с любым из трех компиляторов CodeVision, IAR, GCC
- поддержка клавиатур 4х4 и 3х4
- поддержка работы на общей шине
- возможность подключения к одному или двумя портами
- программная антидребезговая защита
- возможность установки произвольных кодов кнопок
Подключение модуля
- скачиваем архив с модулем
- переписываем файлы keyboard.h и keyboard.c в папку проекта
- переписываем файлы keyboard.h и keyboard.c в папку проекта
- подключаем keyboard.c к проекту внутри среды разработки
- включаем keyboard.h в требуемый файл проекта, например main.c
- настраиваем конфигурацию в файле keyboard.h
- прописываем в свой код вызов пользовательских функций
Настройка конфигурации включает в себя несколько шагов.
Установка тактовой частоты микроконтроллера
#define F_CPU 16000000
При высокой тактовой частоте микроконтроллера логические сигналы, формируемые программным модулем, из-за паразитных емкостей «не успевают» устанавливаться до требуемого уровня. Поэтому в некоторых местах кода используется программная задержка, для вычисления которой требуется значение тактовой частоты.
Установка типа матричной клавиатуры – 4х4 или 3х4
#define KEYBOARD_4X4
Если закомментировать это макроопределение будет установлена клавиатура 3х4.
Тип заданной клавиатуры сообщается пользователю в процессе сборки проекта. Поэтому не удивляйтесь предупреждению в окне Messages.
Установка типа подключения матричной клавиатуры
#define COMMON_BUS
Для подключения клавиатуры и индикаторов часто используют общую шину, что позволяет экономить выводы микроконтроллера. Если это макроопределение не закомментировано, значит, клавиатура подключена именно таким способом.
В этом случае выводы, используемые клавиатурой, конфигурируются лишь на время ее опроса. А по завершению процедуры опроса состояние выводов восстанавливается.
Закомментировав макроопределение, можно сэкономить несколько байт флеш памяти.
Установка портов, к которым подключены строки и столбцы клавиатуры
//порт, к которому подключены строки
#define PORTX_ROW PORTA
#define PINX_ROW PINA
#define DDRX_ROW DDRA
//порт, к которому подключены столбцы
#define PORTX_COL PORTB
#define PINX_COL PINB
#define DDRX_COL DDRB
Все строки клавиатуры должны быть подключены к одному порту микроконтроллера. Данный модуль не позволяет подключить, например, одну строку к порту B, а остальные к порту С. Это же относится и к столбцам клавиатуры.
При этом группа строк или столбцов клавиатуры может быть подключена как к одному, так и к разным портам микроконтроллера.
Установка выводов, к которым подключены строки и столбцы клавиатуры
//выводы, к которым подключены строки
#define PIN_ROW1 4
#define PIN_ROW2 5
#define PIN_ROW3 6
#define PIN_ROW4 7
//выводы, к которым подключены столбцы
#define PIN_COL1 0
#define PIN_COL2 1
#define PIN_COL3 2
#define PIN_COL4 3
Выводы микроконтроллера, подключенные к строкам и столбцам матричной клавиатуры, не должны совпадать между собой. Это требования должно выполняться, когда клавиатура подключена к двум портам микроконтроллера.
Установка кодов кнопок
//коды кнопок
#define EVENT_NULL 0
#define EVENT_KEY0 '0'
#define EVENT_KEY1 '1'
#define EVENT_KEY2 '2'
#define EVENT_KEY3 '3'
#define EVENT_KEY4 '4'
#define EVENT_KEY5 '5'
#define EVENT_KEY6 '6'
#define EVENT_KEY7 '7'
#define EVENT_KEY8 '8'
#define EVENT_KEY9 '9'
#define EVENT_KEYA 'A'
#define EVENT_KEYB 'B'
#define EVENT_KEYC 'C'
#define EVENT_KEYD 'D'
#define EVENT_KEYZ '*'
#define EVENT_KEYR '#'
Здесь никаких требований нет. Коды кнопок совершенно произвольные. Можно задать символьные значения, соответствующие кнопкам клавиатуры, как это сделано по умолчанию. А можно задать коды, которые будут использоваться в событийной системе.
Использование модуля
В модуле реализовано три пользовательские функции.
void KEYB_Init(void) – функция инициализации
void KEYB_ScanKeyboard(void) – функция сканирования клавиатуры
unsigned char KEYB_GetKey(void) – функция проверки буфера
KEYB_Init() нужно запускать перед использованием двух других функций. Обычно это делается в начале main`a.
KEYB_ScanKeyboard() – это основная функция, реализующая всю работу модуля. Она требует периодического запуска. Можно вставить ее в обработчик прерывания таймера, а можно вызывать ее из основного цикла программы по его сигналу. Первый вариант более расточителен в плане ресурсов микроконтроллера.
KEYB_GetKey() – эта функция возвращает код кнопки, заданный в заголовочном файле keyboard.h. Если кнопочный буфер пуст – функция возвращает код EVENT_NULL. Вызываем эту функцию там, где собираемся обрабатывать нажатия кнопок.
Тестовые проекты
Как обычно, прилагаю тестовые проекты для трех компиляторов. Все они были проверены в железе. Схема на рисунке ниже.
Для любителей симуляций - проект для Протеуса. Сделан на скорую руку, поэтому отличается от реальной схемы.
Для любителей симуляций - проект для Протеуса. Сделан на скорую руку, поэтому отличается от реальной схемы.
Файлы
Tagged under
Comments
К тому же проще не значит лучше.
Да и функционал твоего и моего кода отличается.
- возможность использования с любым из трех компиляторов IAR, GCC, CodeVision,
- поддержка клавиатур 4х4 и 3х4
- поддержка работы на общей шине
- программная антидребезговая защита
- зная среду разработки перенести код не составит труда;
- добавив аналогичный в коде фрагмент, возможна поддержка хоть 8х8 (в статье указано);
- хоть на одном порту, хоть вразброс;
- добавляется две строки в зависимости от использования (в прерывании, в цикле);
Я никоим образом не говорю, что мой код лучше))) Я адекватно оцениваю способности людей и могу сказать, что товарищ Pashgan разработчик уровнем выше меня. Форумы для того и нужны, чтобы обмениваться опытом, искать что-то новое. Всем удачи!
Code:
...
volatile unsigned char flag = 0;
...
int main(void)
{
...
while(1){
if (flag){
KEYB_ScanKeyboard();
flag = 0;
}
}
}
....
//прерывание таймера
...
{
flag = 1;
}
Code:
if (~PINX_ROW & ROW_MASK) {
keyCode = PINX_ROW & ROW_MASK;
keyCode |= PORTX_COL & COL_MASK;
return;
Quote:
Error 4 variable 'keyTable' must be const in order to be put into read-only section by means of '__attribute__( (progmem))' C:\ Users\gadmin\Do cuments\Atmel Studio\GccApplication2\GccApplication2\keyboard.c 61 39 GccApplication2
как это исправить
`
В файле протеуса ножки строк клавиатуры подключены к МК паралельно ногам шины даных LCD.Все симулируется нормально.
Поскажите как в реальной схеме защищаться от одновременого нажатия двух кнопок,залипани й и тд.,чтобы остались целыми контролер и LCD?Достаточно ли одних резисторов 100 Ом?
Хочу использовать для подключения 4 кнопок.
Грубо говоря получается клавиатура 1*4 или 4*1. Причем кнопки будут подключены на корпус одним выводом, т.е. 4 ряда на контроллер, а 1 столбец на корпус или наоборот.
Подскажите что надо на контроллер - ряды или столбцы?
Еще раз спасибо автору за материал.Особен но радует совместное использование портов для клавы и LCD.Проверял в реальном железе,усе работает.Резист оры по 100 Ом.
У меня вопрос.А возможно ли переделать библиотеку под 3*3 кнопки?Вот "юзал" 3*4 все гуд,но для многих целей вполне достаточно 3*3 + выиграш в 1 пин.
variable 'keyTable' must be const in order to be put into read-only section by means of '__attribute__( (progmem))'
Как бы скорректировать запись в память программы.
Gadmin уже интересовался. Решения по прежнему нет?
Code:
#define FLASH_ATR PROGMEM const
Code:
FLASH_ATR const unsigned char keyTable[][2] = {
{((~(1<<PIN_ROW1)&(ROW_MASK))|(~(1<<PIN_COL1)&(COL_MASK))), EVENT_KEY1},
{((~(1<<PIN_ROW1)&(ROW_MASK))|(~(1<<PIN_COL2)&(COL_MASK))), EVENT_KEY2},
{((~(1<<PIN_ROW1)&(ROW_MASK))|(~(1<<PIN_COL3)&(COL_MASK))), EVENT_KEY3},
RSS feed for comments to this post