ESP8266_RTOSv3.X第一弹——GPIO的使用和代码讲解

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_27865227/article/details/94468930

一、GPIO介绍

  1. IO数量及功能
    关于esp8266的板子上的引脚,是这样子的,ESP芯片一共33个个引脚,其中包括电源,使能引脚、深度睡眠唤醒引脚、SPI引脚以及连接晶振和作为烧写Flash的引脚。所谓的GPIO(General-purpose input/output)引脚一共有17个,esp8266的SDK把其放进了一个枚举类型里。源码如下:

    typedef enum {
        GPIO_NUM_0 = 0,     /*!< GPIO0, input and output */
        GPIO_NUM_1 = 1,     /*!< GPIO1, input and output */
        GPIO_NUM_2 = 2,     /*!< GPIO2, input and output */
        GPIO_NUM_3 = 3,     /*!< GPIO3, input and output */
        GPIO_NUM_4 = 4,     /*!< GPIO4, input and output */
        GPIO_NUM_5 = 5,     /*!< GPIO5, input and output */
        GPIO_NUM_6 = 6,     /*!< GPIO6, input and output */
        GPIO_NUM_7 = 7,     /*!< GPIO7, input and output */
        GPIO_NUM_8 = 8,     /*!< GPIO8, input and output */
        GPIO_NUM_9 = 9,     /*!< GPIO9, input and output */
        GPIO_NUM_10 = 10,   /*!< GPIO10, input and output */
        GPIO_NUM_11 = 11,   /*!< GPIO11, input and output */
        GPIO_NUM_12 = 12,   /*!< GPIO12, input and output */
        GPIO_NUM_13 = 13,   /*!< GPIO13, input and output */
        GPIO_NUM_14 = 14,   /*!< GPIO14, input and output */
        GPIO_NUM_15 = 15,   /*!< GPIO15, input and output */
        GPIO_NUM_16 = 16,   /*!< GPIO16, input and output */
        GPIO_NUM_MAX = 17,
        /** @endcond */
    } gpio_num_t;
    
    
  2. 初始化函数及结构体
    众所周知,想使用一个东西之前,一定要先把其初始化,如果是使用C语言,又要初始化一个比较多参数的东东,那估计就要用结构体了,ESP82666 GPIO的初始化函数是

    esp_err_t gpio_config(const gpio_config_t * pGPIOConfig )		//参数是gpio_config_t 类型的指针
    

    这个函数的返回值是esp_err_t,其值如果是ESP_OK就代表成功,如果是ESP_ERR_INVALID_ARG意思是参数错误,这个时候我们就要去检查一次参数了,参数是什么呢?参数是gpio_config_t 类型的指针

    那我们再看一下gpio_config_t 的定义:

    /**
     * @brief  gpio_config函数的配置参数
     */
    typedef struct {
        uint32_t pin_bit_mask;          /*!< 引脚: 32位的参数,每一位对应着一个GPIO*/
        gpio_mode_t mode;               /*!<模式:设置输入或者输出模式 */
        gpio_pullup_t pull_up_en;       /*!< GPIO上拉 */
        gpio_pulldown_t pull_down_en;   /*!< GPIO下拉 */
        gpio_int_type_t intr_type;      /*!< GPIO中断类型 */
    } gpio_config_t;
    
    

    每个参数我们再分析一下

    类型 参数名 说明
    uint32_t pin_bit_mask 32位的参数,参数的每一位对应着一个引脚,如果要使能哪一位,就把哪一位置为1,如果要使用若干位,可以让其同时为1
    io_mode_t mode GPIO模式选择,gpio_mode_t 是一个枚举类型,其值有四个,分别代表着,不输入不输出;仅输入模式;仅输出模式;仅开漏输出;
    io_pullup_t pull_up_en GPIO_PULLUP_DISABLE(0x0)不使用上拉电阻,GPIO_PULLUP_ENABLE(0x1)使用上拉电阻
    io_pulldown_t pull_down_en GPIO_PULLDOWN_DISABLE(0x0)关闭下拉电阻,GPIO_PULLDOWN_ENABLE(0x1)使能下拉电阻
    io_int_type_t intr_type 一共有6中模式, 关闭中断(GPIO_INTR_DISABLE =0),上升沿触发(GPIO_INTR_POSEDGE =1),下降沿触发(GPIO_INTR_NEGEDGE =2),上升沿和下降沿触发(GPIO_INTR_ANYEDGE =3) ,输入低电平触发(GPIO_INTR_LOW_LEVEL =4),输入高电平触发(GPIO_INTR_HIGH_LEVEL =5)

    关于gpio_int_type_t 的这个中断配置枚举类,我们再看一下其定义:

     typedef enum {
         GPIO_INTR_DISABLE = 0,    /*!< Disable GPIO interrupt  关闭中断*/
         GPIO_INTR_POSEDGE = 1,    /*!< GPIO interrupt type : rising edge  上升沿触发*/
         GPIO_INTR_NEGEDGE = 2,    /*!< GPIO interrupt type : falling edge 下降沿触发*/
         GPIO_INTR_ANYEDGE = 3,    /*!< GPIO interrupt type : both rising and falling edge 上升沿和下降沿触发 */
         GPIO_INTR_LOW_LEVEL = 4,  /*!< GPIO interrupt type : input low level trigger 输入低电平触发 */
         GPIO_INTR_HIGH_LEVEL = 5, /*!< GPIO interrupt type : input high level trigger  输入高电平触发*/
         GPIO_INTR_MAX,
     } gpio_int_type_t;
    
  3. 设置中断类型函数
    gpio_set_intr_type这个函数用来设置gpio中断类型的设置,参数有两个,一个是GPIO的编号枚举类gpio_num_t和中断类型枚举类gpio_int_type_t。
    再来看一下函数定义:

     ```
     /**
      * @brief  GPIO set interrupt trigger type 设置中断触发类型
      *
      * @param  gpio_num GPIO number. If you want to set the trigger type of e.g. of GPIO12, gpio_num should be GPIO_NUM_12 (12);
      * @param  intr_type Interrupt type, select from gpio_int_type_t
      *
      * @return
      *     - ESP_OK  Success
      *     - ESP_ERR_INVALID_ARG Parameter error
      */
     esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type);
     
     ```
    

    同样的这个函数的返回值也有两个,要么设置成功,要么返回参数无效,不成功,便成仁。

  4. GPIO电平设置
    使用gpio_set_level()函数就可以对其进行高低电平的设置。这个函数一共有两个参数,一个参数是gpio的编号,另外一个是电屏的高低,其中0代表低电平,1代表高电平。
    如果设置失败返回ESP_ERR_INVALID_ARG代表 GPIO number error ,成功返回ESP_OK

     /**
      * @brief GPIO的输出电平
      *
      * @param  gpio_num GPIO number. If you want to set the output level of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
      * @param  level Output level. 0: low ; 1: high
      *
      * @return
      *     - ESP_OK Success
      *     - ESP_ERR_INVALID_ARG GPIO number error
      */
     esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level);
    
  5. 安装GPIO中断服务函数
    gpio_isr_register()安装驱动程序的GPIO ISR处理程序服务,用这个函数会为说有GPIO中断注册单个全局ISP

     /**
        * @brief 安装驱动程序的GPIO ISR处理程序服务,该服务允许每个引脚的GPIO中断处理程序。
       *
        *此函数与gpio_isr_register()不兼容 - 如果使用该函数,则会为所有GPIO中断注册单个全局ISR。 如果使用此功能,则ISR服务提供全局GPIO ISR,并通过gpio_isr_handler_add()函数注册各个引脚处理程序。
       *
        * @param no_use为了与esp32兼容,该参数没有实际意义,可以用0填充。
       *
        * @return
        *  -  ESP_OK成功
        *  -  ESP_ERR_NO_MEM没有内存来安装此服务
        *  -  ESP_ERR_INVALID_STATE 已安装ISR服务。
        *  -  ESP_ERR_NOT_FOUND 未找到指定标志的空闲中断
        *  -  ESP_ERR_INVALID_ARG GPIO错误
       */
     esp_err_t gpio_install_isr_service(int no_use);
    

6.为指定GPIO引脚添加/删除ISR
使用函数gpio_isr_handler_add()和gpio_isr_handler_remove()进行中断服务函数的创建与删除

/ **
  * @brief为相应的GPIO引脚添加ISR处理程序。
  *
  *使用gpio_install_isr_service()后调用此函数
  *安装驱动程序的GPIO ISR处理程序服务。
  *
  *将从ISR调用此ISR处理程序。所以有一个堆栈
  *大小限制(可在menuconfig中配置为“ISR堆栈大小”)。这个
  *与全局GPIO中断处理程序相比,限制较小
  *到额外的间接水平。
  *
  * @param gpio_num GPIO号
  * @param isr_handler相应GPIO号的ISR处理函数。
  * @param args参数用于ISR处理程序。
  *
  * @return
  *  -  ESP_OK成功
  *  -  ESP_ERR_INVALID_STATE错误的状态,ISR服务尚未初始化。
  *  -  ESP_ERR_INVALID_ARG参数错误
  * /
esp_err_t gpio_isr_handler_add(gpio_num_t gpio_num,gpio_isr_t isr_handler,void * args);

/ **
  * @brief删除相应GPIO引脚的ISR处理程序。
  *
  * @param gpio_num GPIO号码
  *
  * @return
  *  -  ESP_OK成功
  *  -  ESP_ERR_INVALID_STATE错误的状态,ISR服务尚未初始化。
  *  -  ESP_ERR_INVALID_ARG参数错误
  * /
esp_err_t gpio_isr_handler_remove(gpio_num_t gpio_num);

二、点亮一颗小灯程序

点亮一个小灯是多么的困难的一件事呢?接下来让我们体验一下。

注:nodemcu的小灯在GPIO2

第一步宏定义一些参数:

#define GPIO_OUTPUT_IO_0    2`在这里插入代码片`
#define GPIO_OUTPUT_PIN_SEL  ((1ULL<<GPIO_OUTPUT_IO_0))

第二步定义初始化结构体:

  gpio_config_t io_conf;
    //关闭中断
    io_conf.intr_type = GPIO_INTR_DISABLE;
    //输出模式
    io_conf.mode = GPIO_MODE_OUTPUT;
    //GPIO2
    io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
    //关闭下拉电阻
    io_conf.pull_down_en = 0;
    //关闭上拉电阻
    io_conf.pull_up_en = 0;

第三步进行初始化:

gpio_config(&io_conf);

第四步进行电平设置:

gpio_set_level(GPIO_OUTPUT_IO_0, 0);	//灯采用灌点流的方式进行连接的,所以当把引脚置为低电平的时候可以点亮小灯。

成功点亮小灯,恭喜你成功啦~

三、让灯闪起来

这个不得不提一下,RTOS(实时操作系统),ESP8266_RTOS的内核是FreeRTOS,是一种实时性操作系统,主要运行机制是任务的调度。具体的可以参考一下我的其他文章,有对RTOS进行细致的讲解。
话不多说直接上代码:

    int cnt = 0;
    while (1) {
        cnt++;			
        vTaskDelay(1000 / portTICK_RATE_MS);				//延时1s
        gpio_set_level(GPIO_OUTPUT_IO_0, cnt % 2);		//设置电平
    }

四、总结

从配置好环境,到真正意义上的看懂(today),差不过花了20天的时间,最主要的是不能静下心来去看文档,分析代码,畏难心里吧,始终要记得迎难而上~

展开阅读全文

没有更多推荐了,返回首页