#c #debouncing
#c #дебаунсинг
Вопрос:
Я пытаюсь написать дебаунсер, который будет возвращать только допустимый аргумент (> 0), если он был дебатирован (-1 четыре прыжка). Я уже придумал это, но он всегда возвращает -1, почему мне интересно:
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#define BOUNCETIME 500000000 //(500ms)
#define SetTime(x) clock_gettime(CLOCK_REALTIME, (x)); // set time
static struct timespec tset;
struct timespec tnow;
int DeBounce(unsigned int arg)
{
static int val = -1;
long long nsec = 0;
if (val < 0) {
val = arg;
SetTime(amp;tset);
return arg;
} else {
SetTime(amp;tnow);
if (tnow.tv_nsec < tset.tv_nsec)
nsec = tnow.tv_nsec 1000000000;
else
nsec = tnow.tv_nsec;
if (tnow.tv_nsec - tset.tv_nsec > BOUNCETIME) {
printf("arg okayn");
val = -1;
return arg;
}
else
printf("bounce, ignore!n");
return -1;
}
}
int main (void)
{
printf("#1 %dn",DeBounce(0));
usleep(1);
printf("#2 %dn",DeBounce(1));
usleep(200);
printf("#3 %dn",DeBounce(1));
sleep(1);
printf("#4 %dn",DeBounce(1));
}
вывод, который я получаю, это:
$ ./debounce
#1 0
bounce, ignore!
#2 -1
bounce, ignore!
#3 -1
bounce, ignore!
#4 -1
$
Ответ №1:
usleep(600);
составляет 600 микросекунд. Но ваш период дебаунса составляет 500 миллисекунд.
Кроме tnow.tv_nsec - tset.tv_nsec
того, неверно, поскольку tv_nsec
это не полное значение времени, а только количество наносекунд, прошедших со второй. Правильный способ вычисления прошедшего времени в наносекундах выглядит примерно так:
(tnow.tv_sec * 1.0e-9 tnow.tv_nsec) - (tset.tv_sec * 1.0e-9 tset.tv_nsec)
Комментарии:
1. Есть и другая проблема, простое вычитание tnow.tv_nsec — tset.tv_nsec не будет работать должным образом, поскольку tv_nsec — это просто количество наносекунд, прошедших за секунду.
2. @nos Да, сейчас обновляю ответ (просто отвлекся на несколько минут).
3. @kaylum да, следовательно, последний аргумент должен быть принят, а не отменен, но он тоже отменяется…
4. @cerr Почему должно приниматься последнее значение?
usleep
Недостаточно долго, чтобы период дебаунса не истек.5. @cerr Вы не учитываете компонент seconds,
tv_sec
. Вы предполагаете, что делоtnow.tv_nsec < tset.tv_nsec
приравнивается к секундам, которые перевернулись. Но это неверно, поскольку секунды могут перевернуться даже в другом случае. Вы должныtv_sec
каким-то образом посмотреть.