注意

这是最新开发分支配套的文档,可能包含已发布版本中尚未提供的功能。如果您要查看特定版本的文档,请使用左侧的下拉菜单并选择所需要的版本。

GPIO#

概述#

K230 平台提供了两个 GPIO 控制器:

  • GPIO0: 控制器基地址 0x9140b000,提供 32 个 GPIO 引脚 (0-31)

  • GPIO1: 控制器基地址 0x9140c000,提供 32 个 GPIO 引脚 (0-31)

设备树配置#

IO引脚有多个功能,参考如下,把某个io配置(通过IOMUX)为 GPIO 功能,:

&iomux {
    gpio21_pins: gpio21_pins {
        pins = K230_IO21;
        function = "alt0";
    };
    gpio52_pins: gpio52_pins {
        pins = K230_IO52;
        function = "alt0";
    };
};

uboot下如果已经配置为gpio功能,linux下可以不用配置 k230_iomux.py工具也可以配置相关io为gpio功能

驱动使用gpio参考

// 按钮配置 (GPIO21)
btn {
    compatible = "gpio-keys";
    pinctrl-names = "default";
    pinctrl-0 = <&gpio21_pins>;
    status = "okay";

    btn0: btn0 {
        label = "btn";
        linux,code = <KEY_VOLUMEUP>;
        gpios = <&gpio0_ports 21 GPIO_ACTIVE_LOW>;
    };
};

// LED 配置 (GPIO52)
led {
    compatible = "gpio-leds";
    pinctrl-names = "default";
    pinctrl-0 = <&gpio52_pins>;
    status = "okay";

    led0:led0 {
        label = "led";
        gpios = <&gpio1_ports 20 GPIO_ACTIVE_HIGH>;
    };
};

k230默认没有使能key和led框架(使能后无法使用libgpiod操作对应管脚),上述配置仅供参考

libgpiod2工具使用#

K230 Buildroot 默认已集成 libgpiod2 工具,使用参考如下:

gpioget读值#

# 读取单个 GPIO 值 gpio0 (GPIO0_0) - 必须使用 -c 指定 chip
gpioget -c 0 0
# 读取单个 GPIO 值 GPIO52(GPIO1_20) - 必须使用 -c 指定 chip
gpioget -c 1 20

gpioset设置值#

## 设置 GPIO52(GPIO1_20) 为高电平
gpioset -c 1 20=1
## 设置 GPIO52(GPIO1_20) 为低电平
gpioset -c 1 20=0
# 使用 -t 实现自动翻转 (LED 闪烁,不用写循环)
# 每 500ms 翻转一次,持续 5 次后退出
gpioset -c 1 -t 500ms,500ms  20=1

gpiomon监控#

gpiomon - 监控 GPIO 中断事件

# 监控 GPIO0_10 的上升沿和下降沿
gpiomon -e both -c 0 21

# 只监控下降沿 (按钮按下)
gpiomon -e falling -c 0 21

# 只监控上升沿
gpiomon -e rising -c 0 21

# 监控 5 个事件后退出
gpiomon -e falling -n 5 -c 0 21

gpiodetect#

# 列出系统中的所有 GPIO 控制器
gpiodetect
# 列出所有 GPIO 控制器及线信息(推荐)
gpioinfo

c语言编程例子#

LED 闪烁 (C 语言)#

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <gpiod.h>

#define LED_GPIO_CHIP_PATH "/dev/gpiochip1"
#define LED_LINE_NUM       20

// 闪烁间隔(毫秒),可通过命令行参数指定
#define DEFAULT_INTERVAL_MS 500

int main(int argc, char *argv[]) {
    struct gpiod_chip *led_chip = NULL;
    struct gpiod_line_settings *settings = NULL;
    struct gpiod_line_config *line_cfg = NULL;
    struct gpiod_request_config *req_cfg = NULL;
    struct gpiod_line_request *led_request = NULL;
    unsigned int offsets[1];
    int interval_ms = DEFAULT_INTERVAL_MS;
    int ret = EXIT_FAILURE;

    // 解析命令行参数:led_blink [间隔毫秒]
    if (argc > 1) {
        interval_ms = atoi(argv[1]);
        if (interval_ms <= 0) {
            fprintf(stderr, "无效的间隔时间: %s\n", argv[1]);
            fprintf(stderr, "用法: %s [间隔毫秒]\n", argv[0]);
            return EXIT_FAILURE;
        }
    }

    printf("LED 闪烁测试 - 间隔: %d ms\n", interval_ms);

    // 1. 打开 LED GPIO 芯片控制器
    led_chip = gpiod_chip_open(LED_GPIO_CHIP_PATH);
    if (!led_chip) {
        perror("打开 LED gpiochip 失败");
        goto cleanup;
    }

    // 2. 创建并配置引脚设置
    settings = gpiod_line_settings_new();
    if (!settings) {
        perror("创建 line settings 失败");
        goto cleanup;
    }

    // 3. 创建引脚配置
    line_cfg = gpiod_line_config_new();
    if (!line_cfg) {
        perror("创建 line config 失败");
        goto cleanup;
    }

    // 配置 LED 引脚:设置为输出,初始值为 0(熄灭)
    gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_OUTPUT);
    gpiod_line_settings_set_output_value(settings, 0);
    offsets[0] = LED_LINE_NUM;
    if (gpiod_line_config_add_line_settings(line_cfg, &offsets[0], 1, settings) < 0) {
        perror("配置 LED 引脚失败");
        goto cleanup;
    }

    // 4. 创建请求配置
    req_cfg = gpiod_request_config_new();
    if (!req_cfg) {
        perror("创建 request config 失败");
        goto cleanup;
    }
    gpiod_request_config_set_consumer(req_cfg, "k230_led");

    // 5. 请求 LED GPIO 引脚
    led_request = gpiod_chip_request_lines(led_chip, req_cfg, line_cfg);
    if (!led_request) {
        perror("请求 LED GPIO 引脚失败");
        goto cleanup;
    }

    printf("LED 初始化成功!开始闪烁...\n");
    printf("LED: %s:%u\n", LED_GPIO_CHIP_PATH, LED_LINE_NUM);

    // 6. 主循环:LED 闪烁
    while (1) {
        // LED 点亮
        ret = gpiod_line_request_set_value(led_request, LED_LINE_NUM, 1);
        if (ret < 0) {
            perror("写入 LED 失败");
            break;
        }
        printf("LED ON\n");
        usleep(interval_ms * 1000);

        // LED 熄灭
        ret = gpiod_line_request_set_value(led_request, LED_LINE_NUM, 0);
        if (ret < 0) {
            perror("写入 LED 失败");
            break;
        }
        printf("LED OFF\n");
        usleep(interval_ms * 1000);
    }

    ret = EXIT_SUCCESS;

cleanup:
    // 释放资源
    if (led_request) gpiod_line_request_release(led_request);
    if (req_cfg) gpiod_request_config_free(req_cfg);
    if (line_cfg) gpiod_line_config_free(line_cfg);
    if (settings) gpiod_line_settings_free(settings);
    if (led_chip) gpiod_chip_close(led_chip);

    return ret;
}

按钮事件监听 (C 语言)#

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <gpiod.h>
#include <poll.h>

// Modify according to your K230 board pins
#define BUTTON_GPIO_CHIP_PATH "/dev/gpiochip0"
#define BUTTON_LINE_NUM       21

// Helper function to print event type
static void print_edge_event_type(unsigned int event_type) {
    switch (event_type) {
        case GPIOD_EDGE_EVENT_RISING_EDGE:
            printf("[EVENT] Button released! (Event: RISING)\n");
            break;
        case GPIOD_EDGE_EVENT_FALLING_EDGE:
            printf("[EVENT] Button pressed! (Event: FALLING)\n");
            break;
        default:
            printf("[EVENT] Unknown event type: %u\n", event_type);
            break;
    }
}

int main(void) {
    struct gpiod_chip *button_chip = NULL;
    struct gpiod_line_settings *settings = NULL;
    struct gpiod_line_config *line_cfg = NULL;
    struct gpiod_request_config *req_cfg = NULL;
    struct gpiod_line_request *button_request = NULL;
    unsigned int offsets[1];
    int ret = EXIT_FAILURE;

    // 1. Open Button GPIO chip controller
    button_chip = gpiod_chip_open(BUTTON_GPIO_CHIP_PATH);
    if (!button_chip) {
        perror("Failed to open Button gpiochip");
        goto cleanup;
    }

    // 2. Create and configure pin settings
    settings = gpiod_line_settings_new();
    if (!settings) {
        perror("Failed to create line settings");
        goto cleanup;
    }

    // 3. Create pin configuration
    line_cfg = gpiod_line_config_new();
    if (!line_cfg) {
        perror("Failed to create line config");
        goto cleanup;
    }

    // Configure Button pin: set as input
    gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);

    // Enable both-edge interrupt detection
    gpiod_line_settings_set_edge_detection(settings, GPIOD_LINE_EDGE_BOTH);

    offsets[0] = BUTTON_LINE_NUM;
    if (gpiod_line_config_add_line_settings(line_cfg, &offsets[0], 1, settings) < 0) {
        perror("Failed to configure Button pin");
        goto cleanup;
    }

    // 4. Create request configuration
    req_cfg = gpiod_request_config_new();
    if (!req_cfg) {
        perror("Failed to create request config");
        goto cleanup;
    }
    gpiod_request_config_set_consumer(req_cfg, "k230_button_irq");

    // 5. Request Button GPIO pin
    button_request = gpiod_chip_request_lines(button_chip, req_cfg, line_cfg);
    if (!button_request) {
        perror("Failed to request Button GPIO pin");
        goto cleanup;
    }

    // 6. Initialize event buffer (to clear kernel interrupt queue)
    // Capacity of 2 is sufficient for button debouncing and accumulated edge events
    struct gpiod_edge_event_buffer *event_buf = gpiod_edge_event_buffer_new(2);
    if (!event_buf) {
        perror("Failed to create event buffer");
        goto cleanup;
    }

    // 7. Get file descriptor for poll
    int fd = gpiod_line_request_get_fd(button_request);
    if (fd < 0) {
        perror("Failed to get poll file descriptor");
        goto cleanup;
    }

    printf("K230 Button interrupt detection initialized successfully!\n");
    printf("Button: %s, Line: %u\n", BUTTON_GPIO_CHIP_PATH, BUTTON_LINE_NUM);
    printf("Start using poll to wait for button events (CPU usage very low), press Ctrl+C to exit...\n\n");

    // 8. Main loop: wait for interrupts using poll
    while (1) {
        struct pollfd pfd = {
            .fd = fd,
            .events = POLLIN,
            .revents = 0
        };

        // Block indefinitely waiting for interrupt
        int poll_ret = poll(&pfd, 1, -1);
        if (poll_ret < 0) {
            perror("poll failed");
            break;
        }

        if (!(pfd.revents & POLLIN)) continue;

        size_t num_events = gpiod_line_request_read_edge_events(button_request, event_buf, 2);
        if (num_events == 0) continue;

        for (size_t i = 0; i < num_events; i++) {
            struct gpiod_edge_event *event = gpiod_edge_event_buffer_get_event(event_buf, i);
            if (!event) continue;

            unsigned int event_type = gpiod_edge_event_get_event_type(event);
            print_edge_event_type(event_type);
        }
    }

    ret = EXIT_SUCCESS;

cleanup:
    if (event_buf) gpiod_edge_event_buffer_free(event_buf);
    if (button_request) gpiod_line_request_release(button_request);
    if (req_cfg) gpiod_request_config_free(req_cfg);
    if (line_cfg) gpiod_line_config_free(line_cfg);
    if (settings) gpiod_line_settings_free(settings);
    if (button_chip) gpiod_chip_close(button_chip);

    return ret;
}


Python 示例#

led例子(adafruit)#

import board
from digitalio import DigitalInOut, Direction
from time import sleep

# Initialize LED
led = DigitalInOut(board.LED)
led.direction = Direction.OUTPUT

# Blink LED in loop
while True:
    led.value = 1  # Output high level, turn on built-in blue LED
    sleep(1)
    led.value = 0  # Output low level, turn off built-in blue LED
    sleep(1)

按键例子(adafruit)#

'''
Experiment: Button Event Detection
Platform: 01studio
'''

import board
import time
from digitalio import DigitalInOut, Direction, Pull

# Initialize button
key = DigitalInOut(board.KEY)  # Define pin number
key.direction = Direction.INPUT  # Set as input
key.pull = Pull.UP  # Enable pull-up resistor

# Store previous state for edge detection
prev_state = 1

print("Button event detection started. Press Ctrl+C to exit.")

while True:
    current_state = key.value

    # Detect falling edge (pressed)
    if prev_state == 1 and current_state == 0:
        print("[EVENT] Button pressed!")

    # Detect rising edge (released)
    elif prev_state == 0 and current_state == 1:
        print("[EVENT] Button released!")

    prev_state = current_state
    time.sleep(0.2)  # 10ms sleep to reduce CPU usage

led例子(periphery)#

from periphery import GPIO
import time

# Modify the chip path and pin number according to your K230 or other board
# Assuming LED is connected to line 20 of /dev/gpiochip1
LED_CHIP_PATH = "/dev/gpiochip1"
LED_LINE_NUM = 20

try:
    # Open GPIO and configure as output mode ("out")
    # New version of python-periphery no longer supports initial_value parameter
    led = GPIO(LED_CHIP_PATH, LED_LINE_NUM, "out")

    # Manually set initial value to low (LED off)
    led.write(False)

    print(f"Successfully initialized LED pin: {LED_CHIP_PATH} [Line {LED_LINE_NUM}]")
    print("Starting LED blink, press Ctrl+C to exit...")

    while True:
        # Output high level (True), turn on LED
        # Note: If your hardware is active-low, write(True) will turn it off,
        # and write(False) will turn it on
        print("LED ON")
        led.write(True)
        time.sleep(0.9)  # Keep on for 0.5 seconds

        # Output low level (False), turn off LED
        print("LED OFF")
        led.write(False)
        time.sleep(0.9)  # Keep off for 0.5 seconds

except KeyboardInterrupt:
    print("\nProgram terminated.")
except Exception as e:
    print(f"Error occurred: {e}")
finally:
    # Release GPIO resource properly and turn off LED before exiting
    if 'led' in locals():
        led.write(False)
        led.close()
        print("LED resource released.")

按键(periphery)#

from periphery import GPIO

try:
    # Open GPIO and configure: input with pull-up
    button = GPIO("/dev/gpiochip0", 21, "in", bias="pull_up")

    # [Core Magic]: Let Linux kernel handle debouncing, set debounce time to 20ms (20000us)
    # Note: periphery's debounce parameter unit is typically microseconds (us)
    button.debounce = 20000

    # Listen for both edges
    button.edge = "both"

    print("Starting button monitoring with kernel debouncing...")

    while True:
        # Block waiting for clean interrupts filtered by kernel
        if button.poll(timeout=None):
            # Read event to reset the flag
            try:
                _ = button.read_event()
            except Exception:
                pass

            # Read and print, no more bounce issues
            val = button.read()
            print(">>> Button Pressed <<<" if val == 0 else "=== Button Released ===")

except KeyboardInterrupt:
    print("\nProgram terminated.")
except Exception as e:
    print(f"Error: {e}")
finally:
    if 'button' in locals():
        button.close()

评论列表
条评论
登录