04_ESP8266 NONOS_SDK GPIO

我的梦境 提交于 2020-02-01 01:37:54

相关资料准备:

(1)GPIO相关API请查看2c-esp8266_non_os_sdk_api_reference_cn手册

 

(2)GPIO相关寄存器请查看 esp8266-technical_reference_cn 手册

 

(3)ESP8266 的 16 个通⽤ IO 的管脚位置和名称如下表所示:

                                                   图1.1-GPIO管脚定义

其中,在四线( QUAD)模式 Flash 下,有 6 个 IO 口用于 Flash 通讯。
在两线( DUAL)模式 Flash 下,有 4 个 IO 口用于与 Flash 通讯。

说明:

本说明如果对照以下资料阅读,会更有助理解:

• “附录 1 - GPIO 寄存器”

• 引脚功能复⽤表:《 ESP8266_Pin_List.xlsx》

https://www.espressif.com/sites/default/files/documentation/ESP8266_Pin_List.xls

 

一、GPIO口输出

目标:将GPIO2和GPIO4设置成IO口,将管脚设为输出模式,并输出对应电平,加入delay延时,使LED按照一定频率闪烁。步骤如下:

1、首先将添加两个头文件:

"eagle_soc.h"和 "gpio.h"

 2、管脚功能选择:

将GPIO2定义为IO口,PIN_FUNC_SELECT( PERIPHS_IO_MUX_GPIO2_U,FUNC_GPIO2);

PIN_FUNC_SELECT(PIN_NAME, FUNC)为宏定义,宏定义原型为:

 

 

/*===================================================================

         * 功能:管脚功能选择

         * 宏:   PIN_FUNC_SELECT(PIN_NAME,FUNC)

         * 参数:【PIN_NAME】  管脚名        "PERIPHS_IO_MUX_"+ Pin name 管脚名

         *      【FUNC】      管脚功能      功能序号-1

===================================================================*/

第一个参数PIN_NAME,可在"eagle_soc.h"       文件中查阅具体怎么填写实参。比如GPIO2设置为IO,PERIPHS_IO_MUX_GPIO2_U,文件中如下:

 

第二个参数FUNC,管脚功能,它的取值为:功能序号-1(Functionx,其中x就是功能序号),

查看如下表格,GPIO2功能设置为IO功能, GPIO2对应为Function1,则FUNC处填写的就是1-1=0

 

                                                          ESP8266_Pin_List.xls 表格

 可我们填写的是FUNC_GPIO2,为什么呢?查看eagle_soc.h,发现已经有定义好的宏定义:

 

所以,填写0或者FUNC_GPIO2,只要根据ESP8266_Pin_List.xls 表格对应功能序号减1规则来即可:

 

3、将管脚设为输出模式,并输出对应电平:

//此处我们设置GPIO2为输出,输出高电平。

GPIO_OUTPUT_SET(GPIO_ID_PIN(4),1);

宏定义原型为:

 

/*===================================================================

         * 功能:将管脚设为输出模式,并输出对应电平

         * 宏:  GPIO_OUTPUT_SET ( gpio_no , bit_value )

         * 参数:【gpio_no】  管脚名           GPIO_ID_PIN  ( IO端口序列号 )

         *      【bit_value】 输出电平

====================================================================*/

第一个参数gpio_no管脚名,填写格式为GPIO_ID_PIN(IO端口序列号 ),看第一个参数宏定义:

很明显已经帮我们定义好了,我们只需要在n这里填写端口序列号即可将GPIO设置为输出模式。

第二个参数bit_value为输出电平,1为高电平,0为低电平,此处我们填写1(由于我的GPIO2的LED灯是共阳的)

 

4、写毫秒级延时函数

 void ICACHE_FLASH_ATTR  delay_ms(u32 ms_time)

{
         for(;ms_time>0; ms_time--)
         {
                   os_delay_us(1000);
         }
} 

 

5、定义LED每500ms闪烁一次,并串口输出LED状态

 

 

结果:

串口打印正常,每隔500ms输出一次一次。

 

观察灯光情况:每隔500ms闪烁一次。

 

 

 

扩展

         //gpio_output_set(0,0,0,BIT4);  //设置 GPIO12 为输入

         /*===================================================================

         * 功能:将管脚设为输出/输入模式,可以设置输出的位的高低电平,但是不可以设置输入的高低电平

         * 函数:   void    gpio_output_set(

                                               uint32       set_mask,

                                               uint32       clear_mask,

                                               uint32       enable_mask,

                                               uint32       disable_mask

                 )

         * 参数:

         【set_mask】      设置输出为高的位 (假设GPIO2,则填BIT2,即GPIO2输出高电平;如果填写0,则不改变状态)

         【clear_mask】   设置输出为低的位  (假设GPIO2,则填BIT2,即GPIO2输出低电平;如果填写0,则不改变状态)

         【enable_mask】设置使能输出的位  (假设GPIO2,则填BIT2,即使能GPIO2输出)

         【disable_mask】设置使能输入的位  (假设GPIO2,则填BIT2,即使能GPIO2输入)

         * 示例:

         gpio_output_set(BIT12,0,BIT12,0):                    设置 GPIO12 输出高电平;

         gpio_output_set(0,BIT12,BIT12,0):                    设置 GPIO12 输出低电平;

         gpio_output_set(BIT12,BIT13,BIT12|BIT13,0): 设置 GPIO12 输出高电平, GPIO13 输出低电平;

         gpio_output_set(0,0,0,BIT12):                           设置 GPIO12 为输入

         * =================================================================*/

 

二、GPIO输入

目标:GPIO4作为按键IO ,GPIO5作为LED灯的IO,按键按下,灯亮,按键松开,灯灭。

                                                 

1、管脚功能选择

//将LED对应的GPIO5设置为IO

PIN_FUNC_SELECT( PERIPHS_IO_MUX_GPIO5_U,FUNC_GPIO5);

//按键对应的GPIO4设置为IO口

PIN_FUNC_SELECT( PERIPHS_IO_MUX_GPIO4_U,FUNC_GPIO4);

//禁止GPIO4输出

GPIO_DIS_OUTPUT(4);  

2、LED灯初始化

//将GPIO5设置为输出,电平为高电平

GPIO_OUTPUT_SET(GPIO_ID_PIN(5),1);

 注意:如果某个GPIO已经内部上拉了,而你又外接上拉,此时可以

PIN_PULLUP_DIS(4);     //关闭GPIO内部上拉

3、主函数下实现逻辑功能

while(1){

          system_soft_wdt_feed(); //喂狗,防止复位

          Get_Btn_Value = GPIO_INPUT_GET(GPIO_ID_PIN(4)); //获取到的按键电平值

          if(Get_Btn_Value==0){  //若为低电平

                   GPIO_OUTPUT_SET(GPIO_ID_PIN(5),0);   //点亮GPIO5对应的LED灯

          }

          else{   

                    GPIO_OUTPUT_SET(GPIO_ID_PIN(5),1);   //熄灭

          }

}

 

三、GPIO中断

GPIO输入寄存器(可读可写)

寄存器名称

功能说明

寄存器大小

参数说明

GPIO_IN

输入状态寄存器

16 Bit

对应GPIO0-GPIO15

GPIO_PIN12

中断类型寄存器

16 Bit

0:禁用该GPIO的中断

1:上升沿触发中断

2:下降沿触发中断

3:双边沿触发中断

4:低电平触发中断

5:高电平触发中断

GPIO_STATUS

中断状态寄存器

16Bit

位:BIT0 - BIT15

( 对应GPIO0-GPIO15 )

BIT0 - BIT15对应位置1,表示该中断发生。

GPIO_STATUS_W1TC

复位中断标志寄存器

16Bit

位:BIT0 - BIT15

( 对应GPIO0-GPIO15 )

BIT0 - BIT15对应位写1,对应GPIO的中断状态会被清除。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 注:GPIO16不支持触发IO中断。因为如下:

 

GPIO中断相关宏:

ETS_GPIO_INTR_ENABLE() //开 GPIO 中断

ETS_GPIO_INTR_DISABLE() //关 GPIO 中断

ETS_GPIO_INTR_ATTACH(func, arg) //注册 GPIO 中断处理函数

 

GPIO中断相关函数:gpio_pin_intr_state_set

 

GPIO_PIN_INTR_DISABLE = 0,        // 中断失能(不触发中断)

GPIO_PIN_INTR_POSEDGE = 1,       // 上升沿触发中断

GPIO_PIN_INTR_NEGEDGE = 2,       // 下降沿触发中断

GPIO_PIN_INTR_ANYEDGE = 3,       // 双边沿触发中断

GPIO_PIN_INTR_LOLEVEL = 4,        // 低电平触发中断

GPIO_PIN_INTR_HILEVEL = 5         // 高电平触发中断

 

 

 

 

相关宏定义:

 

 

 

 

 

 

 //GPIO_STATUS_ADDRESS: 中断状态寄存器地址

//GPIO_STATUS_W1TC_ADDRESS: 清中断寄存器地址

 

 

 

 

 

 

目标:GPIO4通过10K电阻上拉,作为按键触发中断;GPIO5作为LED指示灯。实现按键按下,GPIO5指示灯亮,串口输出相关信息。

 

(随便画一下记录一下)

 

1、管脚选择

//按键对应的GPIO4设置为IO口

PIN_FUNC_SELECT( PERIPHS_IO_MUX_GPIO4_U,FUNC_GPIO4);

//禁止GPIO4输出

GPIO_DIS_OUTPUT(4);  

 

2、GPIO中断设置

ETS_GPIO_INTR_DISABLE();     //关闭GPIO中断

ETS_GPIO_INTR_ATTACH((ets_isr_t) gpio_intereupt ,NULL);                   // 注册中断回调函数

gpio_pin_intr_state_set(GPIO_ID_PIN(4), GPIO_PIN_INTR_NEGEDGE);   //  GPIO4下降沿触发中断

ETS_GPIO_INTR_ENABLE();       // 使能GPIO中断功能

 

3、写中断函数

//中断函数前面不能有ICACHE_FLASH_ATTR宏

void gpio_intereupt (void){

  //1.清除该中断

  u32 GPIO_STA=0;   // 全部GPIO的中断状态

  u32 GPIO4_STA;    // GPIO_4的中断状态

  GPIO_STA = GPIO_REG_READ(GPIO_STATUS_ADDRESS);  //读取GPIO中断状态

GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, GPIO4_STA); // 清除中断状态位(如果不清除状态位,会一直进入中断)

 

  //2.判断是否是GPIO4口下降沿触发的中断

os_printf("最初获取的GPIO状态:%x\n",GPIO4_STA);

os_printf("\r\n-----------------------------------------------\r\n");

GPIO4_STA = GPIO_STA &(BIT(4));//读取GPIO4中断状态

//GPIO4_STA = GPIO_STA &(0x01<<4);

//读取GPIO4中断状态(这句和上面那个是一样的效果,原因如下图所示:)

 

os_printf("进入中断,GPIO状态:%x\n",GPIO4_STA);

os_printf("\r\n-----------------------------------------------\r\n");

//判断中断管脚是否是GPIO4,只有GPIO4触发中断,该值才不为0,即真,实际值为0x10

  if(GPIO_STA){        os_printf("是下降沿触发中断!");

os_printf("\r\n-----------------------------------------------\r\n");

LED_Flag=!LED_Flag;  // LED_Flag需要定义为全局变量

GPIO_OUTPUT_SET(GPIO_ID_PIN(5),LED_Flag);

//ETS_GPIO_INTR_DISABLE(); //关闭GPIO中断

  }

 

4、效果:

 

 

 

(寒假,硬件上我现手头没按键,用杜邦线轻触GND代替按键按下)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!