Принципиальная разница в том, что сканирование происходит за известное конечное время, которое гораздо меньше периода сканирования. Если ждать отпускания кнопки, то можно попасть на вложенные прерывания и/или вообще не дождаться отпускания кнопки.
Вот пример программы.
Функция drvKbdInit вызывается однократно при инициализации устройств.
Функция drvKbdPutKey вызывается из перывания с периодом 10-50мс. Имеет функцию автоповтора кодов клавиш перемещения (стрелки). При одновременном нажатии нескольких клавиш формируется только один код клавиши, но можно изменить чтобы формировались несколько.
<c>
//==============================================//
// обработка матричной клавиатуры до 16 кнопок //
// содержит функции: //
// -инициализации //
// -сканирования //
//==============================================//
// Автор - rezident (rezident@rbcmail.ru) //
// сopyright (c) февраль, 2005 год //
//==============================================//
#include "..\_INC\drvKBDdef.h"
#include "..\..\_xCOMMON\_LIB\KBD\xKBD_Buf.c"
//==============================================//
// Функция инициализации клавиатуры
//-----------------------------------------------
//аргументы: указатель на структуру переменных
// клавиатуры,
// указатель на стуктуру констант
// клавиатуры,
// указатель на буфер драйвера клавиатуры
//возвращает:ошибку, если нет клавиатуры
//===============================================
xByte drvKbdInit(xVT_KBD_Data *pd, st_drvKBD_Loc *pc, xByte *pKbBuf)
{ st_drvKBD_Data *drv=(st_drvKBD_Data *)&pd->drvData;
if (drvKbdHardInit()!=0) //нет железа или клав-ры?
{ return(1); //возвращ. ошибку (нет клав-ы)
}
drv->matrix=0; //сбросим состояние матрицы
drv->status=0; //сбросим устойчивое состояние
drv->autoKey=KB_NULL; //предуст.код автоповтора
drv->autoDly=pc->dly; //предустановим счетчик за-
//держки автоповтора
drv->autoRpt=0; //сбросим счетчик паузы
//автоповтора
drv->cData=(st_drvKBD_Loc *)pc; //указатель на сегмент констант
pd->flags=drvKBTYPE; //здесь установим тип клав-ры
pd->NumKey=0; //сбросим число кодов в буфере
pd->IdKey=0; //сбросим индекс записи кода в буфере
pd->RdIdxKey=0; //обнулим индекс чтения кода в буфере
pd->LastKey=KB_NULL; //код последней извлеч.клавиши
pd->pBuf=pKbBuf; //указатель на буфер клав-ры
pd->SzBuf=drvKB_MAXBUFSIZE; //уст. размер буфера клавитуры
if (pc->time==0) pd->flags|=VT_FKBD_M_H_LOCKAUTO; //блокируем автоповтор
return(0);
}
//================================================
// Функция сканирования виртуальной клавиатуры
//------------------------------------------------
//аргументы: указатель на структуру клавиатуры
//возвращает:нет
//================================================
void drvKbdPutKey(xVT_KBD_Data *dbuf)
{ st_drvKBD_Data *pd=(st_drvKBD_Data *)&dbuf->drvData;
st_drvKBD_Loc *pc=(st_drvKBD_Loc *)pd->cData;
xWord tmp1=0, tmp2=0;
xByte key;
tmp1=drvKbdHardScan(); //сканирование клав-ры
if ((pd->matrix^tmp1)==0) //предыд. и текущ. состояния
//матрицы совпадают?
{ //да, состояние ее устойчивое
tmp2=pd->status^tmp1; //проверим изменения
if (tmp2!=0) //есть изменения?
{ //да,требуется обработка
pd->autoKey=KB_NULL; //предустановим кодом
//ненажатой клавиши
xWord mask=1; //маска для идентификации
for (xWord i=0; i<drvKB_MAXKEYNUM; i++) //цикл для идентиф. нажатия
{ if ((tmp2&mask)!=0) //сост. этой клав. изменилось?
{ if ((tmp1&mask)!=0) //да, а она нажата?
{ //да, надо писать код в буфер
if ((dbuf->flags&VT_FKBD_M_H_LOCK)==0) //клавиатура не заблокирована?
{ key=pc->Tab[i]; //код клавиши из таблицы
if ((key!=KB_NULL)&&(dbuf->NumKey<dbuf->SzBuf))//код верный и
{ //место в буфере имеется?
dbuf->pBuf[dbuf->IdKey]=key;
if (dbuf->IdKey<(dbuf->SzBuf-1)) dbuf->IdKey++;
else dbuf->IdKey=0;
dbuf->NumKey++;
pd->autoKey=key; //запомним как последний код
pd->autoRpt=0; //сбросим счетчик паузы
//автоповтора
pd->autoDly=pc->dly; //предустановим счетчик
//задержки автоповтора
if ((pd->ctrl&drvKBD_SIGNALBLOCK)==0)//блокировка сигнала есть?
{ pd->ctrl|=drvKBD_SIGNALON; //нету, поморгаем или побибикаем
}
}
i=dbuf->SzBuf; //закончим цикл
}
} //нет, кнопка была отжата
}
mask<<=1; //модифицируем маску бита
}
}
else //нет, устойчивое сост. не
//изменилось, но клавиша-то
//нажата!
if (((dbuf->flags&VT_FKBD_M_H_LOCKAUTO)==0)&& //автоповтор разрешен?
(tmp1!=0) //клавиша нажата
)
{ key=pd->autoKey;
if ((key==KB_UP) ||
(key==KB_DOWN)||
(key==KB_LEFT)||
(key==KB_RIGHT)
) //код клавиши со стрелками?
{ //нет, будем повторять его
if (pd->autoDly>0) //задержка автоповтора уже
//закончилась?
{ pd->autoDly-=1; //еще нет, уменьшим счетчик
}
else //да, задержка закончилась
if (pd->autoRpt>0) //пауза между автоповторами
//закончилась?
{ //нет, не окончилась
pd->autoRpt-=1; //уменьшим счетчик
}
else //да, пауза закончилась
{ if ((dbuf->flags&VT_FKBD_M_H_LOCK)==0) //клавиатура не заблокирована?
{ if ((key!=KB_NULL)&&(dbuf->NumKey<dbuf->SzBuf))//код верный и
{ //место в буфере имеется?
dbuf->pBuf[dbuf->IdKey]=key;
if (dbuf->IdKey<(dbuf->SzBuf-1)) dbuf->IdKey++;
else dbuf->IdKey=0;
dbuf->NumKey++;
}
if ((pd->ctrl&drvKBD_SIGNALBLOCK)==0) //блокировка сигнала есть?
{ pd->ctrl|=drvKBD_SIGNALON; //нету, поморгаем или побикаем
}
}
pd->autoRpt=pc->time; //установим счетчик паузы
} //автоповтора
}
}
pd->status=tmp1; //обновим устойчивое состояние
} //матрицы клавиатуры
pd->matrix=tmp1; //запомним текущ. состояние
} //матрицы
</c>
-
- while у меня ждал прерывания от таймера, раз в 30 мс. Dany(2982 знак., 25.07.2007 17:29, )
- Функция inkey не должна ждать чего-либо. Считала текущее состояние и передала его выше, той функции которая устраняет дребезг, формирует коды клавиш и складывает их в буфер клавиатуры. rezident(193 знак., 25.07.2007 17:56, )
- Решил функцию оставить в следуюшем виде... Dany(335 знак., 25.07.2007 21:30, )
- ИМХО это вариант ничуть не лучше. К тому же программа возвращает не собственно код нажатой клавиши, а битовое состояние матрицы кнопок. rezident(1019 знак., 25.07.2007 23:21, )
- rezident пытаюсь разобрать вашу функцию, объясните на примере первого обращения (matrix=0)... Dany(293 знак., 26.07.2007 08:49, )
- Все разобрался, извините за неаккуратность 10010^0=10010 - Dany(26.07.2007 09:00, )
- rezident пытаюсь разобрать вашу функцию, объясните на примере первого обращения (matrix=0)... Dany(293 знак., 26.07.2007 08:49, )
- ИМХО это вариант ничуть не лучше. К тому же программа возвращает не собственно код нажатой клавиши, а битовое состояние матрицы кнопок. rezident(1019 знак., 25.07.2007 23:21, )
- Понял, учту. - Dany(25.07.2007 18:19, )
- Решил функцию оставить в следуюшем виде... Dany(335 знак., 25.07.2007 21:30, )
- Функция inkey не должна ждать чего-либо. Считала текущее состояние и передала его выше, той функции которая устраняет дребезг, формирует коды клавиш и складывает их в буфер клавиатуры. rezident(193 знак., 25.07.2007 17:56, )
- while у меня ждал прерывания от таймера, раз в 30 мс. Dany(2982 знак., 25.07.2007 17:29, )