提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
记录一下,对知识的整理和复习,方便你我他。。。
只是记录的外设的API函数的使用,外设知识不介绍。
IDF版本V5.1.2
一、需要的头文件
#include "driver/gpio.h"
#include "esp_attr.h"
二、API
/*
函数: gpio_config
功能: gpio通用配置函数
输入: pGPIOConfig:结构体
返回值: ESP_OK:成功;其它:失败
*/
esp_err_t gpio_config(const gpio_config_t *pGPIOConfig)
/*
函数: gpio_set_intr_type
功能: 单独设置中断的触发类型
输入: gpio_num:要配置的引脚号;intr_type:触发类型(枚举值)
返回值: ESP_OK:成功;其它:失败
*/
esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type)
/*
函数: gpio_install_isr_service
功能: 安装GPIO中断服务 -> 分配中断标志,与gpio_isr_register()有冲突。
输入: intr_alloc_flags:中断标志
返回值: ESP_OK:成功;其它:失败
*/
esp_err_t gpio_install_isr_service(int intr_alloc_flags);
/*
函数: gpio_isr_handler_add
功能: 给GPIO添加中断服务函数,可以把多个GPIO的中断服务添加在同一个函数中,用传的引脚号来做区分。猜测是因为中断标志有限才这样做的
输入: gpio_num:引脚号,isr_handler:中断服务函数,args:数据用来区分是哪个引脚触发的
返回值: ESP_OK:成功;其它:失败
*/
esp_err_t gpio_isr_handler_add(gpio_num_t gpio_num, gpio_isr_t isr_handler, void *args);
/*
函数: gpio_isr_handler_add
功能:删除对应GPIO引脚的ISR处理程序。
输入: gpio_num:引脚号
返回值: ESP_OK:成功;其它:失败
*/
esp_err_t gpio_isr_handler_remove(gpio_num_t gpio_num);
三、普通的输入引脚初始化
void KeyInint(void)
{
gpio_config_t GpioConfigt;
GpioConfigt.pin_bit_mask = BIT64(KEY);//设置引脚
GpioConfigt.mode = GPIO_MODE_INPUT;//设置模式
GpioConfigt.pull_up_en = GPIO_PULLUP_ENABLE;//上拉使能
GpioConfigt.pull_down_en = GPIO_PULLDOWN_DISABLE;//下拉失能
GpioConfigt.intr_type = GPIO_INTR_DISABLE;//配置中断
gpio_config(&GpioConfigt);
}
//使用,按一次按键灯翻转一次
void app_main(void)
{
char *tag = "main";
uint8_t flag1 = 0;
esp_log_level_set(tag, ESP_LOG_DEBUG); //设置日志等级
Led_init();
KeyInint();
while(1)
{
if(gpio_get_level(KEY) == 0)
{
vTaskDelay(10);
while(gpio_get_level(KEY) == 0);
flag1 = !flag1;
LED0(flag1);
}
vTaskDelay(10);
}
}
四、外部中断初始化
注意:IRAM_ATTR 需要添加 “esp_attr.h” 头文件,否则会编译报错。
uint8_t flag = 0;
static void IRAM_ATTR gpio_isr_handler(void* arg)
{
uint32_t gpio_num = (uint32_t) arg;
switch(gpio_num)
{
case GPIO_NUM_0:
{
flag = !flag;
LED0(flag);
break;
}
default: break;
}
}
void KeyExtiInit(void)
{
gpio_config_t GpioConfigt;
GpioConfigt.pin_bit_mask = BIT64(KEY);//设置引脚
GpioConfigt.mode = GPIO_MODE_INPUT;//设置模式
GpioConfigt.pull_up_en = GPIO_PULLUP_ENABLE;//上拉使能
GpioConfigt.pull_down_en = GPIO_PULLDOWN_DISABLE;//下拉失能
GpioConfigt.intr_type = GPIO_INTR_POSEDGE;//配置中断,上降沿
gpio_config(&GpioConfigt);
//gpio_set_intr_type(KEY, GPIO_INTR_NEGEDGE);//单独设置引脚的中断
//安装GPIO中断服务 -> 分配中断标志,与gpio_isr_register()有冲突。
gpio_install_isr_service(KeyIntrNo);
//给GPIO添加中断服务函数,可以把多个GPIO的中断服务添加在同一个函数中,用传的引脚号来做区分。猜测是因为中断标志有限才这样做的。
gpio_isr_handler_add(KEY, gpio_isr_handler, (void*) KEY);
//删除gpio号的isr处理程序
// gpio_isr_handler_remove(GPIO_INPUT_IO_0);
}
使用的时候只要初始化一下就行了。每触发一次中断就会执行gpio_isr_handler函数
五、补充
- IRAM_ATTR 需要添加 “esp_attr.h” 头文件,否则会编译报错。
- 不要再中断中用 printf 和 ESP LOGX函数,否则会报硬件错误,网上有大佬说ESP就这样不支持。
- ESPIDF对GPIO的输出没有翻转函数,很麻烦。而且GPIO再输出模式下gpio_get_level()函数是失效的。
- ESPIDF学习还是很慢的,可能会转学Arduino。
- 2024.02.23 GPIO设置为 GPIO_MODE_INPUT_OUTPUT 或者 GPIO_MODE_INPUT_OUTPUT_OD 模式时可以用gpio_get_level()获取引脚的电平情况。