Сам код опроса матричной клавиатуры:
Спойлер
ФАЙЛ MAIN.CКод: Выделить всё
//***************************************************************************
//
// Author(s)...: Pashgan http://ChipEnable.Ru
//
// Target(s)...: ATMega8
//
// Compiler....: GNU GCC
//
// Description.: Опрос матричной клавиатуры. Использование конечного автомата.
//
// Data........: 06.03.10
//
//***************************************************************************
#include <avr/io.h>
#include <avr/interrupt.h>
#include "keyboard.h"
//отправка символа по usart`у
void USART_SendChar(unsigned char sym)
{
while(!(UCSRA & (1<<UDRE)));
UDR = sym;
}
//прерывание таймера Т0 - опрос клавиатуры
ISR(TIMER0_OVF_vect)
{
TCNT0 = 0x83;
ScanKeyboard();
}
int main( void )
{
unsigned char key;
//инициализация USART`a
UBRRH = 0;
UBRRL = 51; //скорость обмена 9600 бод при Fcpu = 8MГц
UCSRB = (1<<TXEN); // разр передачи.
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); //размер слова 8 разрядов
//инициализация таймера Т0
TIMSK = (1<<TOIE0); //разрешение прерывания по переполнению
TCCR0 = (1<<CS02)|(0<<CS01)|(0<<CS00); //предделитель 256
TCNT0 = 0x83; //прерывания каждые 4 мс
//инициализация портов и переменных
InitKeyboard();
sei();
while(1){
//если зафиксировано нажатие,
//отправить код кнопки в терминал
key = GetKey();
if (key)
USART_SendChar(key);
}
return 0;
}
Код: Выделить всё
//***************************************************************************
//
// Author(s)...: Pashgan http://ChipEnable.Ru
//
// Target(s)...: ATMega8
//
// Compiler....: GNU GCC
//
// Description.: Опрос матричной клавиатуры. Использование конечного автомата.
//
// Data........: 06.03.10
//
//***************************************************************************
#ifndef KEYBOARD_H
#define KEYBOARD_H
#include <avr/io.h>
#include <avr/pgmspace.h>
//инициализация портов и внутренних переменных
void InitKeyboard(void);
//сканирование клавиатуры
void ScanKeyboard(void);
//возвращает код нажатой кнопки
unsigned char GetKey(void);
#endif //KEYBOARD_HКод: Выделить всё
#include "keyboard.h"
//хранит текущее состояние автомата
unsigned char keyState;
//хранит код нажатой кнопки
unsigned char keyCode;
//хранит символьное значение нажатой кнопки
unsigned char keyValue;
//флаговая переменная - устанавливается, если кнопка удерживается
unsigned char keyDown;
//флаговая переменная - устанавливается, когда нажата новая кнопка
unsigned char keyNew;
//таблица перекодировки
PROGMEM unsigned char keyTable[][2] = {
{ 0x11, '1'},
{ 0x12, '2'},
{ 0x14, '3'},
{ 0x21, '4'},
{ 0x22, '5'},
{ 0x24, '6'},
{ 0x41, '7'},
{ 0x42, '8'},
{ 0x44, '9'},
{ 0x81, '*'},
{ 0x82, '0'},
{ 0x84, '#'}
};
//прототипы функций используемых автоматом
unsigned char AnyKey(void);
unsigned char SameKey(void);
void ScanKey(void);
unsigned char FindKey(void);
void ClearKey(void);
//инициализация портов, обнуление переменных
void InitKeyboard(void)
{
DDRD |= 0xf0;
PORTD &= 0x0f;
DDRC &= ~0x07;
PORTC &= ~0x07;
keyState = 0;
keyCode = 0;
keyValue = 0;
keyDown = 0;
keyNew = 0;
}
//автомат реализующий опрос клавиатуры, защиту от дребезга
// и распознование нажатой кнопки
void ScanKeyboard(void)
{
switch (keyState){
case 0:
if (AnyKey()) {
ScanKey();
keyState = 1;
}
break;
case 1:
if (SameKey()) {
FindKey();
keyState = 2;
}
else keyState = 0;
break;
case 2:
if (SameKey()){}
else keyState = 3;
break;
case 3:
if (SameKey()) {
keyState = 2;
}
else {
ClearKey();
keyState = 0;
}
break;
default:
break;
}
}
//возвращает true если какая-нибудь кнопка нажата
unsigned char AnyKey(void)
{
PORTD |= 0xf0;
return (PINC & 0x07);
}
// возвращает true если удерживается та же кнопка
//что и в предыдущем цикле опроса
unsigned char SameKey(void)
{
PORTD = (PORTD & 0x0f) | ( keyCode & 0xf0);
return ((PINC & keyCode) & 0x07);
}
//Генерирует нужные сигналы на линиях
//считывает код нажатой кнопки
void ScanKey(void)
{
unsigned char activeRow = (1<<4);
while (activeRow) {
PORTD = (PORTD & 0x0f)|activeRow;
if (PINC & 0x07) {
keyCode = (PINC & 0x07);
keyCode |= (PORTD & 0xf0);
}
activeRow <<= 1;
}
}
// преобразует код кнопки в соответствующий символ
// устанавивает флаги
unsigned char FindKey(void)
{
unsigned char index;
for (index = 0; index < 12; index++) {
if (pgm_read_byte(&keyTable [index][0]) == keyCode) {
keyValue = pgm_read_byte(&keyTable [index][1]);
keyDown = 1;
keyNew = 1;
return 1;
}
}
return 0;
}
//сбрасывает флаг
void ClearKey(void)
{
keyDown = 0;
}
//если зафиксировано нажатие кнопки
//возвращает ее код
unsigned char GetKey(void)
{
if (keyNew){
keyNew = 0;
return keyValue;
}
else
return 0;
}

