logo
当前位置:首 页 > 硬件技术 >ESP8266 > 查看文章

ESP8266 GPIO 输出输入

ESP8266, 硬件技术 你是第2562个围观者 0条评论 供稿者: 标签:,

GPIO输出

开发板原理图如下所示:

引脚功能配置:

在使用 stm32 时,引脚都有很多的复用功能,当我们想要使用引脚的某个功能(如I2C SPI)等,就需要配置引脚的功能。ESP6266也是如此,下面列出了8266引脚的复用功能:

如上图所示,这个引脚的功能1是N0RXD(串口0数据接收引脚),功能2是I2SO_DATA(I2S数据引脚)、功能4是普通的GPIO3、功能5是CLK_XTAL(时钟晶振引脚),然后这个功能配置寄存器的地址如下所示:

在技术参考手册中,也有配置功能的描述:

由上面的分析可知,如果我们希望使用功能4配置为GPIO3,则要往寄存器对应位写入3。在 eagle_soc.h 头文件中,有设置寄存器地址和功能的宏定义:

上图的地址和写入值,都跟我们的分析相一致,使用 PIN_FUNC_SELECT 语句来选择引脚功能。

我们来分析一下 PIN_FUNC_SELECT 这个语句:

可以看到,这个宏定义其实就是往选定的引脚配置寄存器中,写入想要配置的功能(GPIO I2C SPI等)。

 

配置GPIO输出的过程如下:

1 先选定一个GPIO管脚,用 PIN_FUNC_SELECT(PIN_NAME, FUNC) 函数。

比如我选定GPIO14这个管脚,则这样写:PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14);

这里的参数,在下面可以找到:

2 设置GPIO为输出模式,并设置电平;

如果你设置GPIO14这个管脚为高电平,则这样写:GPIO_OUTPUT_SET(GPIO_ID_PIN(14), 1);

GPIO_OUTPUT_SET 这个函数,第一个参数为GPIO引脚编号,定义如下所示:

这里,GPIO引脚编号用了一个宏定义来表示,实际上直接就是IO口的序号,GPIO理论部分结束。

 

点亮流水灯实验:

代码部分非常简单,如下所示:

编译程序并下载,LED灯确实在循环的闪烁,并在串口有调试信息输出:

 

GPIO输入

接下来使用GPIO输入来进行按键检测,首先看下原理图:

可以看到,BOOT引脚接到了GPIO0,默认被10K电阻上拉为高电平;当按键按下时,GPIO0变为低电平。

 

配置输入模式的步骤:

1 调用PIN_FUNC_SELECT函数,配置引脚功能为GPIO;

如配置GPIO0引脚为IO口,则使用语句PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0);

2 配置GPIO引脚为输入模式;

3 设置是否开启GPIO内部上拉;

 

GPIO输入 按键检测实验:

由于我手中的开发板,好像确实是有硬件问题,所以无论是自己写的或者是提供的例程,这个按键检测实验都失败了。

 

EXTI 外部中断

ESP8266的EXTI外部中断配置,其实很简单:

可以看到,前面的配置和基本的GPIO输入模式相同,接下来就是配置外部中断:

1 调用ETS_GPIO_INTR_DISABLE(函数位于ets_sys.h头文件),先关闭GPIO中断,以进行配置;

2 调用ETS_GPIO_INTR_ATTACH这个API,注册中断回调函数(中断函数要自己实现);

3 设置为下降沿中断;

其中,可以设置的中断源如下所示:

4 使能EXTI中断;

5 编写中断服务函数(主要部分);

下面是中断服务函数的主体,来进行逐句分析:

首先是两个宏定义,用于读取寄存器和写入寄存器,如下图所示:

GPIO_REG_READ用于读取寄存器值,GPIO_REG_WRITE向寄存器写入值。

接下来,看一下GPIO相关的寄存器描述:

这就是以下代码的功能描述:

  1. S_GPIO_INT = GPIO_REG_READ(GPIO_STATUS_ADDRESS); // 读取GPIO中断状态
  2. // 清除中断标志位,如果不清除标志位,则会持续进入中断
  3. GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, S_GPIO_INT); // 向GPIO_OUT_W1TC写1会清除中断标志位
  4. F_GPIO_0_INT = S_GPIO_INT & (0X0001 << 0); // 获取GPIO0的中断状态

接下来,判断是否有中断,然后翻转LED,如下所示:

  1. // 未作按键消抖
  2. if (F_GPIO_0_INT) // GPIO0的下降沿中断
  3. {
  4. F_LED = !F_LED;
  5. GPIO_OUTPUT_SET(GPIO_ID_PIN(4), F_LED); // LED状态翻转
  6. }

程序编译下载,能够正确执行。每次按键按下时,LED进行状态翻转,不会出现之前GPIO输入模式时的错误情况。

整个工程代码如下:

  1. /*
  2. * ESPRESSIF MIT License
  3. *
  4. * Copyright (c) 2016 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
  5. *
  6. * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case,
  7. * it is free of charge, to any person obtaining a copy of this software and associated
  8. * documentation files (the “Software”), to deal in the Software without restriction, including
  9. * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10. * and/or sell copies of the Software, and to permit persons to whom the Software is furnished
  11. * to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in all copies or
  14. * substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. *
  23. */
  24. #include “ets_sys.h”
  25. #include “osapi.h”
  26. #include “user_interface.h”
  27. #include “driver/uart.h”
  28. #include “driver/uart_register.h”
  29. /******************************************************************************
  30. * FunctionName : user_rf_cal_sector_set
  31. * Description : SDK just reversed 4 sectors, used for rf init data and paramters.
  32. * We add this function to force users to set rf cal sector, since
  33. * we don’t know which sector is free in user’s application.
  34. * sector map for last several sectors : ABCCC
  35. * A : rf cal
  36. * B : rf init data
  37. * C : sdk parameters
  38. * Parameters : none
  39. * Returns : rf cal sector
  40. *******************************************************************************/
  41. uint32 ICACHE_FLASH_ATTR
  42. user_rf_cal_sector_set(void)
  43. {
  44. enum flash_size_map size_map = system_get_flash_size_map();
  45. uint32 rf_cal_sec = 0;
  46. switch (size_map) {
  47. case FLASH_SIZE_4M_MAP_256_256:
  48. rf_cal_sec = 1285;
  49. break;
  50. case FLASH_SIZE_8M_MAP_512_512:
  51. rf_cal_sec = 2565;
  52. break;
  53. case FLASH_SIZE_16M_MAP_512_512:
  54. rf_cal_sec = 5125;
  55. break;
  56. case FLASH_SIZE_16M_MAP_1024_1024:
  57. rf_cal_sec = 5125;
  58. break;
  59. case FLASH_SIZE_32M_MAP_512_512:
  60. rf_cal_sec = 10245;
  61. break;
  62. case FLASH_SIZE_32M_MAP_1024_1024:
  63. rf_cal_sec = 10245;
  64. break;
  65. case FLASH_SIZE_64M_MAP_1024_1024:
  66. rf_cal_sec = 20485;
  67. break;
  68. case FLASH_SIZE_128M_MAP_1024_1024:
  69. rf_cal_sec = 40965;
  70. break;
  71. default:
  72. rf_cal_sec = 0;
  73. break;
  74. }
  75. return rf_cal_sec;
  76. }
  77. void ICACHE_FLASH_ATTR
  78. user_rf_pre_init(void)
  79. {
  80. }
  81. uint8_t F_LED = 0;
  82. #define ProjectName “GPIO_EXTI” //工程名宏定义
  83. // 自定义的毫秒延时函数(不要延时太久)
  84. void ICACHE_FLASH_ATTR
  85. bsp_delay_ms(uint16_t ms)
  86. {
  87. for (; ms > 0; ms–)
  88. {
  89. os_delay_us(1000);
  90. }
  91. }
  92. // GPIO中断回调函数(注意:函数名前不要有ICACHE_FLASH_ATTR宏定义)
  93. void GPIO_INTERRUPT(void)
  94. {
  95. uint32_t S_GPIO_INT; // 所有IO口的中断状态
  96. uint32_t F_GPIO_0_INT; // GPIO0的中断状态
  97. S_GPIO_INT = GPIO_REG_READ(GPIO_STATUS_ADDRESS); // 读取GPIO中断状态
  98. // 清除中断标志位,如果不清除标志位,则会持续进入中断
  99. GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, S_GPIO_INT); // 向GPIO_OUT_W1TC写1会清除中断标志位
  100. F_GPIO_0_INT = S_GPIO_INT & (0X0001 << 0); // 获取GPIO0的中断状态
  101. // 未作按键消抖
  102. if (F_GPIO_0_INT) // GPIO0的下降沿中断
  103. {
  104. F_LED = !F_LED;
  105. GPIO_OUTPUT_SET(GPIO_ID_PIN(4), F_LED); // LED状态翻转
  106. }
  107. }
  108. /******************************************************************************
  109. * FunctionName : user_init
  110. * Description : entry of user application, init user function here
  111. * Parameters : none
  112. * Returns : none
  113. *******************************************************************************/
  114. void ICACHE_FLASH_ATTR
  115. user_init(void)
  116. {
  117. uart_init(115200,115200); // 初始化串口波特率
  118. os_delay_us(10000); // 等待串口稳定
  119. os_printf(“\r\n=================================================\r\n”);
  120. os_printf(“\t Project:\t%s\r\n”, ProjectName);
  121. os_printf(“\t SDK version:\t%s”, system_get_sdk_version());
  122. os_printf(“\r\n=================================================\r\n”);
  123. // 初始化LED
  124. PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4); // 将GPIO4设为IO口
  125. GPIO_OUTPUT_SET(GPIO_ID_PIN(4), 1); // GPIO4设置为输出模式,高电平
  126. // 初始化按键 BOOT == GPIO0
  127. PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0); // 将GPIO0设为IO口
  128. GPIO_DIS_OUTPUT(GPIO_ID_PIN(0)); // 失能GPIO0输出(默认),设为输入模式
  129. //PIN_PULLUP_DIS(PERIPHS_IO_MUX_GPIO0_U); // 失能GPIO0内部上拉(默认),由硬件电路上拉
  130. // GPIO0中断配置
  131. ETS_GPIO_INTR_DISABLE(); // 先关闭GPIO中断
  132. ETS_GPIO_INTR_ATTACH((ets_isr_t)GPIO_INTERRUPT, NULL); // 注册中断回调函数
  133. gpio_pin_intr_state_set(GPIO_ID_PIN(0), GPIO_PIN_INTR_NEGEDGE); // GPIO0 下降沿中断
  134. ETS_GPIO_INTR_ENABLE(); // 使能GPIO中断
  135. while(1)
  136. {
  137. system_soft_wdt_feed(); // 喂狗,防止复位
  138. }
  139. }

 

说说梦想,谈谈感悟 ,聊聊技术,有啥要说的来github留言吧 https://github.com/cjx2328

—— 陈 建鑫

陈建鑫
你可能也喜欢Related Posts
footer logo
未经许可请勿自行使用、转载、修改、复制、发行、出售、发表或以其它方式利用本网站之内容。站长联系:cjx2328#126.com(修改#为@)
Copyright ©ziao Studio All Rights Reserved. E-mail:cjx2328#126.com(#号改成@) 沪ICP备14052271号-3