ESP32学习笔记(2)——GPIO接口使用
一、简介
ESP32 芯片有 40 个物理 GPIO pad。每个 pad 都可用作一个通用 IO,或连接一个内部的外设信号。IO_MUX、RTC IO_MUX 和 GPIO 交换矩阵用于将信号从外设传输至 GPIO pad。这些模块共同组成了芯片的 IO 控制。
注意:其中 GPIO 34-39 仅用作输入管脚,其他的既可以作为输入又可以作为输出管脚。
GPIO6-11通常用于SPI闪存。
1.1 官方资料
ESP-IDF 编程指南——GPIO&RTC GPIO
ESP32 技术参考手册——4 IO_MUX 和 GPIO 交换矩阵 (GPIO, IO_MUX)
gpio_example
1.2 包含头文件
#include "driver/gpio.h"
1.3 IO功能表
二、GPIO输出
2.1 引脚确定
我使用的是 ESP32-LyraT V4.3
开发板
有个 IO 口为 22 的绿色 LED 灯
2.2 简单方法
gpio_pad_select_gpio(GPIO_NUM_22); // 选择一个GPIO
gpio_set_direction(GPIO_NUM_22, GPIO_MODE_OUTPUT);// 把这个GPIO作为输出
gpio_set_level(GPIO_NUM_22, 0); // 把这个GPIO输出低电平
2.3 结构体方法
#define GPIO_OUTPUT_IO_0 22
#define GPIO_OUTPUT_PIN_SEL (1ULL<<GPIO_OUTPUT_IO_0) // 配置GPIO_OUT位寄存器void gpio_init(void)
{gpio_config_t io_conf; // 定义一个gpio_config类型的结构体,下面的都算对其进行的配置io_conf.intr_type = GPIO_PIN_INTR_DISABLE; // 禁止中断 io_conf.mode = GPIO_MODE_OUTPUT; // 选择输出模式io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL; // 配置GPIO_OUT寄存器io_conf.pull_down_en = 0; // 禁止下拉io_conf.pull_up_en = 0; // 禁止上拉gpio_config(&io_conf); // 最后配置使能
}gpio_set_level(GPIO_OUTPUT_IO_0, 0); // 把这个GPIO输出低电平
gpio_set_level(GPIO_OUTPUT_IO_0, 1); // 把这个GPIO输出高电平
2.4 LED灯闪烁
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"void app_main(void)
{gpio_pad_select_gpio(GPIO_NUM_22);//gpio_init();/* Set the GPIO as a push/pull output */gpio_set_direction(GPIO_NUM_22, GPIO_MODE_OUTPUT);while(1) {/* Blink off (output low) */printf("Turning off the LED\n");gpio_set_level(GPIO_NUM_22, 0);vTaskDelay(1000 / portTICK_PERIOD_MS);/* Blink on (output high) */printf("Turning on the LED\n");gpio_set_level(GPIO_NUM_22, 1);vTaskDelay(1000 / portTICK_PERIOD_MS);}
}
三、GPIO输入
3.1 引脚确定
我使用的是 ESP32-LyraT V4.3
开发板
有个 IO 口为 36 的按键,SENSOR_VP--->GPIO36
3.2 简单方法
gpio_pad_select_gpio(GPIO_NUM_36); // 选择一个GPIO
gpio_set_direction(GPIO_NUM_36, GPIO_MODE_INPUT); // 把这个GPIO作为输入
gpio_get_level(GPIO_NUM_36);
3.3 结构体方法
#define GPIO_INPUT_IO_0 36
#define GPIO_INPUT_PIN_SEL (1ULL<<GPIO_INPUT_IO_0) // 配置GPIO_IN位寄存器void gpio_init(void)
{gpio_config_t io_conf; // 定义一个gpio_config类型的结构体,下面的都算对其进行的配置io_conf.intr_type = GPIO_PIN_INTR_DISABLE; // 禁止中断 io_conf.mode = GPIO_MODE_INPUT; // 选择输入模式io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL; // 配置GPIO_IN寄存器io_conf.pull_down_en = 0; // 禁止下拉io_conf.pull_up_en = 0; // 禁止上拉gpio_config(&io_conf); // 最后配置使能
}gpio_get_level(GPIO_INPUT_IO_0, 0); // 读取这个GPIO电平
3.4 轮询检测按键输入
500ms读取GPIO36的输入电平状态,并且打印出来!
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"void app_main(void)
{gpio_pad_select_gpio(GPIO_NUM_36);//gpio_init();/* Set the GPIO as a push/pull output */gpio_set_direction(GPIO_NUM_36, GPIO_MODE_INPUT);while(1) {printf(" Current Gpio36 Level is : %d \r\n\r\n",gpio_get_level(GPIO_NUM_36));vTaskDelay(1000 / portTICK_PERIOD_MS);}
}
查看打印:
四、GPIO中断
4.1 引脚确定
同上 3.1
4.2 触发方式
GPIO_INTR_DISABLE //禁用GPIO中断
GPIO_INTR_POSEDGE //GPIO中断类型:上升沿
GPIO_INTR_NEGEDGE //下降沿
GPIO_INTR_ANYEDGE //上升沿和下降沿
GPIO_INTR_LOW_LEVEL //输入低电平触发
GPIO_INTR_HIGH_LEVEL //输入高电平触发
4.2.1 简单方法
当使用启用睡眠模式的ADC或Wi-Fi时,请不要使用GPIO 36和GPIO 39的中断。
gpio_pad_select_gpio(GPIO_NUM_36);
gpio_set_direction(GPIO_NUM_36, GPIO_MODE_INPUT);
gpio_intr_enable(GPIO_NUM_36);
gpio_set_intr_type(GPIO_NUM_36, GPIO_INTR_NEGEDGE);
gpio_pullup_en(GPIO_NUM_36);
4.2.2 结构体方法
输入模式:不下拉,内部上拉!原因在于内部上拉,就是高电平短脚,可以检测到下降沿。
#define GPIO_INPUT_IO_0 36
#define GPIO_INPUT_PIN_SEL (1ULL<<GPIO_INPUT_IO_0) // 配置GPIO_IN位寄存器void gpio_init(void)
{gpio_config_t io_conf; // 定义一个gpio_config类型的结构体,下面的都算对其进行的配置io_conf.intr_type = GPIO_INTR_NEGEDGE; // 下降沿触发io_conf.mode = GPIO_MODE_INPUT; // 选择输入模式io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL; // 配置GPIO_IN寄存器io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;io_conf.pull_up_en = GPIO_PULLUP_ENABLE; // 内部上拉gpio_config(&io_conf); // 最后配置使能
}
4.3 配置FreeRTOS任务和队列
注意:gpio_isr_handler中断回调函数是加载在IRAM_ATTR中,不能执行其他耗时操作,包括printf打印信息
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"#define ESP_INTR_FLAG_DEFAULT 0static xQueueHandle gpio_evt_queue = NULL; //定义一个队列返回变量void IRAM_ATTR gpio_isr_handler(void* arg)
{//把中断消息插入到队列的后面,将gpio的io参数传递到队列中uint32_t gpio_num = (uint32_t) arg;xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}void gpio_task(void* arg)
{printf(" \r\n start gpio task ...\r\n ");uint32_t io_num;for(;;){//不断读取gpio队列,读取完后将删除队列if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)){printf("GPIO[%d] intr, val: %d\n", io_num, gpio_get_level(io_num));}}
}void gpio_intr_init(void)
{// 注册中断服务gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);// 设置GPIO的中断回调函数gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);// 创建一个消息队列,从中获取队列句柄gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));// 创建GPIO检测任务xTaskCreate(gpio_task // 任务函数, "gpio_task_example" // 任务名字, 2048 // 任务堆栈大小, NULL // 传递给任务函数的参数, 10 // 任务优先级, NULL); // 任務句柄
}
4.4 按键中断
注意:gpio_isr_handler中断回调函数是加载在IRAM_ATTR中,不能执行其他耗时操作,包括printf打印信息
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"#define GPIO_INPUT_IO_0 36
#define GPIO_INPUT_PIN_SEL (1ULL<<GPIO_INPUT_IO_0) // 配置GPIO_IN位寄存器
#define ESP_INTR_FLAG_DEFAULT 0static xQueueHandle gpio_evt_queue = NULL; //定义一个队列返回变量void IRAM_ATTR gpio_isr_handler(void* arg)
{//把中断消息插入到队列的后面,将gpio的io参数传递到队列中uint32_t gpio_num = (uint32_t) arg;xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}void gpio_task(void* arg)
{printf(" \r\n start gpio task ...\r\n ");uint32_t io_num;for(;;){//不断读取gpio队列,读取完后将删除队列if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)){printf("GPIO[%d] intr, val: %d\n", io_num, gpio_get_level(io_num));}}
}void gpio_init(void)
{gpio_config_t io_conf; // 定义一个gpio_config类型的结构体,下面的都算对其进行的配置io_conf.intr_type = GPIO_INTR_NEGEDGE; // 下降沿触发io_conf.mode = GPIO_MODE_INPUT; // 选择输入模式io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL; // 配置GPIO_IN寄存器io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;io_conf.pull_up_en = GPIO_PULLUP_ENABLE; // 内部上拉gpio_config(&io_conf); // 最后配置使能
}void gpio_intr_init(void)
{// 注册中断服务gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);// 设置GPIO的中断回调函数gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);// 创建一个消息队列,从中获取队列句柄gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));// 创建GPIO检测任务xTaskCreate(gpio_task // 任务函数, "gpio_task_example" // 任务名字, 2048 // 任务堆栈大小, NULL // 传递给任务函数的参数, 10 // 任务优先级, NULL); // 任務句柄
}void app_main(void)
{//gpio_pad_select_gpio(GPIO_NUM_36);//gpio_set_direction(GPIO_NUM_36, GPIO_MODE_INPUT);//gpio_intr_enable(GPIO_NUM_36);//gpio_set_intr_type(GPIO_NUM_36, GPIO_INTR_NEGEDGE);//gpio_pullup_en(GPIO_NUM_36);gpio_init();gpio_intr_init();while(1) {vTaskDelay(1000 / portTICK_PERIOD_MS);}
}
查看打印:
• 由 Leung 写于 2021 年 4 月 14 日
• 参考:乐鑫Esp32学习之旅③ 认识并学习使用esp32的GPIO接口,开始点亮您的第一盏 LED和中断回调实现按键功能
ESP32学习笔记(2)——GPIO接口使用相关推荐
- 启明云端分享|ESP32学习笔记参考GPIO口操作
提示:作为Espressif(乐鑫科技)大中华区合作伙伴及sigmastar(厦门星宸)VAD合作伙伴,我们不仅用心整理了你在开发过程中可能会遇到的问题以及快速上手的简明教程供开发小伙伴参考.同时也用 ...
- ESP32学习笔记(20)——SPI(从机)接口使用
一.SPI简介 SPI(Serial Peripheral Interface) 协议是由摩托罗拉公司提出的通讯协议,即串行外围设备接口,是一种高速全双工的通信总线.它被广泛地使用在 ADC.LCD ...
- ESP32学习笔记(19)——SPI(主机)接口使用
一.SPI简介 SPI(Serial Peripheral Interface) 协议是由摩托罗拉公司提出的通讯协议,即串行外围设备接口,是一种高速全双工的通信总线.它被广泛地使用在 ADC.LCD ...
- ESP32学习笔记(7)——SmartConfig接口使用(ESP-Touch和AirKiss)
一.概述 SmartConfig是TI开发的一种配置技术,用于将新的Wi-Fi设备连接到Wi-Fi网络.它使用移动应用程序将网络凭据从智能手机或平板电脑广播到未配置的Wi-Fi设备. 该技术的优点是设 ...
- ESP32学习笔记( VSCode + ESP-IDF环境) 3 ——GPIO相关的简单外设驱动
1.如何在VSCode和ESP-IDF的环境下创建工程 说实话,这是我用ESP-IDF在VSCode环境下最不喜欢的事情,在一顿CSDN和百度之后,很多大佬博主都推荐使用VSCode,通过官方示例来进 ...
- ESP32学习笔记(49)——RFID RC522使用
一.简介 MF RC522 是应用于 13.56MHz 非接触式通信中高集成度读写卡系列芯片中的一员.是 NXP 公司针对"三表"应用推出的一款低电压.低成本.体积小的非接触式读写 ...
- ESP32学习笔记(27)——BLE GAP主机端扫描
一.背景 1.1 低功耗蓝牙(BLE)协议栈 链路层(LL) 控制设备的射频状态,有五个设备状态:待机.广播.扫描.初始化和连接. 广播 为广播数据包,而 扫描 则是监听广播. GAP通信中角色,中心 ...
- ESP32学习笔记(一) 芯片型号介绍
ESP32学习笔记(一) 芯片型号介绍 目录: ESP32学习笔记(一) 芯片型号介绍 ESP32学习笔记(二) 开发环境搭建 VSCode+platformio ESP32学习笔记(三) 硬件资源介 ...
- ESP32学习笔记(30)——BLE GATT服务端自定义服务和特征
一.简介 1.1 低功耗蓝牙(BLE)协议栈 链路层(LL) 控制设备的射频状态,有五个设备状态:待机.广播.扫描.初始化和连接. 广播 为广播数据包,而 扫描 则是监听广播. GAP通信中角色,中心 ...
- [ESP32]学习笔记03
今天我们使用ESP32自带的LEDC外设制作一个LED呼吸灯 目录 前言 一.呼吸灯是什么 二.首先我们在Blink实例的基础上建立工程 1.引入库添加宏定义 2.修改主函数 最后我们看一下呼吸灯的效 ...
最新文章
- 另外一些MySQL优化措施
- Python PIPEs
- Recommendation
- 【知识图谱系列】基于2D卷积的知识图谱嵌入
- unity接入 微信登录sdk
- 债券中的久期是什么意思
- masquerade词根词缀_词根词缀总结
- 帝国理工大学计算机本科笔试题,共同努力 成功申请帝国理工学院计算机科学专业...
- 国王匿名信息服务器,扮国王还是卫兵? 角色扮演服务器登录美服
- 手机怎么调整照片分辨率?照片清晰度dpi怎么调整?
- 从初级晋级高级UI设计师学习路线+全套视频
- 关于Contiguous()方法
- 计算机思维在化工方面的应用,计算思维在化学上的应用.pdf
- 使用spoon(kettle)工具抽取Elasticsearch的数据并入库
- 咨询顾问长啥样儿?——北漂18年(88)
- 臀纬痈粕吃种鼗拼舅怂
- moxa uport1150串口驱动下载地址及安装方式
- 手写oracle分页,oracle分页代码(超简略写法)
- TCP连接建立与断开
- 批处理命令set /p是什么意思
热门文章
- [转] Julia 高性能动态编程语言入门
- matlab海图栅格化_matlab栅格化图片代码
- IC Insights:2021年汽车和物联网芯片销售额将达到429亿美元
- 免费使用QQ邮箱“邮件短信通知”服务
- python中for ch in是什么意思_python中for是什么
- 阿里云提示ECS实例存在挖矿活动的处理
- 计算机系统如何恢复出厂设置路由器,迅捷(fast)路由器恢复出厂设置后怎么重新设置?...
- 生信人的20个R语言习题
- 2016.7.14 noip2014模拟题 LGTB的日常~(自己乱安的名字hhh
- Xcode—新建/配置pch文件