[Źródło: http://www.atmel.com/images/Atmel-8135-8-and-16-bit-AVR-microcontroller-ATxmega16D4-32D4-64D4-128D4_datasheet.pdf]
Poniżej opiszę wszystkie potrzebne funkcje dla obsługi klawiatury z 12 przyciskami 3x4.
Na samym początku należy zdefiniować następujące parametry:
Pierwsza wartość oznacza, że kliknięcie przycisku i przytrzymanie będzie blokowane aż do jego puszczenia. Nie nastąpi ponowny odczyt wybranego przycisku po odczekaniu interwału czasowego. Druga wartość określa wartość przycisku, gdy żaden nie został wybrany.
Następnym elementem jest definicja numeru dla klikniętego klawisza:
Program:
Poniżej opiszę wszystkie potrzebne funkcje dla obsługi klawiatury z 12 przyciskami 3x4.
Na samym początku należy zdefiniować następujące parametry:
- #define KEYPAD_BLOCK_SAME_BTN_CLICKED
- #define KEYPAD_NO_PRESSED (uint8_t)0xFF
- #define KEYPAD_READ_INTERVAL 100
Pierwsza wartość oznacza, że kliknięcie przycisku i przytrzymanie będzie blokowane aż do jego puszczenia. Nie nastąpi ponowny odczyt wybranego przycisku po odczekaniu interwału czasowego. Druga wartość określa wartość przycisku, gdy żaden nie został wybrany.
Następnym elementem jest definicja numeru dla klikniętego klawisza:
- typedef enum {
- Btn_0 = 0x00,
- Btn_1 = 0x01,
- Btn_2 = 0x02,
- Btn_3 = 0x03,
- Btn_4 = 0x04,
- Btn_5 = 0x05,
- Btn_6 = 0x06,
- Btn_7 = 0x07,
- Btn_8 = 0x08,
- Btn_9 = 0x09,
- Btn_Star = 0x0A,
- Btn_Hash = 0x0B,
- Btn_None = KEYPAD_NO_PRESSED
- } Keyboard_Btn_Typedef;
Dalej znajduje się struktura przechowująca ostatnie dwa kliknięte przyciski:
- typedef struct {
- volatile Keyboard_Btn_Typedef clickedBtn;
- #ifdef KEYPAD_BLOCK_SAME_BTN_CLICKED
- volatile Keyboard_Btn_Typedef prevClickedBtn;
- #endif
- }keypad_TypeDef_Struct;
Tablica z klawiaturą, oraz inicjalizacja struktury:
Inicjalizacja pinów:
Odczytanie stanu klawisza wygląda następująco:
Sprawdzenie stanu linii i wpisanie wprowadzanego klawisza:
Funkcja KeyPad_Update aby działa poprawnie i sprawnie musi być wywoływana w przerwaniu od timera. Dzięki temu nie doświadczy się opóźnień w jej działaniu.
Wcześniejsza funkcja Keypad_ReadBtn może być wywoływana w pętli głównej przed obsłużeniem klikniętego przycisku.
Ustawienie stanu kolumn:
Sprawdzenie stanu na wierszach:
Funkcja odczytująca który klawisz został kliknięty:
Obsługa wciśniętego klawisza:
- uint8_t keypadBtn[4][3] = {
- {Btn_1, Btn_2, Btn_3},
- {Btn_4, Btn_5, Btn_6},
- {Btn_7, Btn_8, Btn_9},
- {Btn_Star, Btn_0, Btn_Hash}
- };
- static volatile keypad_TypeDef_Struct keypadStatusClicked = {
- .clickedBtn = Btn_None,
- .prevClickedBtn = Btn_None
- };
Inicjalizacja pinów:
- static inline void ioport_configure_pin(port_pin_t pin, port_pin_flags_t flags)
- {
- ioport_configure_port_pin(arch_ioport_pin_to_base(pin),
- arch_ioport_pin_to_mask(pin), flags);
- }
- void KeypadInit(void)
- {
- //KLAW_V3 - IOPORT_CREATE_PIN(PORTB, 0)
- //KLAW_V3_CONFIG - IOPORT_DIR_OUTPUT | IOPORT_INIT_LOW
- ioport_configure_pin(KLAW_V1, KLAW_V3_CONFIG);
- ioport_configure_pin(KLAW_V2, KLAW_V2_CONFIG);
- ioport_configure_pin(KLAW_V3, KLAW_V1_CONFIG);
- //KLAW_H4 - IOPORT_CREATE_PIN(PORTA, 4)
- //KLAW_H4_CONFIG - IOPORT_DIR_INPUT | IOPORT_PULL_UP
- ioport_configure_pin(KLAW_H1, KLAW_H4_CONFIG);
- ioport_configure_pin(KLAW_H2, KLAW_H3_CONFIG);
- ioport_configure_pin(KLAW_H3, KLAW_H2_CONFIG);
- ioport_configure_pin(KLAW_H4, KLAW_H1_CONFIG);
- }
Odczytanie stanu klawisza wygląda następująco:
- Keyboard_Btn_Typedef KeyPad_ReadBtn(void)
- {
- Keyboard_Btn_Typedef tempRead;
- tempRead = keypadStatusClicked.clickedBtn;
- keypadStatusClicked.clickedBtn = KEYPAD_NO_PRESSED;
- return tempRead;
- }
Sprawdzenie stanu linii i wpisanie wprowadzanego klawisza:
- void KeyPad_Update(void)
- {
- static uint16_t timeCounter = 0;
- #ifdef KEYPAD_BLOCK_SAME_BTN_CLICKED
- volatile Keyboard_Btn_Typedef tmpClickedBtn;
- #endif
- timeCounter++;
- if (timeCounter >= KEYPAD_READ_INTERVAL && keypadStatusClicked.clickedBtn == KEYPAD_NO_PRESSED)
- {
- timeCounter = 0;
- #ifdef KEYPAD_BLOCK_SAME_BTN_CLICKED
- tmpClickedBtn = (Keyboard_Btn_Typedef)keyPad_Read();
- if(tmpClickedBtn == keypadStatusClicked.prevClickedBtn)
- {
- keypadStatusClicked.clickedBtn = KEYPAD_NO_PRESSED;
- }
- else
- {
- keypadStatusClicked.clickedBtn = tmpClickedBtn;
- keypadStatusClicked.prevClickedBtn = tmpClickedBtn;
- tmpClickedBtn = KEYPAD_NO_PRESSED;
- }
- #else
- keypadStatusClicked.clickedBtn = (Keyboard_Btn_Typedef)keyPad_Read();
- #endif
- }
- }
Funkcja KeyPad_Update aby działa poprawnie i sprawnie musi być wywoływana w przerwaniu od timera. Dzięki temu nie doświadczy się opóźnień w jej działaniu.
Wcześniejsza funkcja Keypad_ReadBtn może być wywoływana w pętli głównej przed obsłużeniem klikniętego przycisku.
Ustawienie stanu kolumn:
- static void keyPad_SetColumn(uint8_t column)
- {
- gpio_set_pin_high(KLAW_V1);
- gpio_set_pin_high(KLAW_V2);
- gpio_set_pin_high(KLAW_V3);
- /* Set column low */
- if (column == 1) {
- gpio_set_pin_low(KLAW_V1);
- }
- if (column == 2) {
- gpio_set_pin_low(KLAW_V2);
- }
- if (column == 3) {
- gpio_set_pin_low(KLAW_V3);
- }
- }
Sprawdzenie stanu na wierszach:
- static uint8_t keyPad_CheckRow(uint8_t column)
- {
- if (gpio_pin_is_low(KLAW_H1)) { return keypadBtn[0][column - 1]; } /* Scan row 1 */
- if (gpio_pin_is_low(KLAW_H2)) { return keypadBtn[1][column - 1]; } /* Scan row 2 */
- if (gpio_pin_is_low(KLAW_H3)) { return keypadBtn[2][column - 1]; } /* Scan row 3 */
- if (gpio_pin_is_low(KLAW_H4)) { return keypadBtn[3][column - 1]; } /* Scan row 4 */
- return KEYPAD_NO_PRESSED;
- }
Funkcja odczytująca który klawisz został kliknięty:
- static uint8_t keyPad_Read(void)
- {
- uint8_t check;
- for(volatile uint8_t i = 1; i<=3; i++)
- {
- keyPad_SetColumn(i);
- check = keyPad_CheckRow(i);
- if (check != KEYPAD_NO_PRESSED) { return check; }
- }
- return KEYPAD_NO_PRESSED;
- }
Obsługa wciśniętego klawisza:
- void KeyToWiegand(keypad_TypeDef_Struct *btnStruct)
- {
- if(btnStruct->clickedBtn == (Btn_Hash+1))
- {
- return;
- }
- if(btnStruct->clickedBtn == Btn_0)
- {
- }
- else if(btnStruct->clickedBtn == Btn_1)
- {
- }
- else if(btnStruct->clickedBtn == Btn_2)
- {
- }
- else if(btnStruct->clickedBtn == Btn_3)
- {
- }
- else if(btnStruct->clickedBtn == Btn_4)
- {
- }
- else if(btnStruct->clickedBtn == Btn_5)
- {
- }
- else if(btnStruct->clickedBtn == Btn_6)
- {
- }
- else if(btnStruct->clickedBtn == Btn_7)
- {
- }
- else if(btnStruct->clickedBtn == Btn_8)
- {
- }
- else if(btnStruct->clickedBtn == Btn_9)
- {
- }
- else if(btnStruct->clickedBtn == Btn_Star)
- {
- }
- else if(btnStruct->clickedBtn == Btn_Hash)
- {
- }
- }