RK3568 Android 15驱动开发实战:从环境搭建到HAL集成
在嵌入式开发领域RK3568 作为一款性能均衡、接口丰富的通用型 SoC被广泛应用于智能终端、工业控制和边缘计算设备。随着 Android 15 的发布开发者面临新的系统特性和驱动适配需求。正点原子推出的 RK3568 开发板为学习和实战提供了稳定的硬件平台而驱动开发作为连接硬件与操作系统的核心环节其规范性和可调试性直接决定了项目的成败。本文将以正点原子 RK3568 开发板为硬件基础基于 Android 15 系统完整演示一个可实操的驱动开发流程。内容涵盖环境搭建、内核配置、驱动模块编写、编译调试、HAL 层对接以及常见问题排查目标是让读者掌握从零开始为 RK3568 开发定制外设驱动的能力并理解 Android 系统下驱动开发的完整链路。1. RK3568 与 Android 15 驱动开发环境准备1.1 硬件与软件基础要求在开始驱动开发前需确保具备以下基础环境硬件平台正点原子 RK3568 开发板至少配备 4GB RAM、32GB eMMC、Type-C 数据线、12V 电源适配器、串口调试工具如 USB 转 TTL 模块。主机环境Ubuntu 20.04 LTS 或 22.04 LTS推荐 16GB 内存、200GB 可用磁盘空间。工具链RK3568 官方提供的 GCC 交叉编译工具链aarch64-linux-gnu-。源码准备Android 15 系统源码、RK3568 内核源码版本需与 Android 系统匹配。以下为环境依赖的详细清单组件版本/型号获取方式备注开发板正点原子 RK3568官方渠道确认板载外设接口如 GPIO、I2C、SPI主机系统Ubuntu 20.04/22.04官网下载需安装必备软件包git、curl、tar、make工具链aarch64-linux-gnu-gcc 10.3RK 官网或 Linaro注意与内核编译配置一致内核源码kernel-5.10Rockchip GitHub 仓库对应 Android 15 的基线版本Android 源码android-15.0.0_r1AOSP 镜像站可仅下载设备相关部分1.2 开发环境配置步骤1. 安装基础依赖包在 Ubuntu 终端中执行以下命令安装编译所需的软件包sudo apt update sudo apt install -y git curl wget make gcc g libssl-dev libncurses-dev \ bison flex libelf-dev bc device-tree-compiler lz4 liblz4-tool2. 配置交叉编译工具链下载并解压工具链将其路径加入环境变量# 下载工具链以 Linaro 为例 wget https://releases.linaro.org/components/toolchain/binaries/10.3-2021.07/aarch64-linux-gnu/gcc-linaro-10.3.1-2021.07-x86_64_aarch64-linux-gnu.tar.xz tar -xf gcc-linaro-10.3.1-2021.07-x86_64_aarch64-linux-gnu.tar.xz sudo mv gcc-linaro-10.3.1-2021.07-x86_64_aarch64-linux-gnu /opt/ # 永久添加环境变量 echo export PATH/opt/gcc-linaro-10.3.1-2021.07-x86_64_aarch64-linux-gnu/bin:$PATH ~/.bashrc source ~/.bashrc # 验证工具链 aarch64-linux-gnu-gcc --version3. 获取内核源码并切换分支使用 git 克隆 Rockchip 内核仓库并切换到与 Android 15 匹配的分支git clone https://github.com/rockchip-linux/kernel.git cd kernel git checkout origin/kernel-5.10 -b android15-rk3568注意内核版本与 Android 系统的兼容性至关重要。若使用不匹配的分支可能导致编译错误或运行时异常。2. RK3568 内核配置与驱动框架理解2.1 内核配置与编译验证RK3568 的内核配置需针对具体硬件进行定制。正点原子开发板的设备树文件通常已由厂商提供但开发者仍需掌握如何调整配置以适应外设需求。执行内核配置菜单# 进入内核源码目录 cd kernel # 使用默认配置正点原子提供 make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- rockchip_defconfig # 启动图形化配置 make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- menuconfig在 menuconfig 中重点关注以下选项Device Drivers→Character devices→ 启用动态设备号分配CONFIG_DYNAMIC_DEVNODevice Drivers→GPIO Support→ 启用 Rockchip GPIO 驱动CONFIG_GPIO_ROCKCHIPFile systems→ 启用用于模块加载的CONFIG_MODULE_FORCE_LOADKernel hacking→ 启用CONFIG_DEBUG_KERNEL和CONFIG_DEBUG_DRIVER以便调试编译内核与模块# 编译内核镜像 make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- -j$(nproc) # 编译设备树二进制文件 make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- dtbs # 编译外部模块准备驱动开发环境 make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- modules_prepare编译成功后会在arch/arm64/boot/下生成Image内核镜像在arch/arm64/boot/dts/rockchip/下生成rk3568-evb.dtb等设备树文件。2.2 Linux 驱动框架核心概念在编写具体驱动前需理解 Linux 内核驱动的几个基础框架1. 字符设备驱动最基础的驱动类型适用于 GPIO、串口等逐字节读写的外设。核心结构体包括struct file_operations定义驱动支持的操作open、read、write、ioctl 等struct cdev表示一个字符设备dev_t设备号主设备号次设备号2. 平台设备与驱动用于描述 SoC 内部集成的外设如 I2C 控制器、SPI 总线。通过设备树Device Tree描述硬件资源驱动通过of_match_table匹配设备。3. 设备树Device TreeRK3568 使用设备树替代传统的板级文件board file描述硬件连接关系。设备树源文件.dts编译后生成二进制文件.dtb由内核解析。一个典型的 GPIO LED 设备树节点示例如下// 在 rk3568-evb.dtsi 中添加 leds { compatible gpio-leds; user_led: led-0 { label user_led; gpios gpio0 10 GPIO_ACTIVE_HIGH; // GPIO0_A10 linux,default-trigger heartbeat; default-state off; }; };设备树修改后需重新编译 dtb 文件并更新到开发板的 boot 分区。3. 实战编写一个简单的字符设备驱动3.1 驱动模块基础代码结构以下以一个最简单的虚拟字符设备为例演示完整的驱动编写流程。该设备通过/dev/hello_dev节点提供读写接口。创建驱动源码文件hello_driver.c#include linux/module.h #include linux/fs.h #include linux/cdev.h #include linux/device.h #include linux/uaccess.h #include linux/slab.h #define DEVICE_NAME hello_dev #define CLASS_NAME hello_class static int major_num; static struct class *hello_class NULL; static struct cdev hello_cdev; static char *buffer NULL; static size_t buffer_size 1024; // 设备打开函数 static int hello_open(struct inode *inode, struct file *file) { printk(KERN_INFO Hello driver: device opened\n); return 0; } // 设备释放函数 static int hello_release(struct inode *inode, struct file *file) { printk(KERN_INFO Hello driver: device closed\n); return 0; } // 设备读取函数 static ssize_t hello_read(struct file *file, char __user *user_buf, size_t count, loff_t *offset) { size_t len min(count, buffer_size); if (copy_to_user(user_buf, buffer, len)) { return -EFAULT; } printk(KERN_INFO Hello driver: read %zu bytes\n, len); return len; } // 设备写入函数 static ssize_t hello_write(struct file *file, const char __user *user_buf, size_t count, loff_t *offset) { size_t len min(count, buffer_size); if (copy_from_user(buffer, user_buf, len)) { return -EFAULT; } printk(KERN_INFO Hello driver: wrote %zu bytes\n, len); return len; } // 文件操作结构体 static struct file_operations hello_fops { .owner THIS_MODULE, .open hello_open, .release hello_release, .read hello_read, .write hello_write, }; // 模块初始化函数 static int __init hello_init(void) { dev_t dev_num; // 动态申请设备号 if (alloc_chrdev_region(dev_num, 0, 1, DEVICE_NAME) 0) { printk(KERN_ALERT Failed to allocate device number\n); return -1; } major_num MAJOR(dev_num); // 创建字符设备 cdev_init(hello_cdev, hello_fops); if (cdev_add(hello_cdev, dev_num, 1) 0) { unregister_chrdev_region(dev_num, 1); printk(KERN_ALERT Failed to add cdev\n); return -1; } // 创建设备类 hello_class class_create(THIS_MODULE, CLASS_NAME); if (IS_ERR(hello_class)) { cdev_del(hello_cdev); unregister_chrdev_region(dev_num, 1); printk(KERN_ALERT Failed to create class\n); return PTR_ERR(hello_class); } // 在 /dev 下创建设备节点 device_create(hello_class, NULL, dev_num, NULL, DEVICE_NAME); // 分配缓冲区 buffer kzalloc(buffer_size, GFP_KERNEL); if (!buffer) { device_destroy(hello_class, dev_num); class_destroy(hello_class); cdev_del(hello_cdev); unregister_chrdev_region(dev_num, 1); printk(KERN_ALERT Failed to allocate buffer\n); return -ENOMEM; } printk(KERN_INFO Hello driver loaded with major number %d\n, major_num); return 0; } // 模块清理函数 static void __exit hello_exit(void) { dev_t dev_num MKDEV(major_num, 0); device_destroy(hello_class, dev_num); class_destroy(hello_class); cdev_del(hello_cdev); unregister_chrdev_region(dev_num, 1); kfree(buffer); printk(KERN_INFO Hello driver unloaded\n); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE(GPL); MODULE_AUTHOR(Your Name); MODULE_DESCRIPTION(A simple hello world character device driver);3.2 编译驱动模块的 Makefile 配置为驱动代码编写对应的 Makefile# 指定内核源码路径根据实际路径修改 KDIR : /path/to/your/kernel # 指定架构和交叉编译工具链 ARCH : arm64 CROSS_COMPILE : aarch64-linux-gnu- # 模块目标名称 obj-m hello_driver.o all: $(MAKE) -C $(KDIR) M$(PWD) ARCH$(ARCH) CROSS_COMPILE$(CROSS_COMPILE) modules clean: $(MAKE) -C $(KDIR) M$(PWD) ARCH$(ARCH) CROSS_COMPILE$(CROSS_COMPILE) clean .PHONY: all clean编译驱动模块make成功编译后将生成hello_driver.ko文件这就是可加载到 RK3568 内核的驱动模块。3.3 在开发板上测试驱动模块1. 将模块文件传输到开发板使用 ADB 或 SCP 将编译好的模块文件传输到开发板adb push hello_driver.ko /data/2. 加载驱动模块在开发板的终端中执行# 切换到模块所在目录 cd /data # 加载模块 insmod hello_driver.ko # 检查模块是否加载成功 lsmod | grep hello_driver # 查看内核日志确认初始化信息 dmesg | tail -103. 测试设备节点功能驱动加载后会在/dev下生成hello_dev设备节点# 检查设备节点是否存在 ls -l /dev/hello_dev # 测试写入功能 echo test message /dev/hello_dev # 测试读取功能 cat /dev/hello_dev # 查看操作日志 dmesg | tail -54. 卸载驱动模块测试完成后卸载模块rmmod hello_driver4. Android 15 系统下的驱动集成与 HAL 适配4.1 将驱动集成到 Android 系统镜像在原型验证通过后需要将驱动正式集成到 Android 系统构建流程中使其随系统启动自动加载。1. 将驱动源码放入内核目录在内核源码的drivers/char/目录下创建hello_driver/文件夹将hello_driver.c和Kconfig、Makefile放入其中。配置 Kconfig 文件# drivers/char/hello_driver/Kconfig config HELLO_DRIVER tristate Simple Hello World Driver default n help This is a simple hello world character device driver for demonstration.配置 Makefile 文件# drivers/char/hello_driver/Makefile obj-$(CONFIG_HELLO_DRIVER) hello_driver.o2. 修改上层 Kconfig 和 Makefile在drivers/char/Kconfig中添加source drivers/char/hello_driver/Kconfig在drivers/char/Makefile中添加obj-$(CONFIG_HELLO_DRIVER) hello_driver/3. 配置内核并重新编译在menuconfig中启用该驱动make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- menuconfig导航到Device Drivers → Character devices → Simple Hello World Driver选择M编译为模块或*编译进内核。重新编译内核和模块make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- -j$(nproc) make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- modules4.2 为驱动编写 Android HAL 层在 Android 系统中应用层通常不直接访问内核驱动而是通过 HALHardware Abstraction Layer进行交互。以下为 hello_driver 创建一个简单的 HAL 服务。1. 创建 HAL 接口定义文件在hardware/interfaces/hello/1.0/目录下创建IHello.halpackage android.hardware.hello1.0; interface IHello { write(string data) generates (bool success); read() generates (string data); };2. 生成 HAL 代码框架使用hidl-gen工具生成代码框架hidl-gen -o hardware/interfaces/hello/1.0/default/ \ -Lc-impl -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport android.hardware.hello1.0 hidl-gen -o hardware/interfaces/hello/1.0/default/ \ -Landroidbp-impl -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport android.hardware.hello1.03. 实现 HAL 服务在生成的Hello.cpp中实现具体的读写逻辑#include hidl/LegacySupport.h #include hidl/HidlSupport.h #include Hello.h #include fcntl.h #include unistd.h #include string using android::hardware::hello::V1_0::IHello; using android::hardware::Return; using android::hardware::Void; struct Hello : public IHello { Returnbool write(const hidl_string data) override { int fd open(/dev/hello_dev, O_WRONLY); if (fd 0) return false; ssize_t ret ::write(fd, data.c_str(), data.size()); close(fd); return (ret (ssize_t)data.size()); } Returnhidl_string read() override { int fd open(/dev/hello_dev, O_RDONLY); if (fd 0) return hidl_string(); char buffer[1024]; ssize_t ret ::read(fd, buffer, sizeof(buffer)-1); close(fd); if (ret 0) { buffer[ret] \0; return hidl_string(buffer); } return hidl_string(); } }; int main() { return android::hardware::configureRpcThreadpool(1, true) | android::hardware::registerAsService(new Hello()); }4. 配置 SELinux 策略在device/rockchip/rk3568/sepolicy/中添加策略文件允许 HAL 服务访问设备节点# hello_driver.te type hello_device, dev_type; type hello_service, system_api_service_type, service_manager_type; allow hello_service hello_device:chr_file { open read write };4.3 集成到 Android 构建系统1. 修改设备配置在设备 Makefile 中添加# device/rockchip/rk3568/device.mk PRODUCT_PACKAGES \ android.hardware.hello1.0-service2. 编译并刷写系统重新编译 Android 系统并刷写到开发板source build/envsetup.sh lunch rk3568-userdebug make -j$(nproc) # 刷写系统 fastboot flash boot out/target/product/rk3568/boot.img fastboot flash system out/target/product/rk3568/system.img fastboot reboot5. 驱动开发中的常见问题与排查方法5.1 编译阶段问题排查问题 1交叉编译工具链不匹配现象编译时出现未定义的架构相关错误。排查检查工具链版本与内核配置是否一致。解决使用内核源码目录中scripts/diffconfig对比配置差异或使用厂商推荐的工具链。问题 2内核头文件缺失现象编译驱动时找不到头文件。排查确认KDIR路径正确且已执行make modules_prepare。解决完整编译一次内核确保头文件生成。5.2 运行时问题排查问题 1模块加载失败现象insmod返回 Invalid module format 或 Unknown symbol。排查步骤检查内核版本是否匹配uname -r与编译时内核版本一致查看详细错误信息dmesg | tail -20检查符号依赖modinfo hello_driver.ko问题 2设备节点权限不足现象应用层无法打开设备节点。排查检查/dev/hello_dev的权限和所属组。解决在 init 脚本中设置正确权限或配置 udev 规则。5.3 调试技巧与工具使用1. 内核日志分级查看使用dmesg查看内核日志可通过级别过滤重要信息# 只显示错误和警告信息 dmesg -l err,warn # 实时监控新日志 dmesg -w2. 使用 printk 调试在驱动代码中合理添加 printk 语句注意日志级别printk(KERN_DEBUG Debug: variable value %d\n, var); // 调试信息 printk(KERN_INFO Info: device opened\n); // 普通信息 printk(KERN_WARNING Warning: unusual condition\n); // 警告 printk(KERN_ERR Error: operation failed\n); // 错误3. 使用 strace 跟踪系统调用在应用层调试时使用 strace 跟踪对设备节点的访问strace -e open,read,write,ioctl cat /dev/hello_dev6. 生产环境驱动开发最佳实践6.1 代码质量与维护性1. 错误处理要完整每个可能失败的操作都要有错误处理确保资源正确释放int example_probe(struct platform_device *pdev) { struct resource *res; void __iomem *base; res platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(pdev-dev, Failed to get memory resource\n); return -ENODEV; } base devm_ioremap_resource(pdev-dev, res); if (IS_ERR(base)) { dev_err(pdev-dev, Failed to map memory\n); return PTR_ERR(base); } // ... 其他初始化代码 return 0; }2. 使用 devm_ 资源管理函数自动管理资源生命周期避免内存泄漏// 传统方式需要手动释放 ptr kmalloc(size, GFP_KERNEL); // ... 使用 ptr kfree(ptr); // 推荐方式自动释放 ptr devm_kzalloc(pdev-dev, size, GFP_KERNEL);6.2 性能与稳定性考量1. 避免在中断上下文中进行耗时操作将耗时任务推送到工作队列或线程中执行static struct work_struct my_work; static void my_work_handler(struct work_struct *work) { // 耗时操作 msleep(100); printk(KERN_INFO Work completed\n); } // 在中断处理函数中调度工作 irqreturn_t my_interrupt_handler(int irq, void *dev_id) { schedule_work(my_work); return IRQ_HANDLED; }2. 合理使用互斥锁保护共享资源确保多线程访问时的数据一致性static DEFINE_MUTEX(my_lock); static int shared_data; static ssize_t my_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { int ret; mutex_lock(my_lock); // 读写共享数据 ret copy_to_user(buf, shared_data, sizeof(shared_data)); mutex_unlock(my_lock); return ret; }6.3 电源管理适配为驱动添加电源管理支持确保系统休眠时正确处理设备状态static int my_suspend(struct device *dev) { struct my_device *my_dev dev_get_drvdata(dev); // 保存设备状态 my_dev-saved_reg readl(my_dev-base REG_OFFSET); // 关闭设备时钟或电源 clk_disable(my_dev-clk); return 0; } static int my_resume(struct device *dev) { struct my_device *my_dev dev_get_drvdata(dev); // 恢复时钟和电源 clk_enable(my_dev-clk); // 恢复设备状态 writel(my_dev-saved_reg, my_dev-base REG_OFFSET); return 0; } static const struct dev_pm_ops my_pm_ops { .suspend my_suspend, .resume my_resume, };RK3568 的 Android 15 驱动开发需要平衡功能实现、系统稳定性和长期维护成本。从最简单的字符设备开始逐步掌握平台设备、中断处理、DMA 传输等复杂机制最终能够为复杂外设编写完整的驱动栈。在实际项目中建议先通过模块化开发验证基本功能再集成到系统镜像并建立完整的测试和调试流程。

相关新闻

APDS-9960传感器实战:从I2C通信到色彩校准的嵌入式开发指南

APDS-9960传感器实战:从I2C通信到色彩校准的嵌入式开发指南

1. 项目缘起:从“免费试用”到“深度把玩”的契机最近在逛一些硬件开发社区时,发现了一个挺有意思的免费试用活动,主角是一款集成了红外手势识别、RGB颜色检测和环境光检测的传感器模块。说实话,这类“三合一”的传感器在创客圈里…

2026/7/29 2:22:18阅读更多 →
SteamAutoCrack完整指南:3步轻松实现游戏DRM自动破解

SteamAutoCrack完整指南:3步轻松实现游戏DRM自动破解

SteamAutoCrack完整指南:3步轻松实现游戏DRM自动破解 【免费下载链接】Steam-auto-crack Steam Game Automatic Cracker 项目地址: https://gitcode.com/gh_mirrors/st/Steam-auto-crack SteamAutoCrack是一款专业的Steam游戏自动破解工具,能够帮…

2026/7/29 2:22:18阅读更多 →
OPENC函数在CAM/NC编程中的高效应用与优化技巧

OPENC函数在CAM/NC编程中的高效应用与优化技巧

1. OPENC函数在CAM/NC编程中的核心价值解析在机械加工领域,OPENC函数库中的UF_CAM和UF_NCGROUP模块组堪称数控编程的"瑞士军刀"。作为NX/UG二次开发的核心接口,它们直接打通了CAD模型到G代码的自动化通道。我使用这套API完成过五轴联动叶轮加工…

2026/7/29 2:22:18阅读更多 →
Maven Surefire与Failsafe插件实现单元测试与集成测试分离的完整指南

Maven Surefire与Failsafe插件实现单元测试与集成测试分离的完整指南

1. 项目概述:为什么我们需要分离单元测试与集成测试?在Java后端开发中,测试是保证代码质量的基石。但很多团队,尤其是项目初期,往往会把所有测试一股脑地扔给Maven Surefire插件去执行。这会导致一个典型问题&#xff…

2026/7/29 3:26:31阅读更多 →
自注意力机制原理与Transformer模型实践指南

自注意力机制原理与Transformer模型实践指南

1. 从生活场景理解自注意力机制想象你正在阅读一本侦探小说,主角在犯罪现场发现了几十个线索。普通人的做法可能是按顺序逐个查看每个线索,但侦探会怎么做?他会快速扫视所有线索,然后:重点关注带血的匕首(相…

2026/7/29 3:26:31阅读更多 →
Qt6自定义QML组件加载失败:从原理到CMake配置的完整解决方案

Qt6自定义QML组件加载失败:从原理到CMake配置的完整解决方案

1. 从一次“文件找不到”的报错说起 最近在把项目从 Qt5 升级到 Qt6 的过程中,我遇到了一个挺典型的坑:在尝试加载一个自定义的 QML 文件时,程序直接崩溃了,控制台抛出的错误信息是 file:///.../MyCustomComponent.qml: No such …

2026/7/29 3:26:31阅读更多 →
Brocade 交换机进入 EOS 后,为什么有些命令不能使用?

Brocade 交换机进入 EOS 后,为什么有些命令不能使用?

写在前面近期越来越多的用户反馈在维护 Brocade 光纤交换机时,会发现原来可以执行的命令突然失败,例如:This product has passed its End of Support date and functionality has been restricted.Please contact your Service Provider for …

2026/7/29 3:26:31阅读更多 →
黄仁勋牵头组建Open Secure AI Alliance:一场AI自主攻击事件如何倒逼全球科技巨头联手

黄仁勋牵头组建Open Secure AI Alliance:一场AI自主攻击事件如何倒逼全球科技巨头联手

2026年7月下旬,硅谷发生了一件足以改写网络安全史的事件。OpenAI在一次内部模型能力评估中,其前沿AI系统竟自主突破了隔离环境,对开源AI平台Hugging Face发起了一场完整的网络入侵。这场"自己人打自己人"的意外,没有演变…

2026/7/29 3:26:31阅读更多 →
庭院设计中硬景和软景的基本概念与分类

庭院设计中硬景和软景的基本概念与分类

前阵子有个业主朋友发来一张照片,是他在自家院子里铺完石材后的效果。整个院子看起来硬邦邦的,像个小广场,完全没有花园该有的生机。他问我:“我是不是买错材料了?”其实不是材料的问题,是他对庭院设计里两…

2026/7/29 3:24:30阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/28 4:06:39阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/28 2:08:06阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/28 1:38:28阅读更多 →
28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“!

28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“!

28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“! 在构建复杂的 Agent 系统时,我们经常会遇到这样的场景:Agent 正在执行一个多步骤的任务,比如“下单购买商品”,但执行到一半时,我们…

2026/7/29 0:01:46阅读更多 →
自律同行,突破无界!NANK南卡正式官宣曾舜晞成为品牌代言人

自律同行,突破无界!NANK南卡正式官宣曾舜晞成为品牌代言人

近日,国际专注开放式技术研发的声学品牌Nank南卡,正式官宣实力艺人曾舜晞担任品牌代言人。消息一经发出便轰动全网。为什么耳机品牌不选择流量明星、老牌歌手?而且是选择曾舜晞?让我们一起来探索一下!比起短期的流量&a…

2026/7/29 0:01:46阅读更多 →
【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

一、本文介绍 🔥本文在RT-DETR多模态融合目标检测中引入RLAB残差线性注意力模块,可在不同模态特征交互阶段进行多次残差细化,使可见光、红外等特征在尺度、语义和空间位置上更好对齐;随后将细化特征与解码器输出拼接并生成Q、K、V,通过线性注意力自适应强化关键通道、目…

2026/7/29 0:01:46阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/28 20:22:24阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/28 3:17:03阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/28 2:35:58阅读更多 →