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

本篇文章我们再回到基础篇,难道你还以为我会讲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接口的说明,只有这个读懂了,我们才能更好的去使用它。

image
image
image

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

image

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

image

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

连尚Wi-Fi卫星

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

image
image

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

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

image

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

/************************
 *   STATIC VARIABLES   *
 ************************/
os_timer_t blue_led_timer;
os_timer_t key_read_timer;

/************************
 *   STATIC FUNCTIONS   *
 ************************/

/**
 * LED定时反转函数,1s状态反转一次
 */
static void ICACHE_FLASH_ATTR
blue_led_timer_toggle(void){
    os_timer_disarm(&blue_led_timer);//取消定时器
    uint32 status = GPIO_INPUT_GET(GPIO_ID_PIN(2));//获取蓝灯管脚状态
    GPIO_OUTPUT_SET(GPIO_ID_PIN(2),!status);//取反实现蓝灯管脚电平反转,从而实现亮灭操作
    os_timer_arm(&blue_led_timer, 1000, true);//使能定时器
}

/**
 * 按键定时状态读取函数,10ms获取一次按键状态
 */
static void ICACHE_FLASH_ATTR
key_read_value(void){
    os_timer_disarm(&key_read_timer);//取消定时器
    if(GPIO_INPUT_GET(GPIO_ID_PIN(14)) == 0x00){//如果按键按下,低电平
        os_delay_us(20000);//延时20ms消抖
        if(GPIO_INPUT_GET(GPIO_ID_PIN(14)) == 0x00){//再次判断状态,防止误触
            uint32 status = GPIO_INPUT_GET(GPIO_ID_PIN(4));//获取当前管脚状态
            GPIO_OUTPUT_SET(GPIO_ID_PIN(4),!status);//取反实现管脚电平反转
            while(GPIO_INPUT_GET(GPIO_ID_PIN(14)));//等待按键松开
        }
    }
    os_timer_arm(&key_read_timer, 10, true);//使能定时器
}

/**
 *按键中断服务函数,高电平触发
 */
static void ICACHE_FLASH_ATTR
key_intr_handler(void){
    uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);//读取GPIO寄存器状态,获取中断信息
    uint8 level = 0;
    GPIO_REG_WRITE(GPIO_STATUS_ADDRESS,gpio_status);//清楚中断信息
    if(gpio_status & (BIT(15))){//判断是否是gpio15
        if(GPIO_INPUT_GET(15)){//如果是高电平
            GPIO_OUTPUT_SET(GPIO_ID_PIN(5),0);//熄灭红灯
            GPIO_OUTPUT_SET(GPIO_ID_PIN(12),1);//熄灭黄灯
            GPIO_OUTPUT_SET(GPIO_ID_PIN(4),0);//熄灭绿灯
            GPIO_OUTPUT_SET(GPIO_ID_PIN(2),0);//熄灭蓝灯
            os_timer_disarm(&key_read_timer);//取消按键定时器
            os_timer_disarm(&blue_led_timer);//取消蓝灯定时反转定时器
        }else{//如果是低电平
            //不做处理
        }
    }else{//如果不是gpio15
        //不做处理
    }
}

/************************
 *   GLOBAL FUNCTIONS   *
 ************************/
void ICACHE_FLASH_ATTR
gpio_test(void){

    gpio_init();//初始化GPIO

    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U,FUNC_GPIO5);//红灯
    GPIO_OUTPUT_SET(GPIO_ID_PIN(5),1);//高电平点亮,常亮

    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U,FUNC_GPIO12);//黄灯
    GPIO_OUTPUT_SET(GPIO_ID_PIN(12),0);//低电平点亮,常亮

    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U,FUNC_GPIO2);//蓝灯
    os_timer_disarm(&blue_led_timer);
    os_timer_setfn(&blue_led_timer, (os_timer_func_t *) blue_led_timer_toggle,NULL);//定时回调函数
    os_timer_arm(&blue_led_timer, 1000, true);//设置时间为1s

    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U,FUNC_GPIO4);//绿灯,按键触发,反转
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U,FUNC_GPIO14);//按键
    GPIO_DIS_OUTPUT(GPIO_ID_PIN(14));//按键设置为输入模式
    PIN_PULLUP_EN(PERIPHS_IO_MUX_MTMS_U);//引脚上拉使能
    os_timer_disarm(&key_read_timer);
    os_timer_setfn(&key_read_timer, (os_timer_func_t *) key_read_value,NULL);//定时回调函数
    os_timer_arm(&key_read_timer, 10, true);//设置时间为10ms

    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U,FUNC_GPIO15);//中断按键
    GPIO_DIS_OUTPUT(GPIO_ID_PIN(15));//设置为输入模式
    PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTDO_U);//下拉使能
    ETS_GPIO_INTR_DISABLE();//禁止所有GPIO中断
    ETS_GPIO_INTR_ATTACH((void *)key_intr_handler,NULL);//注册GPIO中断处理函数
    gpio_pin_intr_state_set(GPIO_ID_PIN(15),GPIO_PIN_INTR_HILEVEL);//设置高电平触发中断
    ETS_GPIO_INTR_ENABLE();//使能所有GPIO中断

}

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

视频还在找托管方~

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

image

源码可以在这里下载:

makingfunxyz-esp8266

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

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

视频可以去知乎上的文章查看~
QQ交流群:592587184

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容