FPGA与PC高速数据通道:基于FTDI同步FIFO的实战设计

news2026/5/15 4:27:45
1. 项目概述一个连接FPGA与PC的“高速数据通道”如果你玩过FPGA肯定遇到过这个头疼的问题调试时怎么把板子上的海量数据快速、稳定地传到电脑上用串口速度太慢115200的波特率传一张小图片都得等半天。用板载的USB转串口芯片通常也只是个CDC设备速度和协议都受限。这时候一个名为“FPGA-ftdi245fifo”的开源项目就进入了我的视野。简单来说它利用一颗非常常见的USB桥接芯片——FTDI的FT245R或FT232H在FPGA内部实现了一个高效的FIFO先进先出队列控制器从而在FPGA和PC之间打通了一条最高速度可达数MB/s甚至更高的同步或异步并行数据通道。我第一次接触这个方案是在一个图像采集项目里。我们需要把FPGA从CMOS传感器采集到的原始图像数据每秒几十兆字节实时传到上位机进行显示和算法处理。尝试了各种方案后最终基于这个核心思想搭建的系统不仅稳定跑满了USB2.0 High-Speed模式下的理论带宽而且FPGA端的逻辑设计清晰简洁上位机驱动成熟可靠。这个项目WangXuan95/FPGA-ftdi245fifo提供了一个非常优雅的Verilog实现参考但它更像是一个“内核”或“引擎”。要真正让它跑起来你需要围绕它搭建一整套系统包括FPGA端的接口适配、时钟管理、状态机以及PC端的驱动和应用程序。接下来我就结合自己多次实战的经验把这个“高速通道”从原理到上手的每一个细节掰开揉碎了讲清楚。2. 核心硬件与协议原理深度拆解2.1 FTDI FT245R/FT232H芯片的角色解析首先得明白我们依赖的“硬件桥梁”是什么。FTDI公司生产的FT245R和FT232H是两款经典的USB转并行FIFO接口芯片。它们核心的功能就是将一个USB端口“伪装”成一个简单的8位或16位并行数据端口附带一些控制信号。FT245R更早期、更基础的型号。它提供了一个8位双向数据总线D0-D7以及读写使能RXF#, TXE#、读写选通RD#, WR等信号。它工作在异步模式下速度相对较慢典型值在每秒1兆字节1MB/s左右但对于很多中低速数据流如ADC采集数据、低速图像、大量传感器数据已经绰绰有余。它的优点是电路简单价格便宜在很多开发板上都能找到。FT232H功能更强大的型号。它除了支持类似FT245R的异步并行FIFO模式还支持同步FIFO模式。在同步模式下芯片会输出一个时钟信号CLKOUT数据在时钟边沿被锁存这使得数据传输可以更高速、更稳定地进行速率可以轻松达到30-40MB/s逼近USB2.0 High-Speed的理论极限。此外FT232H还支持更多的GPIO和多种工作模式如UART, JTAG等灵活性更高。注意选择哪款芯片首先看你的硬件底板。很多FPGA开发板集成了FT232H或FT2232H双通道版。如果自己设计底板根据速度和成本权衡选择。对于绝大多数需要高于串口速度的应用FT232H的同步模式是首选。这个项目的核心逻辑就是让FPGA通过几根简单的连线遵循FTDI芯片定义的时序去读写这个“并行端口”从而实现与PC之间大数据量的交换。PC端则通过FTDI官方提供的D2XX驱动以库函数DLL/SO的方式直接访问这个USB设备读写其内部的FIFO缓冲区完全绕开了操作系统繁琐的串口抽象层这也是其高速的秘诀所在。2.2 同步FIFO模式时序与关键信号我们重点剖析效率最高的同步FIFO模式这是项目发挥性能的关键。你需要像阅读芯片手册一样理解这几个信号以FPGA为视角CLKOUT (60MHz)由FT232H芯片产生的输出时钟所有其他输入输出信号的时序都以此时钟为参考。FPGA端必须使用这个时钟来采样输入信号和驱动输出信号。这意味着你的FPGA设计里需要一个对应的时钟域。DATA[7:0] (或DATA[15:0])8位或16位双向数据总线。方向由读写操作决定。RXF# (Read Enable FIFO)输入信号低有效。当RXF#为低时表示FT232H芯片内的接收FIFOUSB-FPGA方向非空FPGA可以从中读取数据。这是FPGA发起读操作的“许可信号”。TXE# (Transmit Enable FIFO)输入信号低有效。当TXE#为低时表示FT232H芯片内的发送FIFOFPGA-USB方向非满FPGA可以向其中写入数据。这是FPGA发起写操作的“许可信号”。RD# (Read Strobe)输出信号低有效。当RXF#为低且FPGA准备读取数据时FPGA将RD#拉低一个CLKOUT周期FT232H会在RD#的上升沿将数据送到DATA总线上FPGA在此时钟周期内采样数据。WR# (Write Strobe)输出信号低有效。当TXE#为低且FPGA准备写入数据时FPGA将待写数据放到DATA总线上并将WR#拉低一个CLKOUT周期FT232H会在WR#的上升沿将数据锁存进发送FIFO。读操作的关键时序RXF#0- FPGA拉低RD#- 下一个时钟上升沿FPGA采样DATA总线 - FPGA拉高RD#。必须严格保证RD#低脉冲宽度至少为一个CLKOUT周期。写操作的关键时序TXE#0- FPGA将数据置于DATA总线 - FPGA拉低WR#数据需在WR#下降沿前已稳定- 保持一个周期 - FPGA拉高WR#。理解这个硬件握手协议是编写或理解控制器逻辑的基础。项目FPGA-ftdi245fifo中的Verilog代码本质上就是一个严格按照此时序工作的状态机。2.3 项目源码结构透视打开项目仓库你会发现核心文件非常精简这正体现了其“内核”的定位。通常包含ftdi_245fifo.v/ftdi_245fifo_sync.v核心控制器模块。它实现了上述的同步FIFO协议状态机。模块对外提供两套类FIFO接口一套用于FPGA向PC发送数据tx_data,tx_valid,tx_ready另一套用于FPGA从PC接收数据rx_data,rx_valid,rx_ready。你的用户逻辑如图像采集、数据处理模块就通过这套简单的握手信号与它交互完全不用关心底层的USB时序细节。tb_ftdi_245fifo.v测试文件用于仿真验证控制器的逻辑正确性。top_example.v一个顶层的示例展示了如何将控制器模块实例化并连接到一个简单的回环测试逻辑将接收到的数据原样发回。这个设计的美妙之处在于抽象分层。控制器模块处理了最底层的、与FTDI芯片信号直接交互的繁琐时序并向用户逻辑提供了一个干净、标准的流式接口Avalon-ST或类似风格。作为用户你只需要在合适的时钟域CLKOUT下像操作一个普通FIFO一样向tx接口灌数据或从rx接口取数据即可。3. FPGA端系统集成与设计要点拿到这个“内核”后你需要为它打造一个运行的“身体”这涉及到时钟、跨时钟域、数据打包等一系列工程问题。3.1 时钟域处理系统的节拍器这是第一个也是最重要的挑战。FTDI控制器工作在CLKOUT例如60MHz时钟域而你的数据产生或消费逻辑例如图像传感器接口、DDR3控制器、算法模块很可能工作在另一个时钟域如像素时钟25MHz、系统时钟100MHz等。错误的做法直接在不同时钟域之间传递数据或握手信号这会导致亚稳态系统行为不可预测表现为随机丢数据或死机。正确的做法使用异步FIFO进行时钟域隔离。发送路径FPGA-PC你的应用逻辑在clk_app域产生数据并写入一个异步FIFO的写端口。这个异步FIFO的读端口在clk_ftdi即CLKOUT域读出的数据连接到ftdi_245fifo模块的tx_data接口。tx_ready信号可以作为异步FIFO的读使能。接收路径PC-FPGAftdi_245fifo模块的rx_data接口在clk_ftdi域输出数据将其写入一个异步FIFO的写端口。你的应用逻辑在clk_app域从该异步FIFO的读端口取出数据消费。FPGA厂商Xilinx, Intel/Altera的IP核库中都提供了高度优化的异步FIFO IP配置时注意设置好两侧的时钟和合理的FIFO深度例如1024或2048个字以平滑数据流的突发。这是保证系统稳定性的基石。3.2 数据流封装与帧结构设计USB通道是流式的没有内置的“包”或“帧”概念。如果你传输的是一系列有结构的“帧”比如一帧图像、一段音频数据、一组传感器读数你必须在数据流中自己加入“帧定界”信息。一个简单可靠的方案是添加帧头和数据长度。例如在发送每一帧数据之前先发送一个固定的帧头如4字节的0xA5A5A5A5紧接着发送一个4字节的帧长度单位可以是字节然后再发送实际的有效载荷数据。FPGA发送侧伪逻辑// 在应用时钟域 clk_app if (frame_valid) begin // 新的一帧数据准备好 async_fifo_wr_data 32‘hA5A5A5A5; // 帧头 async_fifo_wr_en 1‘b1; // ... 下一个周期写入长度 async_fifo_wr_data frame_length; // ... 随后逐个写入帧数据 endPC接收侧处理 你的上位机程序需要维护一个接收缓冲区不断读取USB数据。然后在这个字节流中搜索帧头0xA5A5A5A5找到后读取接下来的4字节作为长度N然后紧接着读取N字节的数据这就完整恢复出了一帧。这种方法能有效处理USB传输中可能发生的字节错位并且允许可变长度的帧。3.3 流控与背压机制虽然FTDI芯片内部的硬件FIFO和FPGA端的异步FIFO提供了一定的缓冲但当上位机处理不及时或数据产生过快时缓冲区仍可能写满。完善的流控是必须的。硬件流控依赖于TXE#信号。当TXE#变高发送FIFO满ftdi_245fifo模块的tx_ready会拉低这会阻止其从上游的异步FIFO中读取数据。如果异步FIFO也因此变满它会向上游的应用逻辑反压通过类似full或almost_full信号要求暂停发送。你需要确保你的数据源能响应这个背压信号。软件流控可以在应用层设计。例如PC端在接收缓冲区快满时通过USB通道向FPGA发送一个“暂停”命令包。FPGA端的接收逻辑解析到这个命令后通知发送逻辑暂停。当PC端缓冲区清空后再发送“继续”命令。这提供了更灵活、更大缓冲的流控能力但实现稍复杂。在实际项目中我通常将硬件流控作为第一道防线确保不会因为短时突发导致丢数。对于长时间、大数据量的传输我会在协议里加入类似“信用窗”的软件流控机制。4. PC端驱动与上位机开发实战FPGA侧准备就绪另一头需要一个强大的PC程序来收发数据。这里的关键是FTDI的D2XX驱动。4.1 D2XX驱动 vs. VCP驱动FTDI提供两种驱动模式VCP (Virtual COM Port)将USB设备虚拟成一个串口如COM3。优点是兼容性极好任何支持串口的程序都能用。但缺点也明显性能低下依赖操作系统串口栈的缓冲和调度延迟高且不稳定无法发挥同步FIFO模式的高速性能。D2XX这是一个直接访问USB设备的原生驱动和API库。它绕过操作系统串口子系统允许程序以接近硬件极限的速度直接读写USB端点缓冲区。要做高速数据传输必须选择D2XX驱动。安装时你需要从FTDI官网下载并安装D2XX驱动。安装后设备管理器中看到的设备名称会是“USB Serial Converter”之类而不是“COM端口”。4.2 使用D2XX API的基本流程以下以C为例勾勒出核心步骤打开设备FT_CreateDeviceInfoList获取设备列表FT_Open或FT_OpenEx通过序列号或描述打开打开特定设备。配置参数这是关键步骤。FT_SetTimeouts(ftHandle, 5000, 5000); // 设置读写超时毫秒 FT_SetUSBParameters(ftHandle, 65536, 65536); // 设置USB传输缓冲区大小尽可能设大 FT_SetFlowControl(ftHandle, FT_FLOW_RTS_CTS, 0, 0); // 通常禁用硬件流控由我们自己的逻辑控制 FT_SetBitMode(ftHandle, 0xFF, 0x40); // 设置FT232H为同步FIFO模式0x40是关键。 FT_SetLatencyTimer(ftHandle, 2); // 设置延迟定时器推荐较小值2-16ms以减少延迟 FT_Purge(ftHandle, FT_PURGE_RX | FT_PURGE_TX); // 清空缓冲区FT_SetBitMode(..., 0x40)这行命令是将FT232H切换到同步245 FIFO模式的魔法指令务必确认执行成功。数据读写写PC-FPGAFT_Write。注意这个函数是阻塞的直到所有数据写入内核驱动缓冲区才返回。对于大量数据可能需要分多次写入或在独立线程中进行。读FPGA-PCFT_Read。更高效的做法是使用异步读FT_SetEventNotification设置事件通知当接收缓冲区有数据时触发事件然后在事件处理函数中调用FT_GetStatus查询可读字节数再用FT_Read读取。或者使用FT_Read的超时机制进行轮询。关闭设备FT_Close。4.3 上位机程序架构与性能优化一个健壮的上位机程序通常采用生产者-消费者模型读线程一个或多个线程专门负责调用FT_Read或响应读事件将收到的原始字节流放入一个线程安全的队列如环形缓冲区。解析线程从队列中取出原始数据进行帧头检测、长度校验、数据解包恢复出有逻辑意义的数据帧再放入另一个处理队列。处理/显示线程消费解析后的数据帧进行图像显示、数据存储、算法分析等。性能优化技巧增大USB缓冲区FT_SetUSBParameters是首要优化点将其设置为最大值通常65536。使用多线程避免读写操作阻塞UI或主逻辑。批量读写每次调用FT_Write或FT_Read时尽量传递较大的数据块如数KB减少系统调用开销。选择合适的LatencyTimer这个值决定了驱动在未满缓冲区的情况下等待多久才将数据提交给USB主机控制器。值越小延迟越低但小数据包开销增大。对于持续流数据设为2-5ms是个不错的起点。关闭流控在驱动层调用FT_SetFlowControl关闭RTS/CTS流控因为我们的流控在应用层实现。5. 从零搭建一个完整的图像传输示例让我们串联所有环节构建一个将FPGA采集的灰度图像640x480 8bit传输到PC显示的系统。5.1 系统框图与模块划分[CMOS Sensor] --(像素时钟、数据)-- [FPGA] | v [Sensor Interface] -- [Pixel Buffer (FIFO)] -- [Frame Packager] | v [PC Display App] -- [USB Driver] -- [FT232H Chip] -- [FTDI Ctrl (ftdi_245fifo.v)]Sensor Interface在像素时钟域接收传感器数据进行简单处理如去噪写入一个异步FIFO写时钟像素时钟。Frame Packager在系统时钟域或单独时钟从上述异步FIFO读端口读取一帧完整图像。计算帧大小640*480307200字节。然后按照[帧头 4字节][长度 4字节][图像数据 307200字节]的格式将数据写入另一个异步FIFO。这个异步FIFO的读时钟连接到clk_ftdi。FTDI Ctrl实例化ftdi_245fifo模块。其tx接口连接到Frame Packager输出的异步FIFO的读端口。clk_ftdi连接FT232H的CLKOUT。PCB连接确保FPGA的IO引脚正确连接到FT232H的DATA[7:0], RXF#, TXE#, RD#, WR#, CLKOUT。注意电平匹配通常都是3.3V LVCMOS。5.2 FPGA关键代码片段// 顶层模块片段 wire clk_ftdi; // 来自FT232H的CLKOUT wire [7:0] ftdi_data; wire ftdi_rxf_n, ftdi_txe_n; wire ftdi_rd_n, ftdi_wr_n; // 实例化FTDI控制器 ftdi_245fifo_sync u_ftdi_ctrl ( .clk (clk_ftdi), // 必须使用CLKOUT .rst_n (sys_rst_n), // FTDI硬件引脚 .ftdi_data (ftdi_data), // 双向数据线 .ftdi_rxf_n (ftdi_rxf_n), .ftdi_txe_n (ftdi_txe_n), .ftdi_rd_n (ftdi_rd_n), .ftdi_wr_n (ftdi_wr_n), // 用户发送接口 (FPGA - PC) .tx_data (tx_data_to_ftdi), // 来自发送异步FIFO的数据 .tx_valid (tx_valid_to_ftdi), // 发送异步FIFO读有效 .tx_ready (tx_ready_from_ftdi), // 连接到发送异步FIFO的读使能 // 用户接收接口 (PC - FPGA) .rx_data (rx_data_from_ftdi), .rx_valid (rx_valid_from_ftdi), .rx_ready (rx_ready_to_ftdi) ); // 实例化发送路径的异步FIFO (Frame Packager - FTDI Ctrl) async_fifo #( .DATA_WIDTH (8), .DEPTH (1024) ) u_async_fifo_tx ( .wr_clk (frame_pack_clk), .wr_rst (~sys_rst_n), .wr_en (fifo_tx_wr_en), .din (fifo_tx_din), .full (fifo_tx_full), .rd_clk (clk_ftdi), .rd_rst (~sys_rst_n), .rd_en (tx_ready_from_ftdi tx_valid_to_ftdi), // FTDI控制器正在读 .dout (tx_data_to_ftdi), .empty (), .valid (tx_valid_to_ftdi) // 当dout有效时拉高 );5.3 PC端C显示程序核心逻辑// 简化的主循环 FT_HANDLE ftHandle; // ... 打开设备配置模式同步FIFO ... std::vectorBYTE rawBuffer; std::queuestd::vectorBYTE frameQueue; // 线程安全队列更佳 const DWORD HEADER 0xA5A5A5A5; while (running) { DWORD bytesReceived 0; BYTE chunk[4096]; // 读取一块数据 FT_Status status FT_Read(ftHandle, chunk, sizeof(chunk), bytesReceived); if (status FT_OK bytesReceived 0) { rawBuffer.insert(rawBuffer.end(), chunk, chunk bytesReceived); // 尝试解析帧 while (rawBuffer.size() 8) { // 至少够帧头长度 // 查找帧头 auto it std::search(rawBuffer.begin(), rawBuffer.end(), reinterpret_castconst BYTE*(HEADER), reinterpret_castconst BYTE*(HEADER) 4); if (it rawBuffer.begin()) { // 找到帧头 if (rawBuffer.size() 8) { DWORD len *reinterpret_castDWORD*(rawBuffer[4]); // 注意字节序 if (rawBuffer.size() 8 len) { // 提取一帧 std::vectorBYTE oneFrame(rawBuffer.begin() 8, rawBuffer.begin() 8 len); frameQueue.push(oneFrame); // 从缓冲区移除已处理数据 rawBuffer.erase(rawBuffer.begin(), rawBuffer.begin() 8 len); } else { break; // 数据不够一帧继续读 } } else { break; } } else if (it ! rawBuffer.end()) { // 帧头不在开头丢弃前面的无效数据 rawBuffer.erase(rawBuffer.begin(), it); } else { // 未找到帧头可能数据不完整清空或保留部分 if (rawBuffer.size() 1024) { // 防止无效数据堆积 rawBuffer.clear(); } break; } } } // 处理完整帧 while (!frameQueue.empty()) { auto frame frameQueue.front(); // 假设是640x480灰度图 cv::Mat img(480, 640, CV_8UC1, frame.data()); cv::imshow(FPGA Image, img); cv::waitKey(1); frameQueue.pop(); } }6. 调试技巧与常见问题排查即使按照上述步骤第一次调试也难免遇到问题。以下是我踩过坑后总结的排查清单。6.1 硬件连接与信号测量电源与地首先确保FTDI芯片和FPGA的电源稳定共地良好。用万用表测量电压。时钟信号用示波器测量FT232H的CLKOUT引脚确认是否有稳定的60MHz或标称频率方波输出。这是整个通信的基准没有时钟一切免谈。控制信号在FPGA程序运行后测量RXF#,TXE#。如果PC端没有打开设备或没有准备读数据TXE#可能常高FIFO满这是正常的。可以尝试让PC端运行一个简单的读循环程序观察RXF#是否会周期性变低表示接收FIFO有数据。数据总线在进行数据传输时用示波器或逻辑分析仪抓取DATA总线和WR#/RD#信号对照芯片手册的时序图检查建立时间、保持时间是否满足。特别注意WR#/RD#的脉冲宽度是否至少为一个CLKOUT周期。6.2 FPGA逻辑调试仿真先行务必使用项目自带的或自己编写的Testbench对ftdi_245fifo控制器进行仿真。模拟RXF#/TXE#信号的变化观察其rd_n/wr_n和数据总线行为是否符合预期。这是排查逻辑错误最快的方法。内嵌逻辑分析仪使用Xilinx的ILA或Intel的SignalTap。抓取关键信号clk_ftdi,tx_valid,tx_ready,rx_valid,rx_ready以及连接到异步FIFO的读写信号。观察数据流是否畅通。tx_ready常低说明PC端未及时读取TXE#为高rx_valid没有脉冲说明PC端没有发送数据或RXF#常高。检查异步FIFO重点监控异步FIFO的空满标志。如果发送路径的FIFO常满说明数据产生速度远大于USB发送速度需要优化源端或协议。如果FIFO既不满也不空但数据不动可能是流控或握手有问题。6.3 PC端软件调试驱动模式确认使用FTDI提供的FT_Prog工具或通过D2XX的FT_GetBitModeAPI确认芯片是否已被正确设置为同步FIFO模式0x40。这是最容易被忽略的一步。设备打开与权限确保程序以管理员权限运行某些系统需要并且设备没有被其他程序如VCP驱动、串口助手占用。简单的回环测试编写一个最简单的程序打开设备配置为同步FIFO然后在一个循环里先写一段固定的数据如“ABCD”到设备紧接着读回来看是否一致。这可以最快速验证整个通路PC驱动-USB-FPGA-USB-PC驱动是否基本通畅。注意这需要FPGA程序实现回环逻辑将接收到的数据直接发回。缓冲区与超时设置如果读不到数据尝试增大FT_SetUSBParameters的缓冲区大小并增加FT_Read的超时时间。同时检查FT_SetLatencyTimer的值是否太小。字节序问题FTDI芯片的数据总线是8位的通常不存在字节序问题。但如果你在协议中使用了多字节整数如帧长度FPGA和PC需要约定一致的字节序通常是小端序。在PC端解析时要注意转换。6.4 性能瓶颈分析如果速度达不到预期比如远低于30MB/s可以按以下顺序排查PC端读取是否及时在PC端读线程中计算实际读取速率。如果读线程被阻塞或调度不及时会导致FTDI芯片内部的FIFO满从而使TXE#变高FPGA停止发送。FPGA端是否持续有数据通过ILA观察tx_valid和tx_ready信号。理想状态下在传输过程中tx_ready应几乎一直为高表示PC随时可收tx_valid也应为高表示FPGA持续提供数据。如果tx_valid断续说明数据源有瓶颈。USB传输设置确认FT_SetUSBParameters设置了最大缓冲区如65536。尝试调整FT_SetLatencyTimer对于大流量连续传输较小的值如2有助于减少延迟但可能会增加CPU占用。可以尝试不同的值进行 benchmark。PC系统因素关闭节能模式确保USB主机控制器驱动为最新尝试将设备插在主板背面的USB口通常由芯片组直连非第三方Hub扩展。这个基于FTDI同步FIFO的方案在我经历的多款产品和项目中都证明了其极高的可靠性和性价比。它不像PCIe或以太网那样需要复杂的协议栈和硬件设计又能提供远超串口的带宽是连接FPGA与PC进行高速数据交互的“瑞士军刀”。掌握它意味着你手里多了一件解决实时数据传输难题的利器。

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