跳转至

01.GPIO的输入输出

GPIO输出

这里以控制一个LED 的输出为例,引脚输出配置有两种方式。

普通模式

在IDF5.x版本中,如下:

gpio_reset_pin(GPIO_NUM_2);//设置配置的引脚
gpio_set_direction(GPIO_NUM_2, GPIO_MODE_OUTPUT);//设置为输出模式

在IDF4.x版本中,如下:

gpio_pad_select_gpio(GPIO_NUM_2);//设置配置的引脚
gpio_set_direction(GPIO_NUM_2, GPIO_MODE_OUTPUT);//设置为输出模式

结构体模式

void bsp_led_init()
{
    gpio_config_t io_conf = {};
    
    io_conf.intr_type = GPIO_INTR_DISABLE;  //关闭中断
    io_conf.mode = GPIO_MODE_OUTPUT;        //输出模式
    io_conf.pin_bit_mask = (1ULL<<GPIO_NUM_2); //设置引脚 多个((1ULL<<GPIO_NUM_2)|(1ULL<<GPIO_NUM_3))
    io_conf.pull_down_en = 0;                //失能下拉
    io_conf.pull_up_en = 1;                  //使能上拉
    
    gpio_config(&io_conf);
}

控制引脚电平

gpio_set_level(GPIO_NUM_2, 0);//设置输出低电平
gpio_set_level(GPIO_NUM_2, 1);//设置输出高电平

GPIO输入--普通模式

这里以检测一个按键的输入为例,引脚输入配置如下。

普通模式

在IDF5.x版本中,如下:

gpio_reset_pin(GPIO_NUM_3);//设置配置的引脚
gpio_set_direction(GPIO_NUM_3, GPIO_MODE_INPUT);//设置为输入模式

在IDF4.x版本中,如下:

gpio_pad_select_gpio(GPIO_NUM_3);//设置配置的引脚
gpio_set_direction(GPIO_NUM_3, GPIO_MODE_INPUT);//设置为输入模式

结构体模式

void bsp_key_init()
{
    gpio_config_t io_conf = {};
    
    io_conf.intr_type = GPIO_INTR_DISABLE;  //关闭中断
    io_conf.mode = GPIO_MODE_INPUT;        //输入模式
    io_conf.pin_bit_mask = (1ULL<<GPIO_NUM_3); //设置引脚 多个((1ULL<<GPIO_NUM_2)|(1ULL<<GPIO_NUM_3))
    io_conf.pull_down_en = 0;                //失能下拉
    io_conf.pull_up_en = 1;                  //使能上拉
    
    gpio_config(&io_conf);
}

获得引脚电平

gpio_get_level(GPIO_NUM_3);

GPIO输入--中断模式

这里以检测一个按键的输入为例,引脚输入配置如下。

触发方式

GPIO_INTR_DISABLE //禁用GPIO中断
GPIO_INTR_POSEDGE //GPIO中断类型:上升沿
GPIO_INTR_NEGEDGE //下降沿
GPIO_INTR_ANYEDGE //上升沿和下降沿
GPIO_INTR_LOW_LEVEL //输入低电平触发
GPIO_INTR_HIGH_LEVEL //输入高电平触发

普通模式

在IDF5.x版本中,如下:

gpio_reset_pin(GPIO_NUM_3);//设置配置的引脚
gpio_set_direction(GPIO_NUM_3, GPIO_MODE_INPUT);//设置为输入模式
gpio_intr_enable(GPIO_NUM_3);//使能中断
gpio_set_intr_type(GPIO_NUM_3, GPIO_INTR_NEGEDGE);//下降沿
gpio_pullup_en(GPIO_NUM_3);//引脚上拉

在IDF4.x版本中,如下:

gpio_pad_select_gpio(GPIO_NUM_3);//设置配置的引脚
gpio_set_direction(GPIO_NUM_3, GPIO_MODE_INPUT);//设置为输入模式
gpio_intr_enable(GPIO_NUM_3);//使能中断
gpio_set_intr_type(GPIO_NUM_3, GPIO_INTR_NEGEDGE);//下降沿
gpio_pullup_en(GPIO_NUM_3);//引脚上拉

结构体模式

void bsp_key_init()
{
    gpio_config_t io_conf = {};

    io_conf.intr_type = GPIO_INTR_NEGEDGE;  //下降沿触发
    io_conf.mode = GPIO_MODE_INPUT;
    io_conf.pin_bit_mask = (1ULL<<GPIO_NUM_3); //设置引脚 多个((1ULL<<GPIO_NUM_2)|(1ULL<<GPIO_NUM_3))
    io_conf.pull_down_en = 0;                  //使能上下拉
    io_conf.pull_up_en = 1;

    gpio_config(&io_conf);
}

获得引脚电平

gpio_get_level(GPIO_NUM_3);

配置FreeRTOS任务和队列

注意:gpio_isr_handler中断回调函数是加载在IRAM_ATTR中,不能执行其他耗时操作,包括printf打印信息

void gpio_intr_init(void)
{
    // 注册中断服务 设置优先级
    gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1);
    // 设置GPIO的中断回调函数 并将参数传入
    gpio_isr_handler_add(GPIO_NUM_3, gpio_isr_handler, (void*) GPIO_NUM_3);
    // 创建一个消息队列,从中获取队列句柄
    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
}

中断任务

static void IRAM_ATTR gpio_isr_handler(void* arg)
{
    //获得传入的参数
    uint32_t gpio_num = (uint32_t) arg;
    //将传入的参数放入队列
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}