Обработчик матричной клавиатуры

Здравствуйте. У меня давно валяется без дела матричная клавиатура 4*4. Несколько дней назад я озадачился созданием запасного устройства ввода для девайса, которое могло бы частично заменить основной интерфейс, например с компьютером. Кроме того, либа для клавиатуры в хозяйстве не помешает, решил написать сам — в порядке самообразования. Идея в целом удалась, получился довольно портабельный обработчик, тестировал с платой Arduino Nano v3, работает в железе. Также имеется симуляция в Proteus. Быстродействие не ахти — функция опроса клавиатуры выполняется приблизительно за 600мкс на частоте 8мГц. Это первая версия, я ее особо не оптимизировал, оверхеда добавляет и универсальность — выбирать строки и столбцы можно произвольно на порту, хотя порт должен быть один. Обработчик различает короткие и длинные нажатия, есть некая защита от дребезга. Опрос клавиатуры выполняет функция kbd_scan. Ее аргумент — указатель на структуру типа key_struct_t. Структура проста:
typedef struct
{
	unsigned int key_pressed;
	unsigned int key_holded;
	unsigned int holdtime[16];
}key_struct_t;


key_pressed содержит флаги нажатых кнопок, key_holded — флаги кнопок которые удерживаются. Обработчик работает итерационно. Кнопка считается нажатой только если она находится в нажатом состоянии несколько опросов подряд. При этом количество срабатываний фиксируется в holdtime для соответствующей кнопки. Если кнопка была нажата в течение времени меньшего чем KBD_STAB_TIME, счетчик обнуляется. Таким образом выполняется защита от дребезга.Если величина в holdtime для данной кнопки достигло KBD_STAB_TIME то после отпускания тип нажатия будет зависеть от времени удержания. Если holdtime не достигло KBD_HOLD_TIME то установится бит переменной key_pressed структуры key_struct_t. Если же кнопка удерживается дольше и переменная счетчик holdtime успеет натикать до KBD_HOLD_TIME, то после отпускания кнопки установится бит в переменной key_holded. Функция опроса возвращает 0 если нажатий не было, и 1 если нажатия были. В последнем случае необходимо считать key_pressed и key_holded для того чтобы узнать какая именно кнопка была нажата и какой тип нажатия. При следующем опросе клавиатуры флаги будут сброшены. Код обвешан макросами для повышения портируемости и настраиваемости. К статье приложен проектик для теста клавиатуры в составе mRTOS. Клавиатура опрашивается с интервалом 10мс, удержанием считается нажатие в течение 1сек и более. Можно выбрать размер клавиатуры 3*4 или 4*4. Я проводил манипуляции с режимом 3*4. Обработку клавиатуры сопровождает простенький код с двумя светодиодиками, дублирующими длинное и короткое срабатывание клавиатуры, есть видос, попробую прицепить. В случае если отбросить универсальность, код станет проворнее, я так думаю. С другой стороны, не всегда нужно опрашивать клавиатуру так часто. Кто захочет — улучшит. На портах не хватает защитных диодов на случай конфликта сканирующего уровня ноги с остальными, я не стал ставить их в макет, просто испытывал осторожнее.

видос:
  • -1
  • 07 декабря 2013, 20:23
  • XOR
  • 1
Файлы в топике: Atmega328_GPIO.zip

Комментарии (20)

RSS свернуть / развернуть
таки видео нет:)
0
Не знаю что делать. Редактирование не работает. Не могу ничего исправить.
Видео тут www.youtube.com/watch?v=_g_AVONZlss
0
ага
0
#include "kbd.c"
0
Не понимаю. в kbd.h заинклюден kbd.c. Все компилируется. Я ж рабочий проект приложил. Там правда в папке валяются лишние файлы, от других умственных страданий, не почистил, ага.
0
Си-файлы не инклудяться ниоткуда. Каждый Си-файл компилится в отдельный обьектник и потом линкуется линкером, инклудить си-файлы неправильно, инклудят хедеры: .h .hpp etc.
0
Убрать с личный блог
0
*в личный блог
0
Нужно переписать, чтобы клавиатуре не опрашивалась каждый раз, а брались последние измеренные значения. Типа кэширование.

1. Одна функция вызывается с интервалом, например, 5 мс, опрашивает всю клавиатуру (считает длительность нажатия и т.п.) и записывает всё в массив.
2. Вторая функция по запросу выдаёт состояние из массива.

Ну и говнокод, конечно!

Не надо инклудить *.c в хидере.
if (unsigned int x != 0) можно заменить просто if (unsigned int x)
Не знаю, как в твоём компиляторе, но (unsigned) int на AVR может иметь размер и два байта. В функции, где у тебя возвращается 1 или 0 его лучше заменить unsigned char.

Дальше лень разбираться.
0
Не знаю, как в твоём компиляторе, но (unsigned) int на AVR может иметь размер и два байта. В функции, где у тебя возвращается 1 или 0 его лучше заменить unsigned char.
В эмбеде с такими типами лучше вообще не связываться. Размер char, int, etc при портировании малопредсказуем, лучше пользоваться uint8_t, uint16_t и подобными.
0
Конечно, там и был char, это я поставил инт в процессе отладки и забыл поменять обратно.
0
Я постепенно стремлюсь принимать меры по искоренению говнокода. Если товарищи ткнут носом, мне это сильно поможет. Для AVR я пишу под Code Vision, хотя все делаю из студии 6.1, cv прицеплен как компилятор и только. При ковырянии stm я использую типы uint8_t и подобные, cv валится с ошибкой.
0
Обычно они объявлены в stdint.h, подключи его.
0
if (unsigned int x != 0) можно заменить просто if (unsigned int x)
Компилятору по барабану, а первый вариант читается легче.
0
Некоторые компиляторы выдают предупреждение о бесполезном сравнении беззнакового типа с нулём.
0
В каком месте здесь бесполезное сравнение с нулем?!
0
Как по мне так беззнаковое сравнивать с нулем вполне корректно. Вот если пытаться сравнивать беззнаковое на меньше нуля — то это да, бесполезно, а так все норм!
0
#if (defined KBD_3_4)
вполне себе заменяется на
#ifdef KBD_3_4
0
#if (defined KBD_3_4)
уж слишком часто мельтешит по коду=) Не проще ли всего один дефайн на количество столбцов?
#define KBD_COL_NUM 4
unsigned char columns[KBD_COL_NUM];


#if (defined KBD_3_4)
	for(column=0;column<3;column++)//для каждого столбца
	#else
	for(column=0;column<4;column++)
	#endif
	{


станет
for(column=0;column<KBD_COL_NUM;column++)
0
Всем спасибо за советы. Посмотрел программы больших дядей, таки дефайнят.С файлы иногда. Как уменьшить количество писанины в коде, я еще подумаю. Я слишком засиделся над диссертацией, мало реального программирования.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.