ESP32 FreeRTOS二值信号量按键控制LED翻转异常问题
问题根因与修复方案
这个故障和GPIO基础配置无关,是代码逻辑错误导致的,具体问题和对应修复方式如下:
- 核心逻辑错误:LED控制逻辑完全不符合预期
你在按键任务中的执行顺序是:检测到按键按下(电平为0)→ 空转阻塞直到按键完全松开(电平回到1)→ 打印日志、释放二值信号量。等LED任务拿到信号量开始执行时,按键早就已经处于松开状态,此时读取按键引脚电平永远是1,所以每次都会执行gpio_set_level(BLINK_GPIO, 0)把LED熄灭,根本不可能实现按下按键翻转LED的效果,这就是你看到LED亮一下马上熄灭的直接原因。
要实现LED翻转,根本不需要在LED任务里读取按键电平,直接读取LED当前的输出电平取反设置即可,把task_blink里的电平设置代码替换为:uint8_t led_cur = gpio_get_level(BLINK_GPIO); gpio_set_level(BLINK_GPIO, !led_cur); - 按键检测逻辑存在资源浪费和误触发隐患
你写的等待按键松开的空循环while(gpio_get_level(BUTTON_GPIO) == 0){}没有加任何任务延时,按键按下的全过程中这个任务会满优先级占满CPU核心,影响其他任务调度;同时没有做按键消抖,机械按键的抖动会导致一次按压多次触发信号量。另外建议给按键引脚显式配置内部上拉(适配按键按下接GND的常规硬件设计),修改按键初始化和检测逻辑:// 按键GPIO初始化补充上拉配置 gpio_set_pull_mode(BUTTON_GPIO, GPIO_PULLUP_ONLY); // 按键检测逻辑修改为带消抖、带延时的版本 void task_botao(void *pvParameters) { while(1) { if(gpio_get_level(BUTTON_GPIO) == 0) { vTaskDelay(pdMS_TO_TICKS(20)); // 20ms消抖 if(gpio_get_level(BUTTON_GPIO) != 0) { vTaskDelay(1); continue; } // 等待按键松开,循环内加延时避免CPU空转 while(gpio_get_level(BUTTON_GPIO) == 0) { vTaskDelay(pdMS_TO_TICKS(10)); } printf("Botao Pressionado!!!\r\n"); xSemaphoreGive(sem_sinc); } vTaskDelay(1); } } - 二值信号量初始化存在冗余兼容问题
旧接口vSemaphoreCreateBinary创建的二值信号量初始计数值本来就是0,你后面额外调用xSemaphoreTake(sem_sinc,0)做初始化是多余的,部分新版ESP-IDF中更推荐使用返回值明确的xSemaphoreCreateBinary()接口创建,避免宏定义兼容问题:// 替换app_main中原来的信号量创建代码 sem_sinc = xSemaphoreCreateBinary(); // 删除后面多余的xSemaphoreTake(sem_sinc,0); 初始化语句
补充说明:你使用GPIO0作为按键输入是可行的,它是启动模式strapping引脚而非复位引脚,只要不在上电复位阶段将其拉到错误电平触发下载模式,正常运行时作为普通GPIO输入完全没有问题,这一点确实不是故障原因。
内容的提问来源于stack exchange,提问作者caio_alBR
相关产品推荐
相关产品推荐

