esp32开发快速入门 4 : GPIO

esp32 是乐鑫即ESP8266后又一款标杆性的芯片,拥有低功耗,wifi&蓝牙双模,音频视频的应用等优点,在加上它良好的开源社区使得它在国内外物联网领域都十分流行。


废话不多说直接进入主题 :

esp32开发使用官方提供的esp-idf开发框架

开发环境大家参考DIY智能家居设备:基于esp32和阿里云云智能APP完成智能灯泡的开发 - 知乎

esp-idf对于各种外设提供了丰富的接口函数和例程,用户只需阅读例程和函数注释就完全可以使用esp32的各种外设。

  1. gpio配置结构体,对于gpio初始化主要是是对这个接口进行配置。
/**
 * @brief Configuration parameters of GPIO pad for gpio_config function
 */
typedef struct {
    uint64_t pin_bit_mask;          /*!< GPIO pin: set with bit mask, each bit maps to a GPIO */
    gpio_mode_t mode;               /*!< GPIO引脚输入输出模式  内容参考gpio_mode_t */
    gpio_pullup_t pull_up_en;       /*!< GPIO pull-up         是否使能上拉                                 */
    gpio_pulldown_t pull_down_en;   /*!< GPIO pull-down 是否使能下拉                            */
    gpio_int_type_t intr_type;      /*!< GPIO interrupt type  中断类型 上升沿/下降沿等                                */
} gpio_config_t;

2. 将gpio_config_t 赋值后,使用 gpio_config(&io_conf);完成配置,执行完此函数后这个引脚就算配置完成了。

3. 之后只需要执行 gpio_set_level(gpio_num_t gpio_num, uint32_t level);函数就可以使起输出高低电平了。

4. 如果想使用中断的话,则需要在后gpio_config(&io_conf);后配置中断。

//定义回调函数
//注意IRAM_ATTR ,是将定义的中断回调函数定义在iram区
static void IRAM_ATTR isr_handler(void* arg)
{
   ....
}
//install gpio isr service
esp_err_t gpio_install_isr_service(int intr_alloc_flags)//注册中断号
//hook isr handler for specific gpio pin
//将中断回调函数与中断号关联起来,当中断发生时,会触发中断回调函数。
esp_err_t gpio_isr_handler_add(gpio_num_t gpio_num, gpio_isr_t isr_handler, void* args)

5. 例程讲解:

/* GPIO Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"

/**
 * Brief:
 * This test code shows how to configure gpio and how to use gpio interrupt.
 *
 * GPIO status:
 * GPIO18: output
 * GPIO19: output
 * GPIO4:  input, pulled up, interrupt from rising edge and falling edge
 * GPIO5:  input, pulled up, interrupt from rising edge.
 *
 * Test:
 * Connect GPIO18 with GPIO4
 * Connect GPIO19 with GPIO5
 * Generate pulses on GPIO18/19, that triggers interrupt on GPIO4/5
 *
 */

#define GPIO_OUTPUT_IO_0    18//要定义为输出的的io编号
#define GPIO_OUTPUT_IO_1    19//要定义为输出的的io编号
#define GPIO_OUTPUT_PIN_SEL  ((1ULL<<GPIO_OUTPUT_IO_0) | (1ULL<<GPIO_OUTPUT_IO_1))//打开引脚标志  1为打开 0为关闭
#define GPIO_INPUT_IO_0     4    //要定义为输入的的io编号
#define GPIO_INPUT_IO_1     5    //要定义为输入的的io编号
#define GPIO_INPUT_PIN_SEL  ((1ULL<<GPIO_INPUT_IO_0) | (1ULL<<GPIO_INPUT_IO_1))//打开引脚标志
#define ESP_INTR_FLAG_DEFAULT 0   //设置中断编号

static xQueueHandle gpio_evt_queue = NULL;//定义gpio消息队,用于传输消息
/*定义gpio 中断回调函数*/
static void IRAM_ATTR gpio_isr_handler(void* arg)
{
    uint32_t gpio_num = (uint32_t) arg;
    //在中断中向消息队列发送数据,
    //注意freeRTOS中断操作都是用带有ISR的函数
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}

static void gpio_task_example(void* arg)
{
    uint32_t io_num;
    for(;;) {
        if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {//接收队列消息,如果成功接收到数据 ,打印消息
            printf("GPIO[%d] intr, val: %d\n", io_num, gpio_get_level(io_num));
        }
    }
}

void app_main(void)
{
    gpio_config_t io_conf;
    //disable interrupt
    io_conf.intr_type = GPIO_PIN_INTR_DISABLE;//关闭中断
    //set as output mode
    io_conf.mode = GPIO_MODE_OUTPUT;//设置成输出引脚
    //bit mask of the pins that you want to set,e.g.GPIO18/19
    io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;//打开gpio18/19
    //disable pull-down mode
    io_conf.pull_down_en = 0;//关闭下拉
    //disable pull-up mode
    io_conf.pull_up_en = 0;//关闭上拉
    //configure GPIO with the given settings
    gpio_config(&io_conf);//执行配置

    //interrupt of rising edge
    io_conf.intr_type = GPIO_PIN_INTR_POSEDGE;//设置中断为上升沿触发
    //bit mask of the pins, use GPIO4/5 here
    io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
    //set as input mode    
    io_conf.mode = GPIO_MODE_INPUT;
    //enable pull-up mode
    io_conf.pull_up_en = 1;
    gpio_config(&io_conf);

    //change gpio intrrupt type for one pin
    //改变中断触发方式为双边沿触发
    gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE);

    //create a queue to handle gpio event from isr
    //创建长度为10的队列
    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
    //start gpio task
    //创建gpio测试任务函数
    xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);

    //install gpio isr service
    //注册中断
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    //hook isr handler for specific gpio pin
    //添加中断回调函数
    gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
    //hook isr handler for specific gpio pin
    //添加中断回调函数
    gpio_isr_handler_add(GPIO_INPUT_IO_1, gpio_isr_handler, (void*) GPIO_INPUT_IO_1);

    //remove isr handler for gpio number.
    //移除中断
    gpio_isr_handler_remove(GPIO_INPUT_IO_0);
    //hook isr handler for specific gpio pin again
    //重新添加中断
    gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);

    int cnt = 0;
    while(1) {
        printf("cnt: %d\n", cnt++);
        vTaskDelay(1000 / portTICK_RATE_MS);
        gpio_set_level(GPIO_OUTPUT_IO_0, cnt % 2);//设置电平信号
        gpio_set_level(GPIO_OUTPUT_IO_1, cnt % 2);//设置电平信号
    }
}

以上是esp-idf提供的官方例程,我只是添加了注释而已,其实想使用GPIO的读者只需阅读gpio.h 即可。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值