ESP32 - Micropython ESP-IDF 双线教程 输入捕获KEY
输入捕获介绍和使用 - Mrcropython
本节教程实现按键的功能,但是不是普通的通过GPIO电平来判断按键是够被按下,在 ESP32 的 MicroPython 环境中,使用 GPIO 的中断(IRQ, Interrupt Request)功能来实现类似于STM32输入捕获的效果。这允许你在 GPIO 引脚状态改变时(例如,从低电平变为高电平,即按键按下)触发一个函数或回调函数。
示例代码:使用 Micropython 获取 ESP32 的 GPIO 状态(按键功能)
为了使用 Micropython 获取 ESP32 的 GPIO 状态并实现按键功能,可以为 GPIO 引脚设置一个中断,并在按键按下时触发一个函数。以下是一个示例代码,它演示了如何使用 Micropython 来检测按键的按下,并根据按键的状态来控制一个 LED 的开关和反转。
示例代码
from machine import Pin, Timer
import utime
# 定义引脚号
LED_PIN = 2 # 假设 LED 连接到 GPIO 2
BUTTON_PIN = 0 # 假设 按键连接到 GPIO 0
# 初始化 LED 引脚为输出模式
led = Pin(LED_PIN, Pin.OUT)
# 初始化按键引脚为输入模式,并启用上拉电阻
button = Pin(BUTTON_PIN, Pin.IN, Pin.PULL_UP)
# 按键状态变量
led_state = False
# 按键中断处理函数
def button_callback(pin):
global led_state
# 按键被按下时,pin.value() 将返回 0
if not pin.value():
led_state = not led_state # 反转 LED 状态
led.value(led_state) # 设置 LED 状态
# 为按键引脚设置中断
button.irq(trigger=Pin.IRQ_FALLING, handler=button_callback)
# 可选:使用 Timer 来轮询 LED 状态(这里仅用于演示,实际上中断已经足够)
def check_led_state(timer):
print("LED state:", led.value())
# 创建一个每秒触发一次的 Timer
tim = Timer()
tim.init(period=1000, mode=Timer.PERIODIC, callback=check_led_state)
# 主程序持续运行,等待中断发生
try:
while True:
utime.sleep_ms(100) # 防止主循环过于繁忙
except KeyboardInterrupt:
# 如果按下 Ctrl+C,则清理并退出
tim.deinit()
print("Exiting...")
代码介绍
- 引脚定义:我们定义了两个引脚号,一个用于 LED(
LED_PIN
),另一个用于按键(BUTTON_PIN
)。 - 引脚初始化:LED 引脚被初始化为输出模式,而按键引脚被初始化为输入模式,并启用了上拉电阻。这样,当按键未按下时,引脚将读取为高电平(由于上拉电阻),而当按键按下时,引脚将读取为低电平。
- 按键中断处理函数:我们定义了一个名为
button_callback
的函数,它将在按键引脚的状态从高变为低(即按键被按下)时被调用。在这个函数中,我们反转了led_state
变量的值,并使用它来设置 LED 的状态。 - 设置中断:我们使用
button.irq()
方法为按键引脚设置了中断。我们指定了中断触发条件为Pin.IRQ_FALLING
(即引脚值从高变为低),并指定了中断处理函数为button_callback
。 - 可选的 Timer:为了演示目的,我们创建了一个每秒触发一次的 Timer,并在其回调函数中打印 LED 的状态。这在实际应用中可能并不需要,因为中断已经足够用来响应按键的按下。
- 主循环:在主程序中,我们使用
while True:
循环来保持程序运行。在这个循环中,我们调用utime.sleep_ms(100)
来防止主循环过于繁忙。如果按下 Ctrl+C,我们将清理 Timer 并退出程序。
输入捕获介绍和使用 - ESP-ISF
在C/C++中,ESP32的输入捕获(Interrupt Capture)通常是通过GPIO(General Purpose Input/Output)中断来实现的。与MicroPython不同,C/C++使用的是ESP-IDF(Espressif IoT Development Framework)来开发ESP32应用程序。在ESP-IDF中,可以通过GPIO中断来捕获外部事件,如按键按下或释放。
关键点
- GPIO中断:可以配置GPIO引脚来在特定事件(如电平变化)上生成中断。
- 中断服务例程(ISR):当中断触发时,会调用一个中断服务例程(ISR)。这个例程是用户定义的,用于处理中断事件。
- 中断配置:需要配置中断的触发方式(上升沿、下降沿或两者都触发)和中断的优先级。
使用ESP-IDF进行输入捕获的步骤
- 初始化GPIO:使用
gpio_pad_select_gpio()
函数将GPIO引脚从其他功能(如UART、SPI等)切换回GPIO模式。 - 设置GPIO方向:使用
gpio_set_direction()
函数设置GPIO引脚的方向为输入。 - 配置GPIO中断:使用
gpio_isr_handler_add()
函数为GPIO引脚添加一个中断服务例程(ISR)。 - 启用GPIO中断:通过调用
gpio_intr_enable()
函数来启用GPIO中断。 - 编写中断服务例程(ISR):这是一个用户定义的函数,用于处理GPIO中断事件。
示例代码:使用C/C++捕获ESP32的GPIO状态(按键功能)
下面是一个示例代码,演示了如何使用C/C++和ESP-IDF来捕获ESP32的GPIO状态(按键功能),并根据按键的按下状态来控制LED的开关和反转。
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#define LED_GPIO_NUM GPIO_NUM_2 // 假设LED连接到GPIO 2
#define BUTTON_GPIO_NUM GPIO_NUM_0 // 假设按键连接到GPIO 0
// LED状态变量
static volatile bool led_state = false;
// GPIO中断服务例程
void IRAM_ATTR gpio_isr_handler(void* arg) {
// 检查是哪个GPIO引脚触发了中断
uint32_t gpio_num = (uint32_t) arg;
if (gpio_num == BUTTON_GPIO_NUM) {
// 反转LED状态
led_state = !led_state;
// 设置LED状态
gpio_set_level(LED_GPIO_NUM, led_state);
// 清除中断标志位
gpio_intr_clear(gpio_num);
}
}
void app_main(void) {
// 初始化LED引脚为输出模式
gpio_pad_select_gpio(LED_GPIO_NUM);
gpio_set_direction(LED_GPIO_NUM, GPIO_MODE_OUTPUT);
// 初始化按键引脚为输入模式,并启用上拉电阻
gpio_pad_select_gpio(BUTTON_GPIO_NUM);
gpio_set_pull_mode(BUTTON_GPIO_NUM, GPIO_PULLUP_ONLY);
gpio_set_direction(BUTTON_GPIO_NUM, GPIO_MODE_INPUT);
// 配置GPIO中断
gpio_set_intr_type(BUTTON_GPIO_NUM, GPIO_INTR_NEGEDGE); // 下降沿触发
gpio_isr_handler_add(BUTTON_GPIO_NUM, gpio_isr_handler, (void*) BUTTON_GPIO_NUM);
gpio_intr_enable(BUTTON_GPIO_NUM);
// 主循环(在这个例子中,主循环是空闲的,因为中断会处理按键事件)
while (1) {
// 你可以在这里添加其他任务或逻辑
vTaskDelay(pdMS_TO_TICKS(1000)); // 延时1秒,仅用于演示
}
}
代码解释
- 首先,我们包含了必要的头文件,并定义了LED和按键连接的GPIO引脚号。
- 然后,我们定义了一个全局变量
led_state
来跟踪LED的当前状态。 gpio_isr_handler
是一个中断服务例程,它检查触发中断的GPIO引脚,并根据按键的状态反转LED的状态。注意,我们使用了IRAM_ATTR
属性