Код
// Vertical Counters
// идея Scott Dattalo, http://www.dattalo.com
// добавлен PInChg для упрощения обработки изменений в PIn
#define IMask (1<<IBtn0) | (1<<IBtn1) | ...
// независимое устранение дребезга по 8 входам:
// состояние входа считается установившимся при получении
// 4 последовательных одинаковых выборок
void vcountr2(void)
{
// глобальные переменные:
// PIn - отфильтрованные входы
// PInChg - изменения по входам
static uint8_t CntA=0, CntB=0; // vertical counters
uint8_t t1, t2;
CntA ^= CntB;
CntB = ~CntB;
t1 = InPort & IMask;
PInChg = t1 ^ PIn.i;
CntA &= PInChg;
CntB &= PInChg;
t2 = CntA | CntB;
t1 &= ~t2;
PIn &= t2;
PIn |= t1;
PInChg &= ~t2;
// если убрать CntB, получим вариант rezident'a - фильтрация по двум выборкам
// если добавить CntC, получится фильтрация по 8 выборкам
// на ассемблере получается ну очень коротенько:)
}
// --------------------
// пример использования
// --------------------
uint8_t PIn, PInChg;
// хотя я обычно их обзываю
// union
// {
// uint8_t i;
// struct
// {
// uint8_t Btn0 :1;
// uint8_t Btn1 :1;
//...
// } b;
// } PIn, PInChg;
void main (void)
{
// инициализация
PIn = InPort & IMask; // PIn.i = InPort & IMask;
PInChg = 0; // PInChg.i = 0;
...
// рабочий цикл
for(;;)
{
// период опроса входов - по вкусу
// я для устранения дребезга кнопок устраиваю опрос с периодом 8-10 мс
// т.е. установившееся состояние входа получаем не менее чем через 32-40 мс
if(Flags.b._8ms)
{
Flags.b._8ms = 0;
vcountr2();
... // другие 8-мс задачи
}
...
// обработка PIn, PinChg
if(PInChg & (1<<IBtn0)) // if(PInChg.b.Btn0)
{
if(PIn & (1<<IBtn0)) // if(PIn.b.Btn0)
{
// в условиях задачи "Лог. 0 – кнопка нажата"
// сюда попадем при отпускании кнопки на входе Btn0
}
else
{
// а сюда - при нажатии
}
}
if(PInChg & (1<<IBtn1)) // аналогично
{
if(PIn & (1<<IBtn1))
{
}
else
{
}
}
...
} // end for(;;)
} // end main()