嵌入式LCD菜单框架:基于FSM的轻量级状态管理方案

news2026/4/6 0:10:30
1. WSEMenu 库概述WSEMenu 是一个面向嵌入式 LCD 人机交互场景的轻量级状态管理与菜单框架专为字符型液晶显示屏典型规格20×4 字符设计。其核心目标并非提供图形渲染能力而是解决嵌入式系统中普遍存在的“状态跳转混乱”“菜单层级耦合度高”“按键响应逻辑分散”等工程痛点。该库不依赖任何操作系统裸机可用亦可无缝集成 FreeRTOS 等实时内核不绑定特定 MCU 平台仅通过一组精简、明确的硬件抽象接口HAL与底层驱动解耦不强制使用 C 或面向对象语法纯 C 实现兼顾资源受限设备如 STM32F0/F1、NXP KL25Z、ESP32-S2的代码体积与执行效率。从工程视角看WSEMenu 的本质是一个有限状态机FSM 分层菜单树Hierarchical Menu Tree的复合结构。它将用户界面划分为若干逻辑状态State每个状态对应一个独立的显示内容与输入响应逻辑同时将菜单项组织为父子关系的树形结构支持多级嵌套如主菜单 → 设置子菜单 → 时间设置 → 小时调整。这种设计使开发者能以声明式方式定义菜单拓扑而由库自动处理状态切换、焦点移动、按键消抖、屏幕刷新等重复性工作显著降低 UI 层代码的维护成本与出错概率。值得注意的是WSEMenu 并非“全功能 GUI 库”。它不提供字体渲染、位图显示、触摸坐标映射或动画效果。其价值恰恰在于“克制”——在 20×4 LCD 这一物理约束下聚焦于信息呈现的清晰性、操作路径的确定性与资源占用的极致优化。一个典型应用是工业现场仪表的参数配置界面主屏显示实时测量值State: DISPLAY_MAIN长按“SET”键进入一级菜单State: MENU_LEVEL1旋钮编码器上下滚动选择“校准”“通信设置”“系统信息”确认后进入二级子菜单State: MENU_LEVEL2最终通过方向键确认键完成参数修改。整个流程中WSEMenu 负责状态流转控制与菜单项高亮渲染开发者只需实现各状态下的业务逻辑回调函数。2. 核心架构与设计原理2.1 整体架构分层WSEMenu 采用清晰的三层架构符合嵌入式软件分层设计原则层级名称职责与硬件/OS 关系L1硬件抽象层HAL提供统一接口访问 LCD 显示、按键输入、编码器旋转等外设直接操作 GPIO、定时器、ADC 等寄存器或 HAL 库 API必须由用户实现L2状态机与菜单引擎层Core Engine管理当前状态、解析用户输入事件、执行状态迁移、遍历菜单树、触发回调完全平台无关不调用任何 OS API裸机/FreeRTOS 均可L3应用逻辑层User Application定义菜单树结构、编写各状态的显示逻辑render()、输入处理逻辑handle_input()、数据更新逻辑update_data()通过注册回调函数与 Core Engine 交互核心开发区域此分层确保了高度的可移植性更换 MCU 时仅需重写 L1 层 HAL 函数升级 UI 需求时仅需修改 L3 层菜单定义与回调L2 层引擎零改动。2.2 状态机FSM设计详解WSEMenu 的状态机采用事件驱动Event-Driven模式而非轮询Polling。其核心数据结构为wse_state_t枚举类型预定义了基础状态typedef enum { WSE_STATE_NONE 0, // 无效状态初始化用 WSE_STATE_MENU_ROOT, // 根菜单一级菜单 WSE_STATE_MENU_SUB, // 子菜单二级及以上 WSE_STATE_DISPLAY, // 纯数据显示状态如主屏 WSE_STATE_EDIT_VALUE, // 数值编辑状态如修改时间 WSE_STATE_CONFIRM, // 确认对话框状态 WSE_STATE_CUSTOM_0, // 用户自定义状态 0扩展用 WSE_STATE_CUSTOM_1, // 用户自定义状态 1扩展用 } wse_state_t;状态迁移由wse_process_event()函数驱动该函数接收一个wse_event_t类型事件typedef enum { WSE_EVENT_NONE 0, WSE_EVENT_KEY_UP, // 上键按下短按 WSE_EVENT_KEY_DOWN, // 下键按下短按 WSE_EVENT_KEY_LEFT, // 左键按下短按 WSE_EVENT_KEY_RIGHT, // 右键按下短按 WSE_EVENT_KEY_ENTER, // 确认键按下短按 WSE_EVENT_KEY_BACK, // 返回键按下短按 WSE_EVENT_KEY_LONG, // 任意键长按需 HAL 支持计时 WSE_EVENT_ENCODER_INC, // 编码器顺时针旋转1 WSE_EVENT_ENCODER_DEC, // 编码器逆时针旋转-1 } wse_event_t;关键设计原理状态迁移逻辑完全封装在引擎内部。例如当处于WSE_STATE_MENU_ROOT且收到WSE_EVENT_KEY_DOWN事件时引擎自动将焦点移至下一个菜单项若收到WSE_EVENT_KEY_ENTER则根据当前焦点项的type字段决定动作——若为WSE_MENU_ITEM_TYPE_SUBMENU则迁移到WSE_STATE_MENU_SUB并加载子菜单若为WSE_MENU_ITEM_TYPE_ACTION则直接调用其关联的action_cb回调函数。开发者无需编写if (state X event Y) { state Z; }这类易错的硬编码状态跳转。2.3 菜单树Menu Tree数据结构菜单项Menu Item是 WSEMenu 的核心数据单元定义为wse_menu_item_t结构体typedef struct { const char* text; // 菜单项显示文本最大长度由 LCD 列数决定20x4 即 ≤20 wse_menu_item_type_t type; // 类型WSE_MENU_ITEM_TYPE_SUBMENU / ACTION / VALUE / SEPARATOR union { const wse_menu_item_t* submenu; // 指向子菜单数组首地址type SUBMENU void (*action_cb)(void); // 动作回调函数指针type ACTION struct { int32_t* value_ptr; // 指向被编辑变量的指针type VALUE int32_t min; // 最小值用于循环/边界检查 int32_t max; // 最大值 const char* format; // printf 风格格式化字符串如 %02d:%02d } value; }; void (*render_cb)(void); // 自定义渲染回调可选覆盖默认高亮逻辑 } wse_menu_item_t;菜单树通过静态数组构建天然支持编译期确定性。一个典型的三级菜单定义如下// 二级子菜单时间设置 const wse_menu_item_t menu_time_items[] { {小时, WSE_MENU_ITEM_TYPE_VALUE, {.value {.value_ptr g_hour, .min 0, .max 23, .format %02d}}}, {分钟, WSE_MENU_ITEM_TYPE_VALUE, {.value {.value_ptr g_min, .min 0, .max 59, .format %02d}}}, {返回, WSE_MENU_ITEM_TYPE_ACTION, {.action_cb menu_back_to_root}}, {NULL, WSE_MENU_ITEM_TYPE_SEPARATOR, {}} }; // 一级菜单 const wse_menu_item_t menu_root_items[] { {实时数据, WSE_MENU_ITEM_TYPE_ACTION, {.action_cb switch_to_display_state}}, {时间设置, WSE_MENU_ITEM_TYPE_SUBMENU, {.submenu menu_time_items}}, {系统信息, WSE_MENU_ITEM_TYPE_ACTION, {.action_cb show_system_info}}, {重启, WSE_MENU_ITEM_TYPE_ACTION, {.action_cb system_reboot}}, {NULL, WSE_MENU_ITEM_TYPE_SEPARATOR, {}} };设计优势内存高效所有菜单数据存储在 Flash 中运行时仅需少量 RAM焦点索引、当前状态等。编译期检查text字符串长度可在编译时通过static_assert(strlen(text) LCD_COLS)验证避免运行时截断。灵活扩展union设计允许同一结构体承载不同语义的数据render_cb提供深度定制能力如为某项添加闪烁图标。3. 关键 API 接口详解WSEMenu 的 API 设计遵循“最小接口原则”仅暴露必需函数降低学习与误用成本。所有函数均以wse_为前缀避免命名冲突。3.1 初始化与主循环接口函数签名参数说明返回值典型用途void wse_init(const wse_menu_item_t* root_menu)root_menu: 指向根菜单数组的指针void必须首先调用。初始化引擎状态加载根菜单设置初始状态为WSE_STATE_MENU_ROOT。void wse_main_loop(void)无void裸机环境主循环入口。持续调用此函数引擎将自动轮询 HAL 获取输入事件、更新状态、触发渲染。建议置于while(1)内。void wse_process_event(wse_event_t event)event: 触发的事件类型voidFreeRTOS 环境推荐。由按键/编码器中断服务程序ISR或专用输入任务调用将事件注入引擎队列。工程实践要点wse_init()必须在所有外设LCD、按键初始化完成后调用。在 FreeRTOS 中wse_process_event()应在 ISR 中以xQueueSendFromISR()方式发送事件到引擎队列避免在 ISR 中执行耗时操作。wse_main_loop()内部已包含必要的防抖延时基于 HAL 提供的wse_hal_get_tick_ms()开发者无需额外处理。3.2 状态管理与导航接口函数签名参数说明返回值典型用途wse_state_t wse_get_current_state(void)无当前状态枚举值调试时查询当前所处状态条件逻辑分支依据。void wse_set_state(wse_state_t new_state)new_state: 目标状态void强制状态跳转。例如在ACTION回调中调用wse_set_state(WSE_STATE_DISPLAY)直接返回主屏。void wse_go_back(void)无void通用返回操作。引擎自动记录状态历史栈调用此函数将返回上一状态类似浏览器后退。对WSE_STATE_MENU_ROOT无效。void wse_enter_submenu(const wse_menu_item_t* submenu)submenu: 子菜单数组指针void显式进入子菜单。常用于SUBMENU类型项的默认行为也可在自定义逻辑中调用。状态栈机制WSEMenu 维护一个深度为 3 的状态历史栈state_history[3]。每次调用wse_enter_submenu()或wse_set_state()非WSE_STATE_MENU_ROOT时当前状态被压入栈顶。wse_go_back()弹出栈顶并恢复该状态。此机制保证了“返回”操作的可靠性即使在多级嵌套中也能正确回溯。3.3 菜单与数据显示接口函数签名参数说明返回值典型用途void wse_render_current_menu(void)无void强制刷新当前菜单显示。当外部数据变更如传感器值更新需立即反映在菜单屏上时调用。void wse_render_custom_text(const char* line1, const char* line2, const char* line3, const char* line4)各行文本指针NULL表示清空该行void直接输出四行文本。适用于WSE_STATE_DISPLAY等纯显示状态绕过菜单引擎渲染逻辑获得最高控制权。int8_t wse_get_focused_index(void)无当前焦点项在菜单数组中的索引-1 表示无焦点查询当前高亮项位置用于动态生成提示信息如“↑↓选择ENTER确认”。渲染时机控制WSEMenu 采用“脏标记Dirty Flag”机制优化性能。仅当状态改变、焦点移动或显式调用wse_render_current_menu()时才触发 LCD 刷新。避免了每帧都重绘的资源浪费对低功耗应用至关重要。4. 硬件抽象层HAL实现指南HAL 是 WSEMenu 与硬件的唯一桥梁其质量直接决定库的稳定性与易用性。HAL 接口定义在wse_hal.h中用户必须实现以下函数4.1 LCD 显示 HAL函数签名期望行为工程实现建议void wse_hal_lcd_init(void)初始化 LCD 控制器如 HD44780设置 4-bit/8-bit 模式、显示开关、光标模式使用 MCU 的 GPIO 模拟时序或调用 HAL 库的HAL_GPIO_WritePin()务必加入足够延时HAL_Delay(1)或usleep(100)。void wse_hal_lcd_clear(void)清除 LCD 屏幕所有字符发送0x01指令Clear Display并等待执行完成约 1.52ms。void wse_hal_lcd_set_cursor(uint8_t row, uint8_t col)设置光标位置row: 0-3,col: 0-19计算 DDRAM 地址addr (row 0void wse_hal_lcd_write_char(char c)在当前光标位置写入单个 ASCII 字符直接写入数据寄存器。确保c在0x20-0x7E范围内标准 ASCII 可见字符。void wse_hal_lcd_write_string(const char* str)写入字符串自动处理换行与截断循环调用wse_hal_lcd_write_char()遇\0或达到行末20 字符停止自动处理\n换行。关键注意事项所有 LCD 操作必须是阻塞式即函数返回时指令已执行完毕。非阻塞实现会导致显示错乱。wse_hal_lcd_write_string()必须具备智能截断能力若字符串超长只显示前 20 字符若含\n应自动跳转到下一行起始位置。4.2 输入设备 HAL函数签名期望行为工程实现建议wse_event_t wse_hal_get_input_event(void)轮询方式返回最近一次有效事件无事件时返回WSE_EVENT_NONE中断方式可始终返回WSE_EVENT_NONE由 ISR 调用wse_process_event()推荐轮询在wse_main_loop()内周期性调用如每 20ms。读取 GPIO 状态结合软件消抖计数器法。uint32_t wse_hal_get_tick_ms(void)返回自系统启动以来的毫秒计数精度 ≥1ms可直接返回HAL_GetTick()STM32 HAL、xTaskGetTickCount()FreeRTOS或自定义 SysTick 计数器。必须单调递增。void wse_hal_delay_ms(uint32_t ms)毫秒级阻塞延时使用HAL_Delay(ms)或vTaskDelay(pdMS_TO_TICKS(ms))。用于 LCD 初始化时序。按键消抖实现示例GPIO 轮询#define KEY_DEBOUNCE_CNT 20 // 20ms 消抖窗口 static uint8_t key_state[KEY_MAX] {0}; // 当前电平 static uint16_t key_debounce_cnt[KEY_MAX] {0}; // 消抖计数器 wse_event_t wse_hal_get_input_event(void) { static uint32_t last_poll_ms 0; uint32_t now_ms wse_hal_get_tick_ms(); if (now_ms - last_poll_ms 20) return WSE_EVENT_NONE; // 20ms 采样周期 last_poll_ms now_ms; for (int i 0; i KEY_MAX; i) { uint8_t curr_level HAL_GPIO_ReadPin(KEY_PORT[i], KEY_PIN[i]); if (curr_level ! key_state[i]) { key_debounce_cnt[i]; if (key_debounce_cnt[i] KEY_DEBOUNCE_CNT) { key_state[i] curr_level; key_debounce_cnt[i] 0; if (curr_level KEY_PRESSED_LEVEL) { // 低电平有效 return key_event_map[i]; // 映射到 WSE_EVENT_XXX } } } else { key_debounce_cnt[i] 0; // 电平稳定重置计数器 } } return WSE_EVENT_NONE; }5. 典型应用场景与代码示例5.1 场景一工业温控仪主界面与参数设置需求20x4 LCD 显示实时温度、设定值、加热状态通过按键进入菜单修改设定值、PID 参数、报警阈值。实现要点状态划分WSE_STATE_DISPLAY主屏、WSE_STATE_MENU_ROOT设置菜单、WSE_STATE_EDIT_VALUE数值编辑。菜单定义根菜单包含“设定温度”、“PID参数”、“报警设置”三项每项均为WSE_MENU_ITEM_TYPE_VALUE指向对应变量。主屏渲染在WSE_STATE_DISPLAY的render_cb中调用wse_hal_lcd_write_string()动态拼接四行void render_display_state(void) { char line1[21], line2[21], line3[21], line4[21]; snprintf(line1, sizeof(line1), Temp: %d.%dC, temp_int, temp_dec); snprintf(line2, sizeof(line2), Set: %d.%dC, set_int, set_dec); snprintf(line3, sizeof(line3), Heat: %s, heater_on ? ON : OFF); snprintf(line4, sizeof(line4), Status: OK); wse_hal_lcd_clear(); wse_hal_lcd_write_string(line1); wse_hal_lcd_set_cursor(1, 0); wse_hal_lcd_write_string(line2); // ... 同理设置第2、3行 }5.2 场景二集成 FreeRTOS 的多任务菜单系统需求主任务运行 WSEMenu另一任务采集传感器数据并更新全局变量菜单需实时反映最新数据。实现要点任务创建void menu_task(void *pvParameters) { wse_init(menu_root_items); for(;;) { wse_main_loop(); // 引擎自动处理事件 vTaskDelay(10); // 10ms 周期 } } void sensor_task(void *pvParameters) { for(;;) { read_sensor(g_temperature, g_humidity); // 数据更新后通知菜单刷新 wse_render_current_menu(); vTaskDelay(1000); // 1s 采集周期 } }线程安全wse_render_current_menu()是线程安全的可被任意任务调用。全局变量g_temperature需声明为volatile或在访问时加互斥锁若存在并发写入风险。5.3 场景三编码器旋钮导航的高级菜单需求使用旋转编码器替代方向键实现更流畅的菜单浏览与数值调节。HAL 实现// 编码器 A/B 相接入 EXTI 中断 void EXTI0_IRQHandler(void) { static uint8_t last_ab 0; uint8_t curr_ab (HAL_GPIO_ReadPin(ENC_A_PORT, ENC_A_PIN) 1) | HAL_GPIO_ReadPin(ENC_B_PORT, ENC_B_PIN); uint8_t change (last_ab 2) | curr_ab; if (change 0b0001 || change 0b0111 || change 0b1110 || change 0b1000) { wse_process_event(WSE_EVENT_ENCODER_INC); // 顺时针 } else if (change 0b0010 || change 0b1011 || change 0b1101 || change 0b0100) { wse_process_event(WSE_EVENT_ENCODER_DEC); // 逆时针 } last_ab curr_ab; HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); }菜单增强在WSE_MENU_ITEM_TYPE_VALUE项中min/max边界配合编码器旋转实现“循环调节”如小时从 23 直接到 0。6. 调试技巧与常见问题排查6.1 调试辅助工具WSEMenu 提供了两个关键调试钩子Hook位于wse_config.h中可配置WSE_DEBUG_LOG_ENABLE: 启用后引擎会在关键节点状态切换、事件处理、渲染开始通过printf()输出日志。裸机环境需重定向fputc()到 UART。WSE_ASSERT_ENABLE: 启用后对非法参数如NULL菜单指针、越界索引进行assert()断言快速定位逻辑错误。6.2 高频问题与解决方案现象可能原因解决方案菜单不显示LCD 全黑或乱码LCD 初始化时序错误wse_hal_lcd_set_cursor()地址计算错误使用示波器抓取 LCD 时序对照数据手册打印row/col参数验证地址计算公式。按键无响应或响应延迟wse_hal_get_input_event()采样周期过长HAL 消抖参数KEY_DEBOUNCE_CNT过大将采样周期缩短至 10-20ms减小消抖计数器阈值。进入子菜单后无法返回wse_go_back()调用位置错误状态栈溢出3 层确保在ACTION回调中调用wse_go_back()检查是否意外调用了wse_set_state(WSE_STATE_MENU_ROOT)覆盖了历史栈。数值编辑时显示异常如0000value.format字符串错误如%d用于浮点value_ptr指向错误内存严格匹配格式化字符串与变量类型用printf(val%d, *g_var)验证指针有效性。FreeRTOS 下菜单卡死wse_process_event()在 ISR 中未使用FromISR版本 API任务优先级设置不当ISR 中必须使用xQueueSendFromISR()确保菜单任务优先级高于传感器任务避免被长期抢占。6.3 性能与资源占用分析在 STM32F103C8T672MHz上实测Flash 占用核心引擎约 3.2 KB含所有功能。RAM 占用静态分配约 128 字节状态栈、焦点索引、临时缓冲区。CPU 占用wse_main_loop()单次执行约 85μs20x4 LCD4 个菜单项占空比 1%。实时性从按键按下到菜单项高亮变化端到端延迟 ≤ 30ms含消抖。此资源效率使其完美适配 Cortex-M0/M3 内核的主流 MCU无需担心内存或性能瓶颈。7. 项目演进与定制化路径WSEMenu 的设计预留了清晰的扩展接口满足从简单到复杂的应用演进轻量级定制通过wse_config.h宏开关启用/禁用功能如禁用WSE_STATE_CONFIRM节省 200 字节 Flash。中等定制重写wse_render_current_menu()的默认实现添加自定义高亮符号如、→或状态指示灯[ ]、[X]。深度定制继承wse_menu_item_t结构扩展union添加新字段如icon_id并在自定义render_cb中调用图标绘制函数。一个实际案例某医疗设备项目在 WSEMenu 基础上增加了WSE_MENU_ITEM_TYPE_TOGGLE类型用于开关类设置项。其union新增bool* toggle_ptr字段并在渲染时显示[ON]或[OFF]点击即切换布尔值。整个扩展仅新增 42 行代码未修改引擎核心。这种“核心稳定、外围可插拔”的架构正是 WSEMenu 在众多嵌入式项目中得以长期维护与复用的根本原因。

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