ESP-IDF 学习 2 IO & interrupt 的使用

cnblogs 2024-10-11 11:15:00 阅读 81

API of IO

使用 ESP-IDF 的时候,不似STC单片机那样,它帮助我们集成了 FreeRTOS,很少会直接访问寄存器,访问 IO 亦如此,所以我们调用它提供给我们的 API 就可以访问 IO 当前的 level

相应的,我们对 IO 初始化的时候也不是访问 IO 配置寄存器 来初始化 IO 的模式,是通过配置结构体对象,传递给 API 来进行初始化。

IO 初始化如下:

<code>// GPIO结构体

gpio_config_t My_GPIO_structture = {

.pin_bit_mask = (1ULL << 32), // GPIO32, 1左移32bit

.mode = GPIO_MODE_OUTPUT, // 输出模式

.pull_up_en = GPIO_PULLUP_ENABLE, // 上拉电阻, pull up; 下拉电阻, pull down

.pull_down_en = GPIO_PULLDOWN_DISABLE,

.intr_type = GPIO_INTR_DISABLE,

};

ESP_ERROR_CHECK(gpio_config(&My_GPIO_structture)); // 配置 GPIO32且使用ESP_ERROR检查

My_GPIO_structture.pin_bit_mask = (1ULL << 17);

ESP_ERROR_CHECK(gpio_config(&My_GPIO_structture)); // 数码管(A段)

My_GPIO_structture.pin_bit_mask = (1ULL << 15);

ESP_ERROR_CHECK(gpio_config(&My_GPIO_structture)); // 数码管(B段)

设置 IO_level 或读取 IO_level 如下:

err = gpio_set_level(GPIO_NUM_17, level); // A段

// If the pad is not configured for input (or input and output) the returned value is always 0.

clockbell_level = gpio_get_level(io_num);

中断初始化

同样的,对于中断的初始化也是使用官方提供的 API ,以及写中断函数的时候使用者无需标明中断等级( 因为在宏定义里写好了 ),只需把自己的中断处理函数赋给中断接口即可

如下:

// 中断队列

static QueueSetHandle_t gpioISR_evt_queue = NULL;

static uint8_t clockbell_level = false;

/// @brief GPIO中断处理

/// @note IRAM_ATTR

/// @param arg

/// @return

static void IRAM_ATTR gpio_isr_handler(void *arg)

{

// 中断任务内部不执行打印

handler_count++;

uint32_t gpio_num = (uint32_t)arg;

// 从中断任务中发送数据到任务队列, 从中断中使用比较安全

xQueueSendFromISR(gpioISR_evt_queue, &gpio_num, NULL);

return;

}

/// @brief GPIO中断处理接收任务

/// @param arg

static void gpio_isr_handler_receive_task(void *arg)

{

uint32_t io_num = 0;

while (1)

{

if (xQueueReceive(gpioISR_evt_queue, &io_num, portMAX_DELAY))

{

#if ISR_DEBUG

printf("%s GPIO[%" PRIu32 "] intr, val: %d, handler count: %d\n",

__func__, io_num, gpio_get_level(io_num), handler_count);

#endif// 中断里头打印会有问题, 未知原因导致复位, 故此在接收函数里打印

clockbell_level = (uint8_t)gpio_get_level(io_num);

}

}

}

void isr_init(void)

{

// 创建中断接收队列, 没有创建将会导致队列断言失败restart core

gpioISR_evt_queue = xQueueCreate(10, sizeof(uint32_t));

// install gpio isr service, 安装gpio中断服务

ESP_ERROR_CHECK(gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT));

// hook isr handler for specific gpio pin, 添加gpio中断处理函数

ESP_ERROR_CHECK(gpio_isr_handler_add(GPIO_NUM_35,

gpio_isr_handler,

(void *)GPIO_NUM_35));

// start gpio_isr task, 创建gpio中断处理接收任务

xTaskCreatePinnedToCore(gpio_isr_handler_receive_task,

"gpio_isr_handler_task",

2048,

NULL,

10,

NULL,

0);

}

从其中可见,进入中断以后迅速的发送了一个队列消息。在中断以外,创建了一个任务来接收中断任务发送的队列消息,而真正检测 IO_level 也是在接收函数里头



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。