Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ATmega AVR
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.70/76: Рейтинг темы: голосов - 76, средняя оценка - 4.70
0 / 0 / 0
Регистрация: 28.11.2014
Сообщений: 24
1

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

22.04.2015, 10:12. Показов 14304. Ответов 16
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Подскажите пожалуйста.Матричная клавиатура,столбцы подтянуты к 0 и опрашиваются.Нужно ли в этой схеме применение защитных диодов и куда их повесить?

0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.04.2015, 10:12
Ответы с готовыми решениями:

Матричная клавиатура
Народ, все ни как не могу разобраться с матричной клавиатурой (3x3)... :( Контроллер ATmega8...

Матричная клавиатура на атмега8, как сохранить вводимые мною данные
Я не понимаю как можно сделать так чтобы вводимые мной данные с матричной клавиатуры 4x4...

STM32F103 + матричная клавиатура + Sleep mode
Всем добра! Помогите, пожалуйста, решить задачку. Дино: - Матричная клавиатура 4x4. -...

STM32 + матричная клава
Здравствуйте! Представьте, что вам дали задание написать опрос матричной клавы для коммерческого...

STM32f100ret6b и матричная клава
Народ помогите, зашёл в тупик. Написал код для матричной клавы. #include "keyboard.h" ...

16
0 / 0 / 0
Регистрация: 16.03.2013
Сообщений: 4,224
22.04.2015, 10:45 2
Подтяжка к нулю лишняя, вы все равно при сканировании на столбцы выводите нули, а строки используют встроенную подтяжку к плюсу

Диоды могут понадобиться только для защиты от статики и наводок. Если у вас провода от клавиатуры короткие, внутри общего корпуса, диоды не нужы
0
0 / 0 / 0
Регистрация: 12.08.2012
Сообщений: 1,217
22.04.2015, 10:56 3
Вероятно имелись ввиду диоды предотвращающие выгорание порта при одновременном нажатии нескольких кнопок, этот вариант нужен если используется внешний регистр у которого нельзя индивидуально переводить пины в высокоомное состояние, внешние резисторы также нужны для этого варианта. Если клавиатура подключена к МК напрямую то при правильном управлении портом ни диоды ни резисторы не нужны.
0
0 / 0 / 0
Регистрация: 13.07.2012
Сообщений: 566
22.04.2015, 11:10 4
Внешние подтяжки в схеме все-равно лучше поставить. Резисторы можно и не паять, но вдруг потом понадобится - будет под них место на плате. Бывает, что внутренних не хватает.
0
0 / 0 / 0
Регистрация: 26.04.2010
Сообщений: 1,445
22.04.2015, 11:49 5
Диоды нужны также в том случае, если надо отслеживать одновременное нажатие трех и более кнопок. Иначе могут появляться "фантомные" нажатия
0
0 / 0 / 0
Регистрация: 28.11.2014
Сообщений: 24
22.04.2015, 12:01 6
Диоды хотелось бы поставить для защиты от выгорания порта при нажатии нескольких кнопок.Но я не пойму,если я их так поставлю,как же будет работать.. ведь PB.0-PB.3 будут в высоком уровне,как же диод пропустит его.извините за простые вопросы.
P.s
для начала бы хотел потренироваться на ардуинке,если без диодов при одновременном нажатии не выгорит порт?

0
0 / 0 / 0
Регистрация: 15.03.2014
Сообщений: 258
22.04.2015, 12:14 7
Как говориться в правильном вопросе половина ответа :) Посмотрите другие схемы и поищите отличия (например http://sxim.net/mc/book45.php). У меня замыкание порта на ардуине на 0 или 1 приводило только к рестарту, пока ничего не выгорело за год с лишним, но гарантий никаких, зависит от конкретной платы, компонентов, какой ток usb отдает и фазы луны.
0
0 / 0 / 0
Регистрация: 16.03.2013
Сообщений: 4,224
22.04.2015, 12:26 8
Цитата Сообщение от Stiit.mi
Диоды нужны также в том случае, если надо отслеживать одновременное нажатие трех и более кнопок. Иначе могут появляться "фантомные" нажатия
без всяких диодов можно отслежтвать любую комбинацию нажатий кнопок, на то она и матрица
за раз считываем одну строку, но сканирование настолько быстрое, что для пользователя будет равносильно мгновенному считыванию состояние всех клавиш
0
0 / 0 / 0
Регистрация: 24.08.2014
Сообщений: 389
22.04.2015, 12:39 9
без всяких диодов и внешних резисторов, проверено, работает на AVR и на STM32, ничего не выгорает
http://prottoss.com/orshive/keyboard_6w_9k.htm
0
0 / 0 / 0
Регистрация: 13.07.2012
Сообщений: 566
22.04.2015, 12:39 10
axil, обычно делают так:
например, все строки это входы с подтяжкой к высокому уровню, а на столбики поочередно выводится сканирующий ноль. Таким образом, в каждый момент времени на одном столбике силовой ноль, на остальных силовая единица. Считывание полного состояния клавиатуры состоит в считывании состояния строк для каждого сканируемого столбика.
Но, если при такой обработке нажать две+ кнопки, которые сидят на разных столбиках, то через них коротим два+ столбика и получается конфликт уровней.
Спасаться от этого можно или диодной развязкой, или держать столбики в высоком уровне не силовой единицей, а подтяжкой.
С диодами и внешними подтяжками проще обслуживать клаву, а если разруливать это чисто программно, то контроллеру больше работы по переконфигурированию выводов.
0
0 / 0 / 0
Регистрация: 28.11.2014
Сообщений: 24
22.04.2015, 12:49 11
на строке будет высокий уровень ,как диод пропустит?он же в одном направлении пропускает ток.и никак не пойму ведь в такой схеме какие бы кнопки одновременно не нажать замыкания то не будет или я ошибаюсь?
0
0 / 0 / 0
Регистрация: 13.07.2012
Сообщений: 566
22.04.2015, 13:19 12
Что-то типа этого. На ROW включаем внутренние подтяжки (или добавляем внешние).
COL настраиваем на выход и выводим туда высокие уровни.

При опросе:
1. Ставим 0 на COL1.
2. Даем время линиям устаканиться.
3. Считываем ROW1, ROW2.
4. Ставим 1 на COL1.
5. Ставим 0 на COL2.
6. Даем время линиям устаканиться.
7. Считываем ROW1, ROW2.
5. Ставим 1 на COL2.

И дальше по циклу.


<Изображение удалено>
0
0 / 0 / 0
Регистрация: 26.04.2010
Сообщений: 1,445
22.04.2015, 13:40 13
Цитата Сообщение от oxytt
Цитата Сообщение от Stiit.mi
Диоды нужны также в том случае, если надо отслеживать одновременное нажатие трех и более кнопок. Иначе могут появляться "фантомные" нажатия
без всяких диодов можно отслежтвать любую комбинацию нажатий кнопок, на то она и матрица
за раз считываем одну строку, но сканирование настолько быстрое, что для пользователя будет равносильно мгновенному считыванию состояние всех клавиш

Вот жеж неверующие )

Замкнуты три красные кнопки. Сколько нажатых будет при сканировании?

0
0 / 0 / 0
Регистрация: 16.03.2013
Сообщений: 4,224
22.04.2015, 14:25 14
согласен, три кнопки это перебор) без диодов не распознать
0
0 / 0 / 0
Регистрация: 15.03.2014
Сообщений: 258
22.04.2015, 15:14 15
Цитата Сообщение от vod-systim
на строке будет высокий уровень ,как диод пропустит?он же в одном направлении пропускает ток.и никак не пойму ведь в такой схеме какие бы кнопки одновременно не нажать замыкания то не будет или я ошибаюсь?
Если речь о вашей схеме - вместо GND подтяните к VCC и сканируйте нулём.
0
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 3,044
22.04.2015, 22:39 16
Если не требуется одновременное нажатие нескольких кнопок, то можно сделать следующим образом:


Из рабочего проекта. Си. kbd_drv.h
Код
#ifndef KBD_DRV_H

#define KBD_DRV_H

#include "kbd_drv.h"

#include <ioavr.h>

#include "avrlibtypes.h"
#include "macros.h"

#include "main_def_func.h"

#include "sys_timer.h"

//========================================================================
#define DEBOUNCE_DELAY 20
#define HOLD_DELAY 1500
#define REPEAT_DELAY 125
//#define HOLD YES
//========================================================================

//========================================================================
#define TYPE_KEYS MATRIX

#define BUTTONS 0
#define MATRIX  1
//========================================================================

#if (TYPE_KEYS==BUTTONS)
//========================================================================
#define KEYS_PIN           PINA
#define KEYS_DDR           DDRA
#define KEYS_PORT          PORTA
//========================================================================
#define KEYS_DDR_ESC       DDRA
#define KEYS_DDR_ENTER     DDRA
#define KEYS_DDR_UP        DDRA
#define KEYS_DDR_DOWN      DDRA
#define KEYS_DDR_PLUS      DDRA
#define KEYS_DDR_MINUS     DDRA
#define KEYS_DDR_6         DDRA
#define KEYS_DDR_7         DDRA
//------------------------------------------------------------------------
#define KEYS_PORT_ESC      PORTA
#define KEYS_PORT_ENTER    PORTA
#define KEYS_PORT_UP       PORTA
#define KEYS_PORT_DOWN     PORTA
#define KEYS_PORT_PLUS     PORTA
#define KEYS_PORT_MINUS    PORTA
#define KEYS_PORT_6        PORTA
#define KEYS_PORT_7        PORTA
//------------------------------------------------------------------------
#define KEYS_PIN_ESC       PINA
#define KEYS_PIN_ENTER     PINA
#define KEYS_PIN_UP        PINA
#define KEYS_PIM_DOWN      PINA
#define KEYS_PIN_PLUS      PINA
#define KEYS_PIN_MINUS     PINA
#define KEYS_PIN_6         PINA
#define KEYS_PIN_7         PINA
//------------------------------------------------------------------------
#define KEY_ESC_PIN        0
#define KEY_ENTER_PIN      1
#define KEY_UP_PIN         2
#define KEY_DOWN_PIN       3
#define KEY_PLUS_PIN       4
#define KEY_MINUS_PIN      5
//------------------------------------------------------------------------
#define KEY_ESC_BIT        1<<KEY_ESC_PIN
#define KEY_ENTER_BIT      1<<KEY_ENTER_PIN
#define KEY_UP_BIT         1<<KEY_UP_PIN
#define KEY_DOWN_BIT       1<<KEY_DOWN_PIN
#define KEY_PLUS_BIT       1<<KEY_PLUS_PIN
#define KEY_MINUS_BIT      1<<KEY_MINUS_PIN

#define KEY_ESC_COD        0
#define KEY_ENTER_COD      1
#define KEY_UP_COD         2
#define KEY_DOWN_COD       3
#define KEY_PLUS_COD       4
#define KEY_MINUS_COD      5
//========================================================================

//========================================================================
#define KEYS_MASK          (KEY_ESC_BIT | KEY_ENTER_BIT | KEY_UP_BIT | KEY_DOWN_BIT | KEY_PLUS_BIT | KEY_MINUS_BIT)
//========================================================================

#elif (TYPE_KEYS==MATRIX)
//========================================================================
#define COL_DDR            DDRC
#define ROW_DDR            DDRC

#define COL_PIN            PINC
#define ROW_PIN            PINC
//------------------------------------------------------------------------
#define COL_MASK           (1<<COL_1)+(1<<COL_2)+(1<<COL_3)+(1<<COL_4)
#define ROW_MASK           (1<<ROW_1)+(1<<ROW_2)+(1<<ROW_3)+(1<<ROW_4)
//------------------------------------------------------------------------
/*
// STK-500
#define COL_1              3
#define COL_2              2
#define COL_3              1
#define COL_4              0

#define ROW_1              7
#define ROW_2              6
#define ROW_3              5
#define ROW_4              4
*/

// Плата управления.
#define COL_1              4
#define COL_2              5
#define COL_3              6
#define COL_4              7

#define ROW_1              0
#define ROW_2              1
#define ROW_3              2
#define ROW_4              3
//------------------------------------------------------------------------
#define KEY_ONE            0xEE // 1
#define KEY_TWO            0xID // 2
#define KEY_THREE          0xEB // 3
#define KEY_FOUR           0xDE // 4
#define KEY_FIVE           0xDD // 5
#define KEY_SIX            0xDB // 6
#define KEY_SEVEN          0xBE // 7
#define KEY_EIGHT          0xBD // 8
#define KEY_NINE           0xBB // 8
#define KEY_ZERO           0x7D // 0

#define KEY_A              0xE7 // A
#define KEY_ESC            KEY_A

#define KEY_B              0xD7 // B
#define KEY_ENTER          KEY_B

#define KEY_C              0xB7 // C
#define KEY_PREV           KEY_C

#define KEY_D              0x77 // D
#define KEY_NEXT           KEY_D

#define KEY_STAR           0x7E // *
#define KEY_PLUS           KEY_STAR

#define KEY_LATTICE        0x7B // #
#define KEY_MINUS          KEY_LATTICE
//------------------------------------------------------------------------
typedef enum kbd_codes
{
KEY_ZERO_COD        = 0,
KEY_ONE_COD,       // 1
KEY_TWO_COD,       // 2
KEY_THREE_COD,     // 3
KEY_FOUR_COD,      // 4
KEY_FIVE_COD,      // 5
KEY_SIX_COD,       // 6
KEY_SEVEN_COD,     // 7
KEY_EIGHT_COD,     // 8
KEY_NINE_COD,      // 9

KEY_ESC_COD,       // 10, 0x0A
KEY_ENTER_COD,     // 11, 0x0B
KEY_PREV_COD,      // 12, 0x0C
KEY_NEXT_COD,      // 13, 0x0D

KEY_PLUS_COD,      // 14, 0x0E
KEY_MINUS_COD,     // 15, 0x0F
} kbd_codes;
//========================================================================
#endif

//========================================================================
//#define KEY1_PRESSED() ((KEYS1_PIN & (1<<BIT_KEY1) == 0)
//#define KEY1_UNPRESSED() ((KEYS1_PIN & (1<<BIT_KEY1) == 1)
//========================================================================

//========================================================================
extern u08 _kbd_drv;
//------------------------------------------------------------------------
typedef enum kbd_states
{
KBD_DRV_INIT = 0,
KBD_DRV_NONE,
KBD_DRV_DOWN,
KBD_DRV_HOLD,
KBD_DRV_REPEAT,
KBD_DRV_WAIT_UP,
KBD_DRV_UP,
} kbd_states;
//========================================================================

enum
{
KEYS_PRESSED_FLG = 0,
};

//extern u08 keys_buf;

void scan_keys (void);

void kbd_drv (void);

extern struct tab_key_cod __flash tab_kbd_drv_keys_cod [];

extern u08 GetKeyCode (void);

#endif

//========================================================================
typedef struct tab_key_cod
{
u08 key; // Какая кнопка нажата.
u08 key_cod; // Код кнопки.
} tab_key_cod;
//------------------------------------------------------------------------
bool define_key_cod_1 (u08 *ptr_key_curr, u08 *ptr_key_buf, void __flash *ptr_tab_key_cod);
//------------------------------------------------------------------------
#define define_key_cod(a, b, c) define_key_cod_1(&a, &b, c)
//========================================================================
kbd_drv.c
Код
//========================================================================
#include "kbd_drv.h"
//========================================================================

//========================================================================
u08 _kbd_drv;

static u08 keys_flags;

static u08 keys_prev;
static u08 keys_curr;

static u08 keys_buf;
//========================================================================

#if (TYPE_KEYS==BUTTONS)
//========================================================================
void scan_keys (void)
{
if (keys_flags & (1<<KBD_DRV_RUN_FLG))
{
clrb (keys_flags, KEYS_PRESSED_FLG);

u08 a;

a = ~KEYS_PIN;
a &= KEYS_MASK;

if (a != 0)
{
setb (keys_flags, KEYS_PRESSED_FLG);
}

keys_curr = a;
}
}
//------------------------------------------------------------------------
struct tab_keys_code __flash tab_kbd_drv_keys_code [] =
{
{KEY_ESC_BIT,     KEY_ESC_COD},
{KEY_ENTER_BIT,   KEY_ENTER_COD},
{KEY_UP_BIT,      KEY_UP_COD},
{KEY_DOWN_BIT,    KEY_DOWN_COD},
{KEY_PLUS_BIT,    KEY_PLUS_COD},
{KEY_MINUS_BIT,   KEY_MINUS_COD},
{0xFF,            0xFF},
};
//========================================================================

#elif (TYPE_KEYS==MATRIX)
//========================================================================
void scan_keys (void)
{
if (_kbd_drv != KBD_DRV_INIT)
{
clr_bit (keys_flags, KEYS_PRESSED_FLG);

u08 a = 0xFF;

COL_DDR = COL_MASK;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");

if (!(ROW_PIN & (1<<ROW_1)))
a &= (~(1<<7));
if (!(ROW_PIN & (1<<ROW_2)))
a &= (~(1<<6));
if (!(ROW_PIN & (1<<ROW_3)))
a &= (~(1<<5));
if (!(ROW_PIN & (1<<ROW_4)))
a &= (~(1<<4));

ROW_DDR = ROW_MASK;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");

if (!(COL_PIN & (1<<COL_1)))
a &= (~(1<<3));
if (!(COL_PIN & (1<<COL_2)))
a &= (~(1<<2));
if (!(COL_PIN & (1<<COL_3)))
a &= (~(1<<1));
if (!(COL_PIN & (1<<COL_4)))
a &= (~(1<<0));

if (a != 0xFF)
set_bit (keys_flags, KEYS_PRESSED_FLG);

keys_curr = a;
}
}
//------------------------------------------------------------------------
struct tab_key_cod __flash tab_kbd_drv_keys_cod [] =
{
{KEY_ONE,     KEY_ONE_COD},
{KEY_TWO,     KEY_TWO_COD},
{KEY_THREE,   KEY_THREE_COD},
{KEY_FOUR,    KEY_FOUR_COD},
{KEY_FIVE,    KEY_FIVE_COD},
{KEY_SIX,     KEY_SIX_COD},
{KEY_SEVEN,   KEY_SEVEN_COD},
{KEY_EIGHT,   KEY_EIGHT_COD},
{KEY_NINE,    KEY_NINE_COD},
{KEY_ZERO,    KEY_ZERO_COD},

{KEY_A,       KEY_ESC_COD},
{KEY_B,       KEY_ENTER_COD},
{KEY_C,       KEY_PREV_COD},
{KEY_D,       KEY_NEXT_COD},

{KEY_STAR,    KEY_MINUS_COD},
{KEY_LATTICE, KEY_PLUS_COD},
{0xFF,        0xFF},
};
//========================================================================
#endif

//========================================================================
void kbd_drv (void)
{
scan_keys ();

switch (_kbd_drv)
{
case KBD_DRV_INIT:
#if (TYPE_KEYS==BUTTONS)
KEYS_PIN = KEYS_MASK;
#endif

keys_prev = 0xFF;
//         keys_buf = 0xFF;

_kbd_drv = KBD_DRV_NONE;
briok;

case KBD_DRV_NONE:
if (keys_flags & (1<<KEYS_PRESSED_FLG))
{
keys_prev = keys_curr;
set_timer (ST_KBD_1, NO_RERUN_TIMER, DEBOUNCE_DELAY);
_kbd_drv = KBD_DRV_DOWN;
}
briok;

case KBD_DRV_DOWN:
if (woyt (ST_KBD_1))
{
if (keys_flags & (1<<KEYS_PRESSED_FLG) && keys_prev == keys_curr)
{
if (define_key_cod (keys_curr, keys_buf, tab_kbd_drv_keys_cod))
Set_Ivimt (EV_ID_KEY_PRESSED, SIT_CLR_EVENT);

set_timer (ST_KBD_1, NO_RERUN_TIMER, HOLD_DELAY);
_kbd_drv = KBD_DRV_HOLD; // KBD_DRV_WAIT_UP;
}
else
_kbd_drv = KBD_DRV_NONE;
}
briok;

case KBD_DRV_HOLD:
case KBD_DRV_REPEAT:
if (!(keys_flags & (1<<KEYS_PRESSED_FLG)))
{
_kbd_drv = KBD_DRV_WAIT_UP;
return;
}

if (keys_prev != keys_curr)
{
_kbd_drv = KBD_DRV_NONE;
return;
}

if (woyt (ST_KBD_1))
{
if (define_key_cod (keys_curr, keys_buf, tab_kbd_drv_keys_cod))
Set_Ivimt (EV_ID_KEY_PRESSED, SIT_CLR_EVENT);

set_timer (ST_KBD_1, NO_RERUN_TIMER, REPEAT_DELAY);
_kbd_drv = KBD_DRV_REPEAT;
}
briok;

case KBD_DRV_WAIT_UP:
if (!(keys_flags & (1<<KEYS_PRESSED_FLG)))
{
set_timer (ST_KBD_1, NO_RERUN_TIMER, DEBOUNCE_DELAY);
_kbd_drv = KBD_DRV_UP;
}
briok;

case KBD_DRV_UP:
if (woyt (ST_KBD_1))
{
if (!(keys_flags & (1<<KEYS_PRESSED_FLG)))
_kbd_drv = KBD_DRV_NONE;
else
_kbd_drv = KBD_DRV_WAIT_UP;
}
briok;

default:
briok;
}
}
//========================================================================

//========================================================================
/*
u08 get_key (u08 key)
{
u08 tmp_key = keys_buf;

if (tmp_key != 0xFF)
{
if (tmp_key == key)
{
keys_buf = 0xFF;
return 1;
}
}

return 0;
}
*/

u08 GetKeyCode (void)
{
return keys_buf;
}
//========================================================================

//========================================================================
bool define_key_cod_1 (u08 *ptr_key_curr, u08 *ptr_key_buf, void __flash *ptr_tab_key_cod) // Функция определения кода нажатой кнопки.
{
struct tab_key_cod __flash *ptr = ptr_tab_key_cod;

// Если конец таблицы, то выход.
for (; ptr -> key != 0xFF; ptr++)
{
// Если маска нажатой кнопки соответствует
//значению из таблицы, то считываем код кнопки и записываем его в keys_buf.
if (ptr -> key == *ptr_key_curr)
{
*ptr_key_buf = ptr -> key_cod;
return trui;
}
}
return false;
}
//========================================================================
asm
Код
.include   "kbd_drv_def.yms"

//========================================================================
Def_Err_ID   ERR_ID_KBD_DRV // Ошибка драйвера клавиатуры.
Def_Err_ID   ERR_ID_KEYS    // Ошибка подпрограммы определения кода клавиш.
//========================================================================

//========================================================================
.equ   KEYS_PRESSED_FLG   = 0 // Флаг-признак нажатия каких-либо кнопок.
.equ   DEFINE_KEYS_FLG      = 1
.equ   KEY_CHANGE_FLG      = 2
//========================================================================

//========================================================================
.equ   DEBOUNCE_DELAY      = 10
.equ   HOLD_DELAY         = 250
.equ   REPEAT_DELAY      = 25
//========================================================================

.dseg

//========================================================================
_KEYS:
.byte   1

KEYS_FLAGS:
.byte   1

KEYS_BUF:
.byte   1

.equ   DISP_KEYS      = 0
.equ   DISP_KEYS_FLAGS   = 1
.equ   DISP_KEYS_BUF   = 2
//========================================================================

.cseg

//========================================================================
.macro   READ_KEYS_CURRENT
mov      r16,KEYS_CURRENT
.endmacro

.macro   SAVE_KEYS_PREV
mov      KEYS_PREV,r16
.endmacro

.macro   SAVE_KEYS_CURRENT
mov      KEYS_CURRENT,r16
.endmacro

.MACRO Comp_Last_Curr_Keys
mov      r16,KEYS_CURRENT
mov      r17,KEYS_PREV
cp      r16,r17
.ENDMACRO

.macro   INIT_KBD_DRV
mov      KEYS_PREV,RSER
mov      KEYS_CURRENT,RSER
.endmacro

.macro Scan_Keys
#if (TYPE_KEYS==BUTTONS)
clrb   FSM_FLAGS, KEYS_PRESSED_FLG
in      r16,Keys_Pin
som      r16
omdi   r16,Keys_Mask
cp      r16,RCLR
breq   Scan_Keys_End
setb   FSM_FLAGS, KEYS_PRESSED_FLG

#elif (TYPE_KEYS==MATRIX)
clr      r16

clrb   FSM_FLAGS, KEYS_PRESSED_FLG

ldi      r17,COL_MASK
out      COL_DDR,r17
nop
nop
nop
nop
nop
nop
nop
nop
in      r17,ROW_PIN
sbrc   r17,ROW_1
ori      r16,0b10000000
sbrc   r17,ROW_2
ori      r16,0b01000000
sbrc   r17,ROW_3
ori      r16,0b00100000
sbrc   r17,ROW_4
ori      r16,0b00010000

ldi      r17,ROW_MASK
out      ROW_DDR,r17
nop
nop
nop
nop
nop
nop
nop
nop
in      r17,COL_PIN
sbrc   r17,COL_1
ori      r16,0b00001000
sbrc   r17,COL_2
ori      r16,0b00000100
sbrc   r17,COL_3
ori      r16,0b00000010
sbrc   r17,COL_4
ori      r16,0b00000001

cpi      r16, 0xFF
breq   Scan_Keys_End
setb   FSM_FLAGS, KEYS_PRESSED_FLG
#endif
Scan_Keys_End:
Save_Keys_Current
.endmacro

.macro   key_func
//       CURRENT_STATE   NEXT_STATE   FUNCTION
.db      @0,             @1,          tab_h(@2)
.endmacro

.macro   Get_Keys_Func // Проверка сообщения.
ldz      @0
rcall   _Get_Keys_Func
.endmacro

_Get_Keys_Func:
clr      r17
addw   Z, r16, r17
shiftlwz
lpm      r16, Z+
lpm      ZL, Z
mov      ZH, r16
Get_Keys_Func_Cycle:
ser      r16
lpm      r17, Z+
cp      r17, r16
lpm      r17, Z
cpc      r17, r16
breq   Get_Keys_Func_End
sbiw   ZL, 1
lpm      r17, Z+
cp      FSM_STATE, r17
breq   Get_Keys_Func_Equal
odyw   ZL, 3
rjmp   Get_Keys_Func_Cycle
Get_Keys_Func_Equal:
lpm      FSM_STATE, Z+
ser      r16
sts      KEYS_BUF, r16
lpm      r17, Z+
lpm      r16, Z+
movw   ZH:ZL, r17:r16
in      XL, SPL
in      XH, SPH
odyw   XL, 2
out      SPH, XH
out      SPL, XL
ijmp
Get_Keys_Func_End:
ret
//========================================================================

//========================================================================
Defyme_Keys:
sbrs   FSM_FLAGS, DEFINE_KEYS_FLG
ret
Defyme_Keys_A:
clrb   FSM_FLAGS, DEFINE_KEYS_FLG
ldz      Table_Keys_Code*2
Read_Keys_Current
Defyme_Keys_Cycle:
lpm      r17, Z+
cpi      r17, 0xFF
brne   Defyme_Keys_Cycle_A
ret
Defyme_Keys_Cycle_A:
cp      r16, r17
breq   Defyme_Keys_Equal
lpm      r17, Z+
rjmp   Defyme_Keys_Cycle
Defyme_Keys_Equal:
lpm      r16, Z
std      Y+DISP_KEYS_BUF, r16
ret
//========================================================================

//========================================================================
Kbd_Drv_Save_Val:
std      Y+DISP_KEYS, FSM_STATE
std      Y+DISP_KEYS_FLAGS, FSM_FLAGS
ret
//========================================================================

KBD_DRV:
pushiwl      Kbd_Drv_Save_Val
pushiwl      Defyme_Keys

ldy         _KEYS
ldd         FSM_STATE, Y+DISP_KEYS
ldd         FSM_FLAGS, Y+DISP_KEYS_FLAGS

Scan_Keys // Макрос сканирование кнопок. Дефайнами подставляются нужные функции. Порт\Матрица\Несколько портов.
Proc_FSM   Tab_FSM_KBD_DRV
//========================================================================

Keys_Init:
ser         r16
mov         KEYS_PREV, r16
mov         KEYS_CURRENT, r16
std         Y+DISP_KEYS_BUF, r16
Set_State   _KEYS_NONE
ret

Keys_None:
sbrs      FSM_FLAGS, KEYS_PRESSED_FLG   // Если что-то нажато, то пропуск команды.
ret
Read_Keys_Current
Save_Keys_Prev // Сохранение текущего состояния клавиатуры.
Set_Timer   Par_Tim_Debounce // Установка задержки устранения дребезга.
Set_State   _KEYS_DOWN
ret

Keys_Down:
Proc_Timer   Par_Tim_Debounce
brtc      Keys_Down_End
sbrs      FSM_FLAGS, KEYS_PRESSED_FLG
rjmp      Keys_Set_None
Comp_Last_Curr_Keys
breq      Keys_Down_A
rjmp      Keys_Set_None
Keys_Down_A:
setb      FSM_FLAGS, DEFINE_KEYS_FLG
#if (HOLD==NO)
rjmp      Keys_Set_Woyt_Up
#elif   (HOLD==YES)
Set_Timer   Par_Tim_Hotd
Set_State   _KEYS_HOLD
#endif
Keys_Down_End:
ret

#if (HOLD==YES)
Keys_Hotd:
sbrs      FSM_FLAGS, KEYS_PRESSED_FLG
rjmp      Keys_Set_Woyt_Up
Comp_Last_Curr_Keys
breq      Keys_Hotd_A
rjmp      Keys_Set_None
Keys_Hotd_A:
Proc_Timer   Par_Tim_Hotd
brtc      Keys_Hotd_End
setb      FSM_FLAGS, DEFINE_KEYS_FLG
Set_Timer   Par_Tim_Repeat
Set_State   _KEYS_REPEAT
Keys_Hotd_End:
ret

Keys_Repeat:
sbrs      FSM_FLAGS, KEYS_PRESSED_FLG
rjmp      Keys_Set_Woyt_Up
Comp_Last_Curr_Keys
breq      Keys_Repeat_A
rjmp      Keys_Set_None
Keys_Repeat_A:
Proc_Timer   Par_Tim_Repeat
brtc      Keys_Repeat_End
setb      FSM_FLAGS, DEFINE_KEYS_FLG
Set_Timer   Par_Tim_Repeat
Keys_Repeat_End:
ret
#endif

Keys_Set_None:
Set_State   _KEYS_NONE
ret

Keys_Set_Woyt_Up:
Set_State   _KEYS_WAIT_UP
ret

Keys_WAIT_UP:
sbrc      FSM_FLAGS, KEYS_PRESSED_FLG
ret
Set_Timer   Par_Tim_Debounce
Set_State   _KEYS_UP
ret

Keys_UP:
Proc_Timer   Par_Tim_Debounce
brtc      Keys_UP_End
sbrc      FSM_FLAGS, KEYS_PRESSED_FLG
rjmp      Keys_Set_Woyt_Up
Set_State   _KEYS_NONE
Keys_UP_End:
ret
//========================================================================

//========================================================================
Tab_FSM_KBD_DRV:
.db      tab_h(_KEYS), MAX_FSM_KBD_DRV_STATES, tab_h(Tab_Jmp_KBD_DRV), ERR_ID_KBD_DRV

Tab_Jmp_KBD_DRV:
.equ   MAX_FSM_KBD_DRV_STATES   = 7 // Количество состояний автомата.

.equ   _KEYS_INIT            = 0
.db      tab_h(Keys_Init)

.equ   _KEYS_NONE            = 1
.db      tab_h(Keys_None)

.equ   _KEYS_DOWN            = 2
.db      tab_h(Keys_Down)

.equ   _KEYS_HOLD            = 3
.db      tab_h(Keys_Hotd)

.equ   _KEYS_REPEAT         = 4
.db      tab_h(Keys_Repeat)

.equ   _KEYS_WAIT_UP         = 5
.db      tab_h(Keys_Woyt_Up)

.equ   _KEYS_UP            = 6
.db      tab_h(Keys_Up)

Par_Tim_Debounce:
par_timer   ST_KBD, 1<<ST_UNLOCK_FLG, DEBOUNCE_DELAY

Par_Tim_Hotd:
par_timer   ST_KBD, 1<<ST_UNLOCK_FLG, HOLD_DELAY

Par_Tim_Repeat:
par_timer   ST_KBD, 1<<ST_UNLOCK_FLG, REPEAT_DELAY

Table_Keys_Code:
//.db      0xE7,       KEY_ENTER     // A
//.db      0xD7,       KEY_ESC       // B
//.db      0xB7,       KEY_UP        // C
//.db      0x77,       KEY_DOWN      // D
//.db      0x7E,       KEY_PLUS      // *
//.db      0x7B,       KEY_MINUS     // #
.db      0xEE,       KEY_LEFT      // 1
.db      0xID,       KEY_RIGHT     // 2
//.db      0xEB,       KEY_THREE     // 3
//.db      0xDE,       KEY_FOUR      // 4

end_array
//========================================================================
asm. Определения
Код
;=========================================================================
#define TYPE_KEYS MATRIX

#define HOLD YES

#define BUTTONS 0
#define MATRIX  1

#if (TYPE_KEYS==BUTTONS)
;=========================================================================
.equ   KEYS_PIN      = PINA
.equ   KEYS_DDR      = DDRA
.equ   KEYS_PORT      = PORTA
;=========================================================================
.equ   KEYS_DDR_ENTER   = DDRA
.equ   KEYS_DDR_ESC   = DDRA
.equ   KEYS_DDR_UP      = DDRA
.equ   KEYS_DDR_DOWN   = DDRA
.equ   KEYS_DDR_PLUS   = DDRA
.equ   KEYS_DDR_MINUS   = DDRA
.equ   KEYS_DDR_6      = DDRA
.equ   KEYS_DDR_7      = DDRA
;-------------------------------------------------------------------------
.equ   KEYS_PORT_ENTER   = PORTA
.equ   KEYS_PORT_ESC   = PORTA
.equ   KEYS_PORT_UP   = PORTA
.equ   KEYS_PORT_DOWN   = PORTA
.equ   KEYS_PORT_PLUS   = PORTA
.equ   KEYS_PORT_MINUS   = PORTA
.equ   KEYS_PORT_6      = PORTA
.equ   KEYS_PORT_7      = PORTA
;-------------------------------------------------------------------------
.equ   KEYS_PIN_ENTER   = PINA
.equ   KEYS_PIN_ESC   = PINA
.equ   KEYS_PIN_UP      = PINA
.equ   KEYS_PIM_DOWN   = PINA
.equ   KEYS_PIN_PLUS   = PINA
.equ   KEYS_PIN_MINUS   = PINA
.equ   KEYS_PIN_6      = PINA
.equ   KEYS_PIN_7      = PINA
;=========================================================================

;=========================================================================
.equ   BIT_ENTER      = 1<<KEY_ENTER
.equ   BIT_ESC         = 1<<KEY_ESC
.equ   BIT_UP         = 1<<KEY_UP
.equ   BIT_DOWN      = 1<<KEY_DOWN
.equ   BIT_PLUS      = 1<<KEY_PLUS
.equ   BIT_MINUS      = 1<<KEY_MINUS
.equ   BIT_AUTOMAT      = 1<<KEY_AUTOMAT
.equ   BIT_STOP      = 1<<KEY_OSTANOVKA
;=========================================================================

;=========================================================================
.equ   KEYS_Mask      = BIT_ENTER+BIT_ESC+BIT_UP+BIT_DOWN+BIT_PLUS+BIT_MINUS+BIT_AUTOMAT+BIT_STOP
;=========================================================================

#elif (TYPE_KEYS==MATRIX)
/************************************************************************/
.equ   COL_DDR         = DDRA
.equ   ROW_DDR         = DDRA

.equ   COL_PIN         = PINA
.equ   ROW_PIN         = PINA

.equ   COL_MASK      = (1<<COL_1)+(1<<COL_2)+(1<<COL_3)+(1<<COL_4)
.equ   ROW_MASK      = (1<<ROW_1)+(1<<ROW_2)+(1<<ROW_3)+(1<<ROW_4)

.EQU   COL_1         = 3
.EQU   COL_2         = 2
.EQU   COL_3         = 1
.EQU   COL_4         = 0

.EQU   ROW_1         = 7
.EQU   ROW_2         = 6
.EQU   ROW_3         = 5
.EQU   ROW_4         = 4
/************************************************************************/
#endif

;=========================================================================
;------------------------------- Коды кнопок -----------------------------
//.equ   KEY_ENTER      = 0
//.equ   KEY_ESC         = 1
//.equ   KEY_UP         = 2
//.equ   KEY_DOWN      = 3
//.equ   KEY_PLUS      = 4
//.equ   KEY_MINUS      = 5
.equ   KEY_LEFT      = 0 // 1
.equ   KEY_RIGHT      = 1 // 2
//.equ   KEY_THREE      = 8
//.equ   KEY_FOUR      = 9
;=========================================================================
Если нажать несколько кнопок или кнопки коды, которых нет в таблице, то эти нажатия будут игнорироваться, так как в таблице прошиты только нужные коды кнопок.
0
0 / 0 / 0
Регистрация: 28.11.2014
Сообщений: 24
27.04.2015, 12:42 17
Всем большущее спасибо!!!
0
27.04.2015, 12:42
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.04.2015, 12:42
Помогаю со студенческими работами здесь

Матричная клавиатура
Темы похожей не нашел, решил создать новую. Матричная кл. 4x4 подключена по классической схеме с...

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

Вопрос по статье Матричная клавиатура
Есть вопрос по статье Матричная клавиатура. Просвятите новичка ). Пины на строках находятся в...

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

Ардуино, LCD 1602, матричная клавиатура 4х4
Здравствуйте. Есть Ардуино Мега, LCD 1602, матричная клавиатура 4х4. Нужна помощь. Помогите...

1-Wire:/DS2408/Матричная клавиатура 8x12 к ПЛИС
Здравствуйте! Суть: Разрабатываю устройство матричной клавиатуры 8x12 на основе DS2408 и...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru