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?
да, вполне может заменить 1-2 логических элементов в обвесе МК
нагуглить несложно, например https://www.rlocman.ru/review/article.html?di=640073
Глобальную переменную 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;
}
}
Спасибо вам за помощь!!!
всё работает!!!!!
Программирование ESP32 с ESP-IDF в среде platformio #1