手把手教你写RISC-V驱动,C语言实战案例全解析

第一章:RISC-V架构与嵌入式驱动开发概述

RISC-V 是一种基于精简指令集计算(RISC)原则的开源指令集架构(ISA),因其模块化、可扩展和开放授权的特点,正在嵌入式系统和高性能计算领域迅速普及。该架构由加州大学伯克利分校于2010年首次发布,采用宽松的BSD许可证,允许学术界和工业界自由实现和优化,无需支付专利费用。

RISC-V 架构的核心优势

  • 完全开源且无厂商锁定,适合定制化SoC设计
  • 模块化指令集,支持从微控制器到服务器级处理器的广泛实现
  • 清晰的特权架构定义,包含用户态(U)、监督态(S)和机器态(M)

嵌入式驱动开发的关键挑战

在 RISC-V 平台上进行设备驱动开发时,开发者需直接与硬件寄存器交互,并处理中断、内存映射和外设初始化等底层操作。由于缺乏统一的固件标准(如x86的BIOS或ARM的UEFI),通常依赖 OpenSBI 或自定义启动加载程序来提供运行环境。 例如,在初始化一个GPIO控制器时,典型的内存映射访问方式如下:
// 假设GPIO基地址为0x10012000 #define GPIO_BASE_ADDR ((volatile uint32_t*)0x10012000) void gpio_init() { GPIO_BASE_ADDR[0] = 0x1; // 设置引脚方向为输出 GPIO_BASE_ADDR[1] = 0x1; // 输出高电平 }
上述代码通过直接写入内存映射寄存器配置GPIO功能,体现了裸机编程中对物理地址空间的精确控制。

典型开发工具链组成

组件常用工具说明
编译器riscv64-unknown-elf-gcc用于生成RISC-V目标代码
调试器OpenOCD + GDB支持JTAG/SWD硬件调试
仿真器QEMU快速验证驱动逻辑
graph TD A[源代码 .c/.s] --> B(riscv64-elf-gcc) B --> C[可执行文件 .elf] C --> D(OpenOCD) D --> E[JTAG调试器] E --> F[FPGA/ASIC目标板]

第二章:RISC-V基础外设驱动开发实战

2.1 RISC-V内存映射与寄存器访问机制

RISC-V架构采用统一的内存映射I/O机制,外设寄存器通过特定地址段映射到物理内存空间,CPU使用标准的加载(load)和存储(store)指令进行访问。
内存区域划分
典型的RISC-V系统将4GB地址空间划分为多个区域:
  • 0x0000_0000 – 0x7FFF_FFFF:主内存区
  • 0x8000_0000 – 0x8000_FFFF:片上外设寄存器
  • 0xFFFF_F000 – 0xFFFF_FFFF:调试与异常向量区
寄存器访问示例
// 访问UART控制寄存器 #define UART_CTRL_REG (*(volatile uint32_t*)0x80001000) UART_CTRL_REG = 0x1; // 启动发送
上述代码通过强制类型转换将物理地址映射为可操作的指针,volatile确保编译器不优化重复读写。该机制避免专用I/O指令,简化了指令集设计。

2.2 GPIO驱动编写:点亮第一个LED

初始化GPIO引脚
在嵌入式系统中,控制LED需要配置通用输入输出(GPIO)引脚为输出模式。通常通过写入寄存器完成。
// 配置GPIOB的第5位为输出模式 *(volatile unsigned int*)0x40020C00 = 0x1 << 10; // MODER5 = 01 (输出模式)
该代码将地址0x40020C00(GPIOB的MODER寄存器)的第10、11位设置为01,表示PB5工作在通用输出模式。
控制LED亮灭
通过操作ODR(Output Data Register)可改变引脚电平状态。
  • BSRR |= 1 << 5:置高PB5引脚,关闭LED(共阴极接法)
  • BRR |= 1 << 5:拉低PB5引脚,点亮LED
实际应用中需结合硬件连接方式判断高低电平对应的灯状态。

2.3 UART串口通信驱动实现与调试

驱动架构设计
Linux内核中UART驱动基于tty子系统实现,需注册platform_driver并实现核心操作集。关键结构体为`uart_ops`,定义了发送、接收、初始化等回调函数。
static struct uart_ops stm32_uart_ops = { .tx_empty = stm32_uart_tx_empty, .set_mctrl = stm32_uart_set_mctrl, .get_mctrl = stm32_uart_get_mctrl, .stop_tx = stm32_uart_stop_tx, .start_tx = stm32_uart_start_tx, .stop_rx = stm32_uart_stop_rx, };
上述代码注册串口操作函数集,其中`start_tx`用于启动数据发送,由内核在有数据待发时调用。
中断处理与数据收发
使用中断方式实现非阻塞通信,接收数据通过IRQ标志位触发读取。需配置FIFO阈值以平衡响应延迟与中断频率。
寄存器功能典型值
USART_CR1控制寄存器1UE=1, RE=1, TE=1
USART_BRR波特率寄存器0x0683 (115200@72MHz)

2.4 定时器中断驱动与系统滴答配置

在嵌入式实时操作系统中,定时器中断是实现任务调度和时间管理的核心机制。系统滴答(SysTick)通常由硬件定时器提供,周期性触发中断,驱动内核的时间片轮转与延时处理。
系统滴答的典型配置流程
  • 初始化硬件定时器,设定重装载值以确定滴答频率
  • 配置中断优先级并使能中断
  • 注册中断服务例程(ISR),调用系统节拍处理函数
代码示例:ARM Cortex-M SysTick 配置
// 设置SysTick为1ms中断 SysTick_Config(SystemCoreClock / 1000);
该代码将系统时钟分频后加载到重装载寄存器,每毫秒触发一次中断。SystemCoreClock 表示CPU主频,除以1000实现1ms周期。
中断服务例程中的关键操作

中断触发 → 保存上下文 → 调用xPortSysTickHandler() → 调度决策 → 恢复上下文

2.5 外部中断与按键检测驱动开发

在嵌入式系统中,外部中断是实现低功耗、实时响应用户输入的关键机制。通过配置GPIO引脚为中断触发模式,可使MCU在检测到电平变化时立即执行中断服务程序(ISR)。
中断初始化配置
以下代码展示了如何在STM32平台注册外部中断:
// 配置PA0为外部中断输入 EXTI_InitTypeDef EXTI_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0); EXTI_InitStruct.EXTI_Line = EXTI_Line0; EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿触发 EXTI_InitStruct.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStruct); NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x01; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_SetVectorTable(NVIC_InitStruct);
上述配置将PA0引脚连接的按键按下事件(下降沿)作为中断源,避免轮询浪费CPU资源。
去抖动处理策略
机械按键存在物理抖动,需在软件或硬件层面滤波。常用方法包括:
  • 硬件RC滤波电路
  • 中断内延时20ms后再次读取电平状态
  • 使用定时器配合状态机实现精准去抖

第三章:总线协议驱动原理与C语言实现

3.1 I2C总线协议解析与主机驱动编写

I2C(Inter-Integrated Circuit)是一种双线制串行通信协议,广泛用于连接低速外围设备。它仅需两根信号线:SDA(数据线)和SCL(时钟线),支持多主多从架构。
协议核心机制
I2C通过起始位、地址帧、读写位、应答位和停止位完成一次通信。每个从设备具有唯一7位或10位地址,主机在发起通信时首先广播目标地址并等待从机应答。
信号阶段功能说明
起始条件SDA由高变低,SCL保持高电平
停止条件SDA由低变高,SCL保持高电平
ACK/NACK第9个时钟周期,从机拉低SDA表示应答
Linux主机驱动示例
static int i2c_host_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { int ret = 0; for (int i = 0; i < num; i++) { if (msgs[i].flags & I2C_M_RD) ret = read_from_slave(adap, &msgs[i]); // 读操作 else ret = write_to_slave(adap, &msgs[i]); // 写操作 if (ret) break; } return ret; }
该函数遍历消息数组,根据标志位判断读写方向。read_from_slave 和 write_to_slave 实现底层时序控制,确保符合I2C电气规范。参数adap代表适配器实例,msgs为通信消息体,num为消息数量。

3.2 SPI通信驱动设计与Flash读写实践

在嵌入式系统中,SPI(Serial Peripheral Interface)是连接微控制器与外部存储器如Flash芯片的常用高速同步串行总线。其四线制结构(SCLK、MOSI、MISO、CS)支持全双工通信,适用于对性能要求较高的数据存储场景。
SPI初始化配置
驱动设计首先需完成SPI外设的时钟、引脚及工作模式配置。多数Flash芯片支持SPI模式0(CPOL=0, CPHA=0),即空闲时钟低电平、数据在第一个时钟边沿采样。
spi_config_t config = { .mode = SPI_MODE0, .baudrate = 4000000, // 4MHz通信速率 .direction = SPI_DIR_2LINES, }; spi_init(SPI1, &config);
上述代码设置SPI为模式0,通信速率达4MHz,兼顾稳定性与速度。过高的波特率可能导致信号完整性下降,需根据PCB布局和器件规格权衡。
Flash读写操作流程
典型操作包括写使能、页编程、读取数据等指令序列。每次写前必须发送写使能命令(0x06),随后执行页写(0x02)并等待内部写完成。
  • 拉低片选(CS)启动通信
  • 发送操作码与地址
  • 传输数据并释放片选
  • 轮询状态寄存器直至操作完成

3.3 基于MMIO的设备通信接口编程

在嵌入式系统与操作系统底层开发中,内存映射I/O(Memory-Mapped I/O, MMIO)是CPU与外设通信的核心机制。通过将设备寄存器映射到内存地址空间,处理器可使用常规读写指令访问硬件。
MMIO地址映射流程
系统启动时,设备树或ACPI表提供外设寄存器的物理地址。内核使用`ioremap`将其映射至虚拟地址空间:
void __iomem *base = ioremap(PHYS_ADDR, SIZE); writel(value, base + REG_OFFSET); // 写寄存器 value = readl(base + REG_OFFSET); // 读寄存器
其中,PHYS_ADDR为设备控制寄存器物理地址,REG_OFFSET表示寄存器偏移量。通过writelreadl实现对映射内存的访问,实际操作的是硬件寄存器。
典型应用场景
  • 网络控制器配置
  • GPIO状态读写
  • 中断控制器编程

第四章:操作系统级驱动集成与优化

4.1 设备树(Device Tree)在RISC-V中的应用

设备树(Device Tree)是一种描述硬件资源与结构的标准化数据格式,在RISC-V架构中广泛用于实现内核与硬件平台的解耦。通过将CPU、内存、外设等信息以层次化方式组织,设备树使同一内核镜像可适配多种硬件配置。
设备树的核心结构
一个典型的设备树由节点和属性构成,根节点 `/` 包含 `cpus`、`memory` 和 `soc` 等子节点。每个节点描述特定硬件的功能参数。
/ { cpus { #address-cells = <1>; cpu@0 { device_type = "cpu"; reg = <0>; compatible = "riscv"; }; }; memory@80000000 { device_type = "memory"; reg = <0x80000000 0x10000000>; // 起始地址与大小 }; };
上述代码定义了一个单核RISC-V处理器及其512MB内存空间。`reg` 属性表示物理地址和长度,`compatible` 指明驱动匹配依据。
与内核的交互流程
启动阶段,引导程序(如OpenSBI)将设备树二进制文件(.dtb)加载至内存,并将其地址传入内核入口。Linux内核据此解析硬件拓扑,动态加载对应驱动模块。

4.2 驱动与裸机运行时环境的接口封装

在嵌入式系统开发中,驱动程序需与裸机运行时环境无缝对接。为实现硬件抽象与代码可移植性,通常采用接口封装技术,将底层寄存器操作统一为高层API。
接口设计原则
封装应遵循最小暴露原则,仅提供必要的初始化、读写和中断处理接口。通过函数指针结构体模拟面向对象的虚表机制,提升扩展性。
typedef struct { int (*init)(void); int (*read)(uint8_t *buf, size_t len); int (*write)(const uint8_t *buf, size_t len); void (*irq_handler)(void); } driver_ops_t;
上述结构体定义了标准操作集,各具体驱动(如UART、SPI)实现对应函数并注册实例。运行时环境通过统一入口调用,无需感知底层细节。
运行时集成
系统启动后,由运行时环境遍历注册的驱动列表,逐个调用初始化函数,建立中断向量映射,完成资源绑定,确保驱动与硬件同步就绪。

4.3 中断服务例程(ISR)的高效注册与管理

在现代操作系统中,中断服务例程(ISR)的注册与管理直接影响系统响应速度与稳定性。高效的ISR机制需支持动态注册、优先级调度与快速上下文切换。
ISR注册流程设计
采用函数指针数组实现中断向量表,允许运行时绑定处理函数。每个中断源对应唯一索引,提升分发效率。
void register_isr(int irq, void (*handler)(void)) { interrupt_vector[irq] = handler; // 绑定处理函数 enable_irq(irq); // 使能中断 }
上述代码将指定中断请求(IRQ)与处理函数关联,并启用硬件中断。`handler`为无参数无返回的回调函数,确保调用轻量。
中断优先级管理
使用优先级队列对共享中断进行排序处理,避免高频率中断导致低优先级任务饥饿。
  • 优先级基于中断类型设定:硬件故障 > I/O事件 > 定时器
  • 支持嵌套中断,高优先级可抢占低优先级执行
  • 临界区通过关中断保护共享数据

4.4 驱动代码的可移植性设计与宏优化

在跨平台驱动开发中,可移植性是核心考量。通过抽象硬件差异、统一接口定义,可大幅提升代码复用能力。
使用条件编译适配平台差异
#ifdef PLATFORM_X86 #define IO_DELAY() outb(0x80, 0) #elif defined(PLATFORM_ARM) #define IO_DELAY() __asm__ volatile("mov r0, r0" ::: "memory") #endif
该宏根据目标架构插入合适的I/O延迟指令,x86使用空端口写,ARM则插入内存屏障,确保时序正确。
宏封装提升抽象层级
  • 将寄存器访问封装为宏,屏蔽地址映射差异
  • 统一错误码映射,简化错误处理逻辑
  • 利用宏参数实现类型无关的操作模板

第五章:未来展望:RISC-V生态与驱动开发趋势

开源硬件的加速普及
随着SiFive、Andes Technology等厂商推动高性能RISC-V处理器落地,越来越多嵌入式设备开始采用该架构。例如,阿里平头哥的C910处理器已应用于AIoT场景,其Linux内核驱动模块通过GitHub开源,开发者可直接编译适配定制化主板。
驱动开发工具链演进
现代RISC-V平台逐步支持Device Tree Overlay机制,动态加载外设描述成为可能。以下为添加I2C传感器的片段示例:
// i2c-sensor-overlay.dts /dts-v1/; /plugin/; / { fragment@0 { target = <&i2c0>; __overlay__ { status = "okay"; hdc1080: hdc1080@40 { compatible = "ti,hdc1080"; reg = <0x40>; }; }; }; };
跨平台兼容性挑战与应对
不同厂商对PLIC(Platform-Level Interrupt Controller)实现存在差异,导致中断处理代码难以复用。社区正推动标准化头文件统一接口定义:
  • 使用Kconfig分离架构特异性配置
  • 引入libfdt库解析运行时设备树信息
  • 通过kselftest框架验证中断路由正确性
安全驱动的新范式
在可信执行环境(TEE)中,RISC-V的SMEP/SMAP扩展被用于隔离用户态DMA操作。某工业控制器案例中,驱动通过PMP(Physical Memory Protection)区域设置实现外设访问白名单:
RegionBase AddressSize (KB)Permissions
PMP00x8000_00004RWX
PMP10x8000_100064RW--

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1152633.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

纪念币预约自动化工具:告别手动抢购的终极指南

纪念币预约自动化工具&#xff1a;告别手动抢购的终极指南 【免费下载链接】auto_commemorative_coin_booking 项目地址: https://gitcode.com/gh_mirrors/au/auto_commemorative_coin_booking 还在为纪念币预约的激烈竞争而烦恼吗&#xff1f;这款纪念币预约自动化工具…

AI人脸隐私卫士部署教程:金融行业隐私保护方案

AI人脸隐私卫士部署教程&#xff1a;金融行业隐私保护方案 1. 引言 在金融、医疗、政务等对数据安全要求极高的行业中&#xff0c;图像和视频中的人脸信息泄露风险日益突出。传统的手动打码方式效率低下、易遗漏&#xff0c;而依赖云端服务的自动化方案又存在数据外泄隐患。为…

Screen Translator实用指南:屏幕翻译工具操作手册

Screen Translator实用指南&#xff1a;屏幕翻译工具操作手册 【免费下载链接】ScreenTranslator Screen capture, OCR and translation tool. 项目地址: https://gitcode.com/gh_mirrors/sc/ScreenTranslator Screen Translator作为一款集屏幕捕捉、文字识别与多引擎翻…

你还在忽略嵌入式安全?这5个编码错误可能导致系统崩溃!

第一章&#xff1a;嵌入式安全的现状与挑战 随着物联网&#xff08;IoT&#xff09;设备的迅猛普及&#xff0c;嵌入式系统已广泛应用于智能家居、工业控制、医疗设备和汽车电子等领域。然而&#xff0c;这些设备往往资源受限&#xff0c;缺乏足够的计算能力和存储空间来部署传…

Screen Translator:智能屏幕翻译工具全面解析

Screen Translator&#xff1a;智能屏幕翻译工具全面解析 【免费下载链接】ScreenTranslator Screen capture, OCR and translation tool. 项目地址: https://gitcode.com/gh_mirrors/sc/ScreenTranslator Screen Translator是一款功能强大的开源屏幕翻译工具&#xff0…

MediaPipe人脸检测实战:智能打码系统部署参数详解

MediaPipe人脸检测实战&#xff1a;智能打码系统部署参数详解 1. 引言&#xff1a;AI 人脸隐私卫士 - 智能自动打码 在社交媒体、公共展示和数据共享日益频繁的今天&#xff0c;图像中的人脸隐私泄露风险正成为不可忽视的安全隐患。一张未经处理的合照可能暴露多人身份信息&a…

性能翻倍:Qwen3-VL-2B-Instruct视频理解优化技巧

性能翻倍&#xff1a;Qwen3-VL-2B-Instruct视频理解优化技巧 1. 引言 随着多模态大模型在视觉-语言任务中的广泛应用&#xff0c;Qwen3-VL-2B-Instruct作为阿里云最新推出的轻量级视觉语言模型&#xff0c;凭借其卓越的视频理解能力与高效的推理性能&#xff0c;正迅速成为边…

Multisim14.3安装常见问题及解决方法实战案例

Multisim 14.3 安装踩坑实录&#xff1a;从报错到成功的全流程排障指南 你是不是也曾在深夜对着“Setup Wizard ended prematurely”发呆&#xff1f;下载了几个小时的 Multisim 14.3&#xff0c;解压后刚点开 setup.exe 就弹窗退出&#xff1b;或者安装完成却提示“未找到有效…

效果惊艳!HY-MT1.5-1.8B打造的实时翻译案例

效果惊艳&#xff01;HY-MT1.5-1.8B打造的实时翻译案例 1. 引言 在全球化内容传播日益频繁的今天&#xff0c;实时翻译技术已成为跨语言沟通的关键支撑。无论是国际直播、在线教育&#xff0c;还是跨国会议&#xff0c;用户对低延迟、高准确率的字幕生成需求持续攀升。腾讯开…

如何用AzurLaneAutoScript实现全自动化游戏管理:新手完整指南

如何用AzurLaneAutoScript实现全自动化游戏管理&#xff1a;新手完整指南 【免费下载链接】AzurLaneAutoScript Azur Lane bot (CN/EN/JP/TW) 碧蓝航线脚本 | 无缝委托科研&#xff0c;全自动大世界 项目地址: https://gitcode.com/gh_mirrors/az/AzurLaneAutoScript Az…

Windows右键菜单优化全攻略:告别臃肿,重获清爽体验

Windows右键菜单优化全攻略&#xff1a;告别臃肿&#xff0c;重获清爽体验 【免费下载链接】ContextMenuManager &#x1f5b1;️ 纯粹的Windows右键菜单管理程序 项目地址: https://gitcode.com/gh_mirrors/co/ContextMenuManager 你是否曾经在Windows系统中遇到过这样…

百度网盘云存储加速技术实战:突破下载瓶颈的终极方案

百度网盘云存储加速技术实战&#xff1a;突破下载瓶颈的终极方案 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 在数字资源日益丰富的今天&#xff0c;云存储加速和下载优化已…

人脸打码效果对比:传统方法与AI方案差异分析

人脸打码效果对比&#xff1a;传统方法与AI方案差异分析 1. 引言&#xff1a;为何需要智能人脸隐私保护&#xff1f; 随着社交媒体和数字影像的普及&#xff0c;个人隐私泄露风险日益加剧。在发布合照、街拍或监控截图时&#xff0c;未经处理的人脸信息极易被滥用&#xff0c…

智能打码系统部署:从单机到分布式架构的演进

智能打码系统部署&#xff1a;从单机到分布式架构的演进 1. 背景与需求演进&#xff1a;为何需要架构升级&#xff1f; 随着数据隐私保护法规&#xff08;如《个人信息保护法》&#xff09;的逐步落地&#xff0c;图像中的人脸信息处理已成为企业合规的重要环节。传统的手动打…

Qwen3-VL-2B-Instruct效果惊艳!AI识图案例展示

Qwen3-VL-2B-Instruct效果惊艳&#xff01;AI识图案例展示 随着多模态大模型的快速发展&#xff0c;视觉语言模型&#xff08;VLM&#xff09;在图像理解、图文生成、GUI操作等场景中展现出前所未有的能力。阿里最新推出的 Qwen3-VL-2B-Instruct 模型&#xff0c;作为 Qwen 系…

性能翻倍!HY-MT1.5-1.8B量化部署优化技巧分享

性能翻倍&#xff01;HY-MT1.5-1.8B量化部署优化技巧分享 1. 引言&#xff1a;边缘端实时翻译的工程挑战 在多语言交互日益频繁的今天&#xff0c;高质量、低延迟的机器翻译服务已成为智能应用的核心能力之一。然而&#xff0c;传统大模型推理成本高、显存占用大&#xff0c;难…

Unity插件框架崩溃修复:深度剖析与终极解决方案

Unity插件框架崩溃修复&#xff1a;深度剖析与终极解决方案 【免费下载链接】BepInEx Unity / XNA game patcher and plugin framework 项目地址: https://gitcode.com/GitHub_Trending/be/BepInEx 在Unity游戏开发生态中&#xff0c;BepInEx作为备受推崇的插件框架&…

Azur Lane AutoScript技术深度解析:游戏自动化框架的设计与实践

Azur Lane AutoScript技术深度解析&#xff1a;游戏自动化框架的设计与实践 【免费下载链接】AzurLaneAutoScript Azur Lane bot (CN/EN/JP/TW) 碧蓝航线脚本 | 无缝委托科研&#xff0c;全自动大世界 项目地址: https://gitcode.com/gh_mirrors/az/AzurLaneAutoScript …

彻底掌控Windows右键菜单:ContextMenuManager完全使用手册

彻底掌控Windows右键菜单&#xff1a;ContextMenuManager完全使用手册 【免费下载链接】ContextMenuManager &#x1f5b1;️ 纯粹的Windows右键菜单管理程序 项目地址: https://gitcode.com/gh_mirrors/co/ContextMenuManager 你是不是也受够了Windows右键菜单的臃肿不…

Screen Translator:免费开源的屏幕翻译神器完整指南

Screen Translator&#xff1a;免费开源的屏幕翻译神器完整指南 【免费下载链接】ScreenTranslator Screen capture, OCR and translation tool. 项目地址: https://gitcode.com/gh_mirrors/sc/ScreenTranslator 作为一名经常需要处理外文资料的科研人员&#xff0c;我曾…