esp8266教程:GPIO输入输出模式

esp8266教程:GPIO

什么是GPIO?

GPIO是(英语:General-purpose input/output)的简写,翻译成中文就是通用的输入、输出。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Ho4QDw0-在这里插入图片描述
我们看到芯片上面伸出来的金属引脚大部分是GPIO引脚(部分为VCC、GND、模拟输入引脚)。

输出模式

当我们编程把GPIO引脚配置为输出模式的时候,可以控制引脚输出高电平或者低电平,如果芯片供电为5V,我们设置GPIO引脚为高电平,使用万用表测量GPIO的引脚可以量到引脚的电压为5V,反之设置GPIO引脚为低电平,那么通过万用表测试GPIO的引脚电压为0V。如果芯片的供电为3.3V,那么如果引脚设置为输出且为高电平的时候的引脚的电压为3.3v,所以我们可以知道GPIO上面的引脚的高电平的电压等于芯片的供电电压。

输出模式编程

#define GPIO_OUTPUT_IO_0    15  //配置GPIO15
#define GPIO_OUTPUT_IO_1    16  //配置GPIO16
#define GPIO_OUTPUT_PIN_SEL  ((1ULL<<GPIO_OUTPUT_IO_0) | (1ULL<<GPIO_OUTPUT_IO_1))

GPIO初始化部分
gpio_config_t io_conf;  //构建一个gpio_config_t 结构体,然后配置GPIO
//因为设置为输出没有中断,所以关闭中断
io_conf.intr_type = GPIO_INTR_DISABLE;
//设置为输出模式
io_conf.mode = GPIO_MODE_OUTPUT;

//我们要配置两个输出引脚分别为GPIO15和GPIO16
io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
//关闭下拉使能,下拉配置一般是输入的时候配置的
io_conf.pull_down_en = 0;
//关闭上拉使能,上拉配置一般是输入的时候配置的
io_conf.pull_up_en = 0;
//把我们构建的gpio_config_t结构体,传入gpio_config这个函数完成GPIO15和GPIO16输出的配置。
gpio_config(&io_conf);

//调用gpio_set_level这个函数将GPIO15和GPIO16输出低电平
gpio_set_level(GPIO_OUTPUT_IO_0, 0);
gpio_set_level(GPIO_OUTPUT_IO_1, 0);


//调用gpio_set_level这个函数将GPIO15和GPIO16输出高电平,gpio_set_level这个函数需要传入两个参数,
//一个是控制那个GPIO引脚,我们这里是GPIO15和GPIO16,第二个参数代表高低电平,如果设置为高则传入1,反之传入0
gpio_set_level(GPIO_OUTPUT_IO_0, 1);
gpio_set_level(GPIO_OUTPUT_IO_1, 1);

输出模式常用使用场景

在这里插入图片描述
通过控制GPIO引脚点亮LED灯。如图我们可以看到如果我们输出电平为高的时候GPIO引脚P3.0(P3.0只是对一个引脚的别名)和VDD都为高电平,没有电流通过led灯,所以led灯不亮。反之我们把GPIO的引脚配置为低电平,VDD因为是高电平,在led灯两端有电压差,所以就会有电流通过led灯,所以led灯会发光发亮。通过上面的实验我们可以初步的使用GPIO引脚。

输入模式

当我们编程把芯片的引脚配置为输入模式的时候,我们可以读取芯片的某个寄存器可以知道引脚上面的电压是高电平还是低电平。

输入模式的使用场景

在这里插入图片描述
我们有很多的电子产品都有按键,所以我们要知道用户是否按下就需要使用将GPIO引脚设置为输入模式了,当用户按下按键的时候GPIO连接到GND,所以读取寄存器可以读取到的是低电平,用户释放按键的时候,GPIO连接串联一个电阻连接到VCC,所以读取寄存器可以读取到的是高电平。

输入模式编程

#define GPIO_INPUT_IO_0     4  //配置输入引脚GPIO4
#define GPIO_INPUT_IO_1     5  //配置输入引脚GPIO5
#define GPIO_INPUT_PIN_SEL  ((1ULL<<GPIO_INPUT_IO_0) | (1ULL<<GPIO_INPUT_IO_1))

gpio_config_t io_conf;  //构建一个gpio_config_t 结构体,然后配置GPIO

//这里我们不使用中断的方式,中断配置为关闭
io_conf.intr_type = GPIO_INTR_DISABLE;

//我们要配置两个输出引脚分别为GPIO4和GPIO5
io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
//设置为输入模式
io_conf.mode = GPIO_MODE_INPUT;
//配置上拉使能
io_conf.pull_up_en = 1;

//把我们构建的gpio_config_t结构体,传入gpio_config这个函数完成GPIO4和GPIO5输入的配置。
gpio_config(&io_conf);

//使用gpio_get_level这个函数获取GPIO输入的电平是高电平还是低电平,然后赋值给level,如果level为0则是低电平,反之为1则为高电平。
uint8_t level = gpio_get_level(GPIO_INPUT_IO_0);
uint8_t level = gpio_get_level(GPIO_INPUT_IO_1);


输入模式使用中断

从上面的例子可以知道我们可以调用gpio_get_level这个函数知道用户按键是否按下,但是什么时候去调用这个函数呢?可能读者想到了,我可以一直调用gpio_get_level这个函数去读取GPIO的脚是高电平还是低电平,这么做不是不可以,就是太消耗MCU的运算时间了。那么我们有没有别的办法在用户按下的时候我们才去调用gpio_get_level去读取这个gpio的值,当然是有的,那就是中断模式。
gpio中断一般可以配置为上升沿中断,下降沿中断,还有边缘中断。

上升沿触发中断

在这里插入图片描述
上图为用户按下两次按键的时序图,输入电平由低电平转为高电平的时候,即电平上升的时候触发中断,称为上升沿触发中断,如时序图会触发两次中断。

下降触发沿中断

在这里插入图片描述
上图为用户按下两次按键的时序图,输入电平由高电平转为低电平的时候,即电平下降的时候触发中断,称为上升沿触发中断,如时序图会触发两次中断。

边缘触发中断

在这里插入图片描述
上图为用户按下两次按键的时序图,输入电平由高电平转为低电平的时候和输入电平由低转为高的时候,都会触发中断,如时序图会触发四次中断,这种类型的中断称为边缘触发中断。

输入模式使用中断编程


#define GPIO_INPUT_IO_0     4  //配置输入引脚GPIO4
#define GPIO_INPUT_IO_1     5  //配置输入引脚GPIO5
#define GPIO_INPUT_PIN_SEL  ((1ULL<<GPIO_INPUT_IO_0) | (1ULL<<GPIO_INPUT_IO_1))

gpio_config_t io_conf;  //构建一个gpio_config_t 结构体,然后配置GPIO

//这里我们使用中断的方式,配置为边缘触发中断
io_conf.intr_type = GPIO_INTR_POSEDGE;

//我们要配置两个输出引脚分别为GPIO4和GPIO5
io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
//设置为输入模式
io_conf.mode = GPIO_MODE_INPUT;
//配置上拉使能
io_conf.pull_up_en = 1;

//把我们构建的gpio_config_t结构体,传入gpio_config这个函数完成GPIO4和GPIO5输入的配置。
gpio_config(&io_conf);


//安装gpio中断服务
gpio_install_isr_service(0);
//注册发生中断的时候,调用的函数gpio_isr_handler因为我们配置的是边缘触发中断,用户按下按键的时候会调用两次gpio_isr_handler
gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void *) GPIO_INPUT_IO_0);
//注册发生中断的时候,调用的函数gpio_isr_handler因为我们配置的是边缘触发中断,用户按下按键的时候会调用两次gpio_isr_handler
gpio_isr_handler_add(GPIO_INPUT_IO_1, gpio_isr_handler, (void *) GPIO_INPUT_IO_1);

static void gpio_isr_handler(void *arg)
{
   uint32_t gpio_num = (uint32_t) arg;
   ESP_LOGI(TAG, "GPIO[%d] intr, val: %d\n", io_num, gpio_get_level(io_num));   //打印那个按键触发了中断
}

t gpio_num = (uint32_t) arg;
   ESP_LOGI(TAG, "GPIO[%d] intr, val: %d\n", io_num, gpio_get_level(io_num));   //打印那个按键触发了中断
}

Guess you like

Origin blog.csdn.net/qq_27809619/article/details/116480637