Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.72/65: Рейтинг темы: голосов - 65, средняя оценка - 4.72
vod-systim
0 / 0 / 0
Регистрация: 28.11.2014
Сообщений: 24
1

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

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

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

0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
22.04.2015, 10:12
Ответы с готовыми решениями:

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

Клавиатура микроконтроллера
Добрый день, такой вопрос, никто не описывал клавиатуру в симуляторе MSC8052,...

PS/2 клавиатура на AVR
Хочу собрать свою клавиатуру PS/2 на AVR (mega16). Может у кого примерчик...

PC клавиатура+AVR
Здравствуйте. В интернете конечно много всего по этой теме, но пока что я не...

AVR+клавиатура PS/2
Поискал в Сети и нашёл 2 адекватных статьи: 1)...

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

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

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

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

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

0
oxytt
0 / 0 / 0
Регистрация: 16.03.2013
Сообщений: 4,224
22.04.2015, 14:25 14
согласен, три кнопки это перебор) без диодов не распознать
0
Morros
0 / 0 / 0
Регистрация: 15.03.2014
Сообщений: 258
22.04.2015, 15:14 15
Цитата Сообщение от vod-systim
на строке будет высокий уровень ,как диод пропустит?он же в одном направлении пропускает ток.и никак не пойму ведь в такой схеме какие бы кнопки одновременно не нажать замыкания то не будет или я ошибаюсь?
Если речь о вашей схеме - вместо GND подтяните к VCC и сканируйте нулём.
0
dimyurk1978
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,047
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
vod-systim
0 / 0 / 0
Регистрация: 28.11.2014
Сообщений: 24
27.04.2015, 12:42 17
Всем большущее спасибо!!!
0
27.04.2015, 12:42
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.04.2015, 12:42

не работает клавиатура на Atmega16
Здравствуйте. в своем проекте сделал четырехкнопочную клавиатуру. для этого...

Клавиатура 4х4 к Pic18F4520
Как можно реализовать взаимодействие клавиатуры с pic18f4520? Клавиатура - 4х4,...

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


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

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru