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()
