基于ESP-IDF的GPIO中断程序printf出现的问题

文章讲述了在使用乐鑫ESP32-C3开发板时,遇到GPIO触发中断后printf无响应但ESP_LOGI有效的问题。作者分析了原因并提出使用ESP_LOGI进行输出的解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

芯片:乐鑫官网ESP32-C3-DevKitM-1 v1.6

IDE:VSCode+ESP_IDF

程序源码:

#include <stdio.h>
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_log.h"

#define BOOT 9
#define GPIO_INPUT_PIN_SEL (1ULL << BOOT)
#define ESP_INTR_FLAG_DEFAULT 0

static QueueHandle_t gpio_evt_queue = NULL;

void IRAM_ATTR gpio_isr_handler(void *arg)
{
    uint32_t gpio_num = (uint32_t)arg;
    xQueueSendFromISR(gpio_evt_queue,&gpio_num,NULL);
}

void gpio_task(void *arg)
{
    printf("\r\n start gpio task ... \r\n");
    uint32_t io_num;
    while(1)
    {
        
        if (xQueueReceive(gpio_evt_queue,&io_num,portMAX_DELAY))
        {
            printf("\r\n intriggered from GPIO%ld \r\n",io_num);
            //ESP_LOGI("gpio_task","intriggered from GPIO%ld",io_num);
        }
    }
}

void Key_Init()
{
    gpio_config_t gpio_struct =
    {
        .intr_type = GPIO_INTR_POSEDGE,
        .mode=GPIO_MODE_INPUT,
        .pull_up_en=1,
        .pull_down_en=0,
        .pin_bit_mask=GPIO_INPUT_PIN_SEL
    };
    gpio_config(&gpio_struct);

}

void Intr_init(void)
{
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    gpio_isr_handler_add(BOOT,gpio_isr_handler,(void *)BOOT);
    gpio_evt_queue = xQueueCreate(10,sizeof(uint32_t));
    xTaskCreate(gpio_task //任务函数
                ,
                "gpio_task_example" //任务名
                ,
                2048//堆栈大小
                ,
                NULL//传递参数
                ,
                10//任务优先级
                ,
                NULL);//任务句柄
}

void app_main(void)
{
    Key_Init();
    Intr_init();
    while (1)
    {
        vTaskDelay(1000/ portTICK_PERIOD_MS);
    }

}

出现问题:

一次按键无反应,要按多次才会输出,而且换行无效。

解决方法:

调用ESP_LOGI,输出正常。

 

疑问:

无法理解,printf不行但是ESP_LOGI可以的逻辑,存疑 

### ESP-IDF 外部中断 示例代码 教程 在ESP-IDF框架下实现外部中断的功能主要依赖于配置特定的GPIO引脚作为中断源,并编写相应的回调函数处理程序。当指定条件满足时,这些设置会触发CPU执行预先定义好的动作。 对于具体的实施过程,在初始化阶段需调用`gpio_install_isr_service()`安装全局的服务机制以便支持后续各个IO口单独启用IRQ模式[^5]。之后针对每一个期望监听事件变化信号的针脚,通过`gpio_set_intr_type()`指派其工作方式比如低电平触发、高到低跳变沿敏感等特性;紧接着利用`gpio_isr_handler_add()`关联实际物理端子编号同对应的ISR handler即中断服务例程之间关系从而达成软硬件对接目的。 下面给出一段简单的C语言风格示范片段用于说明上述理论要点: ```c #include "driver/gpio.h" #include "esp_system.h" void IRAM_ATTR gpio_isr_handler(void* arg) { uint32_t gpio_num = (uint32_t)arg; printf("Interrupt on pin number-%d\n", gpio_num); } void setup_gpio() { // 设置 GPIO0 为输入模式并开启内部上拉电阻 gpio_config_t io_conf; io_conf.intr_type = GPIO_INTR_DISABLE; //禁用中断 io_conf.mode = GPIO_MODE_INPUT; //设置为输入模式 io_conf.pin_bit_mask = GPIO_SEL_0; //选择GPIO0 io_conf.pull_up_en = 1; //使能上拉 io_conf.pull_down_en = 0; //禁止下拉 gpio_config(&io_conf); // 启动 ISR 服务 gpio_install_isr_service(0); // 配置 GPIO0 的中断类型为下降沿触发 gpio_set_intr_type(GPIO_NUM_0, GPIO_INTR_NEGEDGE); // 将中断处理器附加给 GPIO0 gpio_isr_handler_add(GPIO_NUM_0, gpio_isr_handler, (void*) GPIO_NUM_0); } ``` 此段落展示了如何配置单个I/O线路以响应外界施加的变化情况,并且每当检测到符合条件的状态转换就会自动激活预设的动作序列。值得注意的是这里采用了宏定义`IRAM_ATTR`确保编译后的二进制指令存放在运行速度更快但是容量有限的片内RAM区域之内而不是默认情况下较为缓慢却相对充裕一些的Flash存储介质之中,这对于实时性要求较高的应用场景来说是非常重要的优化措施之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值