当前位置: 首页 > news >正文

ESP32——基于idf框架开发GPIO设备

文章目录

  • 一、sourceinsight使用smaba访问esp-idf工程
  • 二、编译烧写led闪灯示例
  • 三、GPIO硬件原理
    • 3.1 什么是GPIO
    • 3.2 GPIO 用途
  • 四、GPIO控制器
    • 4.1 什么是控制器
    • 4.2 ESP32-C3 GPIO硬件特性
    • 4.3 获取开发板GPIO设备对应引脚编号
      • 4.3.1 查看开发板底板获取都有那些GPIO设备
      • 4.3.2 查看ESP32-C3-DevKit核心板确定引脚编
      • 4.3.3 查看CPU芯片手册确定引脚编号
  • 五、基于ESP-IDF进行GPIO开发
    • 5.1 ESP-IDF的常用GPIO函数
      • 5.1.1 IOMUX功能配置等函数
      • 5.1.2 GPIO操作的相关函数
    • 5.2 操作一个GPIO设备
      • 5.2.1 配置为输出模式
      • 5.2.2 配置为输入模式
      • 5.2.3 配置为中断模式
    • 5.3 使用gpio config配置GPIO
      • 5.3.1 配置输出模式
      • 5.3.2 配置输入模式
      • 5.3.3 配置为中断模式
    • 5.4 扩展示例
      • 5.4.1 使用GPIO控制直流电机风扇旋转
      • 5.4.2 使用GPIO控制三盏LED灯实现流水灯效果
      • 5.4.3 使用GPIO按键控制GPIO LED灯亮灭
      • 5.4.4 使用FreeRTOS实现按键中断
      • 5.4.5 按键控制风扇转动以及灯亮灭

一、sourceinsight使用smaba访问esp-idf工程

我这里使用的是sourceinsight4.0版本,我们首先需要在电脑上映射一个unubtu的网络磁盘:

  • 查看ubuntu的ip地址在这里插入图片描述
  • 在此电脑处添加网络驱动器在这里插入图片描述
  • 我这里是之前已经创建好的,可以进去查看文件目录,跟ubuntu一致在这里插入图片描述
  • 新建一个sourceinsight工程在这里插入图片描述
  • 代码源地址选择创建好的网络磁盘在这里插入图片描述

后面选中需要的文件和文件夹即可,同时去同步解析源码间的调用关系,工程完成创建:
在这里插入图片描述

二、编译烧写led闪灯示例

找到我们事先写好的 blink 文件夹,将其放到 esp 目录下:
在这里插入图片描述

打印一下 blink.c 查看里面的其他要求:(提示了要去 idf.py menuconfig 图形界面下配置某些引脚)在这里插入图片描述

对芯片进行配置:
在这里插入图片描述

输入 idf.py menuconfig 进入配置,输入 / 出现跳转选项,输入 blink 即可找到引脚配置,将其设置为8:
在这里插入图片描述

输入 idf.py build 编译工程:
在这里插入图片描述

输入 esptool.py -p /dev/ttyUSB0 -b 460800 --before default_reset --after hard_reset --chip esp32c3 write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/blink.bin 将程序烧录到开发板上:
+

烧录完之后LED常亮。

三、GPIO硬件原理

3.1 什么是GPIO

通用输入/输出(GPIO) 是一个数字信号管脚的集成电路,其可被用作输入或输出,GPIO 没有预定义用途。如果使用,GPIO 的用途和行为由电路的设计者定义和实现。

3.2 GPIO 用途

GPIO 用于各种应用,限于 GPIO 接口的电气和时序规范以及软件与 GPIO 及时交互的能力的限制。

GPIO 通常采用标准逻辑电平,不能为输出负载提供大量电流。当后面跟适当的大电流输出缓冲器(或机械或固态继电器)时,GPIO才可用于控制大功率设备,例如灯、螺线管、加热器和电机(如风扇和鼓风机)。类似地,输入缓冲器、继电器或光隔离器通常用于将不兼容的信号(例如,高电压)转换为 GPIO 所需的逻辑电平。

四、GPIO控制器

4.1 什么是控制器

控制器(controller)是依据传感器信号,调整发送至状况的装置。举例来说,屋内的空调系统是一个驱动器的输出信号,用以改变受控体(plant)温度控制器,她可以依据温度计测量的气温,来调整冷气机强度,以达到一个舒适的环境温度。
在这里插入图片描述

4.2 ESP32-C3 GPIO硬件特性

ESP32-C3 系列共有22个GPIO管脚,通过配置对应的寄存器,可以为这些管脚分配不同的功能。除作为数字信号管脚外,部分GPIO管脚也可配置为模拟功能管脚,比如ADC等管脚。

所有GPIO都可选择内部上拉/下拉,或设置为高阻。GPIO配置为输入管脚时,可通过读取寄存器获取其输入值。输入管脚也可经设置产生边缘触发或电平触发的CPU中断。数字IO管脚都是双向、非反相和三态的,包括带有三态控制的输入和输出缓冲器。这些管脚可以复用作其他功能,例如UART、SPI等。当芯片低功耗运行时,GPIO可设定为保持状态。

IOMUX和GPIO交换矩阵用于将信号从外设传输至GPIO管脚。两者共同组成了芯片的IO控制。利用GPIO交换矩阵,可配置外设模块的输入信号来源于任何的IO管脚,并且外设模块的输出信号也可连接到任意IO管脚。下图列出了所有GPIO管脚的IOMUX功能。
在这里插入图片描述

每个管脚复位后的默认配置:

  • 0-输入关闭,高阻(IE=0)
  • 1-输入使能,高阻(IE=1)
  • 2-输入使能,下拉电阻使能(IE=1,WPD=1)
  • 3-输入使能,上拉电阻使能(IE=1,WPU=1)
  • 4-输出使能,上拉电阻使能(OE=1,WPU=1)
  • 0*-输入关闭,上拉电阻使能(IE=0,WPU=0,USB_WPU=1),具体见说明
  • 1*-eFuse的EFUSE_DIS_PAD_JTAG位为0时(初始默认值),管脚复位后输入使能,上拉电阻使能(IE=1,WPU=1)1 时,管脚复位后输入使能,高阻(IE=1)

建议对处于高阻态的管脚配置上拉或下拉,以避免不必要的耗电。

在这里插入图片描述

4.3 获取开发板GPIO设备对应引脚编号

4.3.1 查看开发板底板获取都有那些GPIO设备

查看 ESP32_Extend_V2.pdf 百问网独家底板原理图文件,可以看到如下图所示红框内的这几个引脚标号 都是GPIO设备。
在这里插入图片描述

通过搜索可以看到这些引脚都连接到了 ESP32连接排座 ,其中ESP32连接排座又连接至了核心板的两排接口处,可以参考下表对应一下。
在这里插入图片描述

4.3.2 查看ESP32-C3-DevKit核心板确定引脚编

获取信息页面:https://docs.espressif.com/projects/esp-dev-kits/zh_CN/latest/esp32c3/esp32-c3-devkitc-02/index.html#id21
在这里插入图片描述

也可以打开 SCH_ESP32-C3-DEVKITC-02_V1_1_20210126A.pdf 原理图文件,来确认那几个GPIO引脚连接到了模组那些引脚上。
在这里插入图片描述

继续阅读模组手册 esp32-c3-wroom-02_datasheet_cn.pdf 来确认接到了CPU上具体引脚。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.3.3 查看CPU芯片手册确定引脚编号

参考 esp32-c3_datasheet_cn.pdf 手册具体名称为 ESP32-C3 系列芯片技术规格书V1.0
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、基于ESP-IDF进行GPIO开发

5.1 ESP-IDF的常用GPIO函数

参考网址:https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32c3/api-reference/peripherals/gpio.html

5.1.1 IOMUX功能配置等函数

参考文件 esp-idf\components\esp_rom\include\esp32c3\rom\gpio.h

/*** @brief 配置某个引脚为GPIO功能** @param uint32_t gpio_num : gpio number, 0~0x27** @return None*/
void gpio_pad_select_gpio(uint8_t gpio_num);

5.1.2 GPIO操作的相关函数

参考文件 esp-idf\components\driver\include\driver\gpio.h

/*** @brief 配置 GPIO 通用参数** 配置 GPIO 的工作模式、上拉/下拉电阻以及中断触发类型** @param  pGPIOConfig 指向 GPIO 配置结构体的指针** @return*     - ESP_OK 配置成功*     - ESP_ERR_INVALID_ARG 参数错误*/
esp_err_t gpio_config(const gpio_config_t *pGPIOConfig);/*** @brief 将 GPIO 重置为默认状态(选择 GPIO 功能,启用上拉,禁用输入和输出)** @param gpio_num GPIO 编号** @note 此函数还会将该引脚的 IOMUX 配置为 GPIO 功能,*       并断开通过 GPIO 矩阵配置的任何其他外设输出** @return 始终返回 ESP_OK*/
esp_err_t gpio_reset_pin(gpio_num_t gpio_num);/*** @brief 设置 GPIO 中断触发类型** @param  gpio_num GPIO 编号。例如,若要设置 GPIO16 的触发类型,*                  则 gpio_num 应为 GPIO_NUM_16 (16)* @param  intr_type 中断触发类型,从 gpio_int_type_t 中选择** @return*     - ESP_OK 成功*     - ESP_ERR_INVALID_ARG 参数错误*/
esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type);/*** @brief 设置 GPIO 输出电平** @param  gpio_num GPIO 编号。例如,若要设置 GPIO16 的输出电平,*                  则 gpio_num 应为 GPIO_NUM_16 (16)* @param  level 输出电平。0: 低电平; 1: 高电平** @return*     - ESP_OK 成功*     - ESP_ERR_INVALID_ARG GPIO 编号错误*/
esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level);/*** @brief 获取 GPIO 输入电平** @warning 如果该引脚未配置为输入(或输入输出)模式,返回值始终为 0** @param  gpio_num GPIO 编号。例如,若要获取 GPIO16 的逻辑电平,*                  则 gpio_num 应为 GPIO_NUM_16 (16)** @return*     - 0 GPIO 输入电平为 0*     - 1 GPIO 输入电平为 1*/
int gpio_get_level(gpio_num_t gpio_num);/*** @brief 设置 GPIO 方向** 配置 GPIO 的方向,如仅输出、仅输入、输入输出双向** @param  gpio_num 配置的 GPIO 引脚编号。例如,若要设置 GPIO16 的方向,*                  则 gpio_num 应为 GPIO_NUM_16 (16)* @param  mode GPIO 方向模式** @return*     - ESP_OK 成功*     - ESP_ERR_INVALID_ARG GPIO 错误*/
esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode);/*** @brief 启用 GPIO 上拉电阻** @param gpio_num GPIO 编号** @return*     - ESP_OK 成功*     - ESP_ERR_INVALID_ARG 参数错误*/
esp_err_t gpio_pullup_en(gpio_num_t gpio_num);/*** @brief 禁用 GPIO 上拉电阻** @param gpio_num GPIO 编号** @return*     - ESP_OK 成功*     - ESP_ERR_INVALID_ARG 参数错误*/
esp_err_t gpio_pullup_dis(gpio_num_t gpio_num);/*** @brief 启用 GPIO 下拉电阻** @param gpio_num GPIO 编号** @return*     - ESP_OK 成功*     - ESP_ERR_INVALID_ARG 参数错误*/
esp_err_t gpio_pulldown_en(gpio_num_t gpio_num);/*** @brief 禁用 GPIO 下拉电阻** @param gpio_num GPIO 编号** @return*     - ESP_OK 成功*     - ESP_ERR_INVALID_ARG 参数错误*/
esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num);/*** @brief 安装驱动的 GPIO 中断服务程序,支持为每个引脚设置独立的中断处理函数** 此函数与 gpio_isr_register() 不兼容 - 如果使用了 gpio_isr_register(),* 则为所有 GPIO 中断注册一个全局中断处理函数;如果使用此函数,* 中断服务程序会提供一个全局 GPIO 中断处理函数,* 并通过 gpio_isr_handler_add() 函数注册各个引脚的处理函数** @param intr_alloc_flags 用于分配中断的标志。可以是一个或多个标志的按位或** @return*     - ESP_OK 成功*     - ESP_ERR_NO_MEM 没有足够内存安装此服务*     - ESP_ERR_INVALID_STATE 中断服务已安装*     - ESP_ERR_NOT_FOUND 未找到符合指定标志的空闲中断*     - ESP_ERR_INVALID_ARG GPIO 错误*/
esp_err_t gpio_install_isr_service(int intr_alloc_flags);/*** @brief 卸载驱动的 GPIO 中断服务程序,释放相关资源*/
void gpio_uninstall_isr_service(void);/*** @brief 为相应的 GPIO 引脚添加中断处理函数** 在使用 gpio_install_isr_service() 安装驱动的 GPIO 中断服务程序后调用此函数** 引脚中断处理函数不再需要声明为 IRAM_ATTR,* 除非在 gpio_install_isr_service() 分配中断时传递了 ESP_INTR_FLAG_IRAM 标志** 此中断处理函数将从中断服务程序中调用,因此存在堆栈大小限制* (可在 menuconfig 中配置为 "ISR 堆栈大小")* 由于额外的间接调用层级,此限制比全局 GPIO 中断处理函数的限制更小** @param gpio_num GPIO 编号* @param isr_handler 对应 GPIO 编号的中断处理函数* @param args 传递给中断处理函数的参数** @return*     - ESP_OK 成功*     - ESP_ERR_INVALID_STATE 状态错误,中断服务未初始化*     - 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 引脚的中断处理函数** @param gpio_num GPIO 编号** @return*     - ESP_OK 成功*     - ESP_ERR_INVALID_STATE 状态错误,中断服务未初始化*     - ESP_ERR_INVALID_ARG 参数错误*/
esp_err_t gpio_isr_handler_remove(gpio_num_t gpio_num);

5.2 操作一个GPIO设备

  • 硬件&手册资源准备
    • 准备好开发板硬件以及GPIO模块 并连接成功
    • 提前下载好GPIO模块配套的原理图芯片手册等资料
    • 提前准备好CPU开发板配套的原理图 芯片手册等资料
  • 基础知识
    • 了解GPIO硬件通信原理
    • 清楚GPIO模块与CPU引脚连接编号
    • 熟悉ESP-IDF GPIO SDK开发介绍

5.2.1 配置为输出模式

在这里插入图片描述

GPIO配置输出模式流程图
在这里插入图片描述

点亮白色LED灯:

#include <stdio.h>#include <unistd.h>
#include "driver/gpio.h"#define WHITE_LED 5	//LED灯引脚为5void app_main(void)
{gpio_reset_pin(WHITE_LED);				// 复位引脚gpio_pad_select_gpio(WHITE_LED);		// 设置引脚为GPIO功能gpio_set_direction(WHITE_LED, GPIO_MODE_OUTPUT);	// 设置该引脚为输出模式int on = 0;while (1){on = !on;gpio_set_level(WHITE_LED, on);	//设置引脚电平sleep(1);}
}

设置环境变量:

get_idf

设置芯片为 esp32c3:

idf.py set-target esp32c3

编译命令:

idf.py build

烧写(两种方法):

esptool.py -p /dev/ttyUSB0  -b 460800 --before default_reset --after hard_reset --chip esp32c3  write_flash --flash_mode dio -- flash_size detect --flash_freq 80m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/blink.bin
idf.py -p /dev/ttyUSB0 flash

在这里插入图片描述
此时板子上白色LED开始闪烁。

监控:

idf.py -p /dev/ttyUSB0 monitor   

5.2.2 配置为输入模式

在这里插入图片描述

对于输入模式,我们需要设置为上拉模式或者下拉模式:

  • PULLUP&PULLDOWN针对输入模式,比如我们一个单片机的I / O脚接一个按键的左端,按键的右端接正电源,那么我们就要设置I / O脚为下拉模式,因为这样才能使得按键按下去的时候,能把I / O脚拉高,不然设置上拉模式的话,即按键的功能等于摆设。同理,如果按键另一端接地,我们就要设置为上拉模式了。在这里插入图片描述
  • 按键默认情况下是低电平,那么如何区分按键按下或者松开 ? 此时需要高低电平的变化 也就是需要GPIO内部作为输入时 需要有一个上拉电阻 来区分按键按下与松开,当按键按下时,是由高变低也就是低电平;松开时,由低变高也就是高电平。在这里插入图片描述

在这里插入图片描述

#include <stdio.h>
#include <unistd.h>
#include "driver/gpio.h"#define KEY1_BUTTON 18	// 开发板Key1为GPIO19void app_main()
{gpio_pad_select_gpio(KEY1_BUTTON);		// 设置引脚为GPIO功能gpio_set_direction(KEY1_BUTTON, GPIO_MODE_INPUT);	//设置KEY1引脚为输入功能//gpio_pulldown_en(KEY1_BUTTON);//启用下拉电阻gpio_pullup_en(KEY1_BUTTON);	// 启用上拉电阻(默认高电平)//gpio_pullup_dis(KEY1_BUTTON);	// 禁用上拉电阻gpio_pulldown_dis(KEY1_BUTTON);	// 禁用下拉电阻while (true){// 读取GPIO电平状态(0=低电平,1=高电平)int level = gpio_get_level(KEY1_BUTTON);printf("Key1 status %d\n\r",level);sleep(1);}
}

设置环境变量:

get_idf

设置芯片为 esp32c3:

idf.py set-target esp32c3

编译命令:

idf.py build

烧写(两种方法):

esptool.py -p /dev/ttyUSB0  -b 460800 --before default_reset --after hard_reset --chip esp32c3  write_flash --flash_mode dio -- flash_size detect --flash_freq 80m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/blink.bin
idf.py -p /dev/ttyUSB0 flash

在这里插入图片描述

监控:

idf.py -p /dev/ttyUSB0 monitor   

在这里插入图片描述
按键按下时,key1 status=0,松开后key1 status=1。

5.2.3 配置为中断模式

中断讲解:

  • 取个场景解释中断。假设有个大房间里面有小房间,婴儿正在睡觉,他的妈妈在外面看书。
  • 问:这个母亲怎么才能知道这个小孩醒?
  • 方法1:过一会打开一次房门,看婴儿是否睡醒,让后接着看书
  • 方法2: 一直等到婴儿发出声音以后再过去查看,期间都在读书

第一种 叫做查询方式:

  • 优点:简单 缺点: 累

程序中会这样体现:

while(1)
{1 read book(读书)2 open door(开门)if()return(read book)else照顾小孩
}

第二种叫中断方式:

  • 优点:不累 缺点:复杂

程序中应该这样体现:

中断服务程序()
{照顾小孩....
}main()
{register_irq(中断服务程序);while (1){read book; // 读书过程中被哭声打断,就去照顾小孩}
}

GPIO中断操作流程
在这里插入图片描述

配置按键中断为双边沿出发方式来打印按键值:

#include <stdio.h>
#include "driver/gpio.h"
#include "esp_rom_sys.h"#define KEY1_BUTTON 18	// 定义按键连接的GPIO引脚号// 定义GPIO中断服务函数的参数结构体
typedef struct {int gpio_num;	// GPIO引脚编号int isr_cnt;	// 中断触发计数器
} gpio_isr_param_t;static void gpio_isr_handler(void* arg)
{// 将参数转换为结构体指针gpio_isr_param_t *param = (gpio_isr_param_t *)arg;// 打印触发中断的GPIO引脚号及其当前电平esp_rom_printf("GPIO[%d] intr, val: %d\n", param->gpio_num, gpio_get_level(param->gpio_num));// 中断计数器递增param->isr_cnt++;
}void app_main()
{static gpio_isr_param_t io18_param = {.gpio_num =  KEY1_BUTTON,	// 配置为KEY1_BUTTON对应的引脚.isr_cnt = 0,				// 初始化中断计数为0};gpio_pad_select_gpio(KEY1_BUTTON);	// 选择GPIO引脚gpio_set_direction(KEY1_BUTTON, GPIO_MODE_INPUT);	// 设置为输入模式gpio_pulldown_dis(KEY1_BUTTON);	// 禁用下拉电阻gpio_pullup_en(KEY1_BUTTON);	// 启用上拉电阻gpio_set_intr_type(KEY1_BUTTON, GPIO_INTR_ANYEDGE);	// 配置中断触发方式为任意边沿触发(上升沿+下降沿)// 安装GPIO中断服务// 注意:ESP32中必须先调用此函数才能注册具体引脚的中断处理函数gpio_install_isr_service(0);// 为指定GPIO引脚添加中断处理函数gpio_isr_handler_add(KEY1_BUTTON, gpio_isr_handler, (void *)&io18_param);
}

设置环境变量:

get_idf

设置芯片为 esp32c3:

idf.py set-target esp32c3

编译命令:

idf.py build

烧写(两种方法):

esptool.py -p /dev/ttyUSB0  -b 460800 --before default_reset --after hard_reset --chip esp32c3  write_flash --flash_mode dio -- flash_size detect --flash_freq 80m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/blink.bin
idf.py -p /dev/ttyUSB0 flash

监控:

idf.py -p /dev/ttyUSB0 monitor   

在这里插入图片描述

5.3 使用gpio config配置GPIO

在这里插入图片描述

5.3.1 配置输出模式

点亮 白色LED1:

#include <stdio.h>
#include <unistd.h>
#include "driver/gpio.h"// 定义白色LED连接的GPIO引脚
#define WHITE_LED 5void app_main(void)
{// 定义GPIO配置结构体gpio_config_t io_conf;// 配置项1:禁用GPIO中断(不使用中断,仅通过轮询控制)io_conf.intr_type = GPIO_INTR_DISABLE;// 配置项2:设置GPIO为输出模式io_conf.mode = GPIO_MODE_OUTPUT;// 配置项3:设置要配置的GPIO引脚位掩码(使用位移操作指定引脚)io_conf.pin_bit_mask = (1ULL << WHITE_LED);// 配置项4:禁用下拉电阻(确保无下拉影响)io_conf.pull_down_en = 0;// 配置项5:禁用上拉电阻(输出模式通常不需要上拉/下拉)io_conf.pull_up_en = 0;// 将上述配置应用到GPIO控制器gpio_config(&io_conf);// LED状态变量(0=灭,1=亮)int on = 0;// 无限循环:实现LED闪烁效果while (1){// 切换LED状态(亮→灭 或 灭→亮)on = !on;// 设置GPIO输出电平gpio_set_level(WHITE_LED, on);// 延时1秒(注意:此处使用标准库sleep,在ESP32中建议使用vTaskDelay)sleep(1);}
}

设置环境变量:

get_idf

设置芯片为 esp32c3:

idf.py set-target esp32c3

编译命令:

idf.py build

烧写(两种方法):

esptool.py -p /dev/ttyUSB0  -b 460800 --before default_reset --after hard_reset --chip esp32c3  write_flash --flash_mode dio -- flash_size detect --flash_freq 80m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/blink.bin
idf.py -p /dev/ttyUSB0 flash

烧写后白色LED灯不断闪烁。

监控:

idf.py -p /dev/ttyUSB0 monitor   

5.3.2 配置输入模式

配置为输入模式 设置为双边沿触发 并打印按键状态。

#include <stdio.h>
#include <unistd.h>
#include "driver/gpio.h"// 定义按键连接的GPIO引脚号
#define KEY1_BUTTON 18void app_main(void)
{// 定义GPIO配置结构体gpio_config_t io_conf;// 配置项1:禁用GPIO中断(使用轮询方式检测按键)io_conf.intr_type = GPIO_INTR_DISABLE;// 配置项2:设置GPIO模式为输入模式io_conf.mode = GPIO_MODE_INPUT;// 配置项3:设置要配置的GPIO引脚位掩码(使用位移操作指定引脚)io_conf.pin_bit_mask = (1ULL << KEY1_BUTTON);// 配置项4:禁用下拉电阻(确保无下拉影响)io_conf.pull_down_en = 0;// 配置项5:启用上拉电阻(使引脚在无输入时保持高电平)io_conf.pull_up_en = 1;// 将上述配置应用到GPIO控制器gpio_config(&io_conf);// 无限循环:持续检测并打印按键状态while (1){// 读取当前GPIO引脚电平(0=低电平,1=高电平)int level = gpio_get_level(KEY1_BUTTON);// 打印按键状态(\n\r组合确保在不同终端上正确换行)printf("Key1 status %d\n\r", level);// 延时1秒(注意:此处使用标准库sleep,在ESP32中建议使用vTaskDelay)sleep(1);}
}

设置环境变量:

get_idf

设置芯片为 esp32c3:

idf.py set-target esp32c3

编译命令:

idf.py build

烧写(两种方法):

esptool.py -p /dev/ttyUSB0  -b 460800 --before default_reset --after hard_reset --chip esp32c3  write_flash --flash_mode dio -- flash_size detect --flash_freq 80m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/blink.bin
idf.py -p /dev/ttyUSB0 flash

监控:

idf.py -p /dev/ttyUSB0 monitor   

在这里插入图片描述

5.3.3 配置为中断模式

#include <stdio.h>
#include "driver/gpio.h"
#include "esp_rom_sys.h"// 定义按键连接的GPIO引脚号
#define KEY1_BUTTON 18// 定义GPIO中断服务函数的参数结构体
typedef struct {int gpio_num;      // GPIO引脚编号int isr_cnt;       // 中断触发计数器
} gpio_isr_param_t;static void gpio_isr_handler(void* arg)
{// 将参数转换为结构体指针gpio_isr_param_t *param = (gpio_isr_param_t *)arg;// 打印触发中断的GPIO引脚号及其当前电平esp_rom_printf("GPIO[%d] intr, val: %d\n", param->gpio_num, gpio_get_level(param->gpio_num));// 中断计数器递增param->isr_cnt++;
}/*** 应用程序主入口函数*/
void app_main()
{// 静态初始化GPIO参数结构体static gpio_isr_param_t io18_param = {.gpio_num =  KEY1_BUTTON,  // 配置为KEY1_BUTTON对应的引脚.isr_cnt = 0,              // 初始化中断计数为0};// 定义GPIO配置结构体gpio_config_t config;// 配置中断触发类型为双边沿触发(上升沿和下降沿都触发)config.intr_type = GPIO_INTR_ANYEDGE;// 配置GPIO为输入模式config.mode = GPIO_MODE_INPUT;// 禁用下拉电阻(确保无下拉影响)config.pull_down_en = false;// 启用上拉电阻(使引脚在无输入时保持高电平)config.pull_up_en = true;// 设置要配置的GPIO引脚位掩码(使用位移操作指定引脚)config.pin_bit_mask = (1ULL<<KEY1_BUTTON);// 将上述配置应用到GPIO控制器gpio_config(&config);// 安装GPIO中断服务(必须先调用此函数才能注册具体引脚的中断处理函数)// 参数0表示使用默认配置gpio_install_isr_service(0);// 为指定GPIO引脚添加中断处理函数// 参数1:GPIO引脚号// 参数2:中断处理函数指针// 参数3:传递给中断处理函数的参数gpio_isr_handler_add(KEY1_BUTTON, gpio_isr_handler, (void *)&io18_param);// 主函数执行完毕后,系统进入后台运行,中断服务函数会在触发时自动执行
}

设置环境变量:

get_idf

设置芯片为 esp32c3:

idf.py set-target esp32c3

编译命令:

idf.py build

烧写(两种方法):

esptool.py -p /dev/ttyUSB0  -b 460800 --before default_reset --after hard_reset --chip esp32c3  write_flash --flash_mode dio -- flash_size detect --flash_freq 80m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/blink.bin
idf.py -p /dev/ttyUSB0 flash

监控:

idf.py -p /dev/ttyUSB0 monitor   

在这里插入图片描述

5.4 扩展示例

5.4.1 使用GPIO控制直流电机风扇旋转

  • 功能特点:
    • 产品尺寸:50x27x13mm
    • 螺旋桨直径:75mm
    • 工作电压:5V
    • L9110驱动,可控制正反转配有安装孔,兼容舵机舵盘控制优质螺旋桨,效率高。可轻松吹灭20cm外的打火机火焰可用于救火机器人的制作,机器人设计开发必备
  • 模块的VCC接5V, GND接GND,INA接数字接口GPIO1,INB接数字接口GPIO0 其中控制风扇转动方式请参考下述表格。

在这里插入图片描述
在这里插入图片描述

注意: 一定要先断开电源再接 风扇模块 否则会导致 开发板芯片损坏。

#include <stdio.h>
#include <unistd.h>
#include "driver/gpio.h"// 定义电机控制引脚
#define MOTOR_INA 1    // 电机方向控制引脚A
#define MOTOR_INB 0    // 电机方向控制引脚Bvoid app_main(void)
{// 选择GPIO引脚作为输出功能gpio_pad_select_gpio(MOTOR_INA);gpio_pad_select_gpio(MOTOR_INB);// 配置GPIO方向为输出模式gpio_set_direction(MOTOR_INA, GPIO_MODE_OUTPUT);gpio_set_direction(MOTOR_INB, GPIO_MODE_OUTPUT);// 无限循环:持续控制电机运行while (1){/* 正转控制 */// INA=0, INB=1: 电机正转gpio_set_level(MOTOR_INA, 0);gpio_set_level(MOTOR_INB, 1);sleep(3);  // 保持正转3秒/* 反转控制 */// INA=1, INB=0: 电机反转gpio_set_level(MOTOR_INA, 1);gpio_set_level(MOTOR_INB, 0);sleep(3);  // 保持反转3秒/* 停止控制 */// INA=1, INB=1: 电机停止(根据H桥驱动特性)gpio_set_level(MOTOR_INA, 1);gpio_set_level(MOTOR_INB, 1);sleep(3);  // 保持停止3秒}
}

设置环境变量:

get_idf

设置芯片为 esp32c3:

idf.py set-target esp32c3

编译命令:

idf.py build

烧写(两种方法):

esptool.py -p /dev/ttyUSB0  -b 460800 --before default_reset --after hard_reset --chip esp32c3  write_flash --flash_mode dio -- flash_size detect --flash_freq 80m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/blink.bin
idf.py -p /dev/ttyUSB0 flash

监控:

idf.py -p /dev/ttyUSB0 monitor   

5.4.2 使用GPIO控制三盏LED灯实现流水灯效果

#include <stdio.h>
#include <unistd.h>
#include "driver/gpio.h"// 定义三个LED连接的GPIO引脚
#define WHITE_LED 5    // 白色LED连接到GPIO5
#define BLUE_LED  8    // 蓝色LED连接到GPIO8
#define GREEN_LED 10   // 绿色LED连接到GPIO10void app_main(void)
{// 选择并配置GPIO引脚为输出模式gpio_pad_select_gpio(WHITE_LED);gpio_pad_select_gpio(BLUE_LED);gpio_pad_select_gpio(GREEN_LED);gpio_set_direction(WHITE_LED, GPIO_MODE_OUTPUT);gpio_set_direction(BLUE_LED, GPIO_MODE_OUTPUT);gpio_set_direction(GREEN_LED, GPIO_MODE_OUTPUT);int on = 0;  // LED状态变量(0=灭,1=亮)// 无限循环:实现LED流水灯效果while (1){on = !on;  // 切换LED状态(亮→灭 或 灭→亮)// 控制白色LEDgpio_set_level(WHITE_LED, on);usleep(200000);  // 延时200毫秒// 控制蓝色LEDgpio_set_level(BLUE_LED, on);usleep(200000);  // 延时200毫秒// 控制绿色LEDgpio_set_level(GREEN_LED, on);usleep(200000);  // 延时200毫秒}
}

设置环境变量:

get_idf

设置芯片为 esp32c3:

idf.py set-target esp32c3

编译命令:

idf.py build

烧写(两种方法):

esptool.py -p /dev/ttyUSB0  -b 460800 --before default_reset --after hard_reset --chip esp32c3  write_flash --flash_mode dio -- flash_size detect --flash_freq 80m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/blink.bin
idf.py -p /dev/ttyUSB0 flash

监控:

idf.py -p /dev/ttyUSB0 monitor   

5.4.3 使用GPIO按键控制GPIO LED灯亮灭

使用KEY1按键来控制WIHTE LED的亮灭 其中按下按键灯亮 松开按键灯灭。

#include <stdio.h>
#include <unistd.h>
#include "driver/gpio.h"// 定义按键和LED连接的GPIO引脚
#define KEY1_BUTTON 18   // 按键连接到GPIO18
#define WHITE_LED  5    // 白色LED连接到GPIO5void app_main()
{// 配置LED引脚为输出模式gpio_pad_select_gpio(WHITE_LED);gpio_set_direction(WHITE_LED, GPIO_MODE_OUTPUT);// 配置按键引脚为输入模式gpio_pad_select_gpio(KEY1_BUTTON);gpio_set_direction(KEY1_BUTTON, GPIO_MODE_INPUT);gpio_pullup_en(KEY1_BUTTON);    // 启用上拉电阻gpio_pulldown_dis(KEY1_BUTTON); // 禁用下拉电阻// 无限循环:持续检测按键状态并控制LEDwhile (true){// 读取按键引脚电平(0=按下,1=释放)int level = gpio_get_level(KEY1_BUTTON);// 将按键状态直接映射到LED(按下点亮,释放熄灭)gpio_set_level(WHITE_LED, level);// 延时1秒(降低CPU使用率,但会影响响应速度)sleep(1);}
}

设置环境变量:

get_idf

设置芯片为 esp32c3:

idf.py set-target esp32c3

编译命令:

idf.py build

烧写(两种方法):

esptool.py -p /dev/ttyUSB0  -b 460800 --before default_reset --after hard_reset --chip esp32c3  write_flash --flash_mode dio -- flash_size detect --flash_freq 80m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/blink.bin
idf.py -p /dev/ttyUSB0 flash

监控:

idf.py -p /dev/ttyUSB0 monitor   

5.4.4 使用FreeRTOS实现按键中断

基于freertos来实现一个中断处理函数处理按键消息队列。

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"#define KEY1_BUTTON 18   // 定义按键连接的GPIO引脚
#define WHITE_LED   5    // 定义LED连接的GPIO引脚(代码中缺少此定义)xQueueHandle interputQueue;  // 定义中断消息队列句柄static void IRAM_ATTR gpio_isr_handler(void *args)
{int pinNumber = (int)args;// 将触发中断的引脚号发送到队列中xQueueSendFromISR(interputQueue, &pinNumber, NULL);
}void buttonPushedTask(void *params)
{int pinNumber, count = 0;  // 引脚号和按下计数while (true){// 阻塞等待队列消息(portMAX_DELAY表示永久等待)if (xQueueReceive(interputQueue, &pinNumber, portMAX_DELAY)){// 点亮LEDgpio_set_level(WHITE_LED, 1);// 打印按键信息(包括引脚号、按下次数和当前引脚电平)printf("GPIO %d was pressed %d times. The state is %d\n", pinNumber, count++, gpio_get_level(KEY1_BUTTON));}}
}void app_main()
{// 配置按键引脚gpio_pad_select_gpio(KEY1_BUTTON);gpio_set_direction(KEY1_BUTTON, GPIO_MODE_INPUT);gpio_pullup_en(KEY1_BUTTON);     // 启用上拉电阻gpio_pulldown_dis(KEY1_BUTTON);  // 禁用下拉电阻// 设置中断触发类型为双边沿(上升沿+下降沿)gpio_set_intr_type(KEY1_BUTTON, GPIO_INTR_ANYEDGE);// 创建消息队列(最多存储10个int类型数据)interputQueue = xQueueCreate(10, sizeof(int));// 创建按键处理任务xTaskCreate(buttonPushedTask, "buttonPushedTask", 2048, NULL, 1, NULL);// 安装GPIO中断服务(必须先调用此函数才能注册具体引脚的中断处理函数)gpio_install_isr_service(0);// 为指定GPIO引脚添加中断处理函数gpio_isr_handler_add(KEY1_BUTTON, gpio_isr_handler, (void *)KEY1_BUTTON);
}

设置环境变量:

get_idf

设置芯片为 esp32c3:

idf.py set-target esp32c3

编译命令:

idf.py build

烧写(两种方法):

esptool.py -p /dev/ttyUSB0  -b 460800 --before default_reset --after hard_reset --chip esp32c3  write_flash --flash_mode dio -- flash_size detect --flash_freq 80m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/blink.bin
idf.py -p /dev/ttyUSB0 flash

监控:

idf.py -p /dev/ttyUSB0 monitor   

在这里插入图片描述

5.4.5 按键控制风扇转动以及灯亮灭

#include <stdio.h>
#include <unistd.h>
#include "driver/gpio.h"// 定义电机控制引脚
#define MOTOR_INA 1    // 电机方向控制引脚A
#define MOTOR_INB 0    // 电机方向控制引脚B
#define BLUE_LED  8    // 蓝色LED连接到GPIO8
#define GREEN_LED 10   // 绿色LED连接到GPIO10
#define KEY1_BUTTON 18   // 按键连接到GPIO18
#define KEY2_BUTTON 19   // 按键连接到GPIO19void app_main(void)
{// 选择GPIO引脚作为输出功能gpio_pad_select_gpio(MOTOR_INA);gpio_pad_select_gpio(MOTOR_INB);gpio_pad_select_gpio(BLUE_LED);gpio_pad_select_gpio(GREEN_LED);// 配置GPIO方向为输出模式gpio_set_direction(MOTOR_INA, GPIO_MODE_OUTPUT);gpio_set_direction(MOTOR_INB, GPIO_MODE_OUTPUT);gpio_set_direction(BLUE_LED, GPIO_MODE_OUTPUT);gpio_set_direction(GREEN_LED, GPIO_MODE_OUTPUT);// 配置按键引脚为输入模式gpio_pad_select_gpio(KEY2_BUTTON);gpio_set_direction(KEY2_BUTTON, GPIO_MODE_INPUT);gpio_pullup_en(KEY2_BUTTON);    // 启用上拉电阻gpio_pulldown_dis(KEY2_BUTTON); // 禁用下拉电阻// 配置按键引脚为输入模式gpio_pad_select_gpio(KEY1_BUTTON);gpio_set_direction(KEY1_BUTTON, GPIO_MODE_INPUT);gpio_pullup_en(KEY1_BUTTON);    // 启用上拉电阻gpio_pulldown_dis(KEY1_BUTTON); // 禁用下拉电阻    // 初始化状态:风扇不转(INA=1, INB=1),蓝灯灭(LED=1),绿灯灭(LED=1)gpio_set_level(MOTOR_INA, 1);gpio_set_level(MOTOR_INB, 1);gpio_set_level(BLUE_LED, 1);gpio_set_level(GREEN_LED, 1);while (true){// 读取按键状态(0=按下,1=未按下)int level1 = gpio_get_level(KEY1_BUTTON);int level2 = gpio_get_level(KEY2_BUTTON);// 按键2按下if (level2 == 0) {// 电机正转,蓝灯亮gpio_set_level(MOTOR_INA, 0);gpio_set_level(MOTOR_INB, 1);gpio_set_level(BLUE_LED, 0);}else if (level1 == 0){// 电机反转,绿灯亮gpio_set_level(MOTOR_INA, 1);gpio_set_level(MOTOR_INB, 0);gpio_set_level(GREEN_LED, 0);        	}else{// 无按键按下:风扇停止,蓝灯灭,绿灯灭gpio_set_level(MOTOR_INA, 1);gpio_set_level(MOTOR_INB, 1);gpio_set_level(BLUE_LED, 1);	gpio_set_level(GREEN_LED, 1);}}
}

设置环境变量:

get_idf

设置芯片为 esp32c3:

idf.py set-target esp32c3

编译命令:

idf.py build

烧写(两种方法):

esptool.py -p /dev/ttyUSB0  -b 460800 --before default_reset --after hard_reset --chip esp32c3  write_flash --flash_mode dio -- flash_size detect --flash_freq 80m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/blink.bin
idf.py -p /dev/ttyUSB0 flash

监控:

idf.py -p /dev/ttyUSB0 monitor   

按下按键1,电机反转并且绿灯亮;按下按键2,电机正转并且蓝灯亮。

http://www.dtcms.com/a/283495.html

相关文章:

  • 高性能架构模式——高性能NoSQL
  • 如何打造全场景数字化OA办公平台?
  • 网络(数据库1)
  • oracle2kingbase的字段长度问题
  • STM32外设介绍4(ADC)
  • Windows11怎样禁止应用开机启动
  • 评估遥感云雾浓度的无参化指标(适用于其它合成雾的场景)
  • 【JVM】内存分配与回收原则
  • leetcode 3201. 找出有效子序列的最大长度 I II
  • 演示数据库操作
  • 测试学习之——Pytest Day2
  • 《十万线段绘乾坤:Canvas离屏渲染深度剖析》
  • 低代码深度切入制造业需求的实践路径
  • 在 CentOS 8 上彻底卸载 Kubernetes(k8s)
  • 每日钉钉API探索:requestAuthCode网页应用(H5微应用)免登授权
  • 【leetcode】1422. 分割字符串的最大得分
  • 创建SprngBoot项目的四种方式
  • FreeRTOS中断管理STM32
  • 【Java】【力扣】20.有效的括号
  • 基于迁移学习的培养基配方开发方法
  • XSS-LABS的Level1-8
  • Python —— 真题三
  • NumPy 详解
  • 【static 修饰局部变量、全局变量、函数】
  • Swift6.0 - 5、基本运算符
  • 账户和组管理
  • JavaEE——死锁
  • PowerBI实现仅在需要图表时显示图表
  • 傅里叶变换算子性质证明
  • GTSuite许可管理常见问题及解决方案