
Сообщение от
CityAceE
Клавиатура у меня опрашивается 50 раз в секунду
Зачем такие сложности?
По стандарту клавиатура должна работать в режиме опроса, но на деле очень много клавиатур так не работают или работают неправильно.
Клавиатура должна сама отправлять данные когда захочет. В этом режиме 100% клавиатур работают правильно.
Выше давал ссылку на код для AVR.
Продублирую нужные фрагмент кода:
Код:
// External Interrupt 0 service routine //Отрицательный фронт AT Clock ЧИТАЕМ ИЛИ ПИШЕМ
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here
delay_us(3); //Задержка, чтобы установился сигнал Data
if(at_read) //Если читаем из AT
{
if (at_bitcount == 11) //проверяем старт-бит
{
at_even_parity = 0; //Обнуляем бит четности
if (ADATA) at_error = YES; //нет старт-бита? Значит что-то пошло не так
}
else if(at_bitcount > 2) //Перекидываем значащие биты в буфер
{
at_shift_reg = at_shift_reg >> 1;
if (ADATA)
{
at_shift_reg = at_shift_reg | 0x80;
at_even_parity = !at_even_parity;
}
}
else if (at_bitcount == 2) //Если бит чётности (odd parity)
{
if(at_even_parity==ADATA) at_error = YES; //Если бит чётности = биту НЕчётности (взаимная инверсия), то ошибка!
}
else //Если стоп-бит
{
if (ADATA==0) at_error = YES; //нет стоп-бита? Значит что-то пошло не так
else //Если байт принят и всё в порядке,
{
at_buff = at_shift_reg;
at_new_data = YES; //Буфер символа не пуст
at_bitcount = 12; //Взводим счётчик битов (ниже он будет уменьшен на 1 и станет = 11)
ACLK_OUT = NULL; //Опускаем Clock - подтверждение клавиатуре в приёме (не обязательное)
}
}
}
else //Если пишем в AT
{
if (at_bitcount >3) //Отправляем биты в AT
{
if(at_shift_reg & 1)
{
ADATA_OUT = ONE;
at_even_parity = !at_even_parity;
}
else ADATA_OUT = NULL;
at_shift_reg = at_shift_reg >> 1;
}
else if(at_bitcount == 3) //Отправляем бит чётности
{
ADATA_OUT = at_even_parity; //У нас ADATA_OUT инвертировано, но и even_parity инвертировано относительно odd parity (которое и отсылается)
}
else if(at_bitcount == 2) //Отправляем стоп-бит = 1. И, одновременно, включаем порт на приём
{
ADATA_OUT = ONE;
}
else // Иначе at_bitcount == 1, других вариантов быть не может))))
{
if (ADATA) at_error = YES; //нет ACK (подтверждение от клавиатуры)? Значит что-то пошло не так
at_read = 1; //Переводим в режим чтения
at_bitcount = 12; //Взводим счетчик битов
}
}
at_bitcount--; //Уменьшаем на 1 счётчик битов. Причём не зависимо от того, принимаем или передаём.
}
Код:
void at_write (char a) //Пишем байт в AT
{
ACLK_OUT = NULL; //Тянем Clock на землю
GIMSK=0; // Вырубаем прерывания от AT Clock
GIFR=1<<INTF0; //Сбрасываем флаг прерывания от AT Clock (если он уже оказался установлен)
delay_us(100); //Ждём 100мкс (это минимум).
ADATA_OUT = NULL; //Тянем Data на землю
//Готовим данные (это даёт небольшую паузу):
at_shift_reg = a; //Заталкиваем в сдвиговый регистр AT передаваемый байт
at_read = NO; // Сбрасываем режим чтения, значит будет запись в AT
at_bitcount = 11; // Взводим счётчик битов
at_error = NO; //Сбрасываем ошибку работы с AT (если она была)
at_even_parity = 0; //Обнуляем бит четности
ACLK_OUT = OFF; //отпускаем Clock
GIMSK=(1<<INT0); // Включаем прерывание для Clock AT
}
//типовая процедура пропуска подтверждения операции записи в АТ клаву
//(простейшее ожидание и проверка ответа "0xFA")
void FAskip() //Возвращает at_error (если ошибка = 1, иначе = 0)
{
while (!(at_new_data | at_error)); //Пока буфер символа пуст и нет ошибки приёма, ждём (в это время могут выполняться прерывания).
if (at_buff != 0xFA) at_error = YES; //проверяем ответ
at_new_data = NO;
}
void at_init() //Инициализация AT клавиатуры
{
at_write (0xFF); // Сбрасываем клавиатуру
FAskip(); // Пропускаем от клавиатуры символ - подтверждение приёма. ////Если произошла ошибка, выход из процедуры
ACLK_OUT = OFF;
while (!(at_new_data | at_error)); //Пока нет новых данных (и нет ошибки AT), ждём (в это время могут выполняться прерывания)
at_new_data = NO;
if(at_buff != 0xAA) at_error = YES;
}