1. 概述
ESP8266 共有 16 个通用 IO,管脚的位置和管脚的名称分别为:
GPIO NO. | pin NO. | pin name |
GPIO0 | pin 15 | GPIO0_U |
GPIO1 | pin 16 | U0TXD_U |
GPIO2 | pin 14 | GPIO2_U |
GPIO3 | pin 25 | U0RXD_U |
GPIO4 | pin 16 | GPIO4_U |
GPIO5 | pin 24 | GPIO5_U |
GPIO6 | pin 21 | SD_CLK_U |
GPIO7 | pin 22 | SD_DATA0_U |
GPIO8 | pin 23 | SD_DATA1_U |
GPIO9 | pin 18 | SD_DATA2_U |
GPIO10 | pin 19 | SD_DATA3_U |
GPIO11 | pin 20 | SD_CMD_U |
GPIO12 | pin 10 | MTDI_U |
GPIO13 | pin 12 | MTCK_U |
GPIO14 | pin 9 | MTMS_U |
GPIO15 | pin 13 | MTDO_U |
其中,在四线(QUAD)模式 flash 下,有六个 IO 口用于 flash 通讯。
在两线(DUAL)模式 flash 下,有四个 IO 口用于与 flash 通讯。
2. GPIO寄存器说明
2.1 GPIO 功能选择寄存器
下面以8266的MTDI为例,说明GPIO功能的选择。
功能选择寄存器 PERIPHS_IO_MUX_MTDI_U (不同的GPIO,该寄存器不同)
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12);
此处的FUNC_GPIO12 = 3;
不同的 PIN 脚,配置不同。
配置的时候,请参考 ESP8266_Pin_List_xxxxxx.xlsx 表格,在该表格的 Digital Die Pin List 页中可以查到通用的 GPIO 以及复用功能。在 Reg 页可以查阅到 GPIO 功能选择相关的寄存器。
Digital Die Pin List 该页中的 FUNCTION 下拉选择项就是功能的配置选项。需要注意的是,如果需要配置为 FUNCTION3, 应该往寄存器对应的位中写 2,如果需要配置为 FUNCTION2, 应该往寄存器对应的为中写 1, 以此类推。
2.2 GPIO 输出寄存器
a) 输出使能寄存器 GPIO_ENABLE_W1TS
b) 输出禁用寄存器 GPIO_ENABLE_W1TC
c) 输出使能状态寄存器 GPIO_ENABLE
d) 输出低电平寄存器 GPIO_OUT_W1TC
e) 输出高电平寄存器 GPIO_OUT_W1TS
f)输出状态寄存器 GPIO_OUT
2.3 GPIO 输入寄存器
输入状态寄存器 GPIO_IN
2.4 GPIO 中断寄存器
a) 中断类型寄存器 GPIO_PIN12 (中断禁用,上升沿触发,下降沿触发,双沿触发,低电平,高电平)
b) 中断状态寄存器 GPIO_STATUS
c) 清中断寄存器 GPIO_STATUS_W1TC
2.5 GPIO16 对应接口
GPIO16(XPD_DCDC) 不属于通用GPIO模块,属于RTC模块。可以用来在深度睡眠时候唤醒整个芯片,可以配置为输入或者输出模式,但无法触发 IO 中断。使用接口如下:
a). gpio16_output_conf(void): 将 GPIO16 配置为输出模式。
b). gpio16_output_set(uint8 value):
从 GPIO16 输出高电平/低电平,需要先配置为输出模式。
c). gpio16_input_conf(void)
将 GPIO16 的输入电平状态,需要先配置为输入模式。
d). gpio16_input_get(void)
读取 GPIO16 的输入电平状态,需要先配置为输入模式。
3 参数配置
应用场景
1) 配置 MTDI 输出高电平,并能使其上拉;
2) 配置 MTDI 为输入模式,并获取其电平状态;
3) 配置 MTDI 为下降沿触发中断。
3.1 应用场景1参数配置
Step 1) 配置 MTDI 为 GPIO 模式
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12);
该语句的作用是向 PERIPHS_IO_MUX_MTDI_U 寄存器的第4位、第5位写1。
PERIPHS_IO_MUX_MTDI_U 寄存器的第4位和第5位置1表示将 MTDI 配置为 GPIO 功能。 PERIPHS_IO_MUX_MTDI_U 寄存器。
Step 2) 配置 MTDI 输出高电平
GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 1);
该语句有两个作用:
- 向 GPIO_ENABLE_W1TS 的寄存器第12位写1,该位置1表示使能 MTDI 的输出功能。
- 向 GPIO_OUT_W1TS 的寄存器第12位写1,该位置1表示将 MTDI 输出为高电平。
备注:需要 MTDI 配置输出低电平,将该函数额第二个参数设置为0即可。
Step 3) 使能 MTDI 上拉
PIN_PULLUP_EN(PERIPHS_IO_MUX_MTDI_U);
该语句作用是向 PERIPHS_IO_MUX_MTDI_U 的第7位写1.该位置 1 表示使能MTDI 的上拉功能。
备注:如果需要关闭 MTDI 的上拉功能,请使用如下语句
PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTDI_U);
3.2 应用场景2参数配置
Step 1) 配置 MTDI 为 GPIO 模式
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12);
该语句的作用: 向 PERIPHS_IO_MUX_MTDI_U 寄存器的第4位、第5位写 1。PERIPHS_IO_MUX_MTDI_U 寄存器的第4位和第5位置1 表示 将 MTDI 配置为 GPIO 功能。
Step 2) 配置 MTDI 为输入模式
GPIO_DIS_OUTPUT(GPIO_ID_PIN(12));
Step 3) 获取 MTDI 管脚的电平状态
Uint8 level = 0;
level = GPIO_INPUT_GET(GPIO_ID_PIN(12));
GPIO_INPUT_GET(GPIO_ID_PIN(12)) 语句实际是获取 GPIO_IN 寄存器第 12 位的状态,该寄存器的值反映的是对应的管脚的输入电平(必须使能对应的管脚的输入功能,该寄存器的状态才有效)。
备注:
如果 MTDI 的电平为高电平,那么 GPIO_INPUT_GET 的返回值为 1,level = 1;
如果 MTDI 的电平为低电平,那么 GPIO_INPUT_GET 的返回值为 0,level = 0;
3.3 应用场景3参数配置
typedef enum
{
GPIO_PIN_INTR_DISABLE = 0,
GPIO_PIN_INTR_POSEDGE = 1,
GPIO_PIN_INTR_NEGEDGE = 2,
GPIO_PIN_INTR_ANYEGDE = 3,
GPIO_PIN_INTR_LOLEVEL = 4,
GPIO_PIN_INTR_HILEVEL = 5
}GPIO_INIT_TYPE;
该结构体用来配置 gpio 的中断触发方式,该结构体在 gpio.h 中声明。
Step 1) 配置 MTDI 为 GPOI 模式
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12);
该语句的作用是向 PERIPHS_IO_MUX_MTDI_U 寄存器的第4位、第5位写1.PERIPHS_IO_MUX_MTDI_U 寄存器的第4位和第5位置1表示将 MTDI 配置为 GPIO 功能。
Step 2) 配置 MTDI 为输入模式
GPIO_DIS_OUTPUT(GPIO_ID_PIN(12));
Step 3) 禁止所有的IO中断
ETS_GPIO_INTR_DISABLE();
Step 4) 设置中断处理函数
ETS_GPIO_INTR_ATTACH(GPIO_INTERRUPT, NULL);
Step 5) 配置 MTDI 为下降沿中断触发的方式
gpio_pin_intr_state_set(GPIO_ID_PIN(12), GPIO_PIN_INTR_NEGEDGE);
该语句的作用 向GPIO_PIN12 的寄存器的 [9:7]位写入0x02,向该位域内写入0x02, 表示配置为下降沿中断。
备注:若需要禁用 MTDI 的中断功能,只需要将向 GPIO_PIN12 的寄存器的 [9:7]位写入0x00即可。如需配置为其他的中断触发模式,请参阅 GPIO 寄存器章节。
Step 6) 使能 gpio 中断
ETS_GPIO_INTR_ENABLE();
3.4 中断函数处理流程说明
Step 1) 清除该中断
Uint16 gpio_status = 0;
gpio_status = GPIO_REG_READ(GPIO_STATUS);
GPIO_REG_WRITE(GPIO_STATUS_W1TC, gpio_status);
GPIO_STATUS 和 GPIO_STATUS_W1TC 说明请参阅 GPIO 寄存器章节。
Step 2) 判断是哪个IO触发的中断(当有多个IO都配置为中断方式时)
If(gpio_status == GPIO_Pin_12)
Step 3) 如果是双沿中断,应该判断此次中断为上升沿中断还是下降沿中断
If(!GPIO_INPUT_GET(GPIO_ID_PIN(12))) // 如果 MTDI 此次触发方式为下降沿
3.5 中断函数处理流程示例
void gpio_intr_handler()
{
uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS); // read interrupt status
uint8 level = 0;
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status); // clear interrupt mask
if (gpio_status & (BIT(12))) // judeg whether interrupt source is gpio12
{
if (GPIO_INPUT_GET(12)) // if gpio12 is high level
{
}
else // if gpio12 is low level
{
}
}
else
{
}
}