Pull to refresh

Comments 17

Если нужно читать данные, которые приходят на GPIO вход, например, со скоростью 100 килобит в секунду, лучше использовать таймер и опрашивать пин, или прерывание тоже подойдет?

Может лучше приспособить для этого модуль RMT в ESP32? По описанию вроде подходит.

Особенность протокола в том что ноль и единица приходят по разным пинам. То есть логическая единица на одном из пинов означает что пришла единица, а на другом что пришел ноль. А если логический ноль на обоих пинах, то это пауза, по которой определяется конец сообщения. А в RMT нет режима приема, который соответствует такой логике

Тогда можно попробовать прерывания. Настройте оба пина на GPIO_INTR_ANYEDGE и в одном ISR читайте оба уровня. Что-то вроде:

static void IRAM_ATTR gpio_isr_handler(void* arg) {
bool bit1 = gpio_get_level(PIN_ONE);
bool bit0 = gpio_get_level(PIN_ZERO);
if (bit1 && !bit0) {
// поймали «1»
} else if (!bit1 && bit0) {
// поймали «0»
} else if (!bit1 && !bit0) {
// пауза → конец сообщения
}
}

Но я все равно не до конца уверен в этой затее с ISR, так как 100кбайт на ядро довольно много. Но если вы не будете задействовать ядро с ISR (Core 0), а все остальные задачи выполнять на Core 1, то может что-то выйдет...

здесь lut выриcовывается который есть в новых attiny но нет в esp32. Наши деды (точнее отцы) в АОН на ВМ80 цифровали в буфер а потом обрабатывали. на esp32 это еще проще

А что такое lut? Look up table?

Глобальную переменную state можно использовать из всех задач? Разве не лучше использовать очередь при общении между задачами?

Я хотел в этой статье разобрать очереди, но получилось довольно много информации на прерывании. Я решил, что первую часть следующей статьи я уделю очереди.

Вы правы, что очереди тут будут лучшим вариантом

Стоит заметить что подход с непосредственным изменением состояния в обработчике прерывания от GPIO нельзя использовать с механическими переключателями из-за явления назвываемого "дребезг контактов".

Про разницу мьютекса и бинарного семафора интересно будет почитать

Добрый день, можете пожалуйста схему подключения показать, а-то я вроде всё правильно сделал а всё равно диод хаотически включается

E (205265) task_wdt: Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:
E (205265) task_wdt: - IDLE0 (CPU 0)
E (205265) task_wdt: Tasks currently running:
E (205265) task_wdt: CPU 0: BLINK
E (205265) task_wdt: CPU 1: IDLE1
E (205265) task_wdt: Print CPU 0 (current core) backtrace

Backtrace: 0x400D492E:0x3FFB1010 0x400D4CF0:0x3FFB1030 0x40083955:0x3FFB1060 0x400D177D:0x3FFB52C0 0x400D0E2B:0x3FFB52F0 0x4008619D:0x3FFB5310

И в мониторе обновляется это инфо

добавил в задачу vTaskDelay(1) и перестал ругаться на wdt,

но диод дальше зажигается хаотически

попробуйте еще дребезг кнопки исправить

Проблема в том, что задача Blink_Task заваливает процессор и никак не отпускает его.
Можно попробовать добавить задержку
void Blink_Task(void *arg) {
while (1) {
gpio_set_level(LED_GPIO, state);
vTaskDelay(pdMS_TO_TICKS(10)); // пусть таска будет опрашивать state каждые 10 мс
}
}

Также еще может быть проблема с дребезгом контактов
Можно прописать простой алгоритм дебаунса

static TickType_t last_toggle = 0;

static void IRAM_ATTR gpio_isr_handler(void *arg) {
TickType_t now = xTaskGetTickCountFromISR();
if (now - last_toggle > pdMS_TO_TICKS(50)) {
state = !state;
last_toggle = now;
}
}

Sign up to leave a comment.

Articles