ESP32全链路硬件开发框架:JTAG统一接口与AI自动化调试实践

news2026/5/5 5:08:52
1. 项目概述为AI编码助手打造的ESP32全链路硬件开发框架如果你和我一样长期在嵌入式开发的一线摸爬滚打那你一定对“烧录-调试-修改-再烧录”这个循环深恶痛绝。每次修改一行代码都要经历编译、连接调试器、打开串口监视器、复位、观察日志、再断开这一系列繁琐操作。当项目复杂到一定程度尤其是需要AI助手比如Claude Code介入进行自动化代码生成和调试时这种传统工作流的割裂感就成了最大的瓶颈。AI可以写代码但它怎么“看”到硬件在运行时的真实状态怎么“感知”到程序崩溃时的寄存器值又怎么“实时”读取日志来判断自己的修改是否生效这正是esp-agentic-dev这个项目要解决的痛点。它不是一个简单的库或工具集而是一套纯JTAG、硬件在环Hardware-in-the-Loop的自动化开发框架。它的核心设计理念极其清晰将整个开发循环开发→编译→烧录→观察→调试的所有环节都统一到JTAG这一个物理接口和OpenOCD这一个控制平面上。这样一来无论是开发者还是AI编码助手都能通过一套稳定的命令行工具获得对ESP32目标板的完全、自主的控制权和近乎无限的观察能力。想象一下这个场景你告诉AI助手“给GPIO2添加一个每秒翻转一次的中断”。AI生成代码、编译、然后通过esp_target.py一键烧录并运行。紧接着它启动rtt_reader.py后台服务像打开一个文件一样持续读取来自芯片内存的实时日志。同时它可以通过esp_target.py decode GPIO.OUT命令直接读取并解析GPIO输出寄存器的每一个比特位亲眼“看到”引脚电平的变化。如果程序跑飞了AI可以立刻让CPU暂停通过GDB检查调用栈查看mcause寄存器确定异常原因修改代码后再次循环。整个过程无需人类手动切换任何工具、界面或线缆。这套框架的价值对于追求高效自动化的嵌入式开发者、以及希望将AI能力深度引入硬件开发流程的团队来说是革命性的。它让“智能体”Agent真正具备了在物理世界中“动手”和“观察”的能力将嵌入式开发从手动劳动密集型转向了可编程、可自动化的新范式。接下来我将为你彻底拆解这套框架的设计精髓、实操细节以及我趟过的那些坑。2. 框架核心设计为什么一切都要通过JTAG在深入命令行之前我们必须先理解esp-agentic-dev的架构哲学。它所有的设计选择都围绕一个目标为自动化智能体提供一个稳定、统一、无歧义的操作界面。2.1 摒弃传统混合接口确立JTAG的绝对核心地位传统的嵌入式开发流程是割裂的用JTAG或USB烧录器进行烧录和调试用UART串口打印日志用逻辑分析仪或示波器观察信号。对于AI来说这意味着它需要理解并管理多个完全不同的通信通道、协议和工具状态同步极其复杂且容易出错。esp-agentic-dev做出了一个大胆而明智的决定所有交互100%通过JTAG完成。这包括程序烧录通过OpenOCD内置的program_esp命令直接通过JTAG接口写入Flash。运行控制通过JTAG调试模块控制CPU的暂停、继续、复位。内存与寄存器访问通过JTAG的DAP调试访问端口直接读写内存和所有外设寄存器。日志输出通过SEGGER RTT技术将日志写入芯片SRAM中的一块环形缓冲区再通过JTAG内存读取命令实时抓取。这样做的好处是颠覆性的状态一致性AI只需要和一个服务OpenOCD守护进程对话所有操作都在同一个会话、同一种连接状态下进行不存在“串口掉了但JTAG还连着”这种令人抓狂的不一致状态。非侵入式调试读取日志、检查内存时完全不需要暂停CPU实现了真正的实时观察。这对于调试时序敏感的通信协议如I2C、SPI至关重要。简化依赖开发者或AI不再需要关心USB转串口驱动、串口波特率、串口线是否松动等问题。一根USB线对于ESP32-C3/C6/S3同时解决供电、编程和调试所有需求。2.2 工具链设计为命令行自动化而生框架内的所有工具esp_target.pyrtt_reader.py都遵循同一个设计原则它们是纯粹的、无状态的命令行工具输入是参数输出是结构化的文本通常是JSON。这与GUI调试器或交互式Shell有本质区别。例如esp_target.py decode GPIO.OUT命令会直接返回类似{value: 0x00000001, fields: {GPIO2_OUT: 1, GPIO1_OUT: 0, ...}}的JSON。这种输出格式对于AI来说是完美的、可解析的反馈。AI可以轻松地从中提取“GPIO2引脚当前输出为高电平”这个事实并作为下一步决策的依据。同样rtt_reader.py以守护进程模式运行将日志写入文件。AI只需要执行cat .esp-agent/rtt.log就能获取所有最新输出就像读取一个普通文本文件一样简单。这种基于文件接口的日志获取方式完美契合了AI处理自然语言文本的能力。实操心得结构化输出的力量最初我尝试让工具输出人类可读的、格式漂亮的表格。但在与AI协作时发现解析多行、对齐不规则的文本非常容易出错。后来统一改为JSON输出AI的指令准确率大幅提升。这也提醒我们设计面向自动化的工具时机器可读性应优先于人类可读性。2.3 基于SVD的硬件抽象让AI“理解”芯片这是框架中最精妙的设计之一。仅仅能读写内存地址如0x3f404000对AI来说是没有意义的。它需要知道这个地址对应的是“GPIO外设”而偏移0x04是“OUT_DATA寄存器”并且该寄存器的第2比特位控制着“GPIO2”。esp-agentic-dev通过集成CMSIS SVDSystem View Description文件解决了这个问题。SVD是ARM社区定义的一种用于描述微控制器外设、寄存器、位域的XML格式标准。Espressif官方为ESP32系列提供了SVD文件。框架中的svd_parser.py会解析这个XML文件并在内存中构建一个完整的硬件模型。因此当AI执行esp_target.py decode GPIO.OUT时背后发生的是工具根据配置找到esp32c3.svd文件。解析器找到名为“GPIO”的外设及其寄存器“OUT”。通过OpenOCD读取0x60004004地址的32位值。根据SVD中对该寄存器的位域定义将原始值解析为{GPIO0_OUT: 0, GPIO1_OUT: 1, ...}这样的键值对。这意味着AI可以像人类工程师查阅数据手册一样以“概念名称”而非“神秘地址”来操作硬件。这是实现自主硬件调试的关键一步。3. 从零开始部署与实战配置理解了设计理念我们动手把它用起来。以下是我在多个项目上部署后的经验总结包含了所有容易踩坑的细节。3.1 环境准备与项目初始化假设你已经在ESP32-C3开发板上进行开发并且ESP-IDF环境已经设置好。# 1. 克隆框架仓库 git clone https://github.com/ccattuto/esp-agentic-dev.git cd your-esp-idf-project # 2. 复制核心工具和模板 # 注意不要简单复制整个目录理解每个文件的作用 cp ../esp-agentic-dev/tools/esp_target.py . cp ../esp-agentic-dev/tools/svd_parser.py . cp ../esp-agentic-dev/tools/rtt_reader.py . # 这些是Python脚本是框架的核心执行器 cp ../esp-agentic-dev/templates/CLAUDE.md . cp ../esp-agentic-dev/templates/esp_target_config.json . cp ../esp-agentic-dev/templates/esp-session-start.sh . cp ../esp-agentic-dev/templates/esp-session-stop.sh . chmod x esp-session-*.sh # 模板文件需要根据你的具体环境进行修改尤其是配置文件和板级描述 # 3. 建立芯片支持目录并获取SVD文件 mkdir -p chips cp ../esp-agentic-dev/chips/esp32c3.json chips/ # 芯片JSON文件定义了内存映射是地址翻译的基础 # 关键一步下载对应芯片的SVD文件 # 务必确认版本使用不匹配的SVD文件会导致外设名称和地址解析错误。 curl -L -o chips/esp32c3.svd \ https://raw.githubusercontent.com/espressif/svd/main/svd/esp32c3.svd3.2 深度解析与定制配置文件esp_target_config.json是框架的大脑几乎所有行为都由它控制。我们来逐项拆解{ chip: chips/esp32c3.json, openocd: { board_cfg: board/esp32c3-builtin.cfg, flash_command: program_esp, tcl_port: 6666, gdb_port: 3333, telnet_port: 4444 }, toolchain: { prefix: riscv32-esp-elf- }, gdb: { executable: riscv32-esp-elf-gdb-no-python }, logging: { method: rtt } }chip指向芯片描述文件。如果你用的是ESP32-S3就需要创建或获取esp32s3.json并修改此处。该文件主要包含memmap内存映射告诉工具哪些地址范围是Flash哪些是SRAM哪些是外设总线。如果地址错误读写操作会失败。openocd.board_cfg这是第一个大坑。board/esp32c3-builtin.cfg这个路径是相对于OpenOCD的脚本搜索路径而言的而不是你当前项目的路径。通常这个文件位于$IDF_PATH/tools/openocd-esp32/share/openocd/scripts/board/。你需要确认该文件存在。更稳妥的做法是使用绝对路径或者在启动脚本中设置OPENOCD_SCRIPTS环境变量。openocd.flash_command对于ESP32系列必须使用program_esp而不是通用的flash write_image。因为program_esp封装了ESP32 Flash加密、校验和写入等特殊操作。toolchain.prefix与gdb.executable必须与你的ESP-IDF环境匹配。使用riscv32-esp-elf-gdb-no-python是为了避免Python环境冲突这是一个非常实用的选择。避坑指南OpenOCD配置与权限在Linux或macOS上直接使用USB-JTAG可能会遇到权限问题。你需要将用户加入到dialoutLinux或wheelmacOS组或者创建udev规则。一个快速的测试方法是不通过框架直接运行openocd -f board/esp32c3-builtin.cfg。如果看到成功连接目标芯片的信息说明基础环境是通的。如果出现“无法打开USB设备”的错误那就是权限问题。3.3 板级描述文件赋予AI硬件上下文board.md文件的重要性被严重低估。它不仅仅是给人类看的说明书更是AI编码助手理解物理世界的“眼睛”。# My ESP32-C3 Dev Board ## Pin Mapping (Critical for AI) - **LED**: Connected to GPIO2 (Active High) - **Boot Button**: Connected to GPIO9 (Pressed LOW) - **I2C0**: - SDA: GPIO4 - SCL: GPIO5 - Pull-up resistors: 4.7kΩ onboard - **SPI2** (默认用于外部Flash已被占用) - **Available GPIOs**: 0, 1, 3, 6, 7, 8, 10, 18, 19 ## Hardware Constraints - GPIO6-11 用于内部Flash不可用作普通IO。 - 芯片内置USB-JTAG无需额外调试器。 - 供电USB 5V最大电流500mA。 ## Peripheral Initialization Hints - 使用 gpio_set_direction(GPIO_NUM_2, GPIO_MODE_OUTPUT) 初始化LED。 - I2C初始化后需调用 i2c_param_config 和 i2c_driver_install。当AI需要实现一个“按键控制LED”的功能时它会读取这个文件知道应该去操作GPIO9和GPIO2而不是随机选两个引脚。这极大地减少了因硬件接线不明导致的逻辑错误。你应该为每一块不同的开发板维护一个独立的board.md文件。4. 核心工具链实操详解框架的核心是三个Python工具。它们看起来简单但用好了威力无穷。4.1esp_target.py硬件操作的瑞士军刀这个工具是与硬件交互的主要门户。其命令大致可分为几类1. 状态与基础控制# 健康检查这是所有操作的起点 python3 esp_target.py health # 输出示例{ok: true, state: running, chip: ESP32-C3, openocd: 0.12.0} # 如果返回错误首先检查OpenOCD是否在运行配置文件中端口是否正确。 # 运行控制 python3 esp_target.py halt # 暂停CPU python3 esp_target.py state # 查看当前状态running/halted python3 esp_target.py resume # 恢复运行 python3 esp_target.py reset run # 执行硬件复位并立即运行比先halt再resume更干净2. Flash编程核心中的核心# 完整烧录bootloader 分区表 应用程序 python3 esp_target.py flash build/ # 这个过程会先擦除必要区域然后写入。时间较长。 # 仅烧录应用程序增量开发时极快 python3 esp_target.py flash build/ --app-only # 这只会更新 build/project.bin 对应的Flash区域通常在10秒内完成。 # 烧录并自动运行最常用的开发循环命令 python3 esp_target.py flash-and-run build/ --app-only # 等价于 flash reset run。是AI完成代码修改后最应该执行的命令。实操心得--app-only的巨大价值在快速迭代开发中Bootloader和分区表很少改动。使用--app-only可以节省大量时间。但要注意如果你修改了partitions.csv或sdkconfig中影响Bootloader的配置如Flash大小、加密方式则必须进行完整烧录否则会导致设备无法启动。一个稳妥的做法是在AI的指令集中默认使用--app-only但当检测到分区表或Bootloader相关文件被修改时自动切换为完整烧录。3. 内存与寄存器洞察调试利器# 原始内存读写底层操作 python3 esp_target.py read 0x3FC80000 4 # 从SRAM起始地址读4个字16字节 python3 esp_target.py write 0x50000000 0xA5A5A5A5 # 向RTC内存写入一个魔数 # CPU寄存器访问CPU必须处于halted状态 python3 esp_target.py cpu-regs # 查看所有核心寄存器PC, RA, SP...和关键CSR python3 esp_target.py cpu-reg mcause # 查看异常原因寄存器诊断崩溃 python3 esp_target.py cpu-reg-write a0 0x1234 # 修改寄存器a0的值用于动态测试 # SVD外设访问高级抽象推荐使用 python3 esp_target.py list-periph # 列出所有外设GPIO, UART, TIMG0... python3 esp_target.py list-regs GPIO # 列出GPIO外设的所有寄存器 python3 esp_target.py read-reg GPIO.OUT # 读取GPIO输出寄存器值 python3 esp_target.py decode GPIO.OUT # 解码GPIO输出寄存器的每一个位 # 输出示例{value: 0x0000_0005, fields: {GPIO0_OUT: 1, GPIO1_OUT: 0, GPIO2_OUT: 1}} python3 esp_target.py inspect UART0 # 检查UART0所有寄存器的当前状态 python3 esp_target.py write-reg GPIO.OUT_W1TS 0x0004 # 将GPIO2置为高电平Set4. 信息查询与原始命令python3 esp_target.py memmap # 显示芯片的内存映射确认地址范围 python3 esp_target.py info # 显示当前加载的完整配置信息 python3 esp_target.py raw targets # 发送原始OpenOCD Tcl命令高级调试用4.2rtt_reader.py无干扰的实时日志流SEGGER RTT是替代UART日志的绝佳方案。其原理是在芯片SRAM中开辟一块环形缓冲区应用程序通过SEGGER_RTT_printf写入主机通过JTAG直接读取内存来获取日志。部署RTT到你的固件从SEGGER官网下载SEGGER_RTT.c,SEGGER_RTT.h,SEGGER_RTT_printf.c。关键步骤使用本项目rtt/目录下的SEGGER_RTT_Conf.h。这个文件包含了针对RISC-V架构ESP32-C3/C6的中断锁宏定义原版文件只支持ARM。将以上文件添加到你的main组件的CMakeLists.txt中。在代码中#include SEGGER_RTT.h然后像使用printf一样使用SEGGER_RTT_printf(0, Value: %d\n, var)。启动日志守护进程# 最佳实践使用ELF文件自动定位RTT控制块地址 python3 rtt_reader.py --elf build/your_project.elf --output .esp-agent/rtt.log --daemonize # --daemonize 会让它在后台运行并将PID写入 .esp-agent/rtt_reader.pid # 随后AI或你可以通过以下命令实时查看日志 tail -f .esp-agent/rtt.log注意事项RTT缓冲区大小默认的RTT缓冲区可能较小通常1KB左右。如果日志输出非常频繁可能导致旧日志被覆盖。你可以在SEGGER_RTT_Conf.h中修改BUFFER_SIZE_UP主机到目标和BUFFER_SIZE_DOWN目标到主机即日志方向来增大缓冲区。但请注意这会占用更多的SRAM。4.3 会话管理脚本环境隔离的艺术esp-session-start.sh和esp-session-stop.sh这两个脚本的作用是管理OpenOCD守护进程和RTT读取守护进程的生命周期确保环境干净。剖析esp-session-start.sh#!/bin/bash # 它主要做三件事 # 1. 检查必要的环境变量如IDF_PATH和工具。 # 2. 启动OpenOCD守护进程并监听配置文件中指定的TCL端口6666。 # 3. 可选地启动rtt_reader.py守护进程。 # 一个常见的修改点是如果你的OpenOCD板级配置文件不在默认路径需要在这里设置OPENOCD_SCRIPTS环境变量。 export OPENOCD_SCRIPTS$IDF_PATH/tools/openocd-esp32/share/openocd/scripts openocd -f $OPENOCD_SCRIPTS/board/esp32c3-builtin.cfg -c tcl_port 6666; gdb_port 3333; telnet_port 4444 为什么需要会话管理想象一下你同时打开两个终端都尝试连接同一个JTAG端口或者AI在操作时你手动插拔了USB线。没有清晰的会话管理会导致端口冲突、状态混乱。这两个脚本确保了在一个“会话”中所有资源进程、端口、日志文件都被妥善地创建和清理。在开始与AI协作前务必先启动会话结束后务必停止会话。5. 与AI编码助手深度集成实战这是整个框架的终极目标。我们将以Claude Code为例展示如何构建一个完全自主的嵌入式开发智能体。5.1 配置AI助手的工作空间与权限首先将CLAUDE.md复制到项目根目录。这个文件是给AI的“工作说明书”。然后在Claude Code的配置目录通常是~/.claude/下创建或修改settings.json授予其必要的工具权限{ allowedTools: [ Read, Edit, Write, Bash(python3 esp_target.py:*), Bash(python3 rtt_reader.py:*), Bash(idf.py:*), Bash(riscv32-esp-elf-gdb-no-python:*), Bash(cat:*), Bash(tail:*), Bash(grep:*) ] }这个配置允许Claude执行构建、烧录、调试、查看日志等所有关键操作。注意权限要精确避免开放不必要的系统命令。5.2 模拟一次完整的AI驱动开发循环假设我们要实现一个呼吸灯效果。以下是AI可能执行的命令序列以及背后的逻辑理解任务AI读取CLAUDE.md和board.md知道LED在GPIO2并需要一个PWM信号。编写代码AI编辑main.c使用LEDCLED PWM控制器外设初始化GPIO2并编写一个渐变循环。首次构建与烧录idf.py build # AI会解析编译输出。如果有错误它会直接阅读错误信息并修复。 python3 esp_target.py flash-and-run build/ --app-only观察与诊断# 启动日志监控如果还没启动 python3 rtt_reader.py --elf build/project.elf --output .esp-agent/rtt.log --daemonize # 读取最新日志确认程序是否启动PWM是否初始化成功 tail -n 20 .esp-agent/rtt.log # 如果日志没有输出或者输出错误AI需要诊断。 # 首先检查硬件状态GPIO2模式设置对了吗 python3 esp_target.py decode GPIO.ENABLE # 如果ENABLE寄存器显示GPIO2未启用则说明初始化代码有问题。 # 其次检查外设LEDC模块的时钟配置好了吗 python3 esp_target.py inspect LEDC # 通过查看LEDC的CONF0、DUTY等寄存器可以判断PWM是否真正在工作。迭代与调试场景一程序崩溃Watchdog复位。AI会在日志中看到复位信息然后执行python3 esp_target.py halt python3 esp_target.py cpu-regs python3 esp_target.py cpu-reg mcause # 通过mcause寄存器值如0x1表示非法指令和PC指针结合ELF文件AI可以运行 riscv32-esp-elf-addr2line 来定位崩溃的源代码行。场景二逻辑错误灯不亮。AI可以单步或设置断点。它需要编写一个GDB批处理脚本例如debug.gdb:target remote :3333 file build/project.elf break app_main continue然后执行riscv32-esp-elf-gdb-no-python -x debug.gdb。虽然框架没有直接封装GDB图形交互但通过批处理脚本AI同样可以实现自动化断点调试和变量检查。修复与验证AI根据观察到的现象修改代码重新执行步骤3和4直到呼吸灯功能正常。5.3 为其他AI助手如Cursor、Codex CLI适配框架是通用的。对于其他支持命令行工具的AI助手你只需要将CLAUDE.md重命名为AGENTS.md或该助手约定的文件名。在该助手的配置中允许其执行python3,idf.py,openocd等命令。确保助手的工作环境shell已经通过source $IDF_PATH/export.sh激活了ESP-IDF环境。这是最容易出错的一步因为许多AI助手启动的是全新的、纯净的shell会话。6. 高级技巧、问题排查与经验总结经过多个项目的实战我积累了一些在官方文档里找不到的“生存指南”。6.1 性能优化与稳定性提升OpenOCD连接不稳定有时会出现“JTAG扫描链中断”的错误。尝试降低JTAG时钟频率。在board/esp32c3-builtin.cfg或自定义配置文件中找到adapter speed设置将其从2000020MHz降低到10000或5000。RTT日志延迟或丢失rtt_reader.py默认的轮询间隔是0.1秒。如果日志量极大可以适当降低间隔如--poll-interval 0.05但会增加JTAG总线负载。根本解决方法是增大固件中的RTT缓冲区并优化日志输出频率避免在高速中断服务程序中使用printf风格日志。并行操作冲突避免在rtt_reader.py持续读取内存的同时进行大规模的Flash擦写操作。Flash操作会短暂独占JTAG可能导致RTT读取超时。稳妥的做法是在烧录前暂停RTT读取进程。6.2 常见问题排查速查表问题现象可能原因排查步骤esp_target.py health返回连接失败1. OpenOCD未运行2. 端口被占用3. 板子未连接/供电不足1. 检查./esp-session-start.sh是否执行成功查看openocd.log。2. netstat -an烧录成功但程序不运行1. Bootloader/分区表不匹配2.--app-only但APP偏移地址错误3. 芯片进入Boot模式1. 尝试完整烧录esp_target.py flash build/。2. 检查esp_target_config.json中的chip文件内存映射是否正确。3. 按住BOOT键按一下RST键再释放BOOT键强制进入下载模式后重新烧录。RTT无日志输出1. 固件未集成RTT2. RTT控制块地址不对3. 缓冲区已满且覆盖1. 确认SEGGER_RTT_*文件已加入编译且调用了SEGGER_RTT_Init。2. 使用rtt_reader.py --elf build/project.elf --scan-only验证地址。3. 检查固件中SEGGER_RTT_Conf.h的缓冲区大小。decode或inspect命令报错“Peripheral not found”1. SVD文件不匹配2. 芯片型号配置错误3. SVD解析缓存出错1. 确认chips/下的.svd文件与你的芯片型号完全一致。2. 确认esp_target_config.json中的chip指向正确的JSON文件。3. 删除~/.cache/esp_agentic_dev/目录下的缓存文件强制重新解析SVD。AI助手无法执行idf.pyESP-IDF环境未激活确保在启动AI助手的同一个终端或环境里已经执行了source $IDF_PATH/export.sh。许多AI助手不会继承父shell的所有环境变量。6.3 扩展框架支持新芯片与新板型框架的扩展性很好。要支持一款新的ESP32芯片例如ESP32-P4你需要获取SVD文件从Espressif的svd仓库下载对应的.svd文件。创建芯片描述文件参考chips/esp32c3.json创建一个esp32p4.json。核心是定义memmap你需要从芯片技术参考手册中找出Flash、SRAM、外设总线的起始地址和大小。确定OpenOCD配置在$IDF_PATH/tools/openocd-esp32/share/openocd/scripts/board/或interface/目录下找到对应的.cfg文件。更新配置文件在esp_target_config.json中修改chip、openocd.board_cfg、toolchain.prefix如果是RISC-V则是riscv32-esp-elf-和gdb.executable。贡献如果你测试成功非常欢迎向原项目提交Pull Request帮助社区完善。最后我想分享一点最深的体会esp-agentic-dev带来的最大改变不是调试速度的提升而是思维模式的转变。它将硬件调试从一种“手工技艺”变成了“可编程流程”。你现在可以编写脚本让AI自动测试GPIO的上升沿响应时间或者遍历I2C总线上的所有设备地址并报告结果。这种可编程的、闭环的硬件交互能力为嵌入式系统的自动化测试、持续集成、甚至基于强化学习的硬件参数调优打开了一扇全新的大门。一开始你可能会觉得配置繁琐但一旦打通你会发现再也回不去那个需要不停切换窗口、插拔串口线的时代了。

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

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

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…