
Matter Silabs 平台通用应用行为详解LCD 屏幕、按键与 LED 状态机【免费下载链接】connectedhomeipMatter (formerly Project CHIP) creates more connections between more objects, simplifying development for manufacturers and increasing compatibility for consumers, guided by the Connectivity Standards Alliance.项目地址: https://gitcode.com/GitHub_Trending/co/connectedhomeipMatter原 Project CHIPSDK 中 Silicon LabsSilabs平台的所有示例应用共享一套由examples/platform/silabs目录实现的“通用行为”LCD 三屏切换与二维码展示、BTN0/BTN1 双按键的配网与恢复出厂流程、LED0/LED1 双 LED 的配网状态指示。本文基于官方文档docs/platforms/silabs/silabs_common_app_behavior.md完整展开这套行为规范并结合BaseApplication、SilabsLCD、LEDWidget等源码逐条印证其底层实现帮助你在移植或调试 Silabs Matter 示例时快速理解每一个按钮、屏幕与 LED 闪烁模式背后的状态机。一、总体架构通用行为代码在哪里文档开宗明义所有 Silabs 示例应用lighting-app、all-clusters-app、contact-sensor-app 等的通用功能实现位于示例平台目录 examples/platform/silabs 下。核心的几个文件为文件职责BaseApplication.h / BaseApplication.cpp应用基类事件队列、按键处理、工厂重置、状态 LED 模式、二维码输出、LCD 状态屏刷新display/lcd.h / display/lcd.cppSilabsLCD类屏幕枚举、Demo/Status/QRCode 三屏绘制与循环切换LEDWidget.h / LEDWidget.cppLED 抽象Set/Blink/Animate闪烁时序控制main.cpp / MatterConfig.cppapp_init()入口调用SilabsMatterConfig::AppInit()启动 Matter 应用从源码结构看这套行为以FreeRTOS 任务 CMSIS-OS 消息队列事件驱动的方式组织见 BaseApplication.cppApp 任务StartAppTask()创建一个默认 4096 字节栈APP_TASK_STACK_SIZE、默认 10 个事件容量APP_EVENT_QUEUE_SIZE的静态内存任务与消息队列所有 UI/按键/定时器回调都通过PostEvent()把AppEvent投递进队列由任务统一DispatchEvent()分发避免在不同线程上下文中直接操作 CHIP 栈两个 CMSIS 软件定时器sFunctionTimer一次性按键功能/工厂重置计时与sLightTimer周期 10ms 的kLightTimerPeriod驱动 LED 动画初始化链路BaseApplication::Init()依次调用BaseInit()注册平台事件处理器、创建任务与定时器、初始化 LCD、输出初始二维码、读取配网状态、注册FabricTable::Delegate再调用各示例实现的虚函数AppInit()见 BaseApplication.cpp。理解了这个“事件队列 定时器”骨架下面所有按钮动作、LED 动画、LCD 刷新就都是这条链路上的不同事件处理分支。二、LCD 屏幕三个窗口与循环切换2.1 三屏结构Demo / Status / QRCode文档指出支持 LCD 的开发套件上应用拥有三个独立窗口按BTN0可在三者之间循环当应用 UI 更新而当前正停在其他窗口时LCD 会自动切换到对应窗口。源码中这三个窗口对应SilabsLCD::Screen_e枚举lcd.htypedef enum screen { DemoScreen 0, // 应用 UI每个示例自定义 StatusScreen, // 设备状态屏 #if SL_MATTER_QR_CODE_ENABLED QRCodeScreen, // 配网二维码屏 #endif CycleScreen, InvalidScreen, } Screen_e;切换逻辑在SilabsLCD::CycleScreens()lcd.cpp当前屏加一超过最后一屏则回卷到DemoScreen。按键触发路径为BaseApplication::ButtonHandler()中对未配网/已配网均会执行的PostUpdateDisplayEvent(SilabsLCD::Screen_e::CycleScreen)BaseApplication.cpp事件最终由UpdateDisplayHandler()处理收到CycleScreen时调用UpdateDisplay()刷新状态屏数据并CycleScreens()收到具体屏名时直接SetScreen()BaseApplication.cpp。LCD 硬件层面SilabsLCD::Init()依次使能板载显示屏sl_board_enable_display()、初始化 DMD 显示驱动、初始化 glib 2D 图形上下文白底黑字并初始化 128×128 点阵LCD_SIZE 128见 lcd.cpp。这些功能受SL_MATTER_DISPLAY_ENABLED总开关与SL_MATTER_QR_CODE_ENABLED二维码屏两个编译开关保护无 LCD 的套件如部分 ESP 风格或最小化构建关闭后即可完全剔除这部分代码。2.2 应用 UIDemoScreen每个示例应用有自己的“应用 UI”用于可视化该示例的应用状态如灯的开关/亮度。DemoScreen的默认绘制是 display/demo-ui.c 中的demoUIDisplayApp()应用也可以注册自定义绘制回调SilabsLCD::SetCustomUI(cb)之后WriteDemoUI()会优先调用该回调而不是默认画面lcd.cpp。各示例具体的 UI 内容需参考对应示例的文档如docs/platforms/silabs/下 Getting Started 与examples/lighting-app等示例的 README。2.3 状态屏StatusScreen字段从哪来文档给出的状态屏字段表完整保留如下OpenThread 与 Wi-Fi 设备共有信息LCD UI说明# fabrics设备上已配网的 fabric 数量Connected设备是否已连接到 OpenThread 或 Wi-Fi 网络Advertising设备当前是否正在广播开放的配网窗口Is ICD设备是否为间歇连接设备Intermittently Connected deviceOpenThread 设备特有LCD UI说明PANID已配置 OpenThread 网络的 PANIDOT TypeOpenThread 设备类型FTD / MTDWi-Fi 设备特有LCD UI说明SSID已连接 Wi-Fi 网络的 SSID文档原文标注PANID 信息尚未打印到 LCD、SSID 信息尚未打印到 LCD、ICD 状态屏支持“尚待完成”。注意这与当前仓库源码已有差异BaseApplication::UpdateLCDStatusScreen()BaseApplication.cpp现在已经通过NetworkCommissioning::GetConnectedNetwork()取到 SSID 并拷入status.networkNameWriteStatus()也会绘制 SSID/PANID 两行并依据ICDConfigurationData输出ICD : SIT/LITlcd.cpp。换言之文档中的两条 “not yet printed” 注释属于历史遗留当前实现中这些字段已经在状态屏呈现而 “ICD 状态屏支持待完成” 指的是 ICD 设备专属的完整状态展示状态屏对 ICD 的支持目前主要体现在 ICD 模式标识上。各字段的数据来源在UpdateLCDStatusScreen()中可逐一对应chip::DeviceLayer::PlatformMgr().LockChipStack(); #ifdef SL_WIFI enabled ConnectivityMgr().IsWiFiStationEnabled(); attached ConnectivityMgr().IsWiFiStationConnected(); // 从已连接网络对象中取出 SSID 拷贝到 status.networkName #endif #if CHIP_ENABLE_OPENTHREAD enabled ConnectivityMgr().IsThreadEnabled(); attached ConnectivityMgr().IsThreadAttached(); #endif status.connected enabled attached; status.advertising chip::Server::GetInstance().GetCommissioningWindowManager() .IsCommissioningWindowOpen(); status.nbFabric chip::Server::GetInstance().GetFabricTable().FabricCount(); ... chip::DeviceLayer::PlatformMgr().UnlockChipStack(); slLCD.SetStatus(status);要点Connected enabled attached对 Wi-Fi 即“站点已使能且已关联”对 Thread 即“Thread 已使能且已附着”Advertising直接查询CommissioningWindowManager::IsCommissioningWindowOpen()因此配网窗口一开状态屏的 Advertising 立即变 Y状态屏的自动刷新OnPlatformEvent()监听到kThreadConnectivityChange/kInternetConnectivityChange时若当前正在显示StatusScreen就PostUpdateDisplayEvent(StatusScreen)触发重绘BaseApplication.cpp——这就是文档所说“UI 更新时 LCD 自动切换/刷新”的机制之一。整个读取过程通过LockChipStack()/UnlockChipStack()保护因为 App 任务与 CHIP 栈任务并发运行。DisplayStatus_t结构体lcd.h即文档表格的内存映射nbFabric、connected、networkNameWi-Fi SSID、advertising、icdMode。2.4 二维码屏QRCodeScreen文档说明二维码屏显示的是可用于 BLE 配网与 Basic Commissioning Mode基本配网模式的默认二维码其编码内容遵循 Matter 规范定义并提醒Basic Commissioning Mode 不如 Enhanced Commissioning Mode 安全不推荐使用。源码侧的生成链路BaseApplication::OutputQrCode(bool refreshLCD)BaseApplication.cpp通过Provision::Manager::GetInstance().GetStorage().GetSetupPayload(setupPayload)取出 Base38 格式的 Setup Payload若refreshLCD为真且开启二维码则slLCD.SetQRCode(...)slLCD.ShowQRCode(true)切到QRCodeScreen绘制同时PrintQrCodeURL(setupPayload)把二维码 URL 打印到日志——这正是文档中“按键短按后在 Log 中打印 initial 与 BCM 配网二维码”的实现绘制使用qrcodegen库版本 4 二维码、每个模块 3 像素、误差等级 LOW[lcd.cpp](https://link.gitcode.com/i/77dde88e58994f08b08c07be17443d6a#L36-L38, L260-L289)。两个关键触发点启动时BaseInit()末尾调用OutputQrCode(true)上电后 LCD 默认就显示二维码屏BaseApplication.cpp配网窗口关闭时自动回退BaseApplicationDelegate::OnCommissioningWindowClosed()中若设备已配网且当前停在QRCodeScreen会PostUpdateDisplayEvent(DemoScreen)自动切回应用 UIBaseApplication.cpp。三、按键操作键与应用键3.1 按键定义与硬件差异文档规定所有示例应用按两个按键设计BTN0 操作键Operation ButtonBTN1 应用键Application Button各示例定义其专属功能详见各示例文档。源码中APP_FUNCTION_BUTTON 0、APP_ACTION_BUTTON 1[BaseApplication.cpp](https://link.gitcode.com/i/ca0c78e6469912e97aebe0a118294e41#L33, L117)与之对应。文档同时给出硬件注意事项此处完整保留SparkFun 开发套件BRD2704A没有任何按键部分套件只支持按键或只支持 LED——默认配置以按键支持为准仅有 LED 的套件默认配置为应用 LED。3.2 操作键BTN0行为短按与长按文档给出的 BTN0 动作表执行方式行为短按释放Press and Release① 若设备尚未配网开始以快速模式广播 30 秒30 秒后切换为较慢间隔广播15 分钟后停止广播。② 在日志中打印 initial 与 BCM 配网二维码按压并持有 6 秒工厂重置Factory Reset设备广播“30 秒快播 → 慢速间隔 → 15 分钟停止”是 Matter 规范对 BLE 广播的标准时序由 CHIP 栈的配网窗口机制实现示例应用只负责“开窗”这个动作。源码中 6 秒长按的构成是两个 3 秒超时BaseApplication.cpp#define FACTORY_RESET_TRIGGER_TIMEOUT 3000 // 按住 3 秒触发“工厂重置序列” #define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000 // 触发后的 3 秒取消窗口完整状态机ButtonHandlerFunctionTimerEventHandler[BaseApplication.cpp](https://link.gitcode.com/i/ca0c78e6469912e97aebe0a118294e41#L392-L410, L590-L649)按下SilabsPlatform::ButtonAction::ButtonPressedStartFunctionTimer(FACTORY_RESET_TRIGGER_TIMEOUT)3 秒一次性计时开始3 秒内释放sIsFactoryResetTriggered仍为假走“短按”分支CancelFunctionTimer()若未配网Wi-Fi 查ConnectivityMgr().IsWiFiStationProvisioned()其余查sIsProvisioned锁住 CHIP 栈调用GetCommissioningWindowManager().OpenBasicCommissioningWindow()打开基本配网窗口——这会启动 BLE 广播若已配网打印 Network is already provisioned, Ble advertisement not enabledICD 构建下还会通过ICDNotifier::NotifyNetworkActivityNotification()临时声明网络活动OutputQrCode(false)打印二维码到日志PostUpdateDisplayEvent(CycleScreen)循环 LCD 屏。按住满 3 秒计时器到期FunctionEventHandler发现sIsFactoryResetTriggered false调用StartFactoryResetSequence()再启动 3 秒的取消窗口计时置位sIsFactoryResetTriggered状态 LED 切换为 500ms 均匀闪烁sStatusLED.Blink(500)提示“重置已启动”在取消窗口内松开CancelFactoryResetSequence()取消重置恢复原 LED 模式继续按住满 336 秒第二次计时器到期时sIsFactoryResetTriggered已为真直接ScheduleFactoryReset()执行工厂重置。ScheduleFactoryReset()的实现BaseApplication.cpp值得注意它并非逐键删除 fabric而是走ConfigurationMgr().InitiateFactoryReset()借助 Silabs NVM3 驱动整段删除 KVS 分区——源码注释明确说明这比Server::ScheduleFactoryReset()逐 Key 删除更快并顺带移除 Wi-Fi 场景下的 Matter DNS-SD 服务广告。应用键BTN1文档将其留给各示例自行定义例如灯光应用用于控制灯通用层只保留钩子ScheduleFactoryReset()中若检测到APP_ACTION_BUTTON即 BTN1同时被按下会调用Provision::Manager::SetProvisionRequired(true)标记需要重新配网。四、LED状态 LED 与应用 LED4.1 双 LED 约定文档约定所有示例应用按两个 LED 设计——LED0 为状态 LEDStatus LEDLED1 为应用 LEDApplication LED并在硬件受限时给出降级规则只有按键的套件默认启用按键配置只有 LED 的套件默认启用应用 LED。通用层通过BaseApplication::LinkAppLed(LEDWidget*)/UnlinkAppLed()把应用 LED 挂到基类上下文使两枚 LED 的动画在同一LightEventHandler()中同步推进BaseApplication.h。状态 LED 实例sStatusLED仅在组件目录确认SL_CATALOG_SIMPLE_LED_LED1_PRESENT即ENABLE_WSTK_LEDS且 LED1 存在时启用编号SYSTEM_STATE_LED 0[BaseApplication.cpp](https://link.gitcode.com/i/ca0c78e6469912e97aebe0a118294e41#L114-L116, L135-L137)——这解释了“部分套件无 LED”时的编译期剔除。4.2 状态 LED 的 5 种状态文档的状态 LED 状态表完整如下状态含义Short Flash On50ms 亮 / 950ms 灭设备处于未配网未配对状态等待配网应用连接Rapid Even Flashing100ms 亮 / 100ms 灭设备未配网但已有配网应用通过 BLE 连接Short Flash Off950ms 亮 / 50ms 灭设备已完全配网但尚未具备完整的 Thread 网络或服务连通性Solid On设备已完全配网且具备完整的 Thread 网络与服务连通性Long Even Flashing500ms 亮 / 500ms 灭工厂重置流程已启动这些模式与源码严格对应。ActivateStatusLedPatterns()BaseApplication.cpp中按优先级判断if (sIsProvisioned sIsEnabled) { if (sIsAttached) sStatusLED.Set(true); // Solid On else sStatusLED.Blink(950, 50); // Short Flash Off } else if (sHaveBLEConnections) { sStatusLED.Blink(100, 100); // Rapid Even Flashing } else { sStatusLED.Blink(50, 950); // Short Flash On }其中sHaveBLEConnections (ConnectivityMgr().NumBLEConnections() ! 0)即“BLE 有连接”这一行由栈内 BLE 连接数直接判定。工厂重置的 500ms 均匀闪烁则来自StartFactoryResetSequence()的sStatusLED.Blink(500)。驱动节拍是 10ms 的周期定时器sLightTimerkLightTimerPeriod pdMS_TO_TICKS(10)LightEventHandler()每次先在非 ICD 构建下用TryLockChipStack()非阻塞锁刷新sIsProvisioned/sIsEnabled/sIsAttached/sHaveBLEConnections再调用ActivateStatusLedPatterns()与两枚 LED 的Animate()BaseApplication.cpp。使用非阻塞锁是为了在 CHIP 任务执行长加密操作时不阻塞 UI 动画。4.3 ICD 构建下的 LED 差异源码级补充从源码结构看文档未展开的一个重要细节上述“持续轮询刷新 LED 状态”的分支被#if !(CHIP_CONFIG_ENABLE_ICD_SERVER)包裹。也就是说ICD间歇连接设备构建不常态运行 LED 状态机而是按需启停sLightTimer工厂重置序列启动/取消时StartStatusLEDTimer()/StopStatusLEDTimer()Identify 集群的OnIdentifyStart/OnIdentifyStop、Trigger Effect 开始/完成时同样启停[BaseApplication.cpp](https://link.gitcode.com/i/ca0c78e6469912e97aebe0a118294e41#L729-L793, L822-L895)。这与 ICD“大部分时间休眠”的功耗模型一致LED 动画只在需要提示用户重置中、Identify 中时才消耗计时与唤醒资源。若你的示例启用了CHIP_CONFIG_ENABLE_ICD_SERVER状态 LED 的日常配网状态指示上表前四种将不会自动点亮这是设计使然而非缺陷。4.4 应用 LED文档将应用 LED 的语义留给各示例定义例如用亮度同步灯亮、用闪烁提示动作结果。通用层只负责应用通过LinkAppLed()注册后LightEventHandler()每 10ms 会同时推进sAppActionLed-Animate()保证应用 LED 动画与状态 LED 动画时钟一致不需要应用 LED 的示例可不链接基类对sAppActionLed nullptr已做保护。五、把文档与源码串起来一次典型交互的完整调用链以“未配网设备 短按 BTN0”为例把本文涉及的机制串成一条可验证链路板级按钮 ISR 把ButtonPressed/ButtonReleased包装成AppEvent投递队列ButtonHandler()按下 →StartFunctionTimer(3000)释放 → 取消计时器OpenBasicCommissioningWindow()BLE 开始广播OutputQrCode(false)打印二维码 URLPostUpdateDisplayEvent(CycleScreen)LCD 事件UpdateDisplayHandler()切屏SetScreen()按屏名分派到WriteDemoUI()/WriteStatus()/WriteQRCode()状态 LED 在 10ms 节拍下检测到“未配网且无 BLE 连接”进入 50/950ms 闪烁配网应用通过 BLE 连上后NumBLEConnections() ! 0自动变为 100/100ms 快闪配网完成、OnCommissioningWindowClosed()触发后LCD 若停在二维码屏会自动切回应用 UIOnFabricCommitted()FabricCount() 1把UpdateCommissioningStatus(true)LED 进入 Solid On已附着网络时。反向流程同样闭环最后一个 fabric 被删除时OnFabricRemoved()触发UpdateCommissioningStatus(false)与DoProvisioningReset()——清理 Thread 栈、清除 Wi-Fi 站点配置、强制保存 NVM3 KeyMap并重新打开基本配网窗口BaseApplication.cpp设备回到等待配网的初始状态。六、参考文件索引类别路径官方行为文档docs/platforms/silabs/silabs_common_app_behavior.mdSilabs 平台文档索引docs/platforms/silabs/index.md通用应用基类examples/platforms/silabs/BaseApplication.h、BaseApplication.cppLCD 实现examples/platforms/silabs/display/lcd.h、lcd.cpp、demo-ui.cLED 抽象examples/platforms/silabs/LEDWidget.h、LEDWidget.cpp应用入口examples/platforms/silabs/main.cpp、MatterConfig.cpp适用前提与限制本文行为描述基于当前仓库 Silabs 平台示例EFR32/SiWx917 等套件GN 构建的BaseApplication公共层实现具体某个示例的最终表现还受其.defaults/.conf组件配置影响如是否启用SL_MATTER_DISPLAY_ENABLED、SL_MATTER_QR_CODE_ENABLED、是否 ICD 构建且应用键 BTN1 与部分 LCD 画面由各示例自定义需结合对应示例文档阅读。文档中关于 PANID/SSID 尚未上屏、ICD 状态屏待完成等注释在当前源码中已有部分演进实际以源码行为为准。【免费下载链接】connectedhomeipMatter (formerly Project CHIP) creates more connections between more objects, simplifying development for manufacturers and increasing compatibility for consumers, guided by the Connectivity Standards Alliance.项目地址: https://gitcode.com/GitHub_Trending/co/connectedhomeip创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考