ESP32 IDF定时器中断实现GPIO高低电平切换问题求助
问题分析与修正方案
你的代码存在两个核心问题:
- 函数调用错误:
esp_timer_stop_periodic仅需传入定时器句柄一个参数,你传了两个参数(句柄+6000),这会直接导致编译失败。 - 逻辑设计错误:固定周期的定时器无法实现两种不同时长的电平切换,而且你启动20ms周期后立刻停止定时器,最终定时器根本不会正常工作。
修正后的代码实现
要实现高电平20ms、低电平6ms的交替信号,推荐使用单次定时器:每次触发回调时切换GPIO电平,并根据当前电平状态设置下一次定时器的超时时长。
#include <stdio.h> #include "esp_timer.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_log.h" #include "driver/gpio.h" #define GPIO_OUTPUT_PIN GPIO_NUM_2 static esp_timer_handle_t timer_handler; static bool is_high_level = false; void timer_callback(void *param) { is_high_level = !is_high_level; gpio_set_level(GPIO_OUTPUT_PIN, is_high_level); // 根据当前电平设置下一次定时器超时时间:高电平20ms,低电平6ms uint64_t next_timeout = is_high_level ? 20000 : 6000; // 重新启动单次定时器 ESP_ERROR_CHECK(esp_timer_start_once(timer_handler, next_timeout)); } void app_main(void) { // GPIO初始化 gpio_pad_select_gpio(GPIO_OUTPUT_PIN); gpio_set_direction(GPIO_OUTPUT_PIN, GPIO_MODE_OUTPUT); // 初始设置为低电平 gpio_set_level(GPIO_OUTPUT_PIN, 0); // 创建单次定时器 const esp_timer_create_args_t my_timer_args = { .callback = &timer_callback, .name = "signal_timer"}; ESP_ERROR_CHECK(esp_timer_create(&my_timer_args, &timer_handler)); // 第一次启动定时器,先进入高电平(20ms后触发回调) ESP_ERROR_CHECK(esp_timer_start_once(timer_handler, 20000)); while (true) { // 这里可以保留你的其他逻辑 esp_timer_dump(stdout); vTaskDelay(pdMS_TO_TICKS(1000)); } }
关键逻辑说明
- 单次定时器的复用:每次回调完成电平切换后,根据当前电平状态设置下一次的超时时间,然后重新启动单次定时器,以此实现两种不同时长的交替。
- 初始状态控制:初始将GPIO设为低电平,第一次启动定时器设置20ms超时,触发后切换为高电平,之后循环切换。
- 函数调用规范:严格遵循ESP-IDF的API要求,
esp_timer_start_once用于启动单次触发的定时器,esp_timer_stop(如果需要停止)仅需传入句柄。
内容的提问来源于stack exchange,提问作者Balaji Baski
相关产品推荐
相关产品推荐

