嵌入式Linux SPI转CAN-FD扩展实战:基于i.MX8MP与MCP2518FD

news2026/5/16 21:17:49
1. 项目概述当开发板的CAN口不够用时在嵌入式产品开发中尤其是工业控制、汽车电子或机器人领域CAN总线因其高可靠性和实时性被广泛应用。飞凌嵌入式的OKMX8MP-C开发板基于强大的i.MX8M Plus处理器原生提供了两路CAN-FD总线对于大多数应用来说已经足够。但现实情况往往更复杂你可能需要连接多个不同的CAN网络比如一个用于电机控制一个用于传感器采集还有一个用于上层通信或者你的产品设计需要预留冗余通道。当板载的CAN接口捉襟见肘时我们该怎么办直接更换硬件平台成本高昂周期也长。一个更灵活、更经济的方案是利用开发板上其他丰富的接口进行扩展。OKMX8MP-C核心板除了CAN还提供了多路高速SPI接口。SPI本身是一种高速、全双工的同步串行总线非常适合与各种外设芯片通信。于是“SPI转CAN”就成了一个非常自然的技术选型思路。这就像给你的电脑加装一块PCIe网卡来获得更多网络端口一样我们通过SPI总线“挂接”上一颗专用的CAN控制器芯片从而在软件层面“虚拟”出一个新的CAN接口。今天要分享的就是基于OKMX8MP-C开发板通过其SPI2接口移植MCP2518FD这款芯片的驱动实现新增一路CAN-FD通道的完整过程。这个方法不仅适用于MCP2518FD其原理和步骤同样可以迁移到MCP2515等只支持经典CAN的芯片上。整个流程涉及Linux内核驱动移植、设备树配置、内核编译与测试是嵌入式Linux开发中一次典型的“硬件功能扩展”实操对于想深入理解Linux外设驱动和硬件适配的工程师来说具有很高的参考价值。2. 核心思路与方案选型2.1 为什么选择SPI转CAN面对接口扩展的需求通常有几种路径一是寻找引脚复用的可能性但i.MX8MP的CAN控制器通常与特定引脚绑定复用可能受限或影响其他功能二是使用像PCIE、USB等总线扩展但这往往需要更复杂的硬件设计和驱动支持。相比之下SPI转CAN方案优势明显硬件简单成本低廉SPI转CAN芯片如MCP2518FD、MCP2515是成熟商品价格不高外围电路通常只需一颗晶振、几个阻容和隔离芯片工业环境需要硬件设计难度低。软件生态成熟这类芯片在Linux内核中通常都有成熟的驱动框架。它们作为SPI设备被识别并通过Linux内核标准的CAN子系统SocketCAN向上提供网络接口。这意味着应用层可以使用统一的Socket CAN APIsocket(PF_CAN, ...)进行通信与操作原生CAN口毫无二致。灵活性高SPI接口在开发板上通常有多个且引脚可灵活配置。只要找到一组空闲的SPI和一根GPIO用于中断就可以扩展一路CAN。本次我们选择SPI2正是因为它在OKMX8MP-C的默认配置中就是一个可用的SPI设备接口。性能可接受对于大多数工业应用SPI接口的速度通常可达10-20MHz足以应对CAN-FD最高5Mbps甚至经典CAN1Mbps的数据吞吐量。虽然实时性相比原生CAN控制器略有延迟主要来自SPI传输和中断处理开销但在许多场景下这微秒级的差异是可以接受的。2.2 芯片选型MCP2518FD vs MCP2515输入材料中提到了MCP2518和MCP2515它们都是Microchip公司著名的独立CAN控制器通过SPI与主机通信。MCP2515经典之选。支持经典CAN 2.0B最高速率1Mbps。它久经市场考验资料极多成本更低。如果你的项目只用到经典CAN且对成本敏感MCP2515是稳妥的选择。MCP2518FD新一代产品。最大亮点是支持CAN-FD灵活数据速率数据段最高可达5Mbps甚至8Mbps取决于型号并且数据场最长可达64字节效率远超经典CAN的8字节。它还内置了ECC内存可靠性更高。如何选择如果你的终端设备或网络中的其他节点支持CAN-FD或者你对未来升级有考虑希望获得更高的数据吞吐量那么MCP2518FD是更面向未来的选择。本次实操以MCP2518FD为例但整个移植流程对于MCP2515几乎是完全相同的主要区别在于内核中需要配置和编译的驱动模块名称不同CONFIG_CAN_MCP251X。2.3 整体工作流程梳理在开始动手前先理清我们要做什么。整个过程可以分为软件和硬件两条线软件线核心获取并集成驱动找到适配当前内核版本的MCP2518FD驱动源码放入内核源码树的正确位置。解决依赖与补丁驱动可能依赖某些内核函数如果当前内核没有需要手动添加如示例中的can_rx_offload_add_manual。配置内核修改Kconfig和Makefile将新驱动的编译选项暴露出来并在最终的内核配置文件中启用它。配置设备树这是关键一步。设备树Device Tree告诉内核硬件是如何连接的。我们需要定义一个时钟节点为MCP2518FD提供时钟参考。配置一个GPIO引脚作为中断引脚。修改SPI2的节点将其从连接一个普通的spidev设备改为连接一个mcp2518fd设备并关联时钟和中断。硬件线准备模块准备一个MCP2518FD模块或自己设计焊接的电路板。硬件连接将模块的SPI接口SCK, MOSI, MISO, CS连接到开发板的SPI2接口将模块的中断引脚INT连接到我们指定的GPIO如GPIO4_IO21并接好电源和地。CAN总线连接将模块的CANH和CANL连接到你的CAN网络注意终端电阻的匹配。完成以上步骤后编译内核、更新系统上电后Linux内核就会自动探测到SPI2上的CAN控制器并生成一个can0或can1取决于已有CAN接口数量的网络设备。3. 驱动移植与内核配置详解3.1 驱动源码获取与放置驱动源码是这一切的基础。输入材料提到驱动来源是“i.MX8MQ的源码”这是一个很好的起点因为同系列处理器的内核版本和驱动兼容性更好。通常你有以下几个途径获取驱动从芯片厂商获取Microchip官网通常会提供Linux内核驱动源码。从开发板厂商获取飞凌嵌入式可能会在提供的资料包中附带。从内核主线或相近版本移植在linux/drivers/net/can/spi/目录下寻找mcp25xxfd或mcp251x。如果版本差异不大可以直接使用。操作要点假设你已经拿到了名为mcp25xxfd的驱动文件夹里面包含了.c,.h,Makefile,Kconfig等文件。# 进入你的内核源码目录例如飞凌提供的OK8MP-linux-kernel cd ~/work/OK8MP-linux-kernel # 将整个驱动文件夹复制到内核的CAN SPI驱动目录下 cp -r /path/to/your/mcp25xxfd drivers/net/can/spi/这一步的本质是将第三方驱动“嫁接”到标准的内核驱动框架中。drivers/net/can/spi/这个目录就是专门存放所有通过SPI连接的CAN控制器驱动的。3.2 解决函数依赖补全can_rx_offload_add_manual这是移植过程中非常典型的一个问题——内核符号依赖。新驱动编译时可能会调用一些内核函数。如果当前内核版本没有导出这个函数或者函数签名参数、返回值发生了变化就会导致编译失败。输入材料中遇到的can_rx_offload_add_manual就是一个例子。can_rx_offload是Linux内核CAN子系统的一个中间层用于高效处理CAN帧的接收尤其是负载高时。add_manual是其一个变体。为什么需要手动添加很可能你获取的驱动来自一个较新的内核版本其中这个函数是存在的。而你当前使用的飞凌适配的内核版本基于某个较旧的LTS版本可能还没有包含这个函数或者它是以内联函数、静态函数形式存在没有被导出供模块使用。操作与理解按照材料提示我们需要在两个文件中添加这个函数的实现。添加函数声明在include/linux/can/rx-offload.h中。头文件声明告诉编译器“这个函数存在稍后定义”。// 在rx-offload.h文件的合适位置例如其他can_rx_offload_add_*函数附近添加 int can_rx_offload_add_manual(struct net_device *dev, struct can_rx_offload *offload, unsigned int weight);添加函数实现在drivers/net/can/rx-offload.c中。这是函数的具体代码。// 在rx-offload.c文件的合适位置添加函数体 int can_rx_offload_add_manual(struct net_device *dev, struct can_rx_offload *offload, unsigned int weight) { if (offload-mailbox_read) return -EINVAL; return can_rx_offload_init_queue(dev, offload, weight); } EXPORT_SYMBOL_GPL(can_rx_offload_add_manual);EXPORT_SYMBOL_GPL至关重要它将该函数导出到内核符号表使得编译成模块的mcp25xxfd驱动能够调用它。注意事项在修改内核核心文件时务必小心。最好先搜索一下当前内核中是否已有同名但不同签名的函数避免冲突。添加后建议使用git diff或对比工具确认修改无误。3.3 修改构建系统Makefile与KconfigLinux内核使用一套基于Kconfig和Makefile的复杂构建系统。我们需要告诉这套系统“现在多了一个叫mcp25xxfd的目录需要被编译。”修改上级目录的Makefile(drivers/net/can/spi/Makefile)# 在文件中添加一行表示要进入mcp25xxfd子目录进行构建 obj-y mcp25xxfd/这行代码指示内核构建系统当编译这个目录时需要递归地进入mcp25xxfd目录并处理其中的Makefile。修改上级目录的Kconfig(drivers/net/can/spi/Kconfig)# 在文件中添加一行引入子目录的Kconfig配置 source drivers/net/can/spi/mcp25xxfd/KconfigKconfig文件定义了内核的配置菜单。这行代码将mcp25xxfd目录下的配置选项比如CONFIG_CAN_MCP25XXFD包含到当前菜单中。这样当我们执行make menuconfig时才能在图形化界面里看到这个新驱动的配置选项。3.4 配置内核启用新驱动现在驱动已经就位构建系统也知道了它的存在。接下来就是通过内核配置将其编译进内核或编译为模块。输入材料中直接修改默认配置文件OK8MP-C_defconfig是最直接的方法适用于产品固化配置。定位并修改配置文件vi arch/arm64/configs/OK8MP-C_defconfig进行修改# 找到可能存在的旧版MCP2515配置将其禁用如果不需要的话 # CONFIG_CAN_MCP251X is not set # 添加MCP2518FD的配置y 表示直接编译进内核 CONFIG_CAN_MCP25XXFDy为什么禁用CONFIG_CAN_MCP251X这是为了避免潜在的冲突。虽然理论上可以同时编译多个CAN SPI驱动但如果你当前硬件只接了MCP2518FD禁用不用的驱动可以使内核更精简。如果确实需要MCP2515则应保留并将其设为y或m。替代方法更推荐用于调试阶段使用menuconfig直接修改defconfig是最终手段。在开发阶段使用图形化配置工具更安全它能处理依赖关系。# 首先加载默认配置 make OK8MP-C_defconfig # 启动图形化配置界面 make menuconfig然后通过菜单导航至- Device Drivers- Network device support (NETDEVICES [y])- CAN bus subsystem support (CAN [y])- CAN Device Drivers- CAN SPI interfaces在这里你应该能看到Microchip MCP25xxFD SPI CAN controllers这个新选项按Y键将其选中编译进内核。保存退出后新的配置会保存在.config文件中。之后你可以用make savedefconfig将改动更新回defconfig文件。4. 设备树配置让内核认识你的硬件设备树是现代ARM Linux内核识别硬件的主要方式。它以一种数据结构的形式描述了板子上有什么外设、它们如何连接地址、中断、时钟、引脚复用等。对于SPI设备我们需要在设备树中描述“在SPI2总线上片选0的位置连接了一个兼容Microchip,mcp2518fd的设备它使用哪个时钟中断接到哪个GPIO。”4.1 定义时钟节点MCP2518FD芯片需要一个外部时钟输入通常由外部晶振提供如40MHz。在设备树中我们需要定义一个“固定时钟”节点来模拟或描述这个时钟源。即使这个时钟是由芯片外部晶振直接提供的在设备树中声明它也是一种标准做法有助于驱动正确初始化。// 在设备树的根节点(/)下或clocks节点内添加 clocks { mcp2518fd_clock: mcp2518fd_clock { compatible fixed-clock; #clock-cells 0; clock-frequency 40000000; // 单位Hz根据你的实际晶振频率修改常用40MHz或20MHz }; };compatible fixed-clock告诉内核这是一个频率固定的时钟。clock-frequency必须设置为你电路板上实际连接晶振的频率。驱动会读取这个值来计算CAN总线的时序参数如波特率。此处务必与实际硬件一致否则CAN通信波特率会不准。4.2 配置中断引脚CAN控制器接收到数据或发生错误时需要通过中断通知CPU。我们需要分配一个未被使用的GPIO引脚作为中断线。输入材料中选择了GPIO4_IO21。我们需要在pinctrl配置中定义这个引脚的复用功能为GPIO并设置电气属性。// 在 pinctrl_ecspi2 相关的 pinctrl 节点附近添加 pinctrl_ecspi2_can: ecspi2cangrp { fsl,pins MX8MP_IOMUXC_SAI2_RXFS__GPIO4_IO21 0x40000 ; };MX8MP_IOMUXC_SAI2_RXFS__GPIO4_IO21这是一个宏表示将SAI2_RXFS这个引脚复用为GPIO4_IO21。你需要参考i.MX8MP的参考手册和开发板的引脚复用表来确认。0x40000这是引脚的电属性配置值包括上下拉、驱动强度、速度等。0x40000通常代表一个带内部上拉、中等速度的配置。这个值需要根据硬件设计调整最稳妥的方法是参考开发板原有设备树中对类似GPIO中断引脚的配置。4.3 修改SPI2设备节点这是最关键的一步将SPI2总线上的设备从一个通用的SPI用户设备spidev替换为我们的CAN控制器设备。修改前SPI2节点可能挂载着一个spidev这是一个通用的用户空间SPI设备驱动常用于测试或直接操作SPI。ecspi2 { ... status okay; spidev1: spi0 { reg 0; // 片选0 compatible rohm,dh2228fv; // 通用spidev兼容字符串 spi-max-frequency 500000; }; };修改后我们将其替换为MCP2518FD设备节点ecspi2 { #address-cells 1; #size-cells 0; fsl,spi-num-chipselects 1; pinctrl-names default; // 将我们新定义的中断引脚配置组加入 pinctrl-0 pinctrl_ecspi2 pinctrl_ecspi2_cs pinctrl_ecspi2_can; cs-gpios gpio5 13 GPIO_ACTIVE_LOW; status okay; // 替换spidev节点为mcp2518fd节点 mcp1: mcp2518fd0 { compatible microchip,mcp2518fd; reg 0; // 使用片选0 spi-max-frequency 20000000; // SPI通信时钟最高20MHz clocks mcp2518fd_clock; // 引用上面定义的时钟节点 interrupts-extended gpio4 21 IRQ_TYPE_LEVEL_LOW; // 中断配置GPIO4_21低电平触发 }; };逐项解析pinctrl-0增加了pinctrl_ecspi2_can确保初始化SPI2时也把中断引脚配置为正确的GPIO模式。compatible microchip,mcp2518fd驱动匹配的关键。内核在启动时会遍历设备树。当它发现一个SPI子节点的compatible属性与某个驱动注册的of_device_id表匹配时就会调用该驱动的探测函数。这个字符串必须与驱动源码中定义的一致。spi-max-frequencySPI通信的时钟频率。MCP2518FD最高支持20MHz。设置时需考虑SPI控制器和布线能稳定工作的频率。clocks mcp2518fd_clock指向之前定义的时钟节点为驱动提供时钟频率信息。interrupts-extended指定中断。gpio4 21 IRQ_TYPE_LEVEL_LOW表示使用gpio4控制器的第21号引脚即GPIO4_IO21中断触发方式为低电平有效。这需要与硬件连接MCP2518FD的INT引脚通常是低电平有效以及pinctrl配置保持一致。实操心得设备树修改是嵌入式Linux开发中最容易出错的地方之一。建议每次只修改一个节点并使用dtc工具编译测试设备树源文件(.dts)为二进制文件(.dtb)以检查语法错误dtc -I dts -O dtb -o test.dtb arch/arm64/boot/dts/freescale/OK8MP-C.dts。更重要的修改后一定要与硬件原理图反复核对引脚编号、中断触发方式、时钟频率。5. 内核编译、烧录与上电验证5.1 编译内核与设备树完成所有代码和配置修改后就可以开始编译了。确保你处于内核源码的根目录。# 1. 清理旧编译产物可选但推荐 make distclean # 或者更温和的清理 make clean # 2. 加载我们修改后的默认配置 make OK8MP-C_defconfig # 3. 开始编译。使用-j参数利用多核加速数字根据你的CPU核心数设定 make -j8 Image dtbs modulesImage压缩的内核镜像文件。dtbs编译设备树二进制文件。这个命令会根据你的dts文件生成对应的.dtb文件。modules编译所有配置为模块(m)的驱动。编译成功后关键文件位于内核镜像arch/arm64/boot/Image设备树二进制文件arch/arm64/boot/dts/freescale/OK8MP-C.dtb5.2 更新开发板系统如何更新镜像取决于你的开发板启动方式SD卡、eMMC、网络等。以常见的SD卡启动为例将SD卡插入读卡器连接到编译主机。通常SD卡的第一个分区是FAT格式的启动分区里面存放着内核(Image)和设备树文件(.dtb)。将新编译的Image和OK8MP-C.dtb复制到该分区覆盖旧文件。安全弹出SD卡插入开发板上电启动。5.3 系统启动与功能验证开发板启动后通过串口登录系统。第一步检查驱动是否加载# 查看内核启动日志过滤CAN和MCP相关信息 dmesg | grep -E (can|mcp|spi)你应该能看到类似如下的信息表明SPI设备被成功探测并且MCP2518FD驱动被绑定[ 2.500000] spi2.0: mcp2518fd spi2.0 at 20000000Hz (irq123) [ 2.500100] CAN device driver for MCP25xxFD [ 2.500200] spi2.0: MCP2518 successfully initialized.第二步检查网络接口# 使用ifconfig或ip命令查看所有网络接口 ifconfig -a # 或 ip link show在输出列表中除了常见的eth0、lo你应该能看到一个新的CAN接口例如can0或can1取决于你原生CAN接口的命名。新接口在未配置前通常是DOWN状态。第三步配置并测试CAN接口假设新生成的接口是can1。设置波特率并启动# 设置波特率为500kbps并启动接口。这里假设使用经典CAN如果是CAN-FD参数不同。 sudo ip link set can1 type can bitrate 500000 sudo ip link set up can1检查接口状态ip -details link show can1输出应显示state UP并显示你设置的波特率等信息。基本自发自收测试 打开两个终端窗口。终端1监听CAN数据candump can1终端2发送一条CAN数据帧# 发送一帧标准ID为0x123数据为 0x11, 0x22, 0x33, 0x44 的数据 cansend can1 123#11223344在终端1中你应该能看到接收到的这帧数据。这证明了从应用层到CAN控制器再到总线的完整通路是通的。第四步连接真实CAN网络测试将开发板的CAN接口通过MCP2518FD模块连接到真实的CAN网络如另一个CAN节点或CAN分析仪进行双向通信测试验证错误计数、远程帧等功能是否正常。6. 常见问题排查与调试技巧即使按照步骤操作也可能会遇到问题。这里记录一些常见的坑和排查思路。6.1 驱动未加载ifconfig -a看不到CAN接口检查内核配置确认CONFIG_CAN_MCP25XXFDy确实生效。可以查看/proc/config.gz(如果启用) 或检查/boot/config-*文件。检查设备树兼容性确认设备树中compatible microchip,mcp2518fd与驱动源码中of_device_id表里的字符串完全一致。一个空格都不能差。可以在驱动源码中搜索.of_match_table或compatible来确认。检查设备树语法使用dtc编译.dts文件确保无语法错误。同时检查SPI节点、中断、时钟的路径引用是否正确使用了符号。查看完整内核日志dmesg | grep spi和dmesg | grep mcp。关注是否有探测失败、注册失败的错误信息。常见的错误有probe failed -ENODEV可能设备树节点未正确创建或兼容性字符串不匹配。failed to get irq中断配置错误检查GPIO编号和中断触发方式。failed to get clock时钟节点未找到或#clock-cells设置错误。6.2 CAN接口能UP但无法收发数据检查硬件连接这是最容易被忽略的用万用表确认SPI四根线SCK, MOSI, MISO, CS是否连通有无接反。中断引脚(INT)是否连接正确。CANH和CANL是否接对总线两端是否有120欧姆终端电阻。MCP2518FD的电源3.3V是否稳定。检查SPI通信可以在设备树中暂时将compatible改回rohm,dh2228fvspidev然后使用用户空间工具如spidev_test测试SPI通路是否能正常读写。这能排除SPI控制器配置或硬件连线问题。检查时钟频率确认设备树中clock-frequency设置的值与MCP2518FD外部晶振的实际频率完全一致。频率不准会导致CAN波特率计算错误无法与网络其他节点同步。检查中断启动CAN接口后查看中断计数cat /proc/interrupts | grep -E (spi|gpio4)尝试发送数据观察对应的中断计数是否增加。如果不增加可能是中断引脚配置或硬件连接问题。降低SPI速率将设备树中的spi-max-frequency从20000000降低到10000000或5000000排除因布线不佳导致的高速SPI通信不稳定。使用candump监听回环模式sudo ip link set can1 type can bitrate 500000 loopback on sudo ip link set up can1 cansend can1 123#deadbeef candump can1如果回环模式下自己能收到自己发的数据说明驱动和芯片基本正常问题可能出在CAN总线物理层接线、终端电阻或对端设备。6.3 系统不稳定或偶发性通信失败电源噪声CAN和SPI对电源质量敏感。确保使用线性稳压器或噪声较小的电源为MCP2518FD模块供电并在电源引脚附近放置足够的去耦电容如100nF和10uF。中断风暴如果中断引脚配置错误如边沿触发不稳定可能导致持续中断耗尽CPU资源。检查硬件连接确保中断信号干净无毛刺。可以在驱动代码中添加打印查看中断处理函数是否被异常频繁调用。驱动版本兼容性从不同内核版本移植的驱动其API可能发生变化。除了我们补的can_rx_offload_add_manual还要注意spi_driver结构体、probe函数签名、CAN驱动API等是否与当前内核版本匹配。仔细对照内核源码中同类SPI CAN驱动如mcp251x.c的写法。6.4 性能优化提示SPI时钟与模式MCP2518FD支持SPI模式0,0和1,1。确保设备树中SPI控制器的模式配置与芯片要求一致。提高spi-max-frequency可以提升CAN数据吞吐量但需以稳定为前提。中断线程化在高负载场景下可以考虑将CAN中断处理线程化并赋予较高的实时优先级以减少接收延迟。# 设置中断线程的调度策略和优先级 (需内核支持) chrt -f -p 90 pgrep irq/中断号Socket CAN缓冲区如果应用层接收数据不够快可以增大Socket CAN的接收缓冲区防止丢帧。sudo ip link set can1 txqueuelen 1000整个SPI转CAN的移植过程是一次对Linux驱动、设备树、硬件协同工作的深度实践。成功的关键在于细心仔细核对每一行代码、每一个引脚号、每一个设备树节点的属性。当你在终端看到candump中流动着来自新扩展CAN口的数据时那种对系统掌控感带来的满足正是嵌入式开发的乐趣所在。希望这篇详细的记录能帮你顺利打通这“额外”的CAN通道。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2619427.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;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…