diff --git a/examples/gpio-interrupt.c b/examples/gpio-interrupt.c index de9c698..f3809e4 100644 --- a/examples/gpio-interrupt.c +++ b/examples/gpio-interrupt.c @@ -1,17 +1,11 @@ /* Чтение данных с параллельной 8-битной шины Raspberry Pi 4 - и вывод в stdout (для передачи, например, в Go-сервер). + и вывод в stdout Сборка (внутри WiringPi/examples): make really-all - - Использование: - ./gpio-interrupt # только stdout - ./gpio-interrupt /tmp/log # stdout + лог в файл - ./gpio-interrupt - # лог в stderr - Требования: - - Используется модифицированный WiringPi с функцией digitalReadPins() + Используется модифицированный WiringPi с функцией digitalReadPins() */ #include @@ -34,7 +28,7 @@ 35 - D5 33 - D6 31 - D7 - 36 - такт + 36 - Запись 14 - GND */ @@ -42,7 +36,7 @@ unsigned int wr_pin = 27; // Пин сигнала записи (WR) unsigned int pins[] = { 21, 7, 6, 5, 25, 24, 23, 22 }; // 8-битная шина данных (wPi) const size_t out_buffer_len = 32U; // Размер логируемого пакета -const size_t fifo_buffer_len = 4096U; // Размер FIFO буфера +const size_t fifo_buffer_len = 4096U; // Размер ПППУ в байтах // ================= FIFO ================= @@ -89,7 +83,6 @@ bool fifo_can_read(struct fifo *ff, size_t len) { bool fifo_try_read(struct fifo *ff, char* buffer, size_t len) { if (!fifo_can_read(ff, len)) return false; - memcpy(buffer, &ff->buffer[ff->rdi], len); ff->rdi = (ff->rdi + len) % ff->len; return true; @@ -98,7 +91,6 @@ bool fifo_try_read(struct fifo *ff, char* buffer, size_t len) { bool fifo_try_write(struct fifo *ff, char* buffer, size_t len) { if (!fifo_can_write(ff, len)) return false; - memcpy(&ff->buffer[ff->wri], buffer, len); ff->wri = (ff->wri + len) % ff->len; return true; @@ -108,145 +100,64 @@ bool fifo_try_write(struct fifo *ff, char* buffer, size_t len) { static struct fifo isr_ff; -// Защита от дребезга (debounce) -static volatile struct timeval last_isr_time = {0, 0}; +// Антидребезг +static unsigned long long last_time_us = 0; static const long debounce_us = 5000; // 5 мс // Обработчик прерывания void isr_handle(void) { + unsigned long long now_us; struct timeval now; gettimeofday(&now, NULL); + now_us = now.tv_sec * 1000000LL + now.tv_usec; - long diff = (now.tv_sec - last_isr_time.tv_sec) * 1000000L + - (now.tv_usec - last_isr_time.tv_usec); + if (now_us - last_time_us < debounce_us) return; + last_time_us = now_us; - if (diff < debounce_us) { - return; // игнорируем дребезг - } - - last_isr_time = now; - - // Читать 8 бит char byte_read = 0xff & digitalReadPins(pins, sizeof pins / sizeof pins[0]); - fifo_try_write(&isr_ff, &byte_read, 1); } -// ================= MAIN ================= - int main(int argc, char *argv[]) { - FILE *log_file = NULL; - const char *log_path = NULL; - - // Обработка аргументов - if (argc > 1) { - log_path = argv[1]; - - if (strcmp(log_path, "-") == 0) { - log_file = stderr; - fprintf(stderr, "=== Запуск GPIO-монитора (лог в stderr) ===\n"); - } else { - log_file = fopen(log_path, "a"); - if (!log_file) { - perror("Ошибка открытия лог-файла"); - exit(EXIT_FAILURE); - } - fprintf(stderr, "=== Запуск GPIO-монитора (лог в %s) ===\n", log_path); - fprintf(log_file, "\n=== Новая сессия: %ld ===\n", (long)time(NULL)); - fflush(log_file); - } - } else { - fprintf(stderr, "=== Запуск GPIO-монитора (только stdout) ===\n"); - } - - // FIFO + // Инициализация FIFO if (!fifo_init(&isr_ff, fifo_buffer_len)) { - perror("Ошибка инициализации FIFO"); + perror("fifo_init()"); exit(EXIT_FAILURE); } // WiringPi if (wiringPiSetup() == -1) { - perror("Ошибка wiringPiSetup()"); + perror("wiringPiSetup()"); exit(EXIT_FAILURE); } - // Настройка WR pinMode(wr_pin, INPUT); pullUpDnControl(wr_pin, PUD_UP); // Настройка шины данных for (unsigned int i = 0; i < (sizeof pins / sizeof pins[0]); i++) { unsigned int pin = pins[i]; - - // Используем подтяжку вниз (важно для стабильности) pullUpDnControl(pin, PUD_DOWN); pinMode(pin, INPUT); } // Прерывание по фронту if (wiringPiISR(wr_pin, INT_EDGE_RISING, &isr_handle) != 0) { - perror("Ошибка wiringPiISR()"); + perror("wiringPiISR()"); exit(EXIT_FAILURE); } - fprintf(stderr, "GPIO инициализированы, ожидание данных...\n"); - fprintf(stderr, "Антидребезг: %ld мкс\n", debounce_us); - - // Диагностика - fprintf(stderr, "Начальные состояния пинов:\n"); - for (unsigned int i = 0; i < (sizeof pins / sizeof pins[0]); i++) { - fprintf(stderr, " пин %d = %d\n", pins[i], digitalRead(pins[i])); - } - + // Основной цикл char byte; - char log_buffer[out_buffer_len]; - int log_index = 0; - unsigned long total_bytes = 0; - while (true) { if (fifo_try_read(&isr_ff, &byte, 1)) { - log_buffer[log_index++] = byte; - total_bytes++; - - // Вывод в stdout (побайтно) fwrite(&byte, 1, 1, stdout); fflush(stdout); - - // Логирование блоками - if (log_index >= (int)out_buffer_len && log_file) { - fprintf(log_file, "--- Пакет #%lu (%zu байт) ---\n", - total_bytes / out_buffer_len, out_buffer_len); - - for (int i = 0; i < (int)out_buffer_len; i++) { - fprintf(log_file, " [%02d] = 0x%02x (%3d)\n", - i, - (unsigned char)log_buffer[i], - (unsigned char)log_buffer[i]); - } - - fflush(log_file); - - // Индикатор прогресса - fprintf(stderr, "."); - if (total_bytes % (32 * 10) == 0) { - fprintf(stderr, " [%lu байт]\n", total_bytes); - } - fflush(stderr); - - log_index = 0; - } - } else { - usleep(10000); + usleep(1000); // 1 мс пауза при отсутствии данных } } - // Очистка (теоретически недостижимо, но для порядка) - if (log_file && log_file != stderr) { - fclose(log_file); - } - fifo_uninit(&isr_ff); return EXIT_SUCCESS; } \ No newline at end of file