码迷,mamicode.com
首页 > 其他好文 > 详细

[基础篇]ESP8266-SDK教程(四)之GPIO操作(按键、LED、中断、定时器)

时间:2018-12-09 16:32:42      阅读:233      评论:0      收藏:0      [点我收藏+]

标签:ica   target   特殊   官方   href   没有   article   学习   key   

 

本篇文章我们再回到基础篇,难道你还以为我会讲UDP?啊哈哈哈,UDP肯定是会讲的,但是应用场景不是很多,我们放到后面再讲,不过也是简单一讲,毕竟熟悉UDP协议的人来说,都知道UDP一种不可靠的传输协议,可以这样形容“我(Client)只管发,你(Server)爱收不收”,所以在一些实际应用场景中是不多见的,大多数时候我们还是要保证数据传输的可靠性,准确性!好了,不多扯了,开始今天的简单却很重要的知识学习~

我们先来了解一下什么是GPIO吧,虽然经常说GPIO,但是你有没有真正的去深入了解一下呢?随着知识的不断积累,有些时候去深入的了解某些东西,会让你有很多新的收获。

  • 什么是GPIO

简单来说就是通用输入输出端口,英文全称:General Purpose Input Output。通俗地说,就是一些引脚,可以通过它们输出高低电平,或者通过它们读入引脚的状态是高电平或是低电平。GPIO是个比较重要的概念,用户可以通过GPIO口和硬件进行数据交互(如UART),控制硬件工作(如LED、蜂鸣器等),读取硬件的工作状态信号(如中断信号)等。

  • GPIO的八种模式

这里说的八种模式并不是指ESP8266的八种模式,据我所知ESP8266的GPIO口并没有这么多模式,这里给大家说的是STM32 GPIO的八种模式,STM32单片机的八种模式相对来说是非常全的了,我们这里可以了解一下。

  1. 模拟输入(GPIO_Mode_AIN)
  2. 浮空输入(GPIO_Mode_IN_FLOATING)
  3. 下拉输入(GPIO_Mode_IPD)
  4. 上拉输入(GPIO_Mode_IPU)
  5. 开漏输出(GPIO_Mode_Out_OD)
  6. 推挽输出(GPIO_Mode_Out_PP)
  7. 复用开漏输出(GPIO_Mode_Out_PP)
  8. 复用推挽输出(GPIO_Mode_AF_PP)

这里就不再详细展开叙述了,因为要把这八种模式都搞明白,一两句话是说不完了,有时间在跟大家分享。

  • GPIO可以用来做什么

我们去学一个东西,最重要是知道这个东西可以做什么,最终要落实到实际使用嘛,如果这个GPIO没有实际使用价值,那我们也肯定不会去好好琢磨它了,简单来说,实际使用场景非常多,比如我们常见的只有开关状态的电子器件都可以用GPIO控制,或者间接使用GPIO去控制,举个栗子!LED灯,纳尼?怎么老是说一些跟灯有关的东西,啊哈哈哈哈,因为我还是比较喜欢闪闪发光的小玩意,我们都知道灯只有两种状态,开或者关(不要跟我讲还有坏了这种状态!),开跟关的状态其实就是有无电流经过它,而有无电流经过LED,最重要的是LED两端要有一个电压差,所以我们可以让某一个管脚输出高电平,这样就会在LED两端形成一定的电压差,自然而然的灯就亮了,大家可以暂时这么理解(这里只是讲给不怎么懂电子的人的~)。又比如还可以控制继电器、还可以获取按键状态,复杂一点的还可以模拟I2C总线,总之GPIO是很通用,但是也是非常重要的!

  • ESP8266GPIO接口函数

其实单就ESP8266的GPIO口操作来说,我起初是很不适应的,如果你之前接触的是STM32单片机开发的话,你会感到不适应,但是慢慢的熟悉一下,会发现其实很简单,所以学习最重要的是摒弃固有思维,要能够思维活跃一些。我们先看一下手册当中对GPIO接口的说明,只有这个读懂了,我们才能更好的去使用它。

技术分享图片

技术分享图片

技术分享图片

我这里把几个常用的给圈出来了,基本上我们使用这几个就足够了,GPIO中断这块大家可以好好看一下,有时候我们会用到外部中断的,我们使用管脚去控制一个LED灯的基本流程就是先PIN_FUNC_SELECT(PIN_NAME, FUNC),然后就可以输出高低电平或者设置为输入,或者去读取管脚状态,但是有一点我们需要注意的就是gpio16这个管脚,在官方的技术参考手册中有说明,给大家截图看一下:

技术分享图片

什么意思呢?就是gpio16这个管脚不是GPIO这一伙里,使用它人家有自己的接口函数,不跟其他管脚使用同样的接口函数,这里大家需要注意一些,那么为什么这个管脚这么特殊呢?其实主要时为了低功耗,要知道Wi-Fi的功耗是很大,但是我们如果拿ESP8266做一些便携的设备,靠电池供电是不足以支撑很久的,所以在它没有什么事情的时候,我们需要它进入睡眠模式,这时候整个芯片会关闭除RTC以外的所有模块,此时工作电流是在μA级别,可以说是非常省电的,下面我们看一下官方是如何介绍的低功耗模式:

技术分享图片

可以看出在深度睡眠模式下功耗是极低的,所以我们是可以利用ESP8266做一些可穿戴设备的,但是戴着出去的时候,我们要去连接哪一个Wi-Fi呢?这是很值得思考的,很显然不能手机开热点,那样我们手机的功耗可就大大提高了,不过最近据说有家国内公司叫连尚网络的公司发布了自家的Wi-Fi卫星,据说明年将会搭载长征系列火箭升空,估计到那时候可穿戴Wi-Fi设备才有真正的应用场景,目前还是基于BLE的居多。详情戳卡片:

连尚Wi-Fi卫星

我们看一下三种模式睡眠模式的功耗对比吧!

技术分享图片

技术分享图片

不对,好像又有点扯多了?怎么睡眠模式又写了这么多,好吧,转回正题,大家对低功耗感兴趣的话可以留言,改天我单独整理一篇文章详细介绍一下,要是没有那就先不整理了,啊哈哈哈哈~

我们正式开始我们的点灯、按键点灯、定时器点灯等点灯之旅,不过还有个问题,我们这里如果是使用的NodeMCU(默认大家是使用的NodeMCU)话,我们还需要了解一下管脚定义,因为NodeMCU采用的管脚命名与ESP8266的默认管脚命名是不一样的,所以我们需要对应起来,直接给大家上个图片看一下,建议大家收藏一下,省的以后找起来麻烦。

技术分享图片

话不多说?上代码?得嘞,客官您里边请~

 1 /************************
 2  *   STATIC VARIABLES   *
 3  ************************/
 4 os_timer_t blue_led_timer;
 5 os_timer_t key_read_timer;
 6 
 7 /************************
 8  *   STATIC FUNCTIONS   *
 9  ************************/
10 
11 /**
12  * LED定时反转函数,1s状态反转一次
13  */
14 static void ICACHE_FLASH_ATTR
15 blue_led_timer_toggle(void){
16     os_timer_disarm(&blue_led_timer);//取消定时器
17     uint32 status = GPIO_INPUT_GET(GPIO_ID_PIN(2));//获取蓝灯管脚状态
18     GPIO_OUTPUT_SET(GPIO_ID_PIN(2),!status);//取反实现蓝灯管脚电平反转,从而实现亮灭操作
19     os_timer_arm(&blue_led_timer, 1000, true);//使能定时器
20 }
21 
22 /**
23  * 按键定时状态读取函数,10ms获取一次按键状态
24  */
25 static void ICACHE_FLASH_ATTR
26 key_read_value(void){
27     os_timer_disarm(&key_read_timer);//取消定时器
28     if(GPIO_INPUT_GET(GPIO_ID_PIN(14)) == 0x00){//如果按键按下,低电平
29         os_delay_us(20000);//延时20ms消抖
30         if(GPIO_INPUT_GET(GPIO_ID_PIN(14)) == 0x00){//再次判断状态,防止误触
31             uint32 status = GPIO_INPUT_GET(GPIO_ID_PIN(4));//获取当前管脚状态
32             GPIO_OUTPUT_SET(GPIO_ID_PIN(4),!status);//取反实现管脚电平反转
33             while(GPIO_INPUT_GET(GPIO_ID_PIN(14)));//等待按键松开
34         }
35     }
36     os_timer_arm(&key_read_timer, 10, true);//使能定时器
37 }
38 
39 /**
40  *按键中断服务函数,高电平触发
41  */
42 static void ICACHE_FLASH_ATTR
43 key_intr_handler(void){
44     uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);//读取GPIO寄存器状态,获取中断信息
45     uint8 level = 0;
46     GPIO_REG_WRITE(GPIO_STATUS_ADDRESS,gpio_status);//清楚中断信息
47     if(gpio_status & (BIT(15))){//判断是否是gpio15
48         if(GPIO_INPUT_GET(15)){//如果是高电平
49             GPIO_OUTPUT_SET(GPIO_ID_PIN(5),0);//熄灭红灯
50             GPIO_OUTPUT_SET(GPIO_ID_PIN(12),1);//熄灭黄灯
51             GPIO_OUTPUT_SET(GPIO_ID_PIN(4),0);//熄灭绿灯
52             GPIO_OUTPUT_SET(GPIO_ID_PIN(2),0);//熄灭蓝灯
53             os_timer_disarm(&key_read_timer);//取消按键定时器
54             os_timer_disarm(&blue_led_timer);//取消蓝灯定时反转定时器
55         }else{//如果是低电平
56             //不做处理
57         }
58     }else{//如果不是gpio15
59         //不做处理
60     }
61 }
62 
63 /************************
64  *   GLOBAL FUNCTIONS   *
65  ************************/
66 void ICACHE_FLASH_ATTR
67 gpio_test(void){
68 
69     gpio_init();//初始化GPIO
70 
71     PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U,FUNC_GPIO5);//红灯
72     GPIO_OUTPUT_SET(GPIO_ID_PIN(5),1);//高电平点亮,常亮
73 
74     PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U,FUNC_GPIO12);//黄灯
75     GPIO_OUTPUT_SET(GPIO_ID_PIN(12),0);//低电平点亮,常亮
76 
77     PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U,FUNC_GPIO2);//蓝灯
78     os_timer_disarm(&blue_led_timer);
79     os_timer_setfn(&blue_led_timer, (os_timer_func_t *) blue_led_timer_toggle,NULL);//定时回调函数
80     os_timer_arm(&blue_led_timer, 1000, true);//设置时间为1s
81 
82     PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U,FUNC_GPIO4);//绿灯,按键触发,反转
83     PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U,FUNC_GPIO14);//按键
84     GPIO_DIS_OUTPUT(GPIO_ID_PIN(14));//按键设置为输入模式
85     PIN_PULLUP_EN(PERIPHS_IO_MUX_MTMS_U);//引脚上拉使能
86     os_timer_disarm(&key_read_timer);
87     os_timer_setfn(&key_read_timer, (os_timer_func_t *) key_read_value,NULL);//定时回调函数
88     os_timer_arm(&key_read_timer, 10, true);//设置时间为10ms
89 
90     PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U,FUNC_GPIO15);//中断按键
91     GPIO_DIS_OUTPUT(GPIO_ID_PIN(15));//设置为输入模式
92     PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTDO_U);//下拉使能
93     ETS_GPIO_INTR_DISABLE();//禁止所有GPIO中断
94     ETS_GPIO_INTR_ATTACH((void *)key_intr_handler,NULL);//注册GPIO中断处理函数
95     gpio_pin_intr_state_set(GPIO_ID_PIN(15),GPIO_PIN_INTR_HILEVEL);//设置高电平触发中断
96     ETS_GPIO_INTR_ENABLE();//使能所有GPIO中断
97 
98 }

代码不是很多,都有注释,大家可以自己看一下,最后我们来看一下实际运行效果,请原谅我这不标准的普通话,应该不用给大家加字幕吧?啊哈哈哈,请大家谅解~

视频还在找托管方~

再附上一张手画原理图,电路连接相对简单,就简单一画,应该很好看懂的。

技术分享图片

源码可以在这里下载:

makingfunxyz-esp8266

欢迎大家Star,您的鼓励是我最大的动力,有问题可以私信我,或者提交issues~

本系列文章在知乎同步更新,知乎搜索专栏:IAMLIUBO的神奇物联网之旅

[基础篇]ESP8266-SDK教程(四)之GPIO操作(按键、LED、中断、定时器)

标签:ica   target   特殊   官方   href   没有   article   学习   key   

原文地址:https://www.cnblogs.com/imliubo/p/10090874.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!