原创不易,转载需注明来源:https://blog.csdn.net/qq_32955031
下面程序呢是乐鑫提供的GPIO使用例程,其中包括GPIO的输入输出设置,中断设置,当然避免不了ESP32基于的Free RTOS系统的一些内容,笔者呢,对其进行了一些注解,将一些函数的API解析文件整理了出来(中文的版本的),为了自己方便学习,在运行例程的基础上也对这个例程做了一些改变,对应自己整理处理出的文档实验,方便自己的理解。
下面就是解析后的源码了
/**
* 本例程在Esp 官方例程上加以改动以及注释本人对本例程的理解
* 例程功能见下方Brief(简介)
* 本人联系方式QQ:1737410733
* 本人CSDN博客:https://blog.csdn.net/qq_32955031
*
*/
#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以及如何使用gpio中断。
*
* 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-在GPIO18 / 19上产生脉冲,触发GPIO4 / 5上的中断
*
*/
#define GPIO_OUTPUT_IO_0 18 //定义GPIO18为输出管脚0
#define GPIO_OUTPUT_IO_1 19 //定义GPIO19为输出管脚1
#define GPIO_OUTPUT_PIN_SEL ((1ULL<<GPIO_OUTPUT_IO_0) | (1ULL<<GPIO_OUTPUT_IO_1)) //混合
#define GPIO_INPUT_IO_0 4 //定义GPIO4为输入管脚0
#define GPIO_INPUT_IO_1 5 //定义GPIO5为输入管脚1
#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;
//中断处理函数程序
static void IRAM_ATTR gpio_isr_handler(void* arg)
{
uint32_t gpio_num = (uint32_t) arg;
//向消息队列中投递消息,消息内容为GPIO的管脚号
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}
//GPIO中断消息处理任务
static void gpio_task_example(void* arg)
{
uint32_t io_num;
for(;;) {
//API函数:xQueueReceive,见本人整理文档之FreeRTOS篇【整理以最新版本最优】
//这是一个调用xQueueGenericReceive()函数的宏。
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()
{
//申明GPIO的结构体
gpio_config_t io_conf;
//disable interrupt
//禁用GPIO中断
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
//set as output mode
//GPIO设置为输出模式
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;
//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配置,API函数:gpio_config 见本人整理文档之GPIO篇【整理版本以最新最优】
gpio_config(&io_conf);
//interrupt of rising edge
//GPIO中断类型:上升沿
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
//GPIO输入模式
io_conf.mode = GPIO_MODE_INPUT;
//enable pull-up mode
//势能上拉模式
io_conf.pull_up_en = 1;
//configure GPIO with the given settings
//GPIO配置,API函数:gpio_config, 见本人整理文档之GPIO篇【整理版本以最新最优】
gpio_config(&io_conf);
//change gpio intrrupt type for one pin
//改变其中一个管教的中断管脚;API函数:gpio_set_intr_type,见本人整理文档之GPIO篇【整理版本以最新最优】
gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE);
//create a queue to handle gpio event from isr
//创建一个队列来处理来自isr的gpio事件
//创建新的队列实例,API函数:xQueueCreate,见本人整理文档之FreeRTOS篇
gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
//start gpio task
//创建任务,API函数;xTaskCreate 见本人整理文档之FreeRTOS篇【整理以最新版本最优】
xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);
//install gpio isr service
//安装驱动程序的GPIO ISR处理程序服务,该服务允许每个引脚的GPIO中断处理程序。
//该API函数:gpio_install_isr_service,见本人整理文档之GPIO篇【整理版本以最新最优】
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
//hook isr handler for specific gpio pin
//为相应的GPIO引脚添加ISR处理程序。
//该API函数:gpio_isr_handler_add,见本人整理文档之GPIO篇【整理版本以最新最优】
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处理程序。
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);
//设置RTC IO输出电平。
gpio_set_level(GPIO_OUTPUT_IO_0, cnt % 2);
gpio_set_level(GPIO_OUTPUT_IO_1, cnt % 2);
}
}
这个例程,理解起来并不复杂,总的功能就是把 GPIO 18以及GPIO 19设置为输出管脚,输出电平只有0或者1,即搞定电平,根据ESP32 的供电电压,高电平近3.3V ,低电平约为0V。GPIO 4 与GPIO 5为电平输入管脚,即只能体现输入电压为高电平还是低电平,这个应用可以用于 按键输入控制,根据实际电路情况去对应按键的输入输出情况。
需要注意的是基本GPIO(输入&输出)有上拉、下拉的配置,暂时我没有注意到默认是什么模式。如果有认真看过文档知道也可以评论说一下一起进步啊;
除了设置一些基本的GPIO模式外就是Free RTOS的的事情了,这部分我没有好好研读官方文件,之前了解过的也忘得差不多了。就暂时不误人子弟了。看注释就多多少少能理解了。
效果演示的话,参考下面图片。
因为这里延迟了1秒,即方波的频率为0.5HZ,高电平为3.3。
vTaskDelay(1000 / portTICK_RATE_MS);
这边显示的是串口信息,上电打印了部分系统信息外,还输出了GPIO的设置。
将GPIO4 连接到 GPIO19后的实验现象如下