CircuitPython SD卡文件系统挂载与数据记录实战指南

news2026/5/15 2:27:47
1. 项目概述为什么要在嵌入式系统里折腾SD卡如果你玩过树莓派Pico、Adafruit的Feather系列或者任何一款支持CircuitPython的开发板你肯定对板载的那块小小的存储通常被挂载为CIRCUITPY盘符又爱又恨。爱的是它让编程变得像在U盘里拖放文件一样简单恨的是它的容量实在有限存点代码和库文件还行真要记录长时间的传感器数据、存放大量音频图片资源或者做个离线数据库那点空间眨眼就没了。这时候一块小小的microSD卡就成了你的“外置硬盘”。它能轻松提供从几GB到上百GB的存储空间成本低廉可靠性也经过了时间的考验。但问题来了在资源紧张的微控制器MCU上如何让Python代码像在电脑上一样轻松地读写这张卡里的文件呢答案就是通过文件系统进行挂载。简单来说挂载就像给SD卡这个“物理仓库”在CircuitPython的操作系统里分配一个“门牌号”比如/sd。之后所有对这个“门牌号”的访问都会被自动转译成对SD卡底层存储块的操作。CircuitPython通过adafruit_sdcard库处理底层的SPI通信协议再通过storage模块提供一个符合Python标准的文件系统接口VfsFat。这样一来你就能用熟悉的open()、read()、write()这些函数来操作文件几乎和你在电脑上写Python脚本没有区别。这篇指南就是为你准备的无论你是想为气象站记录长达数月的数据为小型媒体播放器存储歌曲列表还是为机器人保存复杂的动作路径通过SD卡扩展存储都是必由之路。我会带你从硬件连线开始一步步走到稳定可靠的数据读写并分享那些官方文档里不会细说的“坑”和实战技巧。2. 核心硬件连接与SPI通信原理在写第一行代码之前正确的硬件连接是成功的基石。SD卡通常通过SPISerial Peripheral Interface协议与主控芯片通信这是一种高速、全双工的同步串行总线。2.1 SPI引脚定义与接线方案一个标准的SPI总线需要四根线SCK (Serial Clock)时钟线由主设备你的开发板产生用于同步数据。MOSI (Master Out Slave In)主设备输出从设备输入。你的开发板通过这根线向SD卡发送命令和数据。MISO (Master In Slave Out)主设备输入从设备输出。SD卡通过这根线向你的开发板返回数据和状态。CS (Chip Select)片选线有时也标记为SS。用于在多个SPI设备中选择当前要通信的那个。对于SD卡此引脚必须连接。注意大多数开发板的SPI引脚是固定的。例如在常见的RP2040树莓派Pico或ATSAMD21Feather M0芯片上通常有一组“默认”SPI引脚。以树莓派Pico为例其默认SPI0的引脚是SCKGP18,MOSIGP19,MISOGP16。接线时务必查阅你的开发板原理图。除了这四根数据线千万不要忘记连接电源3.3V和地线GND。SD卡的工作电压是3.3V直接连接到5V会永久损坏它一个典型的连接示意图如下以通用开发板为例开发板 MicroSD卡模块 3.3V ---------- VCC GND ---------- GND GP18 ---------- SCK GP19 ---------- MOSI GP16 ---------- MISO GP17 ---------- CS (此处GP17仅为示例可选择任何数字IO口)2.2 SPI总线共享的隐患与解决方案你的开发板上的SPI接口可能非常有限。很多时候除了SD卡模块你可能还想连接OLED屏幕、无线模块如NRF24L01等其他SPI设备。共享SPI总线是允许的但有一个至关重要的顺序要求。官方文档里那句警告值得用红字标出如果SPI总线被其他外设共享必须先初始化SD卡然后才能访问总线上的任何其他外设。为什么这是因为SD卡在上电初始化阶段对总线时序非常敏感。如果其他设备先于SD卡在总线上产生了通信可能会干扰SD卡的初始化序列导致其无法被正确识别。表现出来的现象就是你的代码可能第一次运行失败只有拔插SD卡或重启板子才能恢复。实操心得在我的一个温室监控项目中板子上同时接了SD卡和温湿度传感器。如果先初始化传感器SD卡挂载成功率不到50%。调整顺序先严格按初始化SPI - 初始化SD卡 - 挂载文件系统 - 初始化其他SPI设备的流程操作后稳定性达到100%。所以最好的实践是在代码开头集中完成所有SD卡相关的初始化工作。3. 软件初始化从导入库到挂载文件系统硬件准备就绪后我们进入软件部分。整个过程就像搭积木每一步都有其明确的目的。3.1 导入必要的核心模块首先在code.py的开头我们需要导入所有必需的库。这些库就像是不同工种的工具。import board import busio import digitalio import storage import adafruit_sdcard import osboard提供了对你开发板上特定引脚命名的访问如board.SCK。busio用于管理硬件通信协议这里我们用到它的SPI类。digitalio用于配置和控制数字输入输出引脚这里用来控制片选CS线。storageCircuitPython的核心存储模块提供VfsFatFAT文件系统类和mount挂载函数。adafruit_sdcard这是Adafruit提供的、专门用于和SD卡进行底层SPI通信的驱动库。os可选的但非常有用。它提供了列出目录、获取文件状态等高级文件操作功能。3.2 配置SPI总线与片选引脚接下来我们需要创建SPI总线对象和片选引脚对象。这里的选择会因你的开发板和接线方式而异。# 创建SPI总线对象使用开发板默认的SPI引脚 spi busio.SPI(board.SCK, MOSIboard.MOSI, MISOboard.MISO) # 创建片选(CS)引脚对象 # 情况1如果你使用的是像Feather M0 Adalogger这样有专用SD卡槽的开发板 cs digitalio.DigitalInOut(board.SD_CS) # 引脚名通常是预定义的 # 情况2如果你使用的是通用SD卡模块连接到任意数字IO口例如GPIO5 # cs digitalio.DigitalInOut(board.D5) # 或者 board.GP5具体名称取决于开发板关键细节解析busio.SPI()的第一个参数是时钟引脚SCK之后用关键字参数指定MOSI和MISO。这种调用方式清晰且不易出错。对于片选引脚cs务必将其配置为数字输出模式。虽然DigitalInOut对象默认方向是输入但adafruit_sdcard库在内部会将其设置为输出。为了代码清晰你也可以显式设置cs.direction digitalio.Direction.OUTPUT。选择哪个引脚作为CS答案是除了正在被用作SPI功能SCK, MOSI, MISO的引脚其他任何数字IO口都可以。通常选择你接线的那一个。3.3 创建SD卡与文件系统对象有了SPI和CS我们就可以创建代表SD卡本身的对象了。sdcard adafruit_sdcard.SDCard(spi, cs) vfs storage.VfsFat(sdcard)adafruit_sdcard.SDCard(spi, cs)这个步骤是关键。它实例化一个SDCard对象该对象封装了所有与SD卡进行底层SPI命令交互的复杂逻辑包括初始化和读写扇区。你只需要把配置好的spi和cs对象传给它。storage.VfsFat(sdcard)这是将底层存储“翻译”成文件系统的关键一步。VfsFat是一个实现了FAT16/FAT32文件系统协议这是SD卡最通用的格式的虚拟文件系统类。它接收SDCard对象作为参数意味着“请使用这个SD卡作为你的物理存储后端”。3.4 执行挂载让/sd目录生效最后一步也是让一切变得可用的魔法命令storage.mount(vfs, /sd)storage.mount()函数接收两个参数第一个是我们刚创建的文件系统对象vfs第二个是挂载点路径这里我们指定为/sd。执行这条命令后CircuitPython的虚拟文件系统里就会出现一个名为/sd的目录。所有对这个目录下文件的操作都会通过vfs对象最终落实到那张物理的SD卡上。关于CircuitPython 9的重要变化从CircuitPython 9开始为了提升安全性和一致性SD卡必须且只能挂载到/sd路径。这意味着你不能像以前一样随意指定成/external之类的名字。更关键的是你需要在CIRCUITPY驱动器的根目录下手动创建一个空的sd文件夹。否则挂载时会报错提示找不到挂载点。这是一个非常容易忽略的步骤也是很多人在升级后遇到问题的根源。4. 文件读写操作实战与Python技巧挂载成功之后世界就开阔了。你现在拥有了一块可以通过标准Python文件API访问的大容量存储。让我们深入看看具体怎么用。4.1 基础文件操作写、读、追加操作SD卡上的文件路径都要以/sd/开头。这是区分板载闪存文件和SD卡文件的唯一标识。写入文件# 使用‘w’模式写入如果文件存在会被覆盖 with open(/sd/test.txt, w) as f: f.write(Hello, SD Card!\n) f.write(This is another line.\n)with open(...) as f:这是极其重要的Python上下文管理器用法。它能确保文件在任何情况下包括发生异常都会被正确关闭。在嵌入式系统中文件不关闭可能导致数据丢失或损坏务必养成习惯。w模式代表“写入”。如果文件不存在则创建如果存在则清空后重新写入。注意换行符write()函数不会自动添加换行。你需要像上面那样在字符串末尾加上\nUnix/Linux换行符或\r\nWindows换行符。在文本文件中CircuitPython通常都能正确处理\n。读取文件# 使用‘r’模式读取 with open(/sd/test.txt, r) as f: content f.read() # 一次性读取全部内容 print(content) # 更安全的方式逐行读取适合大文件 with open(/sd/test.txt, r) as f: for line in f: # 文件对象本身是可迭代的 print(line, end) # line已包含换行符所以print用end避免双换行f.read()简单粗暴但会将整个文件内容加载到内存。对于小配置文件几KB没问题但对于日志文件几MB很可能导致内存不足MemoryError。for line in f:这是推荐的做法。它利用惰性读取一次只读一行到内存内存占用恒定非常适合嵌入式环境。追加数据# 使用‘a’模式追加数据会被添加到文件末尾 with open(/sd/log.txt, a) as f: import time timestamp time.monotonic() f.write(fEvent occurred at: {timestamp}\n)a模式代表“追加”。这是数据记录Data Logging场景的标准模式。文件不存在时会创建存在时则在末尾添加新数据原有数据完好无损。4.2 高级文件与目录管理除了基本的读写你经常需要管理文件和目录结构。列出目录内容import os # 列出/sd根目录下的所有文件和文件夹 print(Root directory:) for item in os.listdir(/sd): print(f {item}) # 结合os.stat获取详细信息类型、大小 for item in os.listdir(/sd): item_path /sd/ item stat_info os.stat(item_path) is_dir stat_info[0] 0x4000 # 判断是否为目录的标志位 size stat_info[6] # 文件大小字节 type_str DIR if is_dir else FILE print(f{type_str:4s} {item:20s} {size:8d} bytes)os.listdir(path)返回指定路径下的文件名列表。os.stat(path)返回一个包含文件元数据的元组。索引[6]是文件大小字节索引[0]st_mode包含文件类型和权限信息通过与0x4000进行位与运算可以判断是否为目录。创建目录与路径检查# 创建新目录 os.mkdir(/sd/my_data) # 递归创建多级目录CircuitPython的os.makedirs可能在某些版本可用 # 更通用的方法是逐级检查并创建 def ensure_dir_exists(path): 确保路径中的目录存在如果不存在则创建仅限一级 try: os.stat(path) except OSError: os.mkdir(path) # 使用示例 ensure_dir_exists(/sd/logs/daily) # 需要先确保/sd/logs存在再创建daily # 检查是文件还是目录 try: stat os.stat(/sd/some_path) if stat[0] 0x4000: print(It‘s a directory.) else: print(It‘s a file.) except OSError: print(Path does not exist.)4.3 嵌入式环境下的文件操作最佳实践在资源受限的MCU上文件操作需要更加小心以避免崩溃或数据损坏。频繁写入与电源安全避免在循环中反复打开、关闭文件。但更应避免长时间保持文件打开状态。最佳实践是像之前温度记录的示例一样在with open(...)块内完成写入然后立即关闭。with语句保证了即使写入过程中发生异常文件也会被尽力关闭。对于关键数据可以考虑写满一个缓冲区比如4KB后再一次性写入以减少SD卡磨损但会增加断电丢失数据的风险。错误处理永远要对文件操作进行异常捕获。try: with open(/sd/data.bin, rb) as f: data f.read(1024) except OSError as e: print(fFailed to read file: {e}) # 可能的处理重试、使用默认值、点亮错误LED等OSError是文件系统相关操作最常见的异常可能因为文件不存在、路径错误、SD卡被拔出、IO错误等引发。内存管理使用read(size)指定读取字节数或使用逐行迭代避免一次性读取大文件。处理二进制文件时尤其要注意。文件系统维护虽然FAT文件系统很健壮但不正常的断电仍可能导致文件系统错误。对于非常重要的项目可以定期例如每写入1000次后调用os.sync()如果支持来强制将缓存写入物理介质或者安全卸载后重新挂载。不过CircuitPython的VfsFat和with语句通常已做了足够的缓冲管理。5. 完整项目示例构建一个数据记录仪理论说得再多不如一个实际项目来得透彻。让我们构建一个简单的环境数据记录仪它将温度、湿度假设使用DHT22传感器和光照强度记录到SD卡并包含一些健壮性设计。5.1 硬件清单与接线主控板Adafruit Feather M4 Express或其他支持CircuitPython的板存储MicroSD卡模块SPI接口传感器DHT22温湿度光照强度传感器如APDS-9960或模拟光敏电阻连线SD卡模块按前述连接至板载SPI引脚和某个数字IO作为CS。DHT22数据线连接至另一个数字IO如board.D10。光敏电阻连接至模拟输入引脚如board.A0。5.2 代码实现健壮的数据记录器# SPDX-FileCopyrightText: 2024 Your Name # SPDX-License-Identifier: MIT 一个健壮的SD卡数据记录仪示例 记录温度、湿度和光照强度并处理常见错误。 import time import board import busio import digitalio import analogio import adafruit_dht import adafruit_sdcard import storage import os # --- 1. 硬件初始化 --- print(Initializing Data Logger...) # 初始化LED用于状态指示 led digitalio.DigitalInOut(board.LED) led.direction digitalio.Direction.OUTPUT # 初始化传感器 # 注意DHT22读取可能较慢且有时会失败需要错误处理 dht_sensor adafruit_dht.DHT22(board.D10) light_sensor analogio.AnalogIn(board.A0) # --- 2. SD卡初始化与挂载带重试--- def init_sd_card(): 初始化并挂载SD卡失败时重试几次 max_retries 3 for attempt in range(max_retries): try: led.value True # 点亮LED表示正在尝试 spi busio.SPI(board.SCK, MOSIboard.MOSI, MISOboard.MISO) cs digitalio.DigitalInOut(board.D5) # 假设CS接在D5 sdcard adafruit_sdcard.SDCard(spi, cs) vfs storage.VfsFat(sdcard) storage.mount(vfs, /sd) print(f[Attempt {attempt1}] SD card mounted successfully.) led.value False return True except OSError as e: print(f[Attempt {attempt1}] SD card init failed: {e}) led.value False time.sleep(1) # 等待一秒后重试 print(Failed to initialize SD card after all retries.) return False if not init_sd_card(): # 如果SD卡初始化失败可以进入降级模式例如只打印到串口 print(Entering fallback mode (serial output only).) sd_available False else: sd_available True # 确保日志目录存在 try: os.stat(/sd/logs) except OSError: os.mkdir(/sd/logs) # --- 3. 主循环数据记录 --- LOG_INTERVAL 60 # 记录间隔单位秒 log_count 0 print(Starting main logging loop...) while True: log_count 1 timestamp time.monotonic() # 获取开机后的时间秒适合记录相对时间 # 更佳实践如果有网络可以同步RTC时间否则记录相对时间或简单的计数。 # 读取传感器数据带错误处理 temperature humidity None try: temperature dht_sensor.temperature humidity dht_sensor.humidity except RuntimeError as e: print(fDHT22 read error: {e}) light_value light_sensor.value # 模拟值范围0-65535 # 格式化数据行 data_line f{log_count},{timestamp:.1f},{temperature if temperature is not None else NaN},{humidity if humidity is not None else NaN},{light_value}\n # 输出到串口 print(fLog {log_count}: {data_line.strip()}) # 写入SD卡如果可用 if sd_available: try: # 使用‘a‘模式追加文件会自动创建 # 可以按日期分割文件这里简化为单个文件 with open(/sd/logs/environment.csv, a) as log_file: # 如果是第一次写入可以添加CSV表头 if log_count 1: log_file.write(id,timestamp_seconds,temperature_c,humidity_percent,light_raw\n) log_file.write(data_line) # 可选每记录100次同步一次以确保数据写入物理介质 if log_count % 100 0: os.sync() # 注意os.sync()的可用性取决于CircuitPython版本和端口 print(Checkpoint: Data synced to SD card.) except OSError as e: print(fFailed to write to SD card: {e}) # 这里可以添加更复杂的错误恢复逻辑比如重新初始化SD卡 sd_available False # 暂时禁用SD卡写入避免持续报错 # 等待下一个记录周期 time.sleep(LOG_INTERVAL)5.3 示例代码的关键设计解析模块化与错误处理init_sd_card()函数封装了初始化逻辑并加入了重试机制。传感器读取尤其是DHT22也包裹在try-except中防止单次读取失败导致整个程序崩溃。降级运行如果SD卡完全无法使用程序会将sd_available设为False并继续通过串口打印数据。这保证了核心的传感器读取功能不因存储故障而中断提高了系统鲁棒性。数据格式使用CSV逗号分隔值格式存储数据。第一行是表头明确了每一列的含义。这种格式几乎可以被任何数据分析工具如Excel, Python pandas直接导入非常通用。资源管理文件在with语句块中打开和关闭。虽然每次循环都打开关闭文件会增加一点开销但保证了数据的即时写入降低了因意外断电而丢失大量数据的风险。状态指示使用板载LED在初始化SD卡时闪烁提供了直观的系统状态反馈。6. 故障排除与性能优化实战经验即使按照指南操作你也可能会遇到问题。下面是我在多个项目中总结出的常见“坑”及其解决方案。6.1 常见问题速查表问题现象可能原因排查步骤与解决方案OSError: [Errno 19] No such device或初始化失败1. 硬件接线错误电源、地线、四根数据线。2. CS引脚选择错误或未正确初始化。3. SD卡格式不为FAT16/FAT32。4. SPI总线冲突其他设备先于SD卡初始化。5. (CircuitPython 9) 未在CIRCUITPY创建/sd目录。1.断电检查所有连线确保接触牢固。2. 确认CS引脚号与代码一致并尝试更换其他数字IO口。3. 将SD卡通过读卡器插入电脑格式化为FAT32分配单元大小默认即可。4.确保代码中SD卡初始化在最前面。5. 在CIRCUITPY驱动器根目录新建一个名为sd的文件夹。可以挂载但无法创建/写入文件1. SD卡写保护开关被打开。2. 文件系统已满。3. SD卡损坏或质量太差。4. 在只读模式下挂载非本案例。1. 检查SD卡侧面的物理写保护开关。2. 检查SD卡剩余空间。3. 换一张品牌好、容量适中如16GB/32GB的SD卡。超大容量如128GB以上或杂牌卡兼容性可能不佳。4. 确保使用storage.mount(vfs, /sd)这是读写模式。读取文件内容为空或乱码1. 文件未正确关闭数据还在缓冲区。2. 写入和读取使用的编码不一致如二进制 vs 文本。3. 文件指针问题。1.始终使用with open() as f:语句它能保证文件关闭和缓冲区刷新。2. 文本读写用默认模式二进制数据用rb或wb模式。确保一致。3. 写入后如果立即读取确保先关闭文件再重新打开或者使用f.seek(0)将指针移回文件开头。操作一段时间后SD卡无法访问需要复位1. SPI总线受到干扰如长线、电机等噪声源。2. 电源不稳定导致SD卡掉电复位。3. 文件系统逻辑错误异常断电导致。1. 缩短连接线远离噪声源或在SPI线上加10-100欧姆的串联电阻。2. 为SD卡模块增加一个10-100μF的电解电容在VCC和GND之间提供瞬时电流缓冲。3. 在电脑上修复SD卡文件系统错误。考虑在代码中加入“看门狗”逻辑定期检查SD卡状态失败时尝试重新挂载。写入速度非常慢1. 默认SPI时钟频率较低。2. 每次写入数据量太小如单次写入1字节。3. SD卡本身速度等级低Class 4。1. CircuitPython的busio.SPI通常会自动协商到最高速但可以尝试在初始化后手动设置spi.try_lock(); spi.configure(baudrate8000000)8MHz需在SD卡初始化后尝试且非所有板型支持。2.合并数据减少写入频率。例如将10次传感器读数缓存在列表中每10次写入一次文件。3. 使用Class 10或UHS-I的SD卡。6.2 高级优化技巧缓冲区写入对于高频数据记录频繁的文件打开关闭和小数据写入会成为瓶颈。可以建立一个缓冲区。data_buffer [] BUFFER_SIZE 50 # 积攒50条记录再写入 def log_data(temperature, humidity): data_buffer.append(f{time.monotonic()},{temperature},{humidity}\n) if len(data_buffer) BUFFER_SIZE: with open(/sd/data.csv, a) as f: f.writelines(data_buffer) # 一次性写入多行 data_buffer.clear() # 清空缓冲区这大大减少了文件系统操作次数提升了效率和SD卡寿命。文件轮转避免单个日志文件无限增大。可以按大小或时间分割文件。import os MAX_FILE_SIZE 1024 * 1024 # 1MB current_file /sd/logs/log_1.txt def write_with_rotation(data): global current_file # 检查当前文件大小 try: size os.stat(current_file)[6] except OSError: size 0 if size MAX_FILE_SIZE: # 找到下一个可用的文件编号 index 1 while os.path.exists(f/sd/logs/log_{index}.txt): index 1 current_file f/sd/logs/log_{index}.txt print(fRotating to new file: {current_file}) with open(current_file, a) as f: f.write(data)低功耗考量对于电池供电设备SD卡和SPI总线在闲置时会耗电。可以在数据记录间隔期间彻底断开SD卡电源通过一个MOSFET控制或者将MCU和SD卡都置于睡眠模式。这需要更复杂的硬件和软件设计。通过这篇指南你应该已经从硬件连接到高级应用对CircuitPython下的SD卡文件操作有了全面的了解。记住嵌入式开发总是伴随着调试遇到问题时耐心地从电源、接线、初始化顺序这些基础点查起利用好串口打印信息大部分问题都能迎刃而解。现在就去为你下一个酷炫的物联网项目装上“海量存储”吧。

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