新闻详情

新闻详情

首页 / 资讯中心 / 详情

ShiMetaPi-Pico-G1:外设与接口(1)

发布时间:2026/10/1 10:02:48来源:尧图网络
ShiMetaPi-Pico-G1:外设与接口(1)
1. GPIO子系统在 Linux 系统中GPIO 由专门的 GPIO 子系统统一管理该子系统基于内核的 GPIO 框架gpiolib实现为 GPIO 硬件提供标准化的抽象接口。通过该框架内核能够对不同平台的 GPIO 控制器进行统一封装使用户空间或内核驱动可以以一致的方式访问 GPIO 资源。 GPIO的控制方式有两种通过sysfs文件系统导出到用户空间进行控制从而以文件读写的方式实现对 GPIO 引脚的操作。(旧GPIO接口路径在 /sys/class/gpio/,现在 Linux 内核已经不推荐继续使用)使用基于字符设备的 GPIO 接口gpiochip。(新GPIO接口路径在/dev/gpiochipN,Linux 官方推荐的新方式)GPIO编号计算每组GPIO有8个GPIO管脚GPIO编号等于GPIO组合\*8组内偏移号例如GPIO4_2的GPIO编号为 4\*8234 使用字符设备驱动时GPIO1_4chip_path对应/dev/gpiochip1,line_offset对应42. character GPIO2.1 专业术语libgpiodlibgpiod 是 Linux 用户空间访问 GPIO通用输入输出的标准库是现代 GPIO 子系统gpiolib character device interface的官方用户态接口。ioctlioctl 是一种设备控制系统调用接口用于在 read/write 之外通过命令码request和结构化参数arg与设备驱动进行交互实现设备配置、状态查询和特殊控制功能。说明libgpiod 是 Linux 官方提供的 GPIO 用户空间参考库它对 GPIO character device ioctl 接口进行了封装提供统一的 GPIO line 申请、控制与事件 API。它在功能上相当于 GPIO 的用户态抽象层userspace abstraction layer但本质上仍依赖 ioctl 与内核 gpiolib 交互。同时用户完全可以绕过 libgpiod直接基于 ioctl 实现自己的 GPIO 抽象层。2.2 GPIO ioctl的使用2.2.1 头文件linux/gpio.h这个头文件里定义了常用结构体和 ioctlstruct gpiohandle_requeststruct gpiohandle_datastruct gpioevent_request以及这些 ioctl 命令GPIO_GET_CHIPINFO_IOCTLGPIO_GET_LINEINFO_IOCTLGPIO_GET_LINEHANDLE_IOCTLGPIO_GET_LINEEVENT_IOCTLGPIOHANDLE_GET_LINE_VALUES_IOCTLGPIOHANDLE_SET_LINE_VALUES_IOCTL2.2.2 相关结构体gpiohandle_request用于申请普通输入/输出 GPIO line。关键成员lineoffsets[]line 编号flags输入还是输出default_values[]默认输出值consumer_label给内核看的占用者名字fd成功后返回 line 句柄gpiohandle_data用于读写 line 电平。关键成员values[]每条 line 的值gpioevent_request用于申请中断事件 line。关键成员lineoffsetline 编号handleflags通常输入eventflags上升沿/下降沿/双边沿fd成功后返回事件 fd2.3 实现呼吸灯应用程序参考快速入门/部署第一个应用程序创建并编写gpio_hal.c#include gpio_hal.h #include errno.h #include fcntl.h #include stdio.h #include string.h #include sys/ioctl.h #include unistd.h int gpio_handle_init(gpio_handle_t *gpio_handle) { struct gpiohandle_request req; if (gpio_handle NULL || gpio_handle-chip_path NULL) { errno EINVAL; return -1; } gpio_handle-chip_fd -1; gpio_handle-line_fd -1; gpio_handle-chip_fd open(gpio_handle-chip_path, O_RDONLY); if (gpio_handle-chip_fd 0) { perror(open gpiochip); return -1; } memset(req, 0, sizeof(req)); req.lineoffsets[0] gpio_handle-line_offset; req.flags gpio_handle-gpio_mode; req.default_values[0] gpio_handle-default_value ? 1 : 0; req.lines 1; if (gpio_handle-consumer_label[0] ! \0) { strncpy(req.consumer_label, gpio_handle-consumer_label, sizeof(req.consumer_label) - 1); req.consumer_label[sizeof(req.consumer_label) - 1] \0; } else { strncpy(req.consumer_label, gpio-led, sizeof(req.consumer_label) - 1); req.consumer_label[sizeof(req.consumer_label) - 1] \0; } if (ioctl(gpio_handle-chip_fd, GPIO_GET_LINEHANDLE_IOCTL, req) 0) { perror(GPIO_GET_LINEHANDLE_IOCTL); close(gpio_handle-chip_fd); gpio_handle-chip_fd -1; return -1; } gpio_handle-line_fd req.fd; return 0; } int gpio_set_value(gpio_handle_t *gpio_handle, int value) { struct gpiohandle_data data; if (gpio_handle NULL || gpio_handle-line_fd 0) { errno EINVAL; return -1; } memset(data, 0, sizeof(data)); data.values[0] value ? 1 : 0; if (ioctl(gpio_handle-line_fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, data) 0) { perror(GPIOHANDLE_SET_LINE_VALUES_IOCTL); return -1; } return 0; } void gpio_handle_close(gpio_handle_t *gpio_handle) { if (gpio_handle NULL) return; if (gpio_handle-line_fd 0) { close(gpio_handle-line_fd); gpio_handle-line_fd -1; } if (gpio_handle-chip_fd 0) { close(gpio_handle-chip_fd); gpio_handle-chip_fd -1; } }创建并编写gpio_hal.h#ifndef GPIO_HAL_H #define GPIO_HAL_H #ifdef __cplusplus extern C { #endif #include linux/gpio.h #define GPIO_CONSUMER_LABEL_LEN 32 typedef struct gpio_handle_t { int chip_fd; const char *chip_path; unsigned int line_offset; unsigned int gpio_mode; int default_value; int line_fd; char consumer_label[GPIO_CONSUMER_LABEL_LEN]; } gpio_handle_t; int gpio_handle_init(gpio_handle_t *gpio_handle); int gpio_set_value(gpio_handle_t *gpio_handle, int value); void gpio_handle_close(gpio_handle_t *gpio_handle); #ifdef __cplusplus } #endif #endif创建并编写main.c#include gpio_hal.h #include linux/gpio.h #include stdio.h #include string.h #include unistd.h #define LED_CHIP_PATH /dev/gpiochip1 #define LED_LINE 6 int main(void) { gpio_handle_t led_handle; memset(led_handle, 0, sizeof(led_handle)); led_handle.chip_path LED_CHIP_PATH; led_handle.line_offset LED_LINE; led_handle.gpio_mode GPIOHANDLE_REQUEST_OUTPUT; led_handle.default_value 0; snprintf(led_handle.consumer_label, sizeof(led_handle.consumer_label), led-gpio); if (gpio_handle_init(led_handle) 0) { perror(gpio_handle_init); return 1; } printf(LED GPIO set high\n); if (gpio_set_value(led_handle, 1) 0) { gpio_handle_close(led_handle); return 1; } sleep(5); printf(LED GPIO set low\n); if (gpio_set_value(led_handle, 0) 0) { gpio_handle_close(led_handle); return 1; } gpio_handle_close(led_handle); return 0; }创建并编写MakefileSDK_DIR : $(shell cd $(shell pwd)/../../.. /bin/pwd) include $(SDK_DIR)/build/base.mk TARGET : gpio SRCS : main.c gpio_hal.c OBJS : $(SRCS:.c.o) .PHONY: all clean install all: $(TARGET) $(TARGET): $(OBJS) $(CC) $(SDK_LD_CFLAGS) -o $ $^ %.o: %.c $(CC) $(SDK_USR_CFLAGS) -c -o $ $ install: all mkdir -p $(XMEDIA_ROOTFS_DIR)/usr/bin cp -f $(TARGET) $(XMEDIA_ROOTFS_DIR)/usr/bin/$(TARGET) chmod 755 $(XMEDIA_ROOTFS_DIR)/usr/bin/$(TARGET) echo Installed $(TARGET) to $(XMEDIA_ROOTFS_DIR)/usr/bin/$(TARGET) clean: rm -f $(TARGET) $(OBJS)将应用程序编译进rootfs文件系统登录Pico-G1运行应用程序预期结果LED亮5秒后熄灭3 使用sysfs控制GPIO3.1 将GPIO导出到用户空间在板端 /sys/class/gpio 目录中每个 GPIO 设备都有其自己的文件夹。这些文件夹的名称是 gpio 加上引脚编号例如 /sys/class/gpio/gpio14 表示引脚编号为 14 的引脚即 GPIO1_6。用户可使用如下命令查看~ # echo 14 /sys/class/gpio/export ~ # ls /sys/class/gpio/ export gpiochip0 gpiochip24 gpiochip40 gpiochip56 gpiochip8 gpio14 gpiochip16 gpiochip32 gpiochip48 gpiochip64 unexport说明echo 14 sys/class/gpio 表示把 GPIO14 导出到用户空间,导出后就会生成/sys/class/gpio/gpio14 可以使用 echo 14 /sys/class/gpio/unexport 命令取消导出3.2 GPIO控制目录导出的GPIO对应的控制目录(即/sys/class/gpio/gpio14)里通常会有这些文件:~ # ls /sys/class/gpio/gpio14/ active_low direction power uevent device edge subsystem valueactive_low用于设置 GPIO 电平逻辑是否反向 示例echo 1 /sys/class/gpio/gpio14/active_low # 表示把GPIO14 的电平逻辑设置为反向direction用于设置 GPIO 的方向也就是它是输入还是输出 示例echo in /sys/class/gpio/gpio14/direction #输入 echo out /sys/class/gpio/gpio14/direction #输出power电源管理相关目录/文件一般不直接操作。uevent和设备事件相关通常不是用户日常手工控制 GPIO 时最常用的文件device表示这个 GPIO 所属的设备信息edgeecho both /sys/class/gpio/gpio14/edge配置中断触发边沿常见值none不产生中断rising上升沿触发中断falling下降沿触发中断both双边沿触发中断subsystem表示这个 GPIO 属于哪个子系统value用于读取或设置GPIO的电平值cat /sys/class/gpio/gpio14/value #读取电平echo 1 /sys/class/gpio/gpio14/value #设置为高电平 echo 0 /sys/class/gpio/gpio14/value #设置为低电平
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

徐州汉兴精密配件:口碑好的球磨机钢锻实力加工厂,正规源头的生厂商用户力荐 2026/10/2 5:30:39

徐州汉兴精密配件:口碑好的球磨机钢锻实力加工厂,正规源头的生厂商用户力荐

球磨机钢锻作为矿山、建材、电力等行业粉碎作业的核心耗材,市场需求持续攀升。近年来,随着矿山开采强度加大、设备运转负荷提升,用户对钢锻的耐磨性能、匹配精度和使用寿命提出了更高要求。不少采购方在搜索球磨机钢锻老牌生产厂球磨机钢锻推…

阅读更多 →
openrig开放式机架搭建指南:多卡GPU平台从选型到排障 2026/10/2 5:30:33

openrig开放式机架搭建指南:多卡GPU平台从选型到排障

在圈子里泡久了会发现一个现象:很多人把 openrig 当成一个现成产品,其实它更接近一种思路——把整台主机从封闭机箱里“解放”出来,让主板、显卡、电源全部裸露在一个金属框架上。我第一次见到这种开放式结构时,第一反应是“这也太…

阅读更多 →
Paperclip:Node.js+React+OpenClaw构建可调试AI Agent基座 2026/10/2 5:30:33

Paperclip:Node.js+React+OpenClaw构建可调试AI Agent基座

1. 项目概述:Paperclip 不是回形针,而是一个被严重误读的 AI 工具链命名陷阱“Paperclip”这个词一出来,90%的人第一反应是办公桌上那个弯弯的金属小物件——回形针。但在这个技术语境下,它根本不是物理实体,而是一个在…

阅读更多 →
编译原理实验报告:无符号数识别与逆波兰式的Java实现 2026/10/2 5:30:33

编译原理实验报告:无符号数识别与逆波兰式的Java实现

简介:这是一份编译原理课程配套的PDF版实验报告,源自太原理工大学,面向计算机、软件相关专业学生及需要掌握词法分析基础的学习者。报告以“无符号数的词法分析程序”为实验主线,先给出无符号数的文法规则和程序流程图&#xff0c…

阅读更多 →
智能汽车后台为何越来越像阿里云的主场?端云协同与千问模型落地实践 2026/10/2 5:30:33

智能汽车后台为何越来越像阿里云的主场?端云协同与千问模型落地实践

智能汽车这几年卷得厉害,前两年大家还在比谁的屏幕大、谁的语音助手反应快,现在风向已经悄悄变了。真正在背后决定一辆车"聪不聪明"的,不再是中控台上那块屏,而是看不见的后台——数据怎么传、模型怎么跑、算力怎么调度…

阅读更多 →
山东大学数据结构PDF:高校算法教学与工程判分实践 2026/10/2 5:30:33

山东大学数据结构PDF:高校算法教学与工程判分实践

简介:本资源是山东大学《数据结构》课程核心讲义PDF,面向计算机专业本科生及算法初学者,系统梳理课程基础理论与关键概念。内容覆盖绪论、线性表等核心章节,深入解析数据的基本概念与术语、逻辑结构(集合/线性/树形/网…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉