версия без принтов
This commit is contained in:
@@ -1,17 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
Чтение данных с параллельной 8-битной шины Raspberry Pi 4
|
Чтение данных с параллельной 8-битной шины Raspberry Pi 4
|
||||||
и вывод в stdout (для передачи, например, в Go-сервер).
|
и вывод в stdout
|
||||||
|
|
||||||
Сборка (внутри WiringPi/examples):
|
Сборка (внутри WiringPi/examples):
|
||||||
make really-all
|
make really-all
|
||||||
|
|
||||||
Использование:
|
|
||||||
./gpio-interrupt # только stdout
|
|
||||||
./gpio-interrupt /tmp/log # stdout + лог в файл
|
|
||||||
./gpio-interrupt - # лог в stderr
|
|
||||||
|
|
||||||
Требования:
|
Требования:
|
||||||
- Используется модифицированный WiringPi с функцией digitalReadPins()
|
Используется модифицированный WiringPi с функцией digitalReadPins()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -34,7 +28,7 @@
|
|||||||
35 - D5
|
35 - D5
|
||||||
33 - D6
|
33 - D6
|
||||||
31 - D7
|
31 - D7
|
||||||
36 - такт
|
36 - Запись
|
||||||
14 - GND
|
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)
|
unsigned int pins[] = { 21, 7, 6, 5, 25, 24, 23, 22 }; // 8-битная шина данных (wPi)
|
||||||
|
|
||||||
const size_t out_buffer_len = 32U; // Размер логируемого пакета
|
const size_t out_buffer_len = 32U; // Размер логируемого пакета
|
||||||
const size_t fifo_buffer_len = 4096U; // Размер FIFO буфера
|
const size_t fifo_buffer_len = 4096U; // Размер ПППУ в байтах
|
||||||
|
|
||||||
// ================= FIFO =================
|
// ================= 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) {
|
bool fifo_try_read(struct fifo *ff, char* buffer, size_t len) {
|
||||||
if (!fifo_can_read(ff, len))
|
if (!fifo_can_read(ff, len))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
memcpy(buffer, &ff->buffer[ff->rdi], len);
|
memcpy(buffer, &ff->buffer[ff->rdi], len);
|
||||||
ff->rdi = (ff->rdi + len) % ff->len;
|
ff->rdi = (ff->rdi + len) % ff->len;
|
||||||
return true;
|
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) {
|
bool fifo_try_write(struct fifo *ff, char* buffer, size_t len) {
|
||||||
if (!fifo_can_write(ff, len))
|
if (!fifo_can_write(ff, len))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
memcpy(&ff->buffer[ff->wri], buffer, len);
|
memcpy(&ff->buffer[ff->wri], buffer, len);
|
||||||
ff->wri = (ff->wri + len) % ff->len;
|
ff->wri = (ff->wri + len) % ff->len;
|
||||||
return true;
|
return true;
|
||||||
@@ -108,145 +100,64 @@ bool fifo_try_write(struct fifo *ff, char* buffer, size_t len) {
|
|||||||
|
|
||||||
static struct fifo isr_ff;
|
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 мс
|
static const long debounce_us = 5000; // 5 мс
|
||||||
|
|
||||||
// Обработчик прерывания
|
// Обработчик прерывания
|
||||||
void isr_handle(void) {
|
void isr_handle(void) {
|
||||||
|
unsigned long long now_us;
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
gettimeofday(&now, NULL);
|
gettimeofday(&now, NULL);
|
||||||
|
now_us = now.tv_sec * 1000000LL + now.tv_usec;
|
||||||
|
|
||||||
long diff = (now.tv_sec - last_isr_time.tv_sec) * 1000000L +
|
if (now_us - last_time_us < debounce_us) return;
|
||||||
(now.tv_usec - last_isr_time.tv_usec);
|
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]);
|
char byte_read = 0xff & digitalReadPins(pins, sizeof pins / sizeof pins[0]);
|
||||||
|
|
||||||
fifo_try_write(&isr_ff, &byte_read, 1);
|
fifo_try_write(&isr_ff, &byte_read, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================= MAIN =================
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
FILE *log_file = NULL;
|
// Инициализация FIFO
|
||||||
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
|
|
||||||
if (!fifo_init(&isr_ff, fifo_buffer_len)) {
|
if (!fifo_init(&isr_ff, fifo_buffer_len)) {
|
||||||
perror("Ошибка инициализации FIFO");
|
perror("fifo_init()");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// WiringPi
|
// WiringPi
|
||||||
if (wiringPiSetup() == -1) {
|
if (wiringPiSetup() == -1) {
|
||||||
perror("Ошибка wiringPiSetup()");
|
perror("wiringPiSetup()");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Настройка WR
|
|
||||||
pinMode(wr_pin, INPUT);
|
pinMode(wr_pin, INPUT);
|
||||||
pullUpDnControl(wr_pin, PUD_UP);
|
pullUpDnControl(wr_pin, PUD_UP);
|
||||||
|
|
||||||
// Настройка шины данных
|
// Настройка шины данных
|
||||||
for (unsigned int i = 0; i < (sizeof pins / sizeof pins[0]); i++) {
|
for (unsigned int i = 0; i < (sizeof pins / sizeof pins[0]); i++) {
|
||||||
unsigned int pin = pins[i];
|
unsigned int pin = pins[i];
|
||||||
|
|
||||||
// Используем подтяжку вниз (важно для стабильности)
|
|
||||||
pullUpDnControl(pin, PUD_DOWN);
|
pullUpDnControl(pin, PUD_DOWN);
|
||||||
pinMode(pin, INPUT);
|
pinMode(pin, INPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Прерывание по фронту
|
// Прерывание по фронту
|
||||||
if (wiringPiISR(wr_pin, INT_EDGE_RISING, &isr_handle) != 0) {
|
if (wiringPiISR(wr_pin, INT_EDGE_RISING, &isr_handle) != 0) {
|
||||||
perror("Ошибка wiringPiISR()");
|
perror("wiringPiISR()");
|
||||||
exit(EXIT_FAILURE);
|
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 byte;
|
||||||
char log_buffer[out_buffer_len];
|
|
||||||
int log_index = 0;
|
|
||||||
unsigned long total_bytes = 0;
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (fifo_try_read(&isr_ff, &byte, 1)) {
|
if (fifo_try_read(&isr_ff, &byte, 1)) {
|
||||||
log_buffer[log_index++] = byte;
|
|
||||||
total_bytes++;
|
|
||||||
|
|
||||||
// Вывод в stdout (побайтно)
|
|
||||||
fwrite(&byte, 1, 1, stdout);
|
fwrite(&byte, 1, 1, stdout);
|
||||||
fflush(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 {
|
} else {
|
||||||
usleep(10000);
|
usleep(1000); // 1 мс пауза при отсутствии данных
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Очистка (теоретически недостижимо, но для порядка)
|
|
||||||
if (log_file && log_file != stderr) {
|
|
||||||
fclose(log_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
fifo_uninit(&isr_ff);
|
fifo_uninit(&isr_ff);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user