关于ESP32-C3工程的建立
目前为止,我仍然采用的ESPIDF中的example作为一个最基本的工程,然后在此基础上在加以修改(比较笨,之后找到好的办法再说)
Ctrl + shift + p
可以打开VSCODE的交互界面

之后便可以在这其中选择一个作为工程来创建如图

GPIO接口的使用
概述
ESP32-C3 芯片有22 个物理通用输入输出管脚(GPIO Pin)。每个管脚都可用作一个通用IO,或连接一个内部的外设信号。利用GPIO 交换矩阵和IO MUX,可配置外设模块的输入信号来源于任何的IO 管脚,并且外设模块的输出信号也可连接到任意IO 管脚。这些模块共同组成了芯片的IO 控制。
关于IO MUX 以及GPIO 交换矩阵的理解
结合IO MUX 以及 GPIO交换矩阵的主要特性,配合着二者的工作流程图不难看出
GPIO交换矩阵主要起一个中继的作用,外部的输入信号,以及内部的输出信号可以通过GPIO交换矩阵来配置,从而达到外设模块的输入信号可以来源于任何的IO管脚,通过内部信号也可以通过交换矩阵配置从而可以从任意一个PIN脚输出。十分灵活(不同于STM32这类,硬件I2C或者硬件SPI就必须是某几个固定的PIN脚)?
IO MUX的主要作用就是为每个GPIO管脚提供一个寄存器的作用,用来配置各个管脚功能。
并且为了实现更好的高频特性,SPI,UART等相关外设也可以不通过GPIO交换矩阵,直接通过IO MUX与PIN脚相连接。
关于GPIO的电源域
即GPIO0~5都可以作为唤醒引脚
利用GPIO输出点亮一个LED灯
我的板子上是利用这么几个IO口来控制LED灯的。可以很明显的看出,当GPIO为高电平的时候,LED灯会被点亮。
GPIO输出模式的配置过程
利用ESPIDF配置GPIO口是很简单的。
过程如下(最简单的方法)
gpio_pad_select_gpio(GPIO_NUM_5); // 选择一个GPIO
gpio_set_direction(GPIO_NUM_5, GPIO_MODE_OUTPUT); // 把这个GPIO作为输出
gpio_set_level(GPIO_NUM_5, 0); // 设置这个GPIO的高低电平
使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_5); // 选择一个GPIO
gpio_set_direction(GPIO_NUM_5, GPIO_MODE_OUTPUT);// 把这个GPIO作为输出
while(1)
{
gpio_set_level(GPIO_NUM_5, 1); // 把这个GPIO输出低电平
vTaskDelay(1000 / portTICK_PERIOD_MS);
gpio_set_level(GPIO_NUM_5, 0);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
以上涉及了一些FreeRTOS操作系统的相关函数和库,暂时先不用管,之后会做详细记录
只需知道vTaskDelay(1000 / portTICK_PERIOD_MS)
这个函数是延迟1s就完事了。并且这个函数的使用需要FreeRTOS.h
,task.h
,这两个库的支持
测试
利用GPIO的输入功能来检测按键是否按下
我的板子上是使用这么两个IO口来检测按键的输入的。
GPIO9可以正常作为按键输入的检测。但是CHIP_EN脚是用作于ESP32的使能,失能脚,起到的是复位ESP32的作用。
所以这里选择的是GPIO9脚来作为按键输入的判断。(检测到低电平为按键按下)

GPIO输入模式的配置过程
同理,过程如下(简单方法)
gpio_pad_select_gpio(GPIO_NUM_9); // 选择一个GPIO
gpio_set_direction(GPIO_NUM_9, GPIO_MODE_INPUT); // 把这个GPIO作为输入
gpio_get_level(GPIO_NUM_9); //获取GPIO的电平
获取按键是否按下的代码
#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_9);
gpio_set_direction(GPIO_NUM_9, GPIO_MODE_INPUT);
while(1)
{
printf(" Current Gpio9 Level is : %d \r\n\r\n",
gpio_get_level(GPIO_NUM_9)); //获取一次GPIO_NUM_9的电平
vTaskDelay(500 / portTICK_PERIOD_MS); //每500ms检测一次是否有输入
}
}
测试
配置GPIO来检测中断
首先要注意这几个函数
esp_err_t gpio_isr_register(void (*fn)(void *),
void *arg,
int intr_alloc_flags,
gpio_isr_handle_t *handle, )
这个函数是为GPIO中断注册中断处理程序,这个中断程序会在任何GPIO发生中断的时候被调用。(一般情况下就不用这个函数,用下面的方法来配置GPIO的中断)
- Parameters
fn
: 需要调用的中断函数intr_alloc_flags
: 用于分配中断的标志。
arg
: 传入中断函数的参数handle
: 指向中断函数返回的句柄
esp_err_t gpio_install_isr_service(int intr_alloc_flags)
这个函数用来为GPIO驱动注册中断服务,相当于GPIO中断的总开关。但是这个函数与gpio_isr_register
不兼容。这个函数常常与gpio_isr_handler_add
这个函数配合着使用。
其中的参数intr_alloc_flags
相当于中断的优先级等级。也就是说,整个GPIO的外部输入中断的优先级都一样。不过仍然可以在GPIO中断处理函数中进行判断其优先级
esp_err_t gpio_isr_handler_add(gpio_num_tgpio_num,
gpio_isr_tisr_handler,
void *args)
这个函数的作用是为某个GPIO口来绑定一个中断回调函数。
对于中断回调函数而言,不再需要为其声明IRAM_ATTR
标志。 除非在gpio_install_isr_service()
中分配ISR时传递ESP_INTR_FLAG_IRAM
标志。
- Parameters
gpio_num
: GPIO标号isr_handler
: GPIO口的中断回调函数名args
: 传入GPIO口的参数
GPIO中断配置的过程
首先选定一个GPIO口
设置其输入/输出方向
使能其中断
设置中断的触发类型(见下表)
GPIO_INTR_DISABLE //禁用GPIO中断
GPIO_INTR_POSEDGE //GPIO中断类型:上升沿
GPIO_INTR_NEGEDGE //下降沿
GPIO_INTR_ANYEDGE //上升沿和下降沿
GPIO_INTR_LOW_LEVEL //输入低电平触发
GPIO_INTR_HIGH_LEVEL //输入高电平触发
可选:设置GPIO的上下拉是否使能(上拉后,ESP32可以检测到GPIO的下降沿)。
相关函数如下
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);
目的:
利用一个按键通过中断的方式来控制LED的亮灭
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
uint8_t flag;//按键按下标志位
void IRAM_ATTR gpio_isr_handler(void* arg) //GPIO中断回调函数
{
flag = ~flag;
gpio_set_level(GPIO_NUM_5,flag);//使GPIO5的电平翻转一次
}
void app_main(void)
{
//GPIO5------蓝色LED
gpio_pad_select_gpio(GPIO_NUM_5);
gpio_set_direction(GPIO_NUM_5, GPIO_MODE_OUTPUT);
//GPIO9------按键输入中断配置
gpio_pad_select_gpio(GPIO_NUM_9);
gpio_set_direction(GPIO_NUM_9, GPIO_MODE_INPUT);
gpio_intr_enable(GPIO_NUM_9); //使能GPIO9 上的中断
gpio_set_intr_type(GPIO_NUM_9, GPIO_INTR_NEGEDGE); //配置GPIO9 上中断触发源(下降沿)
gpio_pullup_en(GPIO_NUM_9); //对GPIO9 上拉以便于检测到下降沿或者说低电平
//注册中断服务
gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1);
//设置GPIO的中断回调函数
gpio_isr_handler_add(GPIO_NUM_9,gpio_isr_handler,NULL);
while(1)
{
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
具体的整个流程就是
- 配置GPIO为输入模式
- 开启GPIO口中断
- 设置其中断触发源
- 配置其为上拉模式,以便于检测按键的下降沿
- 为GPIO驱动注册中断服务
- 编写GPIO的中断回调函数
- 设置GPIO的中断回调函数与GPIO口中断绑定
测试
函数总结(便于查阅)
gpio_pad_select_gpio(); 用于选择需要配置的GPIO口
gpio_set_direction(); 用于设置GPIO的输入输出等模式
gpio_set_level(); 用于设置GPIO口的电平
gpio_get_level(); 用于获取指定GPIO口的电平
gpio_intr_enable(); 使能选中的GPIO中断
gpio_set_intr_type(); 用于配置选定的GPIO口的中断触发方式
gpio_pullup_en(); 用于使能GPIO口的上拉
gpio_isr_register(); 用于为GPIO口注册中断(不常用)
gpio_install_isr_service(); 用于为GPIO驱动注册中断
gpio_isr_handler_add(); 用于为GPIO口注册中断回调函数
更多详细的GPIO相关函数还请参考:https://docs.espressif.com/projects/esp-idf/zh_CN/release-v4.3/esp32c3/api-reference/peripherals/gpio.html?highlight=gpio#gpio-rtc-gpio