Для того, чтобы не вносить дополнительных ошибок выкладываю процедуры и библиотеки "как есть" из своего проекта. Всё однозначно рабочее. Клавиатура применена 3х4 с маркировкой как для АОНа. (Использовались данные толкатели). Библиотеки будут вложены, а примеры применения и некоторые подпрограммы - здесь.
Для реализации символьного ввода используется п/п динамического ввода на клавишу из библиотеки клавиатуры. Всё реализовано для atmega8/88
Инициализация
Код
// Инициализировать таймер 0 и прерывания для опроса клавиш
#if __ATmega88__
TCCR0A = 0x02; // Режим СТС
TCCR0B = 0x5; // FCLK/1024 (14.4KHz/69.4mks)
OCR0A = T_INT_TIM*1000000/1024/TCLK; // прерывание T_INT_TIM ms
TIMSK0 = 2; // Прерывания от CTC
#elif __ATmega8__
TCCR0 = 0x05; // Режим NORMAL, FCLK/1024 (14.4KHz/69.4mks)
TIMSK |= 1; // Прерывания от переполнения
#endif
// Инициализировать оборудование
DelayInit(); // Инициализация таймера
LCDInit(); // Инициализировать LCD дисплей
spliter_init(); // Инициализировать сплитер
KeyInit(); // Инициализация клавиатуры
WakeInit(); // Инициализация интерфейса rs485 и протокола WakeUp
__enable_interrupt(); // Разрешить прерывания
#if __ATmega88__
TCCR0A = 0x02; // Режим СТС
TCCR0B = 0x5; // FCLK/1024 (14.4KHz/69.4mks)
OCR0A = T_INT_TIM*1000000/1024/TCLK; // прерывание T_INT_TIM ms
TIMSK0 = 2; // Прерывания от CTC
#elif __ATmega8__
TCCR0 = 0x05; // Режим NORMAL, FCLK/1024 (14.4KHz/69.4mks)
TIMSK |= 1; // Прерывания от переполнения
#endif
// Инициализировать оборудование
DelayInit(); // Инициализация таймера
LCDInit(); // Инициализировать LCD дисплей
spliter_init(); // Инициализировать сплитер
KeyInit(); // Инициализация клавиатуры
WakeInit(); // Инициализация интерфейса rs485 и протокола WakeUp
__enable_interrupt(); // Разрешить прерывания
Символьный ввод
Код
const uint8_t __flash strkey[10][6] =
{
{'0',' ','-','=','+',0},
{'1',',','.',';',':',0},
{'2','А','Б','В','Г',0},
{'3','Д','Е','Ж','З',0},
{'4','И','Й','К','Л',0},
{'5','М','Н','О',0,0},
{'6','П','Р','С',0,0},
{'7','Т','У','Ф','Х',0},
{'8','Ц','Ч','Ш','Щ',0},
{'9','Ы','Э','Ю','Я',0}
};
uint8_t getextchar(void) // Ввести расширенную клавишу
{
uint8_t c, index, old, tekc, d;
index=0;
while(KeyPress()==0); // Если установлен бит Int_Key, то клавиша была нажата
do
{
while(KeyPress()!=0); // ждём пока клавишу отпустят
c = getchar(); // прочитать код клавиши
old=c; // запомнить последнюю нажатую кнопку
if(c < '0') return(c); // Если клавиши управления, то выйти
else c -= '0';
WaitLong = PAUZA; // Измерить паузу после нажатия
tekc=strkey[c][index]; // текущий символ
putchar(tekc); // вывести
do
if(KeyPress()!=0) // Если клавиша была нажата снова
{
d=KeyPress(); // прочитать код клавиши
if(d!=old)return(tekc); // если изменили клавишу, то выйти
index++; // Следующий символ из ряда
if(strkey[c][index]==0)index=0; // если конец ряда, то выйти
putchar(CR_BS); // Забить предыдущий символ
break;
}
while(WaitLong!=0);
}
while(WaitLong!=0);
return(tekc);
}
{
{'0',' ','-','=','+',0},
{'1',',','.',';',':',0},
{'2','А','Б','В','Г',0},
{'3','Д','Е','Ж','З',0},
{'4','И','Й','К','Л',0},
{'5','М','Н','О',0,0},
{'6','П','Р','С',0,0},
{'7','Т','У','Ф','Х',0},
{'8','Ц','Ч','Ш','Щ',0},
{'9','Ы','Э','Ю','Я',0}
};
uint8_t getextchar(void) // Ввести расширенную клавишу
{
uint8_t c, index, old, tekc, d;
index=0;
while(KeyPress()==0); // Если установлен бит Int_Key, то клавиша была нажата
do
{
while(KeyPress()!=0); // ждём пока клавишу отпустят
c = getchar(); // прочитать код клавиши
old=c; // запомнить последнюю нажатую кнопку
if(c < '0') return(c); // Если клавиши управления, то выйти
else c -= '0';
WaitLong = PAUZA; // Измерить паузу после нажатия
tekc=strkey[c][index]; // текущий символ
putchar(tekc); // вывести
do
if(KeyPress()!=0) // Если клавиша была нажата снова
{
d=KeyPress(); // прочитать код клавиши
if(d!=old)return(tekc); // если изменили клавишу, то выйти
index++; // Следующий символ из ряда
if(strkey[c][index]==0)index=0; // если конец ряда, то выйти
putchar(CR_BS); // Забить предыдущий символ
break;
}
while(WaitLong!=0);
}
while(WaitLong!=0);
return(tekc);
}
Само прерывание опроса клавиатуры и меток времени
Код
#ifdef __PORT88__
#pragma vector=TIMER0_COMPA_vect // Метки времени 10 мс
#else
#pragma vector=TIMER0_OVF_vect // Метки времени 10 мс
#endif
__interrupt static void MetkiTime10ms(void)
{
#if __ATmega8__
TCNT0 = -(T_INT_TIM*1000000/1024/TCLK);
#endif
KeyScan(); // Опросить клавиши
KeyStrSet(); // выставить строку
if(WaitLong!=0)WaitLong--; // Высчитать задержку
}
#pragma vector=TIMER0_COMPA_vect // Метки времени 10 мс
#else
#pragma vector=TIMER0_OVF_vect // Метки времени 10 мс
#endif
__interrupt static void MetkiTime10ms(void)
{
#if __ATmega8__
TCNT0 = -(T_INT_TIM*1000000/1024/TCLK);
#endif
KeyScan(); // Опросить клавиши
KeyStrSet(); // выставить строку
if(WaitLong!=0)WaitLong--; // Высчитать задержку
}