<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>Skyforever</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <id>https://blog.skyforever.top/</id>
  <link href="https://blog.skyforever.top/" rel="alternate"/>
  <link href="https://blog.skyforever.top/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, Skyforever</rights>
  <subtitle>记录走下的每一步 | Write by Skyforever</subtitle>
  <title>Sky Blog</title>
  <updated>2026-10-24T09:03:58.000Z</updated>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="嵌入式开发" scheme="https://blog.skyforever.top/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/"/>
    <category term="通信协议" scheme="https://blog.skyforever.top/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/%E9%80%9A%E4%BF%A1%E5%8D%8F%E8%AE%AE/"/>
    <category term="嵌入式开发" scheme="https://blog.skyforever.top/tags/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/"/>
    <category term="USB" scheme="https://blog.skyforever.top/tags/USB/"/>
    <category term="通信协议" scheme="https://blog.skyforever.top/tags/%E9%80%9A%E4%BF%A1%E5%8D%8F%E8%AE%AE/"/>
    <category term="硬件协议" scheme="https://blog.skyforever.top/tags/%E7%A1%AC%E4%BB%B6%E5%8D%8F%E8%AE%AE/"/>
    <content>
      <![CDATA[<h2 id="1、基本概念"><a href="#1、基本概念" class="headerlink" title="1、基本概念"></a>1、基本概念</h2><h3 id="1-1-主从轮询与速率识别"><a href="#1-1-主从轮询与速率识别" class="headerlink" title="1.1 主从轮询与速率识别"></a>1.1 主从轮询与速率识别</h3><p>USB 采用一主多从（Host-Device）架构，所有通信都必须由主机（Host）主动发指令发起，设备（Device）永远不能主动向总线发数据。哪怕是鼠标按键这种“中断传输”，本质上也是主机每隔几毫秒主动去轮询设备“有没有新数据”。</p><p>USB 2.0 共有 4 根线（<code>VBUS</code> 5V 供电、<code>D+</code>、<code>D-</code> 差分数据线、<code>GND</code>）。主机靠检测 <code>D+</code> 或 <code>D-</code> 线上的 <code>1.5kΩ</code> 上拉电阻来发现设备插入并判断速度：</p><ul><li>低速（Low-Speed，<code>1.5 Mbps</code>）设备在 <code>D-</code> 线上接 <code>1.5kΩ</code> 上拉电阻。</li><li>全速（Full-Speed，<code>12 Mbps</code>）设备在 <code>D+</code> 线上接 <code>1.5kΩ</code> 上拉电阻。</li><li>高速（High-Speed，<code>480 Mbps</code>）设备在硬件上同样在 <code>D+</code> 接 <code>1.5kΩ</code> 上拉（先以全速身份接入），随后在总线复位期间通过高频 <code>Chirp K/J</code> 握手信号切换到高速模式，并断开上拉电阻、切入 <code>45Ω</code> 对地终端匹配电阻。</li></ul><h3 id="1-2-地址、端点、接口与管道"><a href="#1-2-地址、端点、接口与管道" class="headerlink" title="1.2 地址、端点、接口与管道"></a>1.2 地址、端点、接口与管道</h3><p>初学者看 USB 资料最容易被这几个词绕晕，拿一个“带麦克风和音量键的 USB 耳机”举例就很容易理解：</p><ul><li>设备地址（Device Address）是整块单片机在 USB 总线上的唯一门牌号，取值范围为 <code>1~127</code>。设备刚插上电脑、还没被分配门牌号时，默认使用 <code>0</code> 号地址。</li><li>端点（Endpoint）是 USB 芯片内部开辟的独立硬件收发缓冲区（FIFO）。一根 USB 线里同时要传耳机声音、麦克风声音、按键状态和系统控制命令，如果全塞进同一个硬件寄存器肯定会串数据，因此需要用不同端点隔开。每个端点有编号（<code>0~15</code>）和固定方向（<code>IN</code> 表示设备发往主机，<code>OUT</code> 表示主机发往设备）。其中 0 号端点（<code>EP0</code>）是所有 USB 设备强制具备的默认双向控制端点，专门用于在刚插上时通报身份和接收配置。</li><li>接口（Interface）是把完成同一个功能的几个端点打包在一起的功能集合。比如 USB 耳机里，“播放+录音”的端点打包成音频接口，“音量加减键”的端点打包成按键接口。一个设备包含多个接口就叫复合设备（Composite Device）。</li><li>管道（Pipe）是主机软件与设备里某一个特定端点建立起来的逻辑通信通道。一个 USB 设备有多个端点，自然就可以建立多条管道。</li></ul><h3 id="1-3-常见设备类-USB-Class"><a href="#1-3-常见设备类-USB-Class" class="headerlink" title="1.3 常见设备类 (USB Class)"></a>1.3 常见设备类 (USB Class)</h3><p>有了“接口”和“端点”的概念后，在嵌入式开发中，USB 协议把不同用途的设备规范成了标准的设备类（USB Device Class）。操作系统自带了这些标准类的通用驱动，只要单片机按对应 Class 的规范配置接口与端点，插上电脑就能直接工作：</p><div class="md-table-scroll"><table><thead><tr><th align="left">设备类协议 (Class)</th><th align="left">常见子协议 / 规范</th><th align="left">典型应用场景</th><th align="left">端点配置与使用的传输类型</th></tr></thead><tbody><tr><td align="left"><code>HID</code> (人机接口类)</td><td align="left">Report Descriptor (报表描述符)</td><td align="left">鼠标、键盘、游戏手柄、Custom HID 免驱透传</td><td align="left">控制传输 + 中断传输 (<code>Interrupt IN/OUT</code>)</td></tr><tr><td align="left"><code>CDC</code> (通信设备类)</td><td align="left"><code>CDC-ACM</code> (虚拟串口 VCP)、<code>RNDIS</code> / <code>CDC-NCM</code> (虚拟网卡)</td><td align="left">USB 转串口、USB 共享网络</td><td align="left">1 个中断 <code>IN</code> 端点（传状态）+ 1 对批量 <code>IN/OUT</code> 端点（传数据）</td></tr><tr><td align="left"><code>MSC</code> (大容量存储类)</td><td align="left"><code>BOT</code> (Bulk-Only Transport) + <code>SCSI</code> 命令集</td><td align="left">U 盘、SD 卡读卡器、移动硬盘</td><td align="left">1 对批量端点 (<code>Bulk IN/OUT</code>)，按 CBW/Data/CSW 三阶段读写扇区</td></tr><tr><td align="left"><code>UAC</code> (音频设备类)</td><td align="left"><code>UAC 1.0</code> / <code>UAC 2.0</code></td><td align="left">USB 麦克风、USB 耳机、外置声卡</td><td align="left">控制传输（调音量/采样率）+ 同步传输 (<code>Isochronous</code>) 传 PCM 音频流</td></tr><tr><td align="left"><code>UVC</code> (视频设备类)</td><td align="left"><code>UVC 1.1</code> / <code>UVC 1.5</code></td><td align="left">USB 摄像头、视频采集卡</td><td align="left">控制传输（调曝光/分辨率）+ 同步传输或批量传输传 YUV/MJPEG/H.264 视频流</td></tr><tr><td align="left"><code>DFU</code> (固件升级类)</td><td align="left">USB DFU 标准协议</td><td align="left">MCU 免烧录器升级固件（如 STM32 内置 DFU Bootloader）</td><td align="left">仅使用端点 0 的控制传输 (<code>Control Transfer</code>) 擦写 Flash</td></tr><tr><td align="left"><code>Vendor Specific</code> (厂商自定义类)</td><td align="left">Class 码 <code>0xFF</code>，配合 <code>WinUSB</code> / <code>libusb</code> 与微软 WCID 描述符</td><td align="left">J-Link / CMSIS-DAP 调试器、逻辑分析仪、高速采集卡</td><td align="left">不受标准类限制，直接用批量传输 (<code>Bulk</code>) 或中断传输高速收发原始数据</td></tr></tbody></table></div><h3 id="1-4-通信三层结构"><a href="#1-4-通信三层结构" class="headerlink" title="1.4 通信三层结构"></a>1.4 通信三层结构</h3><p>在管道内收发数据时，USB 协议从宏观到微观分为“传输 -&gt; 事务 -&gt; 包”三层结构，下文第 2、3、4 节将按此顺序层层往里拆解：</p><ul><li>顶层是传输（Transfer，包括控制、批量、中断、同步 4 种），用于完成一次完整的业务交互（比如读回一整个设备描述符、写完一个数据块），由一个或多个事务（Transaction）组成，可以跨帧完成。</li><li>中层是事务（Transaction，包括 IN、OUT、SETUP 3 种），用于完成一次单包收发握手，由 2～3 个连续的包（Packet）组成，不能打断，也不能跨帧。</li><li>底层是包（Packet，包括令牌包 Token、数据包 Data、握手包 Handshake、特殊包 Special 4 类），是 USB 总线上传输的最小物理单元，由 <code>SYNC + PID + 地址/数据内容 + CRC + EOP</code> 字段构成。</li></ul><h2 id="2、传输类型-Transfer"><a href="#2、传输类型-Transfer" class="headerlink" title="2、传输类型 (Transfer)"></a>2、传输类型 (Transfer)</h2><p>从最宏观的业务层来看，USB 协议定义了 4 种传输类型，分别针对不同的业务需求：</p><ul><li>控制传输 (Control Transfer)</li><li>批量传输 (Bulk Transfer)</li><li>中断传输 (Interrupt Transfer)</li><li>同步传输 (Isochronous Transfer)</li></ul><h3 id="2-1-控制传输-Control"><a href="#2-1-控制传输-Control" class="headerlink" title="2.1 控制传输 (Control)"></a>2.1 控制传输 (Control)</h3><p>控制传输由 2～3 个阶段组成：</p><ol><li>建立阶段 (Setup Stage)</li><li>数据阶段 (Data Stage，无数据控制传输没有此阶段)</li><li>状态阶段 (Status Stage)</li></ol><p>每个阶段都由一次或多次事务传输（Transaction）组成。控制传输主要用于设备枚举阶段读取描述符和下发配置，驱动软件也可使用控制传输实现特定命令交互，其数据传输不允许丢失。</p><h4 id="2-1-1-建立阶段"><a href="#2-1-1-建立阶段" class="headerlink" title="2.1.1 建立阶段"></a>2.1.1 建立阶段</h4><p>主机向 USB 设备发起请求或下发配置参数。建立阶段包含 <code>SETUP</code> 令牌包、紧随其后的 <code>DATA0</code> 数据包以及 <code>ACK</code> 握手包，用来定义本次控制传输的请求内容（即数据阶段是 IN 还是 OUT、需要传输多少字节的数据，都在建立阶段设定好）。</p><p>其中，<code>SETUP</code> 事务里携带的 <code>DATA0</code> 数据包固定为 8 字节（称为标准请求包 Setup Packet），开发中抓包或写固件中断回调时都会直接解析这 8 个字节：</p><div class="md-table-scroll"><table><thead><tr><th align="left">字节偏移</th><th align="left">字段名称</th><th align="left">长度 (Bytes)</th><th align="left">说明</th></tr></thead><tbody><tr><td align="left"><code>0</code></td><td align="left"><code>bmRequestType</code></td><td align="left">1</td><td align="left">请求方向（D7：0=Host-&gt;Device，1=Device-&gt;Host）、请求类型（D6<del>5：标准/类/厂商）与接收者（D4</del>0：设备/接口/端点）</td></tr><tr><td align="left"><code>1</code></td><td align="left"><code>bRequest</code></td><td align="left">1</td><td align="left">具体请求命令码，例如 <code>0x05</code> 为 <code>SET_ADDRESS</code>（分配地址），<code>0x06</code> 为 <code>GET_DESCRIPTOR</code>（读取描述符），<code>0x09</code> 为 <code>SET_CONFIGURATION</code></td></tr><tr><td align="left"><code>2~3</code></td><td align="left"><code>wValue</code></td><td align="left">2</td><td align="left">请求参数值（例如读取描述符时，高字节存描述符类型，低字节存描述符索引）</td></tr><tr><td align="left"><code>4~5</code></td><td align="left"><code>wIndex</code></td><td align="left">2</td><td align="left">索引或偏移量（通常存接口号、端点号或语言 ID）</td></tr><tr><td align="left"><code>6~7</code></td><td align="left"><code>wLength</code></td><td align="left">2</td><td align="left">接下来数据阶段需要传输的字节数（若为 <code>0</code>，表示本次控制传输没有数据阶段）</td></tr></tbody></table></div><p><img src="https://image.skyforever.top/blog/2026/10/3c81acd97819dfc66decc90e64d8c961.webp" alt="控制传输建立阶段时序流程"></p><h4 id="2-1-2-数据阶段"><a href="#2-1-2-数据阶段" class="headerlink" title="2.1.2 数据阶段"></a>2.1.2 数据阶段</h4><p>用来传输主机与设备之间的负载数据。根据数据传输方向，控制传输分为 3 种类型：</p><ol><li>控制读取（读取 USB 描述符）</li><li>控制写入（配置 USB 设备）</li><li>无数据控制</li></ol><ul><li>控制读取（Control Read）是将数据从设备读到主机（如读取设备描述符）。对每个数据包而言，主机先发送 <code>IN</code> 令牌包请求读数据，设备通过 <code>DATA1/DATA0</code> 数据包将数据回传给主机。主机正确接收后回复 <code>ACK</code>；若主机忙则回复 <code>NAK</code>；发生错误则回复 <code>STALL</code>。</li><li>控制写入（Control Write）是将数据从主机传到设备（如发送配置信息）。对每个数据包而言，主机先发送 <code>OUT</code> 令牌包，紧接着通过 <code>DATA1/DATA0</code> 数据包将数据传给设备。设备正确接收后回复 <code>ACK</code>；若设备忙则回复 <code>NAK</code>；发生错误则回复 <code>STALL</code>。</li></ul><p><img src="https://image.skyforever.top/blog/2026/10/9b2ec7f6c4364658910a8d4824e9e033.webp" alt="控制传输读写序列"></p><h4 id="2-1-3-状态阶段"><a href="#2-1-3-状态阶段" class="headerlink" title="2.1.3 状态阶段"></a>2.1.3 状态阶段</h4><p>用来汇报整个控制传输过程已顺利结束。状态阶段的传输方向必须与数据阶段相反（原来是 IN 事务，状态阶段就用 OUT 事务；原来是 OUT 事务，状态阶段就用 IN 事务）：</p><ul><li>在控制读取中，主机发送 <code>OUT</code> 令牌包，随后发送 0 长度的 <code>DATA1</code> 包，设备回应 <code>ACK</code>、<code>NAK</code> 或 <code>STALL</code> 握手包。</li><li>在控制写入中，主机发送 <code>IN</code> 令牌包，设备返回表示完成的 0 长度 <code>DATA1</code> 包，主机回应 <code>ACK</code>、<code>NAK</code> 或 <code>STALL</code> 握手包。</li></ul><h3 id="2-2-批量传输-Bulk"><a href="#2-2-批量传输-Bulk" class="headerlink" title="2.2 批量传输 (Bulk)"></a>2.2 批量传输 (Bulk)</h3><p>用于传输大量数据，要求数据准确无误，但对实时性没有严格要求，常用于打印机、U 盘等大容量存储设备。</p><p>一次批量传输（Transfer）由 1 次到多次批量事务（Transaction）组成。硬件层通过错误检测、握手包反馈和超次重传确保可靠传输：</p><ul><li>发送端按 <code>DATA0-DATA1-DATA0-...</code> 交替翻转 PID 的顺序发送数据包。只有收到 <code>ACK</code> 确认传输成功后才会翻转 PID 发送下一包；若接收端连续收到两个相同 PID（例如连续两个 <code>DATA0</code>），则判定后一个是前一个包的重传。</li><li>USB 允许连续 3 次以内的传输错误并自动重试，一旦成功则将错误计数器清零；若连续失败超过 3 次，Host 判定该端点异常（STALL），放弃传输任务。</li></ul><p>批量事务由三种包组成（IN 事务或 OUT 事务）：</p><ol><li>Token（令牌包）</li><li>Data（数据包）</li><li>Handshake（握手包）</li></ol><p><img src="https://image.skyforever.top/blog/2026/10/c1d72a60c1310494979b6a1b7aa8a39a.webp" alt="批量事务处理格式"></p><ol><li>IN 事务（IN Transaction）的握手响应有三种情况：<ul><li><code>ACK</code> 表示 Host 正确无误地接收到数据。</li><li><code>NAK</code> 指示设备暂时无法返回数据（如设备忙）。</li><li><code>STALL</code> 指示设备端点挂起，需要 Host 软件介入处理（如设备出错）。</li></ul></li><li>OUT 事务（OUT Transaction）的握手响应也有三种情况（若收到的数据包存在 CRC 校验错误，Device 不发送任何握手包）：<ul><li><code>ACK</code> 表示 Device 已正确接收数据包，通知 Host 可以按序发送下一包。</li><li><code>NAK</code> 表示 Device 已正确接收数据包，但因临时状况（如缓冲区满）通知 Host 稍后重传。</li><li><code>STALL</code> 指示 Device 端点已停止，通知 Host 不再重传。</li></ul></li><li>Bulk 读写序列由一系列 IN 事务或 OUT 事务组成：</li></ol><p><img src="https://image.skyforever.top/blog/2026/10/79f4ccd2b855f7bdce3a09b18f52bf87.webp" alt="批量传输读写序列"></p><h3 id="2-3-中断传输-Interrupt"><a href="#2-3-中断传输-Interrupt" class="headerlink" title="2.3 中断传输 (Interrupt)"></a>2.3 中断传输 (Interrupt)</h3><p>中断传输由 IN 或 OUT 事务组成，常用于主机定期轮询设备是否有数据需要传输（如鼠标、键盘）。</p><ul><li>中断传输在流程上除不支持 <code>PING</code> 令牌外，其余机制与批量传输一致，同样采用 <code>DATA0/DATA1</code> PID 翻转机制保证收发端数据同步。</li><li>主机在排定任务时，会根据中断端点描述符中指定的查询间隔周期性发起中断传输。</li><li>中断传输具有较高的优先级，仅次于同步传输。</li></ul><p><img src="https://image.skyforever.top/blog/2026/10/ae776050179fe52a7d5b660b5ff57ff5.webp" alt="中断事务处理格式"></p><h3 id="2-4-同步传输-Isochronous"><a href="#2-4-同步传输-Isochronous" class="headerlink" title="2.4 同步传输 (Isochronous)"></a>2.4 同步传输 (Isochronous)</h3><p>同步传输适用于必须以固定速率或在指定时刻送达、且可以容忍偶尔出错的实时数据流，常用于麦克风、音响喇叭、UVC 摄像头等音视频设备。</p><p>同步传输只包含两个包阶段：</p><ol><li>Token（令牌包）</li><li>Data（数据包）</li></ol><p>由于没有握手包（Handshake），同步传输不支持重传机制，也不支持 PID 翻转，属于不可靠传输；但在主机排定总线带宽和事务传输时，同步传输享有最高的优先级。</p><p><img src="https://image.skyforever.top/blog/2026/10/d8009e7bcd268f083f437d66545d37b2.webp" alt="同步事务处理格式"></p><h3 id="2-5-四种传输类型对比"><a href="#2-5-四种传输类型对比" class="headerlink" title="2.5 四种传输类型对比"></a>2.5 四种传输类型对比</h3><p>在编写端点描述符配置 <code>wMaxPacketSize</code> 时，不同速率下四种传输类型允许的单包最大字节数是严格受限的：</p><div class="md-table-scroll"><table><thead><tr><th align="left">传输类型</th><th align="left">低速 (1.5 Mbps) 最大包长</th><th align="left">全速 (12 Mbps) 最大包长</th><th align="left">高速 (480 Mbps) 最大包长</th><th align="left">错误重传 (Handshake)</th><th align="left">典型设备类 (USB Class)</th></tr></thead><tbody><tr><td align="left">控制传输 (Control)</td><td align="left">8 Bytes</td><td align="left">8 / 16 / 32 / 64 Bytes</td><td align="left">固定 64 Bytes</td><td align="left">支持</td><td align="left">所有设备枚举 (<code>EP0</code>)、<code>DFU</code></td></tr><tr><td align="left">批量传输 (Bulk)</td><td align="left">不支持</td><td align="left">8 / 16 / 32 / 64 Bytes</td><td align="left">固定 512 Bytes</td><td align="left">支持</td><td align="left"><code>MSC</code> (U 盘)、<code>CDC</code> (虚拟串口)、<code>WinUSB</code></td></tr><tr><td align="left">中断传输 (Interrupt)</td><td align="left">最大 8 Bytes</td><td align="left">最大 64 Bytes</td><td align="left">最大 1024 Bytes</td><td align="left">支持</td><td align="left"><code>HID</code> (键鼠/手柄)、<code>CDC</code> 状态端点</td></tr><tr><td align="left">同步传输 (Isochronous)</td><td align="left">不支持</td><td align="left">最大 1023 Bytes</td><td align="left">最大 1024 Bytes</td><td align="left">不支持（无握手包）</td><td align="left"><code>UAC</code> (声卡/麦克风)、<code>UVC</code> (摄像头)</td></tr></tbody></table></div><h2 id="3、事务-Transaction"><a href="#3、事务-Transaction" class="headerlink" title="3、事务 (Transaction)"></a>3、事务 (Transaction)</h2><p>把上面的“传输（Transfer）”往下一层拆解，就是事务（Transaction）。USB 总线上完成一次单包数据接收或发送的完整握手过程称为一次事务，通常由以下 2～3 个连续的包构成：</p><ul><li>一个 Token Packet（令牌包，指明方向与目标端点）</li><li>可选的 Data Packet（数据包，携带有效载荷）</li><li>可选的 Handshake Packet（握手包，汇报接收状态）</li><li>可选的 Special Packet（特殊包）</li></ul><h3 id="3-1-IN-输入"><a href="#3-1-IN-输入" class="headerlink" title="3.1 IN 输入"></a>3.1 IN 输入</h3><p>输入事务处理表示 USB 主机从总线上的某个 USB 设备接收一个数据包的过程。</p><ul><li>正常的输入事务处理</li></ul><p><img src="https://image.skyforever.top/blog/2026/10/f95730aa3470a6cd0e8b2a390d65dff3.png" alt="正常情况下的输入事务处理流程"></p><ul><li>设备忙时的输入事务处理</li></ul><p><img src="https://image.skyforever.top/blog/2026/10/845d1bb167b31b521a3c0c90f5d77d9d.png" alt="设备忙时的输入事务处理流程"></p><ul><li>设备出错时的输入事务处理</li></ul><p><img src="https://image.skyforever.top/blog/2026/10/2896a642102ed310ba619382a77beef1.png" alt="设备出错时的输入事务处理流程"></p><h3 id="3-2-OUT-输出"><a href="#3-2-OUT-输出" class="headerlink" title="3.2 OUT 输出"></a>3.2 OUT 输出</h3><p>输出事务处理表示 USB 主机把一个数据包发送到总线上某个 USB 设备的过程。</p><ul><li>正常的输出事务处理</li></ul><p><img src="https://image.skyforever.top/blog/2026/10/2e90a8d4542df0ef0a115b2e5949628f.png" alt="正常情况下的输出事务处理流程"></p><ul><li>设备忙时的输出事务处理</li></ul><p><img src="https://image.skyforever.top/blog/2026/10/6aa57f751ecbb461c46256685deb9caa.png" alt="设备忙时的输出事务处理流程"></p><ul><li>设备出错时的输出事务处理</li></ul><p><img src="https://image.skyforever.top/blog/2026/10/c739c3b0d8ebabf09fe046a656f4d14c.png" alt="设备出错时的输出事务处理流程"></p><h3 id="3-3-SETUP-设置"><a href="#3-3-SETUP-设置" class="headerlink" title="3.3 SETUP 设置"></a>3.3 SETUP 设置</h3><p>设置事务处理专用于控制传输的建立阶段，主机向设备下发 8 字节请求参数。</p><ul><li>正常的设置事务处理</li></ul><p><img src="https://image.skyforever.top/blog/2026/10/b7657de9ac7f01b99467898b05755960.png" alt="正常情况下的设置事务处理流程"></p><ul><li>设备忙时的设置事务处理</li></ul><p><img src="https://image.skyforever.top/blog/2026/10/b62fa2bb813cb751cc7ee9e37b60ad7c.png" alt="设备忙时的设置事务处理流程"></p><ul><li>设备出错时的设置事务处理</li></ul><p><img src="https://image.skyforever.top/blog/2026/10/65bfd4a5da7c52fad92e85794f0b89b5.webp" alt="设备出错时的设置事务处理流程"></p><h2 id="4、包-Packet"><a href="#4、包-Packet" class="headerlink" title="4、包 (Packet)"></a>4、包 (Packet)</h2><p>再把“事务（Transaction）”拆到最底层，就是包（Packet）。包是 USB 系统中信息传输的最小基本单元，所有数据都必须打包后才能在总线上传输，且包只能在帧内传输。高速 USB 总线的帧周期为 125μs，全速与低速 USB 总线的帧周期为 1ms。帧的起始由专门的 SOF 包标识，帧尾为 EOF（EOF 不是一个包，而是一种电平状态，期间不允许传输数据）。</p><blockquote><p>虽然高速 USB 总线与全速/低速 USB 总线的帧周期不同，但 SOF 包中帧编号的递增速度是一样的。因为在高速 USB 系统中，SOF 包的帧编号实际取的是计数器的高 11 位，最低 3 位作为微帧（Microframe）编号未展示在帧号里，因此帧编号的递增周期同样为 1ms。</p></blockquote><p>USB 总线上的传输时序如下：</p><p><img src="https://image.skyforever.top/blog/2026/10/6b175a3c5e7f3358823d06eeb364d1ef.webp" alt="总线帧结构与包传输时序"></p><ul><li>包是 USB 总线上数据传输的最小单位，不能被打断或干扰，否则会引发错误。</li><li>若干个数据包组成一次事务传输；一次事务传输也不能被打断，属于同一次事务的几个包必须连续，不能跨帧完成。</li><li>一次完整的传输由一次或多次事务传输构成，可以跨帧完成。</li></ul><p>USB 包由五部分组成：同步字段（SYNC）、包标识符字段（PID）、数据字段、循环冗余校验字段（CRC）和包结尾字段（EOP），基本格式如下图：</p><p><img src="https://image.skyforever.top/blog/2026/10/4133af8004e8550246d01b042c4c95a4.webp" alt="包基本格式与字段组成"></p><h3 id="4-1-PID-类型"><a href="#4-1-PID-类型" class="headerlink" title="4.1 PID 类型"></a>4.1 PID 类型</h3><p><img src="https://image.skyforever.top/blog/2026/10/9bce343051792b30f4d25b8d945493c1.webp" alt="令牌类与数据类包标识符编码表"></p><p><img src="https://image.skyforever.top/blog/2026/10/ccca10077b3c1bac083dcb3f122606fb.webp" alt="握手类与特殊类包标识符编码表"></p><h3 id="4-2-令牌包-Token"><a href="#4-2-令牌包-Token" class="headerlink" title="4.2 令牌包 (Token)"></a>4.2 令牌包 (Token)</h3><p><img src="https://image.skyforever.top/blog/2026/10/f9ad2d643f61c09b882b017e43ed9d11.webp" alt="令牌包格式定义"></p><p>此格式适用于 <code>IN</code>、<code>OUT</code>、<code>SETUP</code>、<code>PING</code>，对应的传输方向如下：</p><div class="md-table-scroll"><table><thead><tr><th align="left">PID</th><th align="left">数据传输方向</th></tr></thead><tbody><tr><td align="left"><code>IN</code></td><td align="left">Device -&gt; Host</td></tr><tr><td align="left"><code>OUT</code></td><td align="left">Host -&gt; Device</td></tr><tr><td align="left"><code>SETUP</code></td><td align="left">Host -&gt; Device</td></tr><tr><td align="left"><code>PING</code></td><td align="left">Host -&gt; Device（探测设备是否有空间接收数据）</td></tr></tbody></table></div><h3 id="4-3-帧起始包-SOF"><a href="#4-3-帧起始包-SOF" class="headerlink" title="4.3 帧起始包 (SOF)"></a>4.3 帧起始包 (SOF)</h3><p>SOF 包由 Host 周期性发送给 Device：</p><ol><li>对于全速（Full-Speed）总线，每隔 <code>1.00 ms ± 0.0005 ms</code> 发送一次。</li><li>对于高速（High-Speed）总线，每隔 <code>125 μs ± 0.0625 μs</code> 发送一次。</li></ol><p>SOF 包构成如下图所示：</p><p><img src="https://image.skyforever.top/blog/2026/10/8dd02c6eb611cd585f3c795d2d9e852c.webp" alt="帧起始包格式"></p><p><img src="https://image.skyforever.top/blog/2026/10/ca8cc807bbb3e30405d3fb83645fcc72.webp" alt="全速帧与高速微帧时序关系"></p><h3 id="4-4-数据包-Data"><a href="#4-4-数据包-Data" class="headerlink" title="4.4 数据包 (Data)"></a>4.4 数据包 (Data)</h3><p><img src="https://image.skyforever.top/blog/2026/10/7438b95e9436176480736603179ae501.webp" alt="数据包格式"></p><p>共有四种类型的数据包：<code>DATA0</code>、<code>DATA1</code>、<code>DATA2</code> 和 <code>MDATA</code>，通过 PID 区分。其中 <code>DATA0</code> 和 <code>DATA1</code> 用于实现数据翻转同步（Data Toggle Synchronization）。</p><h3 id="4-5-握手包-Handshake"><a href="#4-5-握手包-Handshake" class="headerlink" title="4.5 握手包 (Handshake)"></a>4.5 握手包 (Handshake)</h3><p><img src="https://image.skyforever.top/blog/2026/10/c2a9775da2ac3b9b3f07d91874a51865.webp" alt="握手包格式"></p><ul><li>对于 IN 事务，<code>ACK</code> 由 Host 发出；对于 OUT、SETUP 和 PING 事务，<code>ACK</code> 由 Device 发出。</li><li>对于 IN 事务，<code>NAK</code> 在数据阶段由 Device 发出；对于 OUT 和 PING 事务，<code>NAK</code> 在握手阶段由 Device 发出。Host 从不发送 NAK 包。</li></ul><h2 id="5、描述符-Descriptors"><a href="#5、描述符-Descriptors" class="headerlink" title="5、描述符 (Descriptors)"></a>5、描述符 (Descriptors)</h2><p>当 USB 设备插上电脑时，电脑之所以知道“这是个鼠标还是个 U 盘、有几个端点、每个端点用什么传输类型”，全靠读取设备内部固化的描述符（Descriptors）结构体数组。</p><p>USB 标准描述符采用自顶向下的四层树状结构：</p><ol><li>设备描述符（Device Descriptor，每个设备仅有 1 个，固定 18 字节）记录设备的全局身份信息，包括 USB 协议版本（<code>bcdUSB</code>）、厂商 ID（<code>idVendor</code>，即 VID）、产品 ID（<code>idProduct</code>，即 PID）、端点 0 的最大包长（<code>bMaxPacketSize0</code>）以及该设备包含的配置描述符个数。</li><li>配置描述符（Configuration Descriptor，通常 1 个）记录设备的供电方式（总线供电还是自供电）、最大耗电电流（<code>bMaxPower</code>，以 2mA 为单位）以及当前配置下包含多少个接口（<code>bNumInterfaces</code>）。</li><li>接口描述符（Interface Descriptor，单功能设备 1 个，复合设备多个）决定该功能模块的真实身份。里面的 <code>bInterfaceClass</code>、<code>bInterfaceSubClass</code>、<code>bInterfaceProtocol</code> 三个字段直接告诉操作系统它属于哪个标准类（如 <code>0x03</code> 是 <code>HID</code>、<code>0x08</code> 是 <code>MSC</code>、<code>0x02/0x0A</code> 是 <code>CDC</code>、<code>0x01</code> 是 <code>UAC</code>、<code>0x0E</code> 是 <code>UVC</code>、<code>0xFF</code> 是厂商自定义类）。</li><li>端点描述符（Endpoint Descriptor，除 EP0 外的每个端点各 1 个）规定该端点的硬件参数，包括端点号与方向（<code>bEndpointAddress</code>，最高位 <code>1</code> 为 <code>IN</code>、<code>0</code> 为 <code>OUT</code>）、传输类型（<code>bmAttributes</code>：控制/同步/批量/中断）、最大包长（<code>wMaxPacketSize</code>）以及轮询时间间隔（<code>bInterval</code>）。</li></ol><p>此外还有两类常用附属描述符：</p><ul><li>字符串描述符（String Descriptor，可选）用来存人类可读的 UTF-16LE 文本（如厂商名、产品名称、序列号 SN）。</li><li>类特殊描述符（Class-Specific Descriptor）用来补充特定设备类的专属参数，例如 <code>HID</code> 设备必须附带报表描述符（Report Descriptor）来定义每个 bit 代表哪个按键或坐标轴。</li></ul><hr><h2 id="6、枚举流程-Enumeration"><a href="#6、枚举流程-Enumeration" class="headerlink" title="6、枚举流程 (Enumeration)"></a>6、枚举流程 (Enumeration)</h2><p>把前面讲的物理层上拉电阻、端点 0、控制传输（<code>SETUP</code> 事务）和描述符串联起来，就是一个 USB 设备插入电脑后完成的枚举（Enumeration）全过程：</p><ol><li>设备插入 USB 口后，设备端的 <code>D+</code>（全速/高速）或 <code>D-</code>（低速）通过 <code>1.5kΩ</code> 上拉电阻被拉高到约 3.3V，主机集线器检测到差分线电平变化，得知有新设备插入并识别出高低速。</li><li>主机将 <code>D+</code> 和 <code>D-</code> 同时拉低（SE0 状态）并保持至少 <code>10 ms</code> 对设备进行总线复位（Reset）。若为高速设备，会在复位期间通过 <code>Chirp K/J</code> 信号完成 480Mbps 高速握手。复位完成后，设备默认监听地址 <code>0</code> 和端点 <code>0</code>。</li><li>主机向地址 <code>0</code>、端点 <code>0</code> 发起首次控制读取传输（<code>GET_DESCRIPTOR</code>）读取设备描述符。由于此时主机还不知道该设备 <code>EP0</code> 的最大包长，Windows 通常只先读取前 8 个字节（第 8 个字节正好是 <code>bMaxPacketSize0</code>），拿到最大包长后立即再次复位总线。</li><li>主机向地址 <code>0</code>、端点 <code>0</code> 发起一次无数据控制传输（<code>SET_ADDRESS</code>），在 <code>SETUP</code> 包的 <code>wValue</code> 字段中填入为该设备分配的唯一新地址（<code>1~127</code> 之间）。设备在状态阶段返回 <code>ACK</code> 后立即启用新地址，此后所有通信全部使用新地址。</li><li>主机使用新地址向端点 <code>0</code> 依次发起控制读取传输，读取完整描述符集合：<ul><li>读取完整的 18 字节设备描述符，获取 VID 和 PID。</li><li>读取配置描述符集合。主机会先读 9 字节配置描述符拿到总长度 <code>wTotalLength</code>，再一口气把配置描述符、接口描述符、类特殊描述符、端点描述符全部读回。</li><li>读取字符串描述符，获取显示在电脑设备管理器里的设备名称与序列号。</li></ul></li><li>操作系统根据读取到的 VID/PID 或接口描述符中的 <code>Class</code> 编码加载对应的驱动程序，最后向设备发送 <code>SET_CONFIGURATION</code> 控制写入请求激活配置。至此枚举彻底完成，设备的各个业务端点（如 Bulk、Interrupt、Isochronous 端点）正式启用并开始正常收发数据。</li></ol>]]>
    </content>
    <id>https://blog.skyforever.top/posts/48921</id>
    <link href="https://blog.skyforever.top/posts/48921"/>
    <published>2026-10-24T09:03:58.000Z</published>
    <summary>从宏观到微观拆解 USB 通信协议，涵盖设备类（USB Class）、端点与管道、四种传输类型（Transfer）、事务处理（Transaction）、底层包（Packet）结构，以及描述符体系与枚举流程。</summary>
    <title>USB 通信协议解释</title>
    <updated>2026-10-24T09:03:58.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="生活日常" scheme="https://blog.skyforever.top/categories/%E7%94%9F%E6%B4%BB%E6%97%A5%E5%B8%B8/"/>
    <category term="医保" scheme="https://blog.skyforever.top/tags/%E5%8C%BB%E4%BF%9D/"/>
    <category term="社保" scheme="https://blog.skyforever.top/tags/%E7%A4%BE%E4%BF%9D/"/>
    <category term="DRG" scheme="https://blog.skyforever.top/tags/DRG/"/>
    <category term="DIP" scheme="https://blog.skyforever.top/tags/DIP/"/>
    <category term="生活常识" scheme="https://blog.skyforever.top/tags/%E7%94%9F%E6%B4%BB%E5%B8%B8%E8%AF%86/"/>
    <content>
      <![CDATA[<p>暂时还没有改完，仅供参考</p><p>中国医保是人类历史上规模最大的医保体系。截至 2024 年底，参保人数达 13.26 亿，覆盖全国 95% 的人口，相当于地球上每 6 个人里就有 1 个是中国医保参保人。医保一年为大家买单 70 亿次，人均花费 2237 元，全年总支出达 3 万亿元，从出生到临终陪伴人的一生。</p><p>本文从医保本质、参保规则、经典报销、DRG/DIP 报销、省钱秘籍、风险预警六个部分，梳理医保的底层逻辑和实用规则。</p><hr><h2 id="医保本质"><a href="#医保本质" class="headerlink" title="医保本质"></a>医保本质</h2><p>“脱贫四五年，一病回从前；辛辛苦苦干一年，不如医院住三天。”要避免因病致贫，核心办法就是花别人的钱看自己的病——这就是医保的本质：让健康者帮助患病者，让年轻人补贴老年人。</p><p>我国基本医保分为两类，每人只能参加其中一种：</p><ul><li>职工医保由在企事业单位上班的人参加。</li><li>居民医保由其余人群参加；没有固定单位的成年人也可以自主选择参加职工医保或居民医保。</li></ul><hr><h2 id="参保规则"><a href="#参保规则" class="headerlink" title="参保规则"></a>参保规则</h2><h3 id="保费缴纳与基金去向"><a href="#保费缴纳与基金去向" class="headerlink" title="保费缴纳与基金去向"></a>保费缴纳与基金去向</h3><p>职工医保按月缴纳，保费约为当月工资的 8%（个人承担 2%，从工资单直接扣除；单位承担 6%，由单位直接划拨）。很多民营企业会按低于实际工资甚至当地最低工资标准缴纳，这种方式不影响看病报销的使用权益。</p><p>居民医保按年缴纳，每年 9 月至 12 月为集中缴费窗口期，次年全年享受待遇。以 2025 年为例，居民医保总保费为 1070 元，其中个人承担 400 元（约占 37%），财政补贴 670 元（约占 63%）。</p><pre class="mermaid">flowchart TD    subgraph 职工医保["职工医保 (按月缴纳，约月工资 8%)"]        W1["个人承担 2%"] --&gt; WA["个人账户基金<br>(专属医疗账户，自己看病买药使用)"]        W2["单位承担 6%"] --&gt; Pool["医保统筹基金<br>(资金池混用，真正的报销来源)"]    end    subgraph 居民医保["居民医保 (按年缴纳，2025 年共 1070 元)"]        R1["个人承担 400 元 (约 37%)"] --&gt; Pool        R2["财政承担 670 元 (约 63%)"] --&gt; Pool    end    Income["银行存款利息与投资收益"] --&gt; Pool</pre><h3 id="生效时间与断缴处理"><a href="#生效时间与断缴处理" class="headerlink" title="生效时间与断缴处理"></a>生效时间与断缴处理</h3><p>医保并非缴费后立刻生效：</p><ul><li>职工医保首次参保通常需连续缴费 3～6 个月后生效。中途断缴 3 个月内补缴的，次月恢复待遇；断缴超过 3 个月则视为重新参保。</li><li>居民医保一般次年 1 月 1 日生效。错过缴费窗口期补缴的，需等待 90 天后才能恢复待遇。</li><li>新生儿在出生后 90 天内参保的，自出生之日起生效；超过 90 天参保的，次月生效。</li></ul><h3 id="退休待遇差异"><a href="#退休待遇差异" class="headerlink" title="退休待遇差异"></a>退休待遇差异</h3><p>职工医保属于积累型医保，个人账户余额一直保留。连续参保达到规定年限后，退休无需再交保费即可终身享受医保，且医保基金每月还会向个人账户返钱（约为当地基本养老金月平均水平的 2%，随年龄增长比例上调）。若退休时未满规定年限，可通过一次性补缴补足。</p><p>居民医保属于共济型医保，不设个人账户，交一年保一年，退休后仍需按年缴纳保费。</p><h3 id="统筹层次与异地就医"><a href="#统筹层次与异地就医" class="headerlink" title="统筹层次与异地就医"></a>统筹层次与异地就医</h3><p>我国医保基金按行政区划管理。2000 年职工医保刚启动时，基本以县级为单位独立统筹，参保人只能在所属统筹区内看病。2010 年后国家逐步将县级统筹提升为市级、省级统筹。目前全国已基本实现省内异地就医直接结算，多数地区开通了跨省实时报销。</p><hr><h2 id="经典报销"><a href="#经典报销" class="headerlink" title="经典报销"></a>经典报销</h2><p>刷自己个人账户里的钱只是花自己的存款，只有花到医保统筹基金里的钱才算真正的报销。在门诊、住院、药店买药三种主要场景下，只有在起付标准以上、最高限额以下的部分，才能按比例用统筹基金报销。</p><pre class="mermaid">flowchart LR    Total["医疗总费用"] --&gt; Base["起付标准以下<br>(个人账户或现金自付)"]    Base --&gt; Valid["起付标准 ～ 最高限额<br>(可按比例由统筹基金报销)"]    Valid --&gt; Cap["超过最高限额部分<br>(基本医保不再报销)"]</pre><h3 id="起付标准与最高限额"><a href="#起付标准与最高限额" class="headerlink" title="起付标准与最高限额"></a>起付标准与最高限额</h3><p>起付标准是个人账户和现金支付累计达到一定门槛后，超出部分才开始报销，一般为当地平均工资的 10% 左右（医院等级越低，起付线越低；退休职工和居民医保的起付线比在职职工更低），共有两种算法：</p><ol><li>门诊和药店买药按年累计计算起付线。近年来随着控费见效，起付线逐步下调。例如 2024 年杭州月平均工资为 11662 元，2025 年门诊起付线从 1000 元下调至 600 元（仅占月平均工资的 5.14%）。</li><li>住院场景按次单独计算起付线，标准与门诊相当。一年内第二次住院起付线会适当降低，第三次及以后住院不再设起付线。</li></ol><p>最高限额（封顶线）一般为当地职工年平均工资的 4 倍左右，门诊与住院分别计算。以杭州为例，门诊限额为 4000 元，住院限额为 40 万元，合计 40.4 万元（2024 年杭州年平均工资的 4 倍约为 56 万元，实际执行限额约占 71.5%）。居民医保的报销限额通常比职工医保低 20%～30%。</p><h3 id="决定报销比例的五个因素"><a href="#决定报销比例的五个因素" class="headerlink" title="决定报销比例的五个因素"></a>决定报销比例的五个因素</h3><p>在起付线以上、封顶线以下的可报销区间内，最终能报销多少比例由以下五个因素共同决定：</p><pre class="mermaid">flowchart TD    Center["最终医保报销比例"]    F1["1. 三大目录<br>药品 / 耗材 / 诊疗服务<br>(甲类 / 乙类 / 丙类)"] --&gt; Center    F2["2. 医院等级<br>社区医院 &gt; 其他医院 &gt; 三级医院<br>(最高相差可达 30%)"] --&gt; Center    F3["3. 使用场景<br>住院报销比例 &gt; 门诊与药店<br>(通常相差约 5%)"] --&gt; Center    F4["4. 人员类别<br>退休 &gt; 在职/灵活就业 &gt;<br>少儿/大学生 &gt; 城乡一档/二档"] --&gt; Center    F5["5. 费用阶段<br>住院总费用分段阶梯报销<br>(费用越高档位比例越高)"] --&gt; Center</pre><h4 id="1-医保三大目录"><a href="#1-医保三大目录" class="headerlink" title="1. 医保三大目录"></a>1. 医保三大目录</h4><p>国家医保局制定了药品目录、耗材目录和诊疗服务目录，只有目录内的项目才能报销，按性质分为甲、乙、丙三类（假设某三级医院报销比例为 60%，以 100 元药品为例）：</p><pre class="mermaid">flowchart LR    subgraph 甲类["甲类 (100% 计入报销基数)"]        A1["总费用 100 元"] --&gt; A2["报销基数 100 元"]        A2 --&gt;|"按 60% 报销"| A3["医保报销 60 元<br>个人支付 40 元"]    end    subgraph 乙类["乙类 (先个人先行自付，再计入基数)"]        B1["总费用 100 元"] --&gt; B2["个人先自付 10% (10 元)<br>剩余 90 元计入报销基数"]        B2 --&gt;|"90 元按 60% 报销"| B3["医保报销 54 元<br>个人共支付 46 元 (10+36)"]    end    subgraph 丙类["丙类 (目录外项目)"]        C1["总费用 100 元"] --&gt; C2["报销基数 0 元"]        C2 --&gt;|"医保不予报销"| C3["医保报销 0 元<br>个人全额自费 100 元"]    end</pre><p>耗材和诊疗服务也按同样方式计算报销基数。</p><h4 id="2-医院等级"><a href="#2-医院等级" class="headerlink" title="2. 医院等级"></a>2. 医院等级</h4><p>为推动分级诊疗，医院等级越高，报销比例越低。通常分为社区医院、其他医院、三级医院三档，社区医院和三级医院的报销比例最高可相差 30%：</p><pre class="mermaid">flowchart LR    Drug["同一种 100 元甲类药"] --&gt; H1["社区医院 (报销 90%)<br>医保付 90 元 / 个人付 10 元"]    Drug --&gt; H3["三级医院 (报销 60%)<br>医保付 60 元 / 个人付 40 元"]</pre><h4 id="3-使用场景"><a href="#3-使用场景" class="headerlink" title="3. 使用场景"></a>3. 使用场景</h4><p>门诊和药店买药的报销比例通常比住院低，差距一般在 5% 左右。</p><h4 id="4-人员类别"><a href="#4-人员类别" class="headerlink" title="4. 人员类别"></a>4. 人员类别</h4><ul><li>职工医保分为在职职工、灵活就业、医保退休三类。</li><li>居民医保根据年龄和缴费档次分为少儿医保、大学生医保、城乡一档、城乡二档四类。</li></ul><p>报销比例从高到低依次为：</p><pre class="mermaid">flowchart LR    P1["医保退休"] --&gt; P2["在职职工 / 灵活就业"] --&gt; P3["少儿医保 / 大学生医保"] --&gt; P4["城乡一档 / 城乡二档"]</pre><h4 id="5-费用阶段"><a href="#5-费用阶段" class="headerlink" title="5. 费用阶段"></a>5. 费用阶段</h4><p>主要用于住院报销，将住院总费用分段按不同比例报销。以杭州住院报销为例：</p><pre class="mermaid">flowchart LR    S0["起付线以下<br>报销 0%"] --&gt; S1["起付线 ～ 4 万元 (一档)<br>报销 82%"]    S1 --&gt; S2["4 万元 ～ 40 万元 (二档)<br>报销 88%"]    S2 --&gt; S3["40 万元以上 (超封顶线)<br>基本医保不报销"]</pre><hr><h2 id="DRG-与-DIP-按病种付费"><a href="#DRG-与-DIP-按病种付费" class="headerlink" title="DRG 与 DIP 按病种付费"></a>DRG 与 DIP 按病种付费</h2><p>传统的“按项目报销”模式下，医生开的药、耗材和检查越多，医保统筹基金支出就越大。随着老龄化加剧、年轻参保人口比例下降，专家测算若维持按项目付费，预计 2026 年医保基金将入不敷出，2034 年累计结余将耗尽。</p><p>为此，国家推行了按病种付费改革：患者自付部分仍按经典模式计算，但医保局与医院之间不再按具体项目结算，而是把疾病和治疗方案打包成固定价格的套餐——<strong>超支由医院自己承担，结余归医院留用</strong>。</p><p>以阑尾炎手术套餐（医保定价 5000 元、患者报销比例 60%、假设零起付且全为目录内项目）为例，医院在不同花费下的盈亏如下：</p><pre class="mermaid">flowchart TD    subgraph Case1["场景一：医院过度治疗 (住院总费用 10000 元)"]        C1_Total["总费用 10000 元"] --&gt; C1_User["患者按 40% 自付：4000 元"]        C1_Total --&gt; C1_Fund["医保按套餐封顶支付：5000 元"]        C1_User &amp; C1_Fund --&gt; C1_Hosp["医院实收 9000 元<br>医院亏损倒贴 1000 元"]    end    subgraph Case2["场景二：医院控费合理 (住院总费用 7000 元)"]        C2_Total["总费用 7000 元"] --&gt; C2_User["患者按 40% 自付：2800 元"]        C2_Total --&gt; C2_Fund["医保仍按套餐支付：5000 元"]        C2_User &amp; C2_Fund --&gt; C2_Hosp["医院实收 7800 元<br>医院获得结余利润 800 元"]    end</pre><p>这也解释了为什么近年很多医院在病人住院满一定天数后会主动安排出院——一旦医疗总费用超出套餐定价，超出部分可能要由医院甚至主治医师个人承担。</p><h3 id="DRG-与-DIP-的区别"><a href="#DRG-与-DIP-的区别" class="headerlink" title="DRG 与 DIP 的区别"></a>DRG 与 DIP 的区别</h3><p>按病种付费在落地时分为 DRG 和 DIP 两种套餐制定方式，同一家医院只会采用其中一种；当疾病已有对应套餐时优先按套餐报销，未制定套餐的疾病则自动回退到经典按项目模式报销：</p><div class="md-table-scroll"><table><thead><tr><th align="left">对比维度</th><th align="left">DRG（疾病诊断相关分组）</th><th align="left">DIP（按病种分值付费）</th></tr></thead><tbody><tr><td align="left">分组颗粒度</td><td align="left">较粗，把一种疾病诊断与多种相关并发症合并为一个大套餐</td><td align="left">更细，先汇总地区全年住院病例，按“诊断 + 治疗方式”细分</td></tr><tr><td align="left">分组规则举例</td><td align="left">鼻窦炎 + 严重并发症与合并症</td><td align="left">病例 ≥15 例为核心病种（如鼻窦炎 + 鼻出血电凝术）；&lt;15 例为综合病种（如鼻窦炎 + 保守治疗）</td></tr><tr><td align="left">某市鼻腔鼻窦手术分组数</td><td align="left">共分为 3 种套餐</td><td align="left">细分为 14 种套餐</td></tr><tr><td align="left">常见适用医院</td><td align="left">一般在三级医院使用</td><td align="left">一般在三级以下医院使用</td></tr></tbody></table></div><hr><h2 id="九大省钱秘籍"><a href="#九大省钱秘籍" class="headerlink" title="九大省钱秘籍"></a>九大省钱秘籍</h2><h3 id="1-根据-DRG-DIP-选对医院"><a href="#1-根据-DRG-DIP-选对医院" class="headerlink" title="1. 根据 DRG/DIP 选对医院"></a>1. 根据 DRG/DIP 选对医院</h3><p>DRG/DIP 付费在 2025 年底已覆盖 90% 的病种和 70% 的医保基金。由于 DRG 和 DIP 颗粒度与定价不同，同一种病在不同医院收费差距很大。以某市鼻腔鼻窦手术为例：</p><ul><li>在 DRG 的 <code>DD21</code> 分组中，采用 DRG 的医院统一按 12903.35 元报销；而对应 DIP 医院按具体治疗方案分为 4 个价格，分布在 4683.43 元～12484.48 元之间，此时去采用 DIP 的医院通常更省钱。</li><li>在 DRG 的 <code>DD23</code> 分组中，采用 DRG 的医院统一定价为 8656.01 元；而采用 DIP 的医院价格在 4683.43 元～13366.25 元之间浮动，需结合具体治疗方案选择医院。</li></ul><p>当地医院采用的结算模式和 DRG/DIP 目录均可在当地医保局公开渠道查询。</p><h3 id="2-大病保险二次报销"><a href="#2-大病保险二次报销" class="headerlink" title="2. 大病保险二次报销"></a>2. 大病保险二次报销</h3><p>职工医保和居民医保均配套有大病保险基金（资金来自医保统筹基金）。大病保险不看具体病种，只要单次住院个人自付金额达到起付线（一般不高于当地上年度居民人均可支配收入的 50%），系统就会自动触发二次报销，无需手动申请。</p><p>大病保险同样采用分段累加报销，封顶线一般不超过 30 万元：</p><pre class="mermaid">flowchart LR    D0["自付 1.8 万元以下<br>(未达大病起付线)"] --&gt; D1["1.8 万 ～ 10 万元部分<br>报销 60%"]    D1 --&gt; D2["10 万 ～ 20 万元部分<br>报销 80%"]    D2 --&gt; D3["20 万元以上部分<br>报销 90%"]</pre><p>此外，当住院总费用超过基本医保统筹封顶线后，大病保险还会继续兜底。例如杭州基本医保统筹封顶线为 40 万元，40 万元～60 万元的部分由大病保险继续报销，变相拉高了封顶线。</p><h3 id="3-两病专项保障"><a href="#3-两病专项保障" class="headerlink" title="3. 两病专项保障"></a>3. 两病专项保障</h3><p>针对高血压和糖尿病患者的门诊用药保障机制，需主动到基层医院办理备案后开启。备案后门诊买药无起付线限制，且报销比例更高，设有独立年度限额：</p><ul><li>高血压：300～400 元/年</li><li>糖尿病：600～800 元/年</li><li>同时患有两种疾病：可叠加至 600～1200 元/年</li></ul><h3 id="4-门诊慢特病报销"><a href="#4-门诊慢特病报销" class="headerlink" title="4. 门诊慢特病报销"></a>4. 门诊慢特病报销</h3><p>针对指定的慢性病（一般为轻症，涵盖高血压、糖尿病、冠心病、慢阻肺、类风湿关节炎、痛风等 68 种）和特殊疾病（一般为重症，如恶性肿瘤门诊放化疗、器官移植术后抗排异治疗、尿毒症透析、血友病、再生障碍性贫血等），给予更高的门诊报销比例和报销限额。同样不会自动生效，需主动到基层医院办理备案。</p><h3 id="5-社区首诊与家庭医生转诊"><a href="#5-社区首诊与家庭医生转诊" class="headerlink" title="5. 社区首诊与家庭医生转诊"></a>5. 社区首诊与家庭医生转诊</h3><p>在社区医院签约家庭医生后，在基层医疗机构看病的报销比例比未签约者高 5%～10%；经家庭医生团队评估并开具转诊单转往三级医院的，在三级医院的报销比例可按首诊基层医疗机构的高标准执行。</p><h3 id="6-个人账户家庭共济"><a href="#6-个人账户家庭共济" class="headerlink" title="6. 个人账户家庭共济"></a>6. 个人账户家庭共济</h3><p>职工医保个人账户余额较多时，可在手机上开通“家庭共济”，授权给已参加基本医保的配偶、父母、子女（部分地区扩展至兄弟姐妹、祖父母等近亲属）使用。当家人个人账户余额为零或参加的是居民医保时，看病买药可直接扣减你的个人账户余额，也可用于代缴家人的居民医保保费。</p><h3 id="7-医疗救助基金"><a href="#7-医疗救助基金" class="headerlink" title="7. 医疗救助基金"></a>7. 医疗救助基金</h3><p>医疗救助基金（资金来自医保统筹基金、财政拨款与社会捐款）专门针对特困人员、孤儿、城乡低保对象、重度残疾人、返贫人口、因病致贫重病患者等群体，不仅为其代缴居民医保保费和大病保险个人缴费部分，还提供更低的起付线、更高的报销比例，甚至取消报销封顶线限制。</p><h3 id="8-失业期间代缴职工医保"><a href="#8-失业期间代缴职工医保" class="headerlink" title="8. 失业期间代缴职工医保"></a>8. 失业期间代缴职工医保</h3><p>失业前参加过失业保险的人员，办理失业登记后不仅能按月领取失业金，政府还会以灵活就业身份替你全额代缴职工医保保费，无需个人掏钱即可继续享受职工医保待遇。</p><h3 id="9-长期护理保险"><a href="#9-长期护理保险" class="headerlink" title="9. 长期护理保险"></a>9. 长期护理保险</h3><p>长期护理保险（简称长护险）是我国社保体系的“第六险”，为因年老、疾病或伤残导致生活无法自理的失能人员提供经济补偿，用于支付基本生活照料和医疗护理服务费用。</p><hr><h2 id="风险预警"><a href="#风险预警" class="headerlink" title="风险预警"></a>风险预警</h2><p>使用医保时需严格遵守以下合规底线，避免触碰法律红线：</p><ul><li>因工伤事故或第三方责任（如交通事故、他人侵权）产生的医疗费，必须优先走工伤保险或由责任方赔付，医保仅承担剩余合规费用。隐瞒真实原因先行刷医保报销会被认定为骗保，面临追回费用、行政处罚乃至刑事责任。</li><li>医保卡实名绑定个人健康信息与资金，严禁外借或冒用。即使借给亲属刷卡看病买药（家庭共济是各自刷自己的医保卡扣共济账户的钱，而非拿别人的卡去刷），或虚构病情骗取报销，均属欺诈骗保行为。</li><li>利用个人账户违规转卖药品会被暂停医保待遇并罚款。参与伪造医疗文书、虚开药品、串换高价耗材等骗保行为，除退回骗保金额外，还将面临骗保金额 2～5 倍罚款；<strong>涉案金额超过 6000 元即构成诈骗罪，最高可判处无期徒刑</strong>。</li></ul>]]>
    </content>
    <id>https://blog.skyforever.top/posts/59318</id>
    <link href="https://blog.skyforever.top/posts/59318"/>
    <published>2026-10-13T06:29:46.000Z</published>
    <summary>梳理中国基本医保的本质、参保规则、经典按项目报销比例计算、DRG/DIP 按病种付费逻辑、九大省钱规则及违规骗保风险。</summary>
    <title>医保政策研究</title>
    <updated>2026-10-13T06:29:46.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="开发工具" scheme="https://blog.skyforever.top/categories/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/"/>
    <category term="技术教程" scheme="https://blog.skyforever.top/categories/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/%E6%8A%80%E6%9C%AF%E6%95%99%E7%A8%8B/"/>
    <category term="1Panel" scheme="https://blog.skyforever.top/tags/1Panel/"/>
    <category term="RustDesk" scheme="https://blog.skyforever.top/tags/RustDesk/"/>
    <category term="远程桌面" scheme="https://blog.skyforever.top/tags/%E8%BF%9C%E7%A8%8B%E6%A1%8C%E9%9D%A2/"/>
    <category term="服务器运维" scheme="https://blog.skyforever.top/tags/%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%90%E7%BB%B4/"/>
    <content>
      <![CDATA[<p>最近受够了todesk的卡，慢，还不支持我喜欢的wayland显示协议；所以干脆直接自己部署一个远程工具，方便我控制自己电脑和公司电脑，用自己服务器价格比todesk还便宜四分之三，而且自己服务器还可以干其他事情。</p><h2 id="安装-1Panel"><a href="#安装-1Panel" class="headerlink" title="安装 1Panel"></a>安装 1Panel</h2><p><a href="https://1panel.cn/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>1Panel 官网</a></p><h2 id="部署服务端"><a href="#部署服务端" class="headerlink" title="部署服务端"></a>部署服务端</h2><h3 id="安装应用"><a href="#安装应用" class="headerlink" title="安装应用"></a>安装应用</h3><p>在 1Panel 应用商店中搜索 RustDesk，点击安装：</p><p><img src="https://image.skyforever.top/blog/2026/10/d9b63fa02c45e55695765f4402d9288d.webp" alt="在应用商店搜索并安装 RustDesk"></p><p>安装时注意以下两项配置：</p><ul><li>IP 地址或域名：必须改成服务器公网 IP 或已解析到该服务器的域名。</li><li>端口外部访问：必须勾选。</li></ul><blockquote><p>注意：服务器防火墙和安全组需要放行 TCP <code>21116-21117</code> 端口和 UDP <code>21116</code> 端口。</p></blockquote><p><img src="https://image.skyforever.top/blog/2026/10/05bf06e3289a42e0daf7055d4264e925.webp" alt="配置 RustDesk 安装参数"></p><h3 id="获取公钥"><a href="#获取公钥" class="headerlink" title="获取公钥"></a>获取公钥</h3><p>进入 1Panel 安装目录下的 <code>/www/1panel/apps/rustdesk/rustdesk/data/hbbs</code>（其中 <code>/www</code> 是 1Panel 的安装根目录，默认安装路径为 <code>/opt</code>）。</p><p>打开 <code>id_ed25519.pub</code> 文件，里面的内容就是连接所需的公钥：</p><p><img src="https://image.skyforever.top/blog/2026/10/a7c08a83bb962cccdaa3fad472683dea.webp" alt="查看并复制公钥文件"></p><h2 id="配置客户端"><a href="#配置客户端" class="headerlink" title="配置客户端"></a>配置客户端</h2><p>前往 <a href="https://github.com/rustdesk/rustdesk/releases" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>RustDesk Releases</a> 下载并安装客户端，在网络设置中填入以下信息：</p><ul><li>ID 服务器：填写服务器 IP 或域名，使用默认 <code>21116</code> 端口时可省略端口号。</li><li>中继服务器：填写服务器 IP 或域名，使用默认 <code>21117</code> 端口时可省略端口号。</li><li>API 服务器：未部署 API 服务，留空不填。</li><li>Key：填入上一步获取的 <code>id_ed25519.pub</code> 公钥内容。</li></ul><p><img src="https://image.skyforever.top/blog/2026/10/0c04ac4735d1fb4a4cf0626e2cf26ad1.webp" alt="配置客户端网络参数"></p>]]>
    </content>
    <id>https://blog.skyforever.top/posts/61842</id>
    <link href="https://blog.skyforever.top/posts/61842"/>
    <published>2026-10-13T01:40:00.000Z</published>
    <summary>介绍如何通过 1Panel 面板应用商店一键部署 RustDesk 自建远程桌面服务端。</summary>
    <title>使用 1Panel 搭建 RustDesk</title>
    <updated>2026-10-13T01:40:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="嵌入式" scheme="https://blog.skyforever.top/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F/"/>
    <category term="资源汇总" scheme="https://blog.skyforever.top/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F/%E8%B5%84%E6%BA%90%E6%B1%87%E6%80%BB/"/>
    <category term="嵌入式" scheme="https://blog.skyforever.top/tags/%E5%B5%8C%E5%85%A5%E5%BC%8F/"/>
    <category term="杰理" scheme="https://blog.skyforever.top/tags/%E6%9D%B0%E7%90%86/"/>
    <category term="蓝牙芯片" scheme="https://blog.skyforever.top/tags/%E8%93%9D%E7%89%99%E8%8A%AF%E7%89%87/"/>
    <category term="逆向工程" scheme="https://blog.skyforever.top/tags/%E9%80%86%E5%90%91%E5%B7%A5%E7%A8%8B/"/>
    <content>
      <![CDATA[<p>地摊上的蓝牙音箱、儿童玩具、百元内耳机和录音笔，拆开看十有八九都是杰理的芯片。杰理芯片集成度高、价格便宜到按毛算，但对个人开发者和折腾硬件的爱好者来说难以上手。主要是因为杰理走的是纯 B2B 路线，只对签了保密协议的大方案商开放 SDK 和技术支持。官方网站上散客连一份普通的数据手册都找不到，很多芯片还用自己魔改的指令集和专有烧录盒，网络资料全散落在各种论坛、网盘和旧帖子里。</p><p>这里把我搜集到的靠谱资源分类整理出来，方便找资料。</p><hr><h2 id="官方资料"><a href="#官方资料" class="headerlink" title="官方资料"></a>官方资料</h2><p>杰理官方近年搭建了在线文档中心，并在 GitHub 和 Gitee 上开放了多条芯片产线的完整 SDK 源码、驱动以及跨平台支持库；同时一级代理商与模块商的公开页面也是获取正规资料的核心途径。</p><h3 id="杰理文档系统门户"><a href="#杰理文档系统门户" class="headerlink" title="杰理文档系统门户"></a>杰理文档系统门户</h3><p>主页：<a href="https://doc.zh-jieli.com/vue/#/docs/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://doc.zh-jieli.com/vue/#/docs/</a><br>官方搭建的文档中心导航网站，是查找官方资料最全的一级入口。该导航站汇集了以下核心资源的跳转入口，无需到处搜寻分散的子链接：</p><ul><li>芯片系列在线文档：覆盖 AC79 系列（WiFi/视频/AIoT）、AC63 系列（通用蓝牙/BLE）、AC82N、AD14/AD15/AD16/AC104（语音芯片与玩具主控）、AD23/AD24（AI语音NPU+FPU）、AW30/AW31/AW33（无线射频/2.4G/BLE）以及通用 MCU。</li><li>开发工具使用指南：提供官方编译链安装配置、烧录工具驱动安装与上位机配置调试软件说明。</li><li>移动端与轻量端生态：提供覆盖 Android、iOS、微信小程序、HarmonyOS 四大平台的 OTA 空中升级、蓝牙连接、杰理之家、健康及 WiFi 视频图传开发文档。</li><li>官方周边渠道：站内直接提供了官方 Gitee/GitHub 代码仓库、官方 B 站技术空间以及各芯片产线的官方钉钉技术支持群入口。</li></ul><h3 id="官方知识库"><a href="#官方知识库" class="headerlink" title="官方知识库"></a>官方知识库</h3><div class="md-table-scroll"><table><thead><tr><th align="left">知识库名称</th><th align="left">链接</th><th align="left">说明</th></tr></thead><tbody><tr><td align="left">KDocs 知识库</td><td align="left"><a href="https://doc.zh-jieli.com/KDocs/master/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>链接</a></td><td align="left">官方知识库入口，包含各产品线架构说明与常见开发规范</td></tr><tr><td align="left">SDKWiki</td><td align="left"><a href="https://doc.zh-jieli.com/SDKWiki/master/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>链接</a></td><td align="left">官方 SDK 架构百科，梳理工程目录结构与通用中间件用法</td></tr></tbody></table></div><h3 id="官方开源矩阵-Jieli-Tech"><a href="#官方开源矩阵-Jieli-Tech" class="headerlink" title="官方开源矩阵 Jieli-Tech"></a>官方开源矩阵 Jieli-Tech</h3><p>主页：GitHub <a href="https://github.com/Jieli-Tech" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>Jieli-Tech</a> / Gitee <a href="https://gitee.com/Jieli-Tech" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>Jieli-Tech</a><br>杰理在开源平台开源了大量芯片的官方底层 SDK、启动引导程序以及跨平台生态，其中Gitee更新的要勤快一点，截至今天，开源平台里的资料有：</p><ul><li>芯片固件与通用 MCU SDK：<ul><li>fw-AC79_AIoT_SDK / fw-AC792_SDK：AC79 系列 WiFi 视频与 AIoT 固件 SDK。</li><li>fw-AC63_BT_SDK / fw-AC63_GP_MCU：AC63 系列通用蓝牙与 MCU 固件 SDK，支持 AC631N、AC632N、AC635N、AC636N、AC637N 等型号。</li><li>fw-AD15N：覆盖 AD14N、AD15N、AC104N、AD17N、AD18N 等多个芯片系列的通用 MCU SDK，内置场景配置工程与 Makefile。</li><li>fw-AD16N：AD16N 系列 32bit DSP 语音芯片的通用 MCU SDK。</li><li>AD23N：带 NPU 与 FPU 的 AI 语音玩具与小音箱通用 MCU SDK。</li><li>AD24N：双发射 32bit DSP 语音芯片通用 MCU SDK。</li><li>AW30N / fw-AW31N_BLE_SDK / fw-aw33n_ble_sdk：支持 BLE 与 2.4GHz 私有协议的无线主控 SDK。</li><li>fw-Bootloader：官方定制的芯片引导程序源码，用于学习上电引导、Flash 分区与固件跳转。</li></ul></li><li>移动端与全平台生态：<ul><li>蓝牙通信库：Android-JL_Bluetooth、iOS-JL_Bluetooth，基于 RCSP 协议实现设备通信与控制，并配套提供 android-bt-demo 与 ios-bt-demo 示例。</li><li>固件 OTA 升级：覆盖 Android-JL_OTA、iOS-JL_OTA、WeChat-Mini-Program-OTA（微信小程序）、HarmonyOS-JL_OTA（鸿蒙系统）以及 JL_OTA_Flutter。</li><li>健康与智能家居：Android-JL_Health、iOS-JL_Health 以及 Flutter-JL_Home 客户端。</li></ul></li></ul><h3 id="官方自建-GitLab"><a href="#官方自建-GitLab" class="headerlink" title="官方自建 GitLab"></a>官方自建 GitLab</h3><p>主页：<a href="https://gitlab.zh-jieli.com/JL-Studio" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://gitlab.zh-jieli.com/JL-Studio</a><br>官方维护的代码托管站，主要用于存放官方定制 IDE（JL-Studio）的插件、核心环境组件与编译支持脚本。</p><h3 id="方案商与代理商"><a href="#方案商与代理商" class="headerlink" title="方案商与代理商"></a>方案商与代理商</h3><div class="md-table-scroll"><table><thead><tr><th align="left">渠道</th><th align="left">链接</th><th align="left">说明</th></tr></thead><tbody><tr><td align="left">极星电子规格书下载站</td><td align="left"><a href="https://www.szjixing.cn/jishuzhichi_guigeshu-custom-72.html" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>链接</a></td><td align="left">可以查到芯片规格书</td></tr><tr><td align="left">云芯文档中心</td><td align="left"><a href="https://doc.yunthinker.com/#/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>链接</a></td><td align="left">技术文档网站，注意右上角有其他文档入口</td></tr><tr><td align="left">云芯官网</td><td align="left"><a href="https://www.yunthinker.com/products.html" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>链接</a></td><td align="left">可以查到杰理芯片的规格书、原理图、方案以及购买样品</td></tr><tr><td align="left">云芯微技术论坛</td><td align="left"><a href="http://bbs.yunthinker.com/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>首页</a> / <a href="http://bbs.yunthinker.com/forum.php?mod=viewthread&amp;tid=15" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>讨论帖</a></td><td align="left">交流论坛，常有坛友分享 SDK 压缩包、烧录软件与排错记录</td></tr></tbody></table></div><hr><h2 id="民间大神"><a href="#民间大神" class="headerlink" title="民间大神"></a>民间大神</h2><p>在官方生态封闭的情况下，国内外极客对杰理芯片进行了深入的底层逆向、工具开发与开源框架移植。</p><h3 id="kagaimiq"><a href="#kagaimiq" class="headerlink" title="kagaimiq"></a>kagaimiq</h3><p>GitHub 主页：<a href="https://github.com/kagaimiq" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://github.com/kagaimiq</a><br>海外逆向极客，长期深耕杰理芯片的底层架构与工具链逆向。其维护的全部杰理与相关仓库包括：</p><ul><li>jielie：杰理逆向知识库，梳理了 pi32 指令集、芯片架构、未公开寄存器地址映射及反汇编脚本。</li><li>jl-uboot-tool：基于芯片内置 Uboot 协议开发的固件读写工具，可通过 USB 或串口直接 dump 固件、擦除与烧录 Flash，脱离官方专用烧录盒。</li><li>jl-misctools：杰理固件解包、重打包与加密校验分析的实用 Python 脚本集。</li><li>jl-msbm：作者编写的杰理芯片专用简易裸机运行工程。</li><li>bluetrum-tools：同类竞品中科蓝讯芯片逆向工具，用于华南白牌音频主控的横向对比研究。</li></ul><h3 id="pla155"><a href="#pla155" class="headerlink" title="pla155"></a>pla155</h3><p>立创开源主页：<a href="https://oshwhub.com/pla155" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>pla155</a><br>活跃创客，专注于低成本硬件下载工具与 CPU 裸机运行探索：</p><ul><li><a href="https://oshwhub.com/pla155/jerry-downloader-v20" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>Jerry Downloader V2.0 烧录器</a>：自制杰理一线通与强制下载器，基于通用元器件实现，开源原理图与 PCB，能低成本替代官方高价烧录盒。</li><li><a href="https://oshwhub.com/pla155/project_hcvexzqr" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>杰理 CPU 裸奔思路与工程</a>：探索杰理 CPU 裸机运行的硬件工程与实现思路。</li></ul><h3 id="冯芳芳"><a href="#冯芳芳" class="headerlink" title="冯芳芳"></a>冯芳芳</h3><p>Gitee 主页：<a href="https://gitee.com/fengfangfang/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>fengfangfang</a><br>国内开发者，致力于把通用开源框架移植到杰理主控上：</p><ul><li><a href="https://gitee.com/fengfangfang/ac636n-arduino" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>AC636N 适配 Arduino</a>（含<a href="https://gitee.com/fengfangfang/ac636n-arduino/blob/master/%E5%86%85%E7%BD%AE%E7%A4%BA%E4%BE%8B%E7%BC%96%E8%AF%91%E6%8A%A5%E5%91%8A.md" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>内置示例编译报告</a>）：将 Arduino 框架移植到 AC636N，并给出了完整的官方示例库编译测试结果。</li><li><a href="https://gitee.com/fengfangfang/ac636n-u8g2" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>AC636N 移植 u8g2</a>：基于 AC636N 官方工程移植集成了 u8g2 单色屏图形驱动库。</li><li><a href="https://oshwhub.com/article/jerry-ac690n-fangfang" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>AC6905 极简裸机环境</a>：在立创开源发表的极简裸机运行环境搭建教程，基于 AC6905 实测验证通过。</li></ul><h3 id="christian-kramer"><a href="#christian-kramer" class="headerlink" title="christian-kramer"></a>christian-kramer</h3><p>GitHub 主页：<a href="https://github.com/christian-kramer" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>christian-kramer</a>  </p><ul><li><a href="https://github.com/christian-kramer/JieLi-AC690X-Familiarization/blob/master/README.md" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>AC690X 逆向笔记</a>：记录了对早期经典主控 AC690X 的摸索手记，包含汇编工具链、引脚排布和实验步骤。</li></ul><h3 id="社区探索与海外论坛"><a href="#社区探索与海外论坛" class="headerlink" title="社区探索与海外论坛"></a>社区探索与海外论坛</h3><ul><li><a href="https://oshwhub.com/article/jerry-ac690n-run-to-free" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>AC690N 裸机开发教程</a>：立创开源平台文章，探讨如何在 AC690N 上脱离官方庞杂 SDK 编写简易裸机代码。</li><li><a href="http://usmi.mybb.ru/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>俄罗斯 USMI 论坛</a>（<a href="https://usmi.mybb.ru/viewtopic.php?id=69&amp;p=6#p4081" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>专帖</a>）：俄罗斯单片机与音频论坛，聚集了大量拆解华强北音箱主控的极客，包含 Flash 飞线读取与固件反编译讨论。</li></ul><hr><h2 id="二开硬件链接"><a href="#二开硬件链接" class="headerlink" title="二开硬件链接"></a>二开硬件链接</h2><p>手头没有现成板子时，可以在淘宝淘一些低成本库存或成品小板做二次开发实验。</p><div class="md-table-scroll"><table><thead><tr><th align="left">板子名称</th><th align="left">参考链接</th><th align="left">说明</th></tr></thead><tbody><tr><td align="left">蓝牙音响库存主板</td><td align="left"><a href="https://e.tb.cn/h.8CW8AZ0I0TMjhzn?tk=kmWqTordlhB" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>淘宝链接</a></td><td align="left">全新库存蓝牙音响主板，无原厂资料，适合买来做硬件逆向和 DIY 研究</td></tr><tr><td align="left">疑似 AC6958 蓝牙主板</td><td align="left"><a href="https://item.taobao.com/item.htm?id=1083524802567" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>淘宝链接</a></td><td align="left">极低成本蓝牙板，适合盲狙赌一把 AC6958 主控</td></tr><tr><td align="left">全新二次开发板 A</td><td align="left"><a href="https://item.taobao.com/item.htm?id=863453419431" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>淘宝链接</a></td><td align="left">全新板子，引脚引出清晰，适合买来直接做二次开发</td></tr><tr><td align="left">全新二次开发板 B</td><td align="left"><a href="https://item.taobao.com/item.htm?id=1005283306017" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>淘宝链接</a></td><td align="left">全新现成小板，外围元件完整，同样很适合拿来做二次开发折腾</td></tr></tbody></table></div><hr><h2 id="杂项"><a href="#杂项" class="headerlink" title="杂项"></a>杂项</h2><p>本节汇总了鸿蒙系统移植仓、入门实战教程、非正规找资料渠道以及开发者交流群。</p><h3 id="移植与实战参考"><a href="#移植与实战参考" class="headerlink" title="移植与实战参考"></a>移植与实战参考</h3><div class="md-table-scroll"><table><thead><tr><th align="left">资源名称</th><th align="left">链接</th><th align="left">说明</th></tr></thead><tbody><tr><td align="left">OpenHarmony 杰理 SoC 仓</td><td align="left"><a href="https://gitcode.com/openharmony-test/device_soc_jieli" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>链接</a></td><td align="left">开源鸿蒙适配仓，半成品，包含 AC695X 的 BSP 驱动与蓝牙协议栈源码</td></tr><tr><td align="left">OpenHarmony 小型系统移植参考</td><td align="left"><a href="https://gitcode.com/openharmony/docs/blob/master/zh-cn/device-dev/porting/porting-bes2600w-on-minisystem-display-demo.md" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>链接</a></td><td align="left">官方小型系统移植展示文档，对同类芯片轻量系统与显示驱动移植有参考价值</td></tr><tr><td align="left">CSDN AC696 入门教程</td><td align="left"><a href="https://blog.csdn.net/qq_42289734/article/details/161203564" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>链接</a></td><td align="left">记录 AC696 系列 SDK 获取方式、工程建立与烧录操作全流程</td></tr><tr><td align="left">尚硅谷杰理蓝牙实战视频</td><td align="left"><a href="https://www.bilibili.com/video/BV1RVR3YNEkN/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>链接</a></td><td align="left">B 站公开的嵌入式杰理芯片实战视频，以蓝牙音箱项目演示基础开发</td></tr><tr><td align="left">牛客网杰理工作体验讨论</td><td align="left"><a href="https://www.nowcoder.com/feed/main/detail/454ae769263d4e5394b6cd61cdaf1a18" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>链接</a></td><td align="left">牛客网上讨论帖，从内部员工视角侧面了解杰理研发文化与技术栈特点</td></tr></tbody></table></div><h3 id="淘宝卖家与闲鱼渠道"><a href="#淘宝卖家与闲鱼渠道" class="headerlink" title="淘宝卖家与闲鱼渠道"></a>淘宝卖家与闲鱼渠道</h3><p>在淘宝购买杰理开发板或芯片时，可以直接向卖家索要商家配套的 SDK 和资料包；也可以在闲鱼搜索对应芯片型号，常有人打包转让内部工程源码与工具链。</p><h3 id="开发者交流群"><a href="#开发者交流群" class="headerlink" title="开发者交流群"></a>开发者交流群</h3><p>遇到深坑或者缺特定 SDK 压缩包时，可以进群求助交流：</p><div class="md-table-scroll"><table><thead><tr><th align="left">群名称</th><th align="left">平台与群号</th></tr></thead><tbody><tr><td align="left">杰理WIFI开源社区</td><td align="left">QQ：593243414</td></tr><tr><td align="left">杰理科技华东技术交流</td><td align="left">QQ：658199016</td></tr><tr><td align="left">JL杰理BLE开源社区</td><td align="left">QQ：661618204</td></tr><tr><td align="left">JL杰理芯片方案开发</td><td align="left">QQ：709159759</td></tr><tr><td align="left">杰理蓝牙mp3方案开发</td><td align="left">QQ：714234904</td></tr><tr><td align="left">杰理蓝牙</td><td align="left">QQ：729059606</td></tr><tr><td align="left">JL杰理蓝牙与音频开源社区</td><td align="left">QQ：764468449</td></tr><tr><td align="left">arm板系统研究</td><td align="left">QQ：973359785</td></tr><tr><td align="left">官方 AC63 技术交流群</td><td align="left">钉钉：107855006323</td></tr><tr><td align="left">官方 AC791 技术交流群</td><td align="left">钉钉：137930001150</td></tr><tr><td align="left">官方 AC792 技术交流群</td><td align="left">钉钉：91050006452</td></tr><tr><td align="left">官方 AC82 技术交流群</td><td align="left">钉钉：42090002468</td></tr><tr><td align="left">官方 AD14/15/16 技术交流群</td><td align="left">钉钉：34733364</td></tr><tr><td align="left">官方 AW30 技术交流群</td><td align="left">钉钉：34743364</td></tr><tr><td align="left">官方 AW31/33 技术交流群</td><td align="left">钉钉：90400000565</td></tr><tr><td align="left">官方通用 MCU 技术交流群</td><td align="left">钉钉：31691148</td></tr></tbody></table></div>]]>
    </content>
    <id>https://blog.skyforever.top/posts/58291</id>
    <link href="https://blog.skyforever.top/posts/58291"/>
    <published>2026-10-08T12:30:00.000Z</published>
    <summary>杰理芯片性价比高但在网上极难找资料。本文汇总整理了官方在线文档、代理商规格书下载站、民间大神逆向工具链、二开硬件板子及实用交流资源。</summary>
    <title>杰理芯片网络资源汇总</title>
    <updated>2026-10-08T12:30:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="开发工具" scheme="https://blog.skyforever.top/categories/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/"/>
    <category term="技术教程" scheme="https://blog.skyforever.top/categories/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/%E6%8A%80%E6%9C%AF%E6%95%99%E7%A8%8B/"/>
    <category term="GitHub" scheme="https://blog.skyforever.top/tags/GitHub/"/>
    <category term="Linux" scheme="https://blog.skyforever.top/tags/Linux/"/>
    <category term="VSCode" scheme="https://blog.skyforever.top/tags/VSCode/"/>
    <category term="开发工具" scheme="https://blog.skyforever.top/tags/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/"/>
    <category term="Codespaces" scheme="https://blog.skyforever.top/tags/Codespaces/"/>
    <category term="代理" scheme="https://blog.skyforever.top/tags/%E4%BB%A3%E7%90%86/"/>
    <content>
      <![CDATA[<h2 id="Codespaces-简介"><a href="#Codespaces-简介" class="headerlink" title="Codespaces 简介"></a>Codespaces 简介</h2><p>GitHub Codespaces 是 <a href="https://github.com/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>Github</a> 提供的云端开发环境，底层是运行在微软云端服务器上的 Docker 容器（Ubuntu 系统），自带常见开发工具。每个月官方会提供免费额度，个人轻度使用完全足够。</p><p>因为 Codespaces 处于境外高速网络环境，我们可以用它运行一个轻量代理工具 Tinyproxy，再借助 VS Code 自带的端口转发功能，把云端网络能力桥接到本地电脑。</p><hr><h2 id="创建-Codespace"><a href="#创建-Codespace" class="headerlink" title="创建 Codespace"></a>创建 Codespace</h2><p>登录 GitHub 账号后，打开 <a href="https://github.com/codespaces" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://github.com/codespaces</a>，点击 New codespace：</p><p><img src="https://image.skyforever.top/blog/2026/10/e4f47dc77ce90178235603a2b1863aed.webp" alt="新建代码空间"></p><p>选择依附的仓库和分支（通常选 main），机型选 2 核基本够用（每月免费额度有 60 核心小时，2 核可用 30 小时）。确认无误后点击 Create codespace：</p><p><img src="https://image.skyforever.top/blog/2026/10/1f151522158e9b88eb65920ed07de2f4.webp" alt="选择关联仓库与 2 核机器规格"></p><p>随后页面会显示正在设置。浏览器生成的实例名称通常是两个随机英文单词（如 curly-space-parakeet），记下这个名字后即可关闭网页：</p><p><img src="https://image.skyforever.top/blog/2026/10/cf1e16e60ee7529590d2a2745ca6a453.webp" alt="Codespace 实例初始化与名称确认"></p><hr><h2 id="使用-VS-Code-连接"><a href="#使用-VS-Code-连接" class="headerlink" title="使用 VS Code 连接"></a>使用 VS Code 连接</h2><p>网页端体验受网络波动影响较大，更推荐用本地 VS Code 客户端连接。</p><p>在 VS Code 插件市场中搜索并安装 GitHub Codespaces 扩展：</p><p><img src="https://image.skyforever.top/blog/2026/10/b2daa454165146bc205a1494238c73ca.webp" alt="在 VS Code 中安装 GitHub Codespaces 扩展"></p><p>安装完成后，点击左侧边栏的远程资源管理器图标，点击登录 GitHub 账号：</p><p><img src="https://image.skyforever.top/blog/2026/10/202827c1857716cfbfda73e93192e38f.webp" alt="在远程资源管理器中登录 GitHub 账号"></p><p>授权登录后，列表中会显示刚才创建的 Codespace 实例。右键点击并选择连接（Connect to Codespace）：</p><p><img src="https://image.skyforever.top/blog/2026/10/25806f6d4061f8a3e426e047f6d7f129.webp" alt="右键选中目标实例并连接"></p><p>等待右下角进度条跑完，左下角显示已连接，就表示已成功连入云端容器。</p><hr><h2 id="配置-Tinyproxy-代理"><a href="#配置-Tinyproxy-代理" class="headerlink" title="配置 Tinyproxy 代理"></a>配置 Tinyproxy 代理</h2><p>在 VS Code 中按下快捷键 <code>Ctrl + ~</code> 打开云端终端，安装轻量代理工具 Tinyproxy：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 更新源并安装 tinyproxy</span></span><br><span class="line">sudo apt update &amp;&amp; sudo apt install -y tinyproxy</span><br></pre></td></tr></tbody></table></figure><p>编辑配置文件 <code>/etc/tinyproxy/tinyproxy.conf</code>：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 打开配置文件</span></span><br><span class="line">sudo vim /etc/tinyproxy/tinyproxy.conf</span><br></pre></td></tr></tbody></table></figure><p>在配置中修改两项：</p><ol><li>找到 <code>Port 8888</code>，确认或修改为所需端口（默认 8888 即可）。</li><li>找到 <code>Allow 127.0.0.1</code> 这一行，在前面加 <code>#</code> 注释掉，表示允许外部连接（由于 Codespaces 处于隔离环境，只有登录了你账号的 VS Code 能访问转发端口，放开是安全的）。</li></ol><p>保存退出后，启动代理服务：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 启动 tinyproxy 服务</span></span><br><span class="line">sudo /etc/init.d/tinyproxy start</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看服务运行状态</span></span><br><span class="line">sudo /etc/init.d/tinyproxy status</span><br></pre></td></tr></tbody></table></figure><hr><h2 id="端口转发与本机测试"><a href="#端口转发与本机测试" class="headerlink" title="端口转发与本机测试"></a>端口转发与本机测试</h2><p>在 VS Code 底部面板切换到“端口（Ports）”选项卡，点击“添加端口（Add Port）”，输入刚才配置的端口 <code>8888</code>。</p><p>此时 VS Code 会自动建立加密通道，将云端 8888 端口映射到本机的 <code>127.0.0.1:8888</code>。</p><p>打开本地终端进行测试：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 测试代理是否生效并查看出口 IP</span></span><br><span class="line">curl -x http://127.0.0.1:8888 https://api.ipify.org</span><br></pre></td></tr></tbody></table></figure><p>测试通过后，即可在系统代理设置或浏览器插件（如 SwitchyOmega）中将 HTTP 代理指向 <code>127.0.0.1:8888</code>。</p><hr><h2 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h2><ul><li>必须保持 VS Code 处于连接状态，代理隧道才会生效。</li><li>Codespaces 闲置超时后会自动关机以节省免费额度。重新连接后若代理不可用，需在云端终端重新运行一次 <code>sudo /etc/init.d/tinyproxy start</code> 唤醒服务。</li></ul>]]>
    </content>
    <id>https://blog.skyforever.top/posts/34640</id>
    <link href="https://blog.skyforever.top/posts/34640"/>
    <published>2026-10-03T08:26:53.000Z</published>
    <summary>介绍如何利用 GitHub Codespaces 提供的云端 Linux 环境，搭配 Tinyproxy 与 VS Code 端口转发能力，快速搭建一个供本地使用的 HTTP 代理通道。</summary>
    <title>建立本机与 Github Codespace 的代理</title>
    <updated>2026-10-03T08:26:53.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="开发工具" scheme="https://blog.skyforever.top/categories/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/"/>
    <category term="编程基础" scheme="https://blog.skyforever.top/categories/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/%E7%BC%96%E7%A8%8B%E5%9F%BA%E7%A1%80/"/>
    <category term="Linux" scheme="https://blog.skyforever.top/tags/Linux/"/>
    <category term="Python" scheme="https://blog.skyforever.top/tags/Python/"/>
    <category term="开发工具" scheme="https://blog.skyforever.top/tags/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/"/>
    <category term="包管理器" scheme="https://blog.skyforever.top/tags/%E5%8C%85%E7%AE%A1%E7%90%86%E5%99%A8/"/>
    <category term="前端开发" scheme="https://blog.skyforever.top/tags/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/"/>
    <category term="uv" scheme="https://blog.skyforever.top/tags/uv/"/>
    <category term="C/C++" scheme="https://blog.skyforever.top/tags/C-C/"/>
    <category term="Rust" scheme="https://blog.skyforever.top/tags/Rust/"/>
    <category term="Go" scheme="https://blog.skyforever.top/tags/Go/"/>
    <category term="Java" scheme="https://blog.skyforever.top/tags/Java/"/>
    <category term="Homebrew" scheme="https://blog.skyforever.top/tags/Homebrew/"/>
    <content>
      <![CDATA[<p>写代码离不开别人的开源库。早期引入第三方依赖全靠手动下载压缩包解压，一旦库版本更新或者出现多层依赖冲突，直接陷入依赖地狱。包管理器就是替我们自动下载、更新并梳理依赖关系的工具。</p><p>今天梳理一下各大主流语言和系统工具的核心区别与常用命令。</p><hr><h2 id="前端与-JS-生态"><a href="#前端与-JS-生态" class="headerlink" title="前端与 JS 生态"></a>前端与 JS 生态</h2><h3 id="npm"><a href="#npm" class="headerlink" title="npm"></a>npm</h3><p>Node.js 官方自带的默认包管理器，也是最大的包仓库，收录超过 200 万个包。初学前端最先接触的一定是它。</p><ul><li>优点：生态最全，开箱即用，所有教程默认通用。</li><li>缺点：每个项目都要完整复制一份依赖，node_modules 文件夹体积大；扁平化安装容易出现幽灵依赖；早期安装速度较慢。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 初始化项目</span></span><br><span class="line">npm init -y</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装依赖</span></span><br><span class="line">npm install &lt;包名&gt;</span><br><span class="line">npm install -D &lt;包名&gt; <span class="comment"># 安装为开发依赖</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装项目所有依赖与运行脚本</span></span><br><span class="line">npm install</span><br><span class="line">npm run &lt;脚本名&gt;</span><br><span class="line">npm update</span><br></pre></td></tr></tbody></table></figure><h3 id="Yarn"><a href="#Yarn" class="headerlink" title="Yarn"></a>Yarn</h3><p>Facebook 为了解决 npm 当时速度慢、版本不稳定的问题推出的工具。</p><ul><li>特点：率先引入了 yarn.lock 锁定文件，保证不同机器安装出来的依赖完全一致；支持离线缓存，下载过的包不用重复下载。</li><li>注意：<strong>同一个项目切忌混用 npm 和 yarn</strong>，混用会导致锁文件冲突和依赖混乱。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 添加依赖</span></span><br><span class="line">yarn add &lt;包名&gt;</span><br><span class="line">yarn add &lt;包名&gt; --dev</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装项目全部依赖与运行</span></span><br><span class="line">yarn install</span><br><span class="line">yarn &lt;脚本名&gt;</span><br></pre></td></tr></tbody></table></figure><h3 id="pnpm"><a href="#pnpm" class="headerlink" title="pnpm"></a>pnpm</h3><p>名字里的 p 代表高性能，主打节省磁盘空间和规范依赖树。</p><ul><li>特点：全电脑只存一份包实体，通过硬链接和软链接组织每个项目的 node_modules。安装一次 React，其他项目直接复用，非常省空间。</li><li>适用：特别适合多项目管理和 Monorepo 大仓。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 全局安装 pnpm</span></span><br><span class="line">npm install -g pnpm</span><br><span class="line"></span><br><span class="line"><span class="comment"># 基础使用</span></span><br><span class="line">pnpm add &lt;包名&gt;</span><br><span class="line">pnpm add -D &lt;包名&gt;</span><br><span class="line">pnpm install</span><br><span class="line">pnpm &lt;脚本名&gt;</span><br></pre></td></tr></tbody></table></figure><h3 id="Bun"><a href="#Bun" class="headerlink" title="Bun"></a>Bun</h3><p>不仅是包管理器，还是一个全新的运行时，用来替代 Node.js。</p><ul><li>特点：使用 Zig 编写，底层 I/O 做了极致优化，安装速度比 npm 快 10 到 20 倍；自带打包器、测试运行器，原生支持 TypeScript。</li><li>适用：追求极致速度的新项目或探索型工具。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 安装依赖</span></span><br><span class="line">bun add &lt;包名&gt;</span><br><span class="line">bun install</span><br><span class="line"></span><br><span class="line"><span class="comment"># 直接运行代码或测试</span></span><br><span class="line">bun run index.ts</span><br><span class="line">bun <span class="built_in">test</span></span><br></pre></td></tr></tbody></table></figure><hr><h2 id="Python系列"><a href="#Python系列" class="headerlink" title="Python系列"></a>Python系列</h2><h3 id="pip"><a href="#pip" class="headerlink" title="pip"></a>pip</h3><p>Python 官方标准包管理器，配合 PyPI 仓库使用。</p><ul><li>核心问题：默认是全局安装，项目一多极易发生版本冲突。</li><li>规则：<strong>必须配合虚拟环境使用</strong>，用 venv 隔离每个项目的依赖。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建并激活虚拟环境</span></span><br><span class="line">python -m venv .venv</span><br><span class="line"></span><br><span class="line"><span class="comment"># Linux 与 macOS 激活</span></span><br><span class="line"><span class="built_in">source</span> .venv/bin/activate</span><br><span class="line"><span class="comment"># Windows PowerShell 激活</span></span><br><span class="line"><span class="comment"># .venv\Scripts\Activate.ps1</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装依赖与导出清单</span></span><br><span class="line">pip install requests</span><br><span class="line">pip freeze &gt; requirements.txt</span><br><span class="line">pip install -r requirements.txt</span><br></pre></td></tr></tbody></table></figure><h3 id="Conda"><a href="#Conda" class="headerlink" title="Conda"></a>Conda</h3><p>数据科学和机器学习领域的标配包与环境管理器。</p><ul><li>特点：不仅管 Python 包，还能管理底层 C/C++ 库和 CUDA 驱动等预编译二进制文件。安装 NumPy、Pandas、TensorFlow 这类带复杂底层编译的库时，比 pip 省心很多。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建指定 Python 版本的独立环境</span></span><br><span class="line">conda create -n ai_env python=3.10</span><br><span class="line"></span><br><span class="line"><span class="comment"># 激活环境并安装科学计算库</span></span><br><span class="line">conda activate ai_env</span><br><span class="line">conda install numpy pandas pytorch</span><br></pre></td></tr></tbody></table></figure><h3 id="uv"><a href="#uv" class="headerlink" title="uv"></a>uv</h3><p>由 Astral 团队用 Rust 开发的新一代极速工具，正在快速席卷 Python 生态。</p><ul><li>特点：速度比传统 pip 快 10 到 100 倍，不仅完全兼容 pip 语法，还把 Python 解释器下载、虚拟环境创建和项目依赖锁定全包揽了。日常开发强烈建议优先尝试。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 兼容替代 pip 极速安装</span></span><br><span class="line">uv pip install requests</span><br><span class="line"></span><br><span class="line"><span class="comment"># 现代项目管理：自动下载依赖并锁定版本</span></span><br><span class="line">uv add requests</span><br><span class="line"></span><br><span class="line"><span class="comment"># 无需手动激活环境，直接在隔离环境中运行脚本</span></span><br><span class="line">uv run main.py</span><br></pre></td></tr></tbody></table></figure><hr><h2 id="C与C"><a href="#C与C" class="headerlink" title="C与C++"></a>C与C++</h2><p>C/C++ 的包管理是所有主流语言里公认最折腾的。因为没有官方统一标准，而且编译受编译器类型、编译参数、架构和二进制兼容（ABI）的严苛限制，导致直到今天都没有一个大一统的工具。</p><p>目前生态里主要分成三派：</p><ol><li>野生流派：许多老项目完全不用包管理器，直接手动把第三方库源码拷进项目，或者用 Git Submodule / CMake FetchContent 在编译时现场拉源码。</li><li>vcpkg 派：微软主导的源码驱动方案，是目前个人开发者和开源社区最流行的选择。</li><li>Conan 派：主打预编译二进制包，配置门槛较高，主要在企业级 CI/CD 和大型跨平台工程中使用。</li></ol><h3 id="vcpkg"><a href="#vcpkg" class="headerlink" title="vcpkg"></a>vcpkg</h3><p>微软开源的跨平台包管理器，对 Windows、Visual Studio 和 CMake 体系支持最成熟。</p><ul><li>特点：本质上是一个庞大的编译脚本库。你让它装某个库，它会自动下载源码并在本地根据你的环境现编出静态或动态库，然后通过 CMake 工具链文件直接喂给你的项目。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 安装开源库</span></span><br><span class="line">vcpkg install <span class="built_in">fmt</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 配合 CMake 项目构建（传入 vcpkg 工具链文件）</span></span><br><span class="line">cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=[vcpkg路径]/scripts/buildsystems/vcpkg.cmake</span><br></pre></td></tr></tbody></table></figure><h3 id="Conan"><a href="#Conan" class="headerlink" title="Conan"></a>Conan</h3><p>JFrog 旗下的开源 C/C++ 二进制包管理器。</p><ul><li>特点：基于 Python 编写。与 vcpkg 默认在本地现场编译不同，Conan 强调直接下载打好的二进制包，避免了大型项目在本地漫长的编译等待，适合企业级私有依赖分发和持续集成。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 生成依赖并安装预编译包</span></span><br><span class="line">conan install . --output-folder=build --build=missing</span><br></pre></td></tr></tbody></table></figure><hr><h2 id="Rust和Go"><a href="#Rust和Go" class="headerlink" title="Rust和Go"></a>Rust和Go</h2><h3 id="Cargo"><a href="#Cargo" class="headerlink" title="Cargo"></a>Cargo</h3><p>Rust 官方标配的工程管理工具，体验公认极其丝滑。</p><ul><li>特点：把创建项目、代码编译、跑测试、生成文档和依赖管理全包了。依托 crates.io 仓库，开箱即用，无需额外折腾配置。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建新项目</span></span><br><span class="line">cargo new my_project</span><br><span class="line"></span><br><span class="line"><span class="comment"># 编译代码</span></span><br><span class="line">cargo build          <span class="comment"># 调试编译</span></span><br><span class="line">cargo build --release <span class="comment"># 生产编译</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 运行与测试</span></span><br><span class="line">cargo run            <span class="comment"># 编译并运行</span></span><br><span class="line">cargo <span class="built_in">test</span>           <span class="comment"># 运行单元测试</span></span><br><span class="line">cargo check          <span class="comment"># 快速检查代码语法</span></span><br></pre></td></tr></tbody></table></figure><h3 id="Go-Modules"><a href="#Go-Modules" class="headerlink" title="Go Modules"></a>Go Modules</h3><p>Go 从 1.11 引入、1.13 成为标准的依赖方案。</p><ul><li>特点：没有中心化注册网站，依赖路径直接就是代码仓库地址；使用最小版本选择机制，写代码直接 import，执行命令自动分析下载，省心且不碍事。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 初始化模块</span></span><br><span class="line">go mod init my_module</span><br><span class="line"></span><br><span class="line"><span class="comment"># 下载指定依赖</span></span><br><span class="line">go get github.com/gin-gonic/gin</span><br><span class="line"></span><br><span class="line"><span class="comment"># 自动清理无用依赖并补全缺失依赖</span></span><br><span class="line">go mod tidy</span><br></pre></td></tr></tbody></table></figure><hr><h2 id="Java和PHP"><a href="#Java和PHP" class="headerlink" title="Java和PHP"></a>Java和PHP</h2><h3 id="Maven"><a href="#Maven" class="headerlink" title="Maven"></a>Maven</h3><p>Java 企业级开发的长青树，2004 年至今依旧广泛使用。</p><ul><li>特点：采用 pom.xml 配置，强制标准项目目录规范。生态极其成熟，但在大型项目上 XML 冗长，全量编译偏慢。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 常用构建命令</span></span><br><span class="line">mvn clean compile <span class="comment"># 清理并编译</span></span><br><span class="line">mvn clean <span class="built_in">test</span>    <span class="comment"># 运行测试</span></span><br><span class="line">mvn clean package <span class="comment"># 打包为 jar 或 war</span></span><br><span class="line">mvn clean install <span class="comment"># 安装到本地仓库</span></span><br></pre></td></tr></tbody></table></figure><h3 id="Gradle"><a href="#Gradle" class="headerlink" title="Gradle"></a>Gradle</h3><p>Java、Kotlin 和 Android 的现代构建工具。</p><ul><li>特点：使用 Groovy 或 Kotlin DSL 代替 XML，支持增量构建与构建缓存，构建速度显著快于 Maven，是 Android 官方钦定的构建工具。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 使用项目 Wrapper 构建与运行</span></span><br><span class="line">./gradlew build</span><br><span class="line">./gradlew <span class="built_in">test</span></span><br><span class="line">./gradlew bootRun</span><br></pre></td></tr></tbody></table></figure><h3 id="Composer"><a href="#Composer" class="headerlink" title="Composer"></a>Composer</h3><p>PHP 现代化的核心支柱。</p><ul><li>特点：彻底改变了过去手动 include 文件的混乱局面，核心是 PSR-4 自动加载规范。现代 Laravel、Symfony 开发必备。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 引入新依赖并安装</span></span><br><span class="line">composer require guzzlehttp/guzzle</span><br><span class="line">composer install</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重新生成自动加载映射文件</span></span><br><span class="line">composer dump-autoload -o</span><br></pre></td></tr></tbody></table></figure><hr><h2 id="系统工具"><a href="#系统工具" class="headerlink" title="系统工具"></a>系统工具</h2><h3 id="Homebrew"><a href="#Homebrew" class="headerlink" title="Homebrew"></a>Homebrew</h3><p>macOS 和 Linux 上最常用的系统包管理器，装机必备。</p><ul><li>特点：Formula 管理命令行工具和数据库，Cask 管理带界面的桌面应用。软件安装在独立目录并通过软链接映射，不污染操作系统本身。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 安装命令行工具与数据库</span></span><br><span class="line">brew install python</span><br><span class="line">brew install postgresql</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装带图形界面的桌面应用</span></span><br><span class="line">brew install --cask visual-studio-code</span><br><span class="line">brew install --cask google-chrome</span><br><span class="line"></span><br><span class="line"><span class="comment"># 日常维护更新</span></span><br><span class="line">brew update</span><br><span class="line">brew upgrade</span><br><span class="line">brew cleanup</span><br></pre></td></tr></tbody></table></figure><hr><h2 id="Linux-系统工具"><a href="#Linux-系统工具" class="headerlink" title="Linux 系统工具"></a>Linux 系统工具</h2><p>除了面向开发语言和跨平台的工具外，Linux 各发行版都有自己的系统级包管理器，用于安装底层服务和运行环境。</p><h3 id="apt"><a href="#apt" class="headerlink" title="apt"></a>apt</h3><p>Debian 和 Ubuntu 系列的标配包管理器。</p><ul><li>特点：底层使用 dpkg 管理 .deb 二进制安装包，上层通过 apt 自动从软件源解析并下载所有关联依赖。日常运维使用最广泛。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 更新本地软件源索引</span></span><br><span class="line">sudo apt update</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装软件</span></span><br><span class="line">sudo apt install nginx</span><br><span class="line"></span><br><span class="line"><span class="comment"># 升级所有已安装软件</span></span><br><span class="line">sudo apt upgrade</span><br></pre></td></tr></tbody></table></figure><h3 id="dnf"><a href="#dnf" class="headerlink" title="dnf"></a>dnf</h3><p>Red Hat、CentOS Stream 和 Fedora 系列的现代包管理器。</p><ul><li>特点：底层使用 rpm 管理 .rpm 安装包。早期系统默认使用 yum，后来为了提升依赖解析速度和降低内存消耗，推出了基于 C 语言重构的 dnf。如今在现代 CentOS/RHEL 系统中，敲 yum 本质上也是软链接到 dnf。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 安装软件</span></span><br><span class="line">sudo dnf install nginx</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查可更新项并升级</span></span><br><span class="line">sudo dnf upgrade</span><br></pre></td></tr></tbody></table></figure><h3 id="pacman"><a href="#pacman" class="headerlink" title="pacman"></a>pacman</h3><p>Arch Linux 及其衍生发行版的专属包管理器。</p><ul><li>特点：专为滚动更新系统设计，采用简单的压缩包格式，依赖解析和安装速度极快。配合 Arch 社区的用户软件仓库 AUR，几乎能装上任何开源软件。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 同步软件源并升级整个系统</span></span><br><span class="line">sudo pacman -Syu</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装软件</span></span><br><span class="line">sudo pacman -S git</span><br></pre></td></tr></tbody></table></figure><h3 id="apk"><a href="#apk" class="headerlink" title="apk"></a>apk</h3><p>Alpine Linux 的轻量级包管理器。</p><ul><li>特点：体积极小，执行速度飞快。因为 Alpine 常被用来制作极度轻量化的 Docker 基础镜像，所以我们在写 Dockerfile 时经常会用到它。</li></ul><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 更新索引并安装软件，不保留本地缓存以减小镜像体积</span></span><br><span class="line">apk add --no-cache curl</span><br></pre></td></tr></tbody></table></figure>]]>
    </content>
    <id>https://blog.skyforever.top/posts/33643</id>
    <link href="https://blog.skyforever.top/posts/33643"/>
    <published>2026-10-02T05:41:28.000Z</published>
    <summary>盘点前端、Python、C/C++、Rust、Go、Java、PHP 以及系统级主流包管理器的核心原理、常用命令与生态现状。</summary>
    <title>包管理器汇总</title>
    <updated>2026-10-02T05:41:28.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="音视频技术" scheme="https://blog.skyforever.top/categories/%E9%9F%B3%E8%A7%86%E9%A2%91%E6%8A%80%E6%9C%AF/"/>
    <category term="音视频" scheme="https://blog.skyforever.top/tags/%E9%9F%B3%E8%A7%86%E9%A2%91/"/>
    <category term="H264" scheme="https://blog.skyforever.top/tags/H264/"/>
    <category term="视频编解码" scheme="https://blog.skyforever.top/tags/%E8%A7%86%E9%A2%91%E7%BC%96%E8%A7%A3%E7%A0%81/"/>
    <category term="计算机视觉" scheme="https://blog.skyforever.top/tags/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89/"/>
    <content>
      <![CDATA[<h2 id="一、视频压缩基础"><a href="#一、视频压缩基础" class="headerlink" title="一、视频压缩基础"></a>一、视频压缩基础</h2><h3 id="1-1-视频压缩必要性"><a href="#1-1-视频压缩必要性" class="headerlink" title="1.1 视频压缩必要性"></a>1.1 视频压缩必要性</h3><p>未经压缩的视频数据量极其庞大。以常见的 1080P 60帧视频为例，画面分辨率为 1920x1080，如果用一张一张的RGB图片来存储，每个像素占 3 个字节：</p><p>单秒数据量 = 1920 x 1080 x 3 x 60 ≈ 373 MB。</p><p>这意味着一部两小时的视频就要吃掉大约 2.6 TB 存储空间。无论硬盘还是网速都无法承受，因此视频在传输和存储前必须进行压缩。</p><p>视频之所以能压缩到原大小的几十分之一甚至上百分之一，是因为连续画面中存在大量重复和不必要的信息（数据冗余）：</p><ul><li>时间冗余：连续播放的前后两帧画面，绝大部分背景和人物都是静止或微动的，内容高度相似。</li><li>视觉冗余：人类眼球对亮度变化非常敏感，但对细微的色度变化和超高频细节相对迟钝，适当剔除这些细节人眼根本察觉不出。</li><li>空间冗余：单张图片内部，相邻像素之间的颜色和亮度往往非常接近，比如大片蓝天或白墙。</li><li>编码冗余：数据中不同数值出现的概率不同，出现频率极高的数值用短码表示，极少出现的用长码表示（如哈夫曼编码），可以缩减总码长。</li></ul><p>市面上常见的视频编码标准主要分为几大阵营：</p><div class="md-table-scroll"><table><thead><tr><th align="left">编码标准</th><th align="left">主导阵营</th><th align="left">当前行业现状与生态</th></tr></thead><tbody><tr><td align="left">H.264 (AVC)</td><td align="left">MPEG / ITU-T</td><td align="left">绝对的兼容性兜底底线，几乎所有设备、浏览器与硬件芯片均支持 100% 硬解</td></tr><tr><td align="left">H.265 (HEVC)</td><td align="left">MPEG / ITU-T</td><td align="left">4K 高清与安防监控主力；主流浏览器（Chrome、Safari、Edge）已普遍支持硬解，但受商业专利池收费困扰</td></tr><tr><td align="left">AV1</td><td align="left">AOMedia（谷歌、苹果、微软等）</td><td align="left">开源免版税新主力，B站、YouTube 及长视频平台大规模使用，近两年的手机与 PC 显卡基本全标配硬解</td></tr><tr><td align="left">VP9</td><td align="left">Google 阵营</td><td align="left">谷歌早期免版税过渡标准，广泛用于 WebRTC 和油管，当前逐步向 AV1 转移</td></tr><tr><td align="left">AVS3</td><td align="left">中国标准工作组</td><td align="left">我国自主研发的新一代超高清标准，主打 8K 广电直播（央视春晚、冬奥等）与自主可控信创领域</td></tr><tr><td align="left">H.266 (VVC)</td><td align="left">MPEG / ITU-T</td><td align="left">压缩率比 H265 再翻倍，但计算开销巨大、硬件解码尚未大规模普及，处于各大平台小范围点播试水阶段</td></tr></tbody></table></div><p>视频编码的最终目的，就是在人眼察觉不到明显失真的前提下，把上述冗余信息全部剔除，将庞大的原始画面压缩为紧凑的数据流。</p><p><img src="https://image.skyforever.top/blog/2026/09/5d6acb17cdf69c8b9014bef9d29defa3.webp" alt="H264编解码基本闭环流程"><br><em>H264编解码基本闭环流程</em></p><h3 id="1-2-封装格式与编码"><a href="#1-2-封装格式与编码" class="headerlink" title="1.2 封装格式与编码"></a>1.2 封装格式与编码</h3><p>初学者常把 mp4、mkv 和 H264 混为一谈：</p><ul><li>视频编码（如 H264、H265）：负责将原始图像数据压缩成紧凑的数据流，决定了<strong>压缩比</strong>和画质。</li><li>封装格式（如 mp4、mov、avi、mkv）：相当于一个<strong>打包</strong>盒子（容器）。它的作用是把压缩好的视频轨、音频轨以及字幕按固定规则装进同一个文件，并记录时长、索引等元数据。</li></ul><h2 id="二、画面组织与分类"><a href="#二、画面组织与分类" class="headerlink" title="二、画面组织与分类"></a>二、画面组织与分类</h2><p>在深入微观算法前，我们先从宏观视角看整部视频是如何由不同的画面角色组织起来的。</p><h3 id="2-1-对画面分类-I-P-B帧"><a href="#2-1-对画面分类-I-P-B帧" class="headerlink" title="2.1 对画面分类 I/P/B帧"></a>2.1 对画面分类 I/P/B帧</h3><p>根据预测依赖关系的不同，H264 将视频帧分为三类：</p><ul><li>I 帧（Intra-coded picture）：关键帧。完全采用帧内预测压缩，不依赖前后任何外部帧即可独立解码，相当于一张完整的全家福照片。它的压缩率最低，体积最大，是所有预测的基准。</li><li>P 帧（Predicted picture）：前向预测帧。只能参考前面的 I 帧或 P 帧进行单向差值计算，体积约为 I 帧的一半。</li><li>B 帧（Bi-directional predicted picture）：双向参考帧。既参考前面的帧，又参考后面的帧。由于能双向借力，它的压缩率最高，体积最小，通常只有 I 帧的五分之一甚至十分之一。</li></ul><p><img src="https://image.skyforever.top/blog/2026/09/563472b49cd3941043c33f9690173617.webp" alt="IPB帧参考关系与编解码顺序对比"><br><em>IPB帧参考关系与编解码顺序对比</em></p><p>引入 B 帧带来了一个重要问题：解码顺序与播放顺序不同。<br>DTS（解码时间戳）告诉解码器什么时候拆包还原画面，PTS（显示时间戳）告诉播放器什么时候把画面亮在屏幕上。因为 B 帧要参考后面的画面，解码器必须先把后面的帧提前解出来放在缓冲区等着，所以解的和播的顺序会有先后倒挂。</p><h3 id="2-2-阻断错误扩散-GOP与IDR刷新机制"><a href="#2-2-阻断错误扩散-GOP与IDR刷新机制" class="headerlink" title="2.2 阻断错误扩散 GOP与IDR刷新机制"></a>2.2 阻断错误扩散 GOP与IDR刷新机制</h3><p>连续的 P 帧和 B 帧都在环环相扣地向前参考。如果网络丢包导致其中一个参考帧损坏，后续所有依赖它的帧就会全部推导失败，导致整个画面撕裂或出现严重色块，这种现象称为错误扩散。</p><p>为了阻止错误无限扩散，编码器必须周期性地插入完全独立的刷新帧。</p><p><img src="https://image.skyforever.top/blog/2026/09/7cf27843a82b590d8b6377108f70d875.webp" alt="GOP图像组内帧序列结构"><br><em>GOP图像组内帧序列结构</em></p><ul><li>IDR 帧（Instantaneous Decoding Refresh，立即刷新帧）：这是一种特殊的 I 帧。当解码器遇到 IDR 帧时，会立刻清空现有的参考帧队列缓存，重新开始一个新的序列。从 IDR 帧之后的所有画面，绝不允许跨过它去参考它前面的帧。</li><li>GOP（Group of Pictures，图像组）：相邻两个 IDR 帧之间的画面序列称为一个 GOP。一个 GOP 内通常只有开头一个 IDR 帧，后面全是由它派生出的 P 帧和 B 帧。</li></ul><p><img src="https://image.skyforever.top/blog/2026/09/4bb5fc4f85e1aae8a784ab8a4d7343ff.webp" alt="IDR帧界定GOP序列示意"><br><em>IDR帧界定GOP序列示意</em></p><p>常见播放异常的本质：</p><ul><li>花屏：GOP 中途发生丢包，P 帧或 B 帧残缺，解码器拿残缺的参考数据强行计算，导致画面破损。</li><li>卡顿：为了避免花屏，解码端在检测到丢包后主动把当前 GOP 剩余的所有数据全部扔掉，停在最后一幅画面静止等待下一个 IDR 帧重新刷屏。在等待新 IDR 帧到来的这段时间，画面定格形成卡顿。</li><li>业务权衡：微信视频通话等实时通信场景，通常选择宁可偶尔卡顿或者快速丢弃请求重传，也要优先保证实时性；而在本地视频播放或广播录制时，则更倾向于丢弃坏帧等待刷新。</li></ul><h3 id="2-3-画质级别"><a href="#2-3-画质级别" class="headerlink" title="2.3 画质级别"></a>2.3 画质级别</h3><p>为了适应从低性能手机、安防摄像头到蓝光光盘的不同硬件能力，H264 定义了不同的 Profile（特性档次开关）：</p><ol><li>Baseline Profile：基础档次。只支持 I/P 帧，不支持 B 帧，仅支持 CAVLC。运算开销最小，延迟最低，广泛应用于实时音视频通信和低端硬件。</li><li>Main Profile：主流档次。增加了对 B 帧、隔行扫描和 CABAC 的支持，适用于绝大多数流媒体和日常视频播放。</li><li>Extended Profile：进阶档次。主要针对网络流媒体抗丢包场景设计，实际工业界极少使用。</li><li>High Profile：高级档次。在 Main 的基础上增加了 8x8 频域变换和自定义量化矩阵，同等画质下比 Main 再省约 10% 码率，广泛应用于广电广播和高清蓝光存储。</li></ol><p><img src="https://image.skyforever.top/blog/2026/09/6712a4c9c0c6c799e75d75a309ec812c.webp" alt="H264各Profile特性支持对比表"><br><em>H264各Profile特性支持对比表</em></p><h2 id="三、图像色彩基础"><a href="#三、图像色彩基础" class="headerlink" title="三、图像色彩基础"></a>三、图像色彩基础</h2><p>宏观上理解了整部视频的帧分工后，再往下一层看单张画面本身是如何存储的——为什么视频不使用电脑屏幕通用的 RGB，而选用 YUV？</p><h3 id="3-1-消除视觉冗余-YUV颜色模型"><a href="#3-1-消除视觉冗余-YUV颜色模型" class="headerlink" title="3.1 消除视觉冗余 YUV颜色模型"></a>3.1 消除视觉冗余 YUV颜色模型</h3><p>计算机显示器普遍使用 RGB（红、绿、蓝）三原色渲染画面，但视频压缩领域几乎全部采用 YUV 格式（也称 YCbCr）。</p><p><a href="https://paaatrick.com/2020-01-26-yuv-pixel-formats/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span> YUV 格式详解</a></p><p>YUV 将色彩信息拆分为两部分：</p><ul><li>Y 分量：表示明亮度（Luminance，以前工程师喜欢<a href="https://baike.baidu.com/item/XYZ%E8%A1%A8%E8%89%B2%E7%B3%BB%E7%BB%9F/22038691" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>用y代表亮度轴</a>），即黑白灰度画面。</li><li>U 和 V 分量：分别表示色度（Chrominance）和浓度（Chroma），即色彩信息。</li></ul><p><img src="https://image.skyforever.top/blog/2026/09/2bfa6dd0708e5a37484afc12cee6b777.webp" alt="YUV全分量彩色渲染效果"><br><em>YUV全分量彩色渲染效果</em></p><p>这种分离设计的最大好处是契合人眼生理特性：人眼视网膜上的视杆细胞（感知明暗）远多于视锥细胞（感知色彩）。哪怕画面完全没有 UV 分量，单纯保留 Y 分量，人眼依然能看清物体的清晰轮廓：</p><div class="md-table-scroll"><table><thead><tr><th align="center">仅保留 Y 亮度分量</th><th align="center">仅保留 U 色度分量</th><th align="center">仅保留 V 色度分量</th></tr></thead><tbody><tr><td align="center"><img src="https://image.skyforever.top/blog/2026/09/54bccb2b83d7d9604d189e201fe5d5bc.webp" alt="仅保留Y亮度分量的灰度图效果"></td><td align="center"><img src="https://image.skyforever.top/blog/2026/09/74de533c5261fa4563f0e0e9f754a1fd.webp" alt="仅保留U色度分量的渲染效果"></td><td align="center"><img src="https://image.skyforever.top/blog/2026/09/b923e94b40db97ffacf4cde65345ea7d.webp" alt="仅保留V色度分量的渲染效果"></td></tr></tbody></table></div><h3 id="3-2-YUV采样格式"><a href="#3-2-YUV采样格式" class="headerlink" title="3.2 YUV采样格式"></a>3.2 YUV采样格式</h3><p>利用人眼对色彩迟钝的特性，工程师在采集图像时就对 UV 分量进行下采样（色彩打折）：</p><ul><li>YUV 4:4:4：每个 Y 像素都对应完整的 U 和 V 分量，完全不压缩色彩，专业调色和制作用。</li><li>YUV 4:2:2：每两个横向相邻的 Y 像素共用一组 UV 分量，色彩数据减半。</li><li>YUV 4:2:0：最常用的通用格式。每 4 个相邻像素（2x2 方阵）只采样一组 UV 分量。相比 RGB 格式，原始图像数据量直接砍掉一半。</li></ul><h2 id="四、H264核心压缩步骤"><a href="#四、H264核心压缩步骤" class="headerlink" title="四、H264核心压缩步骤"></a>四、H264核心压缩步骤</h2><p>弄清楚了画面的色彩格式与宏观角色后，接下来进入微观计算环节：前面提到的 I/P/B 帧，在底层究竟是怎么一步步算出来的？</p><p>宏观与微观的对应关系非常清晰：<br>P 帧和 B 帧在底层靠帧间预测借用前后的画面来推断自己的画面，I 帧靠帧内预测只利用自身画面的相邻像素来推算；两种预测推导出的差值，再统一送进 DCT、量化和熵编码完成终极瘦身。</p><p>我们按照“从整图切块、到多帧位移、再到单帧局部、最后到底层比特”的顺序逐层拆解：</p><p><img src="https://image.skyforever.top/blog/2026/09/2d7cccebafdf922085be6e2c1c7699a0.webp" alt="H264编码原理全流程框架"><br><em>H264编码原理全流程框架</em></p><h3 id="4-1-对画面切块-宏块子块切分"><a href="#4-1-对画面切块-宏块子块切分" class="headerlink" title="4.1 对画面切块 宏块子块切分"></a>4.1 对画面切块 宏块子块切分</h3><p>压缩的第一步是切块。编码器不可能把一整张几百万像素的大图当成一个整体去算，而是将画面切成一个个小方块进行处理。</p><p><img src="https://image.skyforever.top/blog/2026/09/84ed035bf2979d4661b51fd1aa6fa8c8.webp" alt="视频到宏块与子块的层级划分"><br><em>视频到宏块与子块的层级划分</em></p><p><img src="https://image.skyforever.top/blog/2026/09/9b7e33370edf33fe81acabf1240d14ac.webp" alt="待编码的原始画面"><br><em>待编码的原始画面</em></p><p>H264 默认将图像划分为 16x16 像素大小的单元，称为宏块（Macroblock）：</p><p><img src="https://image.skyforever.top/blog/2026/09/2aca4b9adb3c43a2a7bffb3dd463eda2.webp" alt="画面局部16x16宏块网格切分"><br><em>画面局部16x16宏块网格切分</em></p><p>每个宏块在物理上由具体的像素数值矩阵构成：</p><p><img src="https://image.skyforever.top/blog/2026/09/25ed1fe9e7919b75ba6a1285d51d4fa7.webp" alt="8x8像素块的数值立体高度模型"><br><em>8x8像素块的数值立体高度模型</em></p><p><img src="https://image.skyforever.top/blog/2026/09/728105d8dd779bc3e0c4277009eee558.webp" alt="画面拆解为二维像素数值矩阵"><br><em>画面拆解为二维像素数值矩阵</em></p><p>为了兼顾压缩效率与画面细节，H264 引入了灵活的子块划分机制：</p><ul><li>对于天空、草坪等颜色变化平缓的区域，使用完整的 16x16 大宏块，可以用极少的数据描述一大片区域。</li><li>对于建筑边缘、物体轮廓等细节复杂区域，把宏块进一步切分成 16x8、8x16、8x8 甚至 4x4 等更小的子块分别精细编码。</li></ul><p><img src="https://image.skyforever.top/blog/2026/09/65ecb02d72831afc78632b90351a7e73.webp" alt="宏块内部细分为多种灵活子块"><br><em>宏块内部细分为多种灵活子块</em></p><h3 id="4-2-消除时间冗余-帧间预测与运动补偿"><a href="#4-2-消除时间冗余-帧间预测与运动补偿" class="headerlink" title="4.2 消除时间冗余 帧间预测与运动补偿"></a>4.2 消除时间冗余 帧间预测与运动补偿</h3><p>这一步是前面讲到的 P 帧和 B 帧的底层核心实现。切好宏块后，首先处理的是跨越多张连续画面的时间冗余。</p><p>连续播放的视频帧之间大部分背景根本没动，往往只有某些物体发生了位置移动：</p><p><img src="https://image.skyforever.top/blog/2026/09/e79763c5cea96f19b256963fc42bdc46.webp" alt="时间轴上的连续视频帧序列"><br><em>时间轴上的连续视频帧序列</em></p><p><img src="https://image.skyforever.top/blog/2026/09/0cc83e4526368d60165b649da0fc0c66.webp" alt="相邻两帧运动物体的宏块比对"><br><em>相邻两帧运动物体的宏块比对</em></p><p>工程上判断连续帧是否相似的标准通常是：相邻两帧中有差异的像素在 10% 以内，亮度变化小于 2%，色度变化小于 1%。只要满足这些条件，两帧之间就具备极高的时间相关性。</p><p>帧间压缩不需要在后续帧里重复画出物体，而是做运动估计与补偿：</p><ol><li>运动估计：在参考帧的局部搜索窗口内寻找与当前块长得最相似的宏块，计算出它移动了多少距离和方向，这个位移量称为运动矢量（Motion Vector）。</li><li>运动补偿：用参考块加上位移，拼出当前画面的推测图，再用实际画面减去推测图，得到微小的运动残差。</li></ol><p><img src="https://image.skyforever.top/blog/2026/09/061844177dc016c10040d6e5d8a092eb.webp" alt="相邻帧之间的运动估计搜索"><br><em>相邻帧之间的运动估计搜索</em></p><p><img src="https://image.skyforever.top/blog/2026/09/94839daa36c43161632250add751dae3.webp" alt="跨帧运动矢量轨迹计算"><br><em>跨帧运动矢量轨迹计算</em></p><p>这样一来，后续画面只需要存储一个极小的运动矢量加上一点点残差数据，大幅降低了数据体积。</p><h3 id="4-3-消除空间冗余-帧内预测"><a href="#4-3-消除空间冗余-帧内预测" class="headerlink" title="4.3 消除空间冗余 帧内预测"></a>4.3 消除空间冗余 帧内预测</h3><p>这一步是前面讲到的 I 帧（关键帧）的底层核心实现。处理完多帧之间的时间位移后，对于不能参考其他帧的独立画面（或帧内宏块），则深入到单张图片内部去除空间冗余。</p><p>单张图像相邻像素之间颜色往往非常接近。如果在每个宏块里都原原本本地保存全部像素值，会产生极大的浪费。H264 的思路是不存真实像素，只存推测规律和差值：</p><p>当前宏块编码时，编码器利用已经编码完成的左侧和上方边缘像素作为参考物，按照不同方向进行延伸推导，生成一个虚拟的“预测宏块”：</p><p><img src="https://image.skyforever.top/blog/2026/09/c6a09beff7067e8c157a405a888abbd0.webp" alt="4x4亮度块的9种帧内预测模式"><br><em>4x4亮度块的9种帧内预测模式</em></p><ul><li>4x4 亮度子块支持 9 种预测方向模式（垂直、水平、对角线平推等）：</li></ul><div class="md-table-scroll"><table><thead><tr><th align="left">模式</th><th align="left">描述</th></tr></thead><tbody><tr><td align="left">模式 0（垂直）</td><td align="left">由 A、B、C、D 垂直推出相应像素值</td></tr><tr><td align="left">模式 1（水平）</td><td align="left">由 I、J、K、L 水平推出相应像素值</td></tr><tr><td align="left">模式 2（DC）</td><td align="left">由 A<del>D 及 I</del>L 平均值推出所有像素值</td></tr><tr><td align="left">模式 3（下左对角线）</td><td align="left">由 45° 方向像素内插得出相应像素值</td></tr><tr><td align="left">模式 4（下右对角线）</td><td align="left">由 45° 方向像素内插得出相应像素值</td></tr><tr><td align="left">模式 5（右垂直）</td><td align="left">由 26.6° 方向像素值内插得出相应像素值</td></tr><tr><td align="left">模式 6（下水平）</td><td align="left">由 26.6° 方向像素值内插得出相应像素值</td></tr><tr><td align="left">模式 7（左垂直）</td><td align="left">由 26.6° 方向像素值内插得出相应像素值</td></tr><tr><td align="left">模式 8（上水平）</td><td align="left">由 26.6° 方向像素值内插得出相应像素值</td></tr></tbody></table></div><ul><li>16x16 亮度宏块支持 4 种预测模式（垂直、水平、全块均值 DC、线性平面平滑）：</li></ul><div class="md-table-scroll"><table><thead><tr><th align="left">模式</th><th align="left">描述</th></tr></thead><tbody><tr><td align="left">模式 0（垂直）</td><td align="left">由上边像素推出相应像素值</td></tr><tr><td align="left">模式 1（水平）</td><td align="left">由左边像素推出相应像素值</td></tr><tr><td align="left">模式 2（DC）</td><td align="left">由上边和左边像素平均值推出相应像素值</td></tr><tr><td align="left">模式 3（平面）</td><td align="left">利用线性 plane 函数及左、上像素推出相应像素值，适用于亮度变化平缓区域</td></tr></tbody></table></div><p><img src="https://image.skyforever.top/blog/2026/09/9c8f63961a7d62657d5b88cf1df56a4b.webp" alt="帧内预测模式对应的色块纹理示意"><br><em>帧内预测模式对应的色块纹理示意</em></p><p>编码器会把每种模式都试一遍，挑选出一个与原图最像的预测模式：</p><p><img src="https://image.skyforever.top/blog/2026/09/379a27b6b6d2baf221beabd45c66c793.webp" alt="宏块选择最佳预测模式编号的组合画面"><br><em>宏块选择最佳预测模式编号的组合画面</em></p><p><img src="https://image.skyforever.top/blog/2026/09/8edad56853822fa7fc84573baafcedce.webp" alt="预测画面与原始画面效果对比"><br><em>预测画面与原始画面效果对比</em></p><p>选定最佳预测模式后，拿原始图像减去预测图像，得到两者之间的差值，这个差值被称为残差（Residual）：</p><p><img src="https://image.skyforever.top/blog/2026/09/6a2220e9b4b6d7349951a8e4b13baad7.webp" alt="相减后得到的灰度残差数据层"><br><em>相减后得到的灰度残差数据层</em></p><p>最终，编码器只需记录两项数据：所采用的预测模式编号（占几个比特）以及残差数据。解码端拿到这两项数据后，即可通过模式重新推算并加上残差，还原出真实图像。</p><p><img src="https://image.skyforever.top/blog/2026/09/d31826e4af8ed0002138f60bdcabd090.webp" alt="预测模式信息与残差数据合并压缩"><br><em>预测模式信息与残差数据合并压缩</em></p><h3 id="4-4-消除视觉冗余-DCT变换与量化"><a href="#4-4-消除视觉冗余-DCT变换与量化" class="headerlink" title="4.4 消除视觉冗余 DCT变换与量化"></a>4.4 消除视觉冗余 DCT变换与量化</h3><p>不管是帧内预测还是帧间预测，算出来的差值（残差矩阵）依然包含不少细节数据。要进一步大幅瘦身，就需要针对人眼的“视觉冗余”下手。</p><p>人眼视觉有一个显著特点：对平缓的明暗轮廓（低频信息）极度敏感，但对剧烈跳动的微小噪点和细碎纹理（高频信息）非常迟钝，这些看不清的高频信息就是视觉冗余。</p><p><img src="https://image.skyforever.top/blog/2026/09/f411b0cc14d74b1a5a63fec5c06aadf2.webp" alt="片、宏块与残差数据的组织结构"><br><em>片、宏块与残差数据的组织结构</em></p><p>为了把这些视觉冗余挑出来剔除，需要分两步走：</p><ul><li>离散余弦变换（DCT）：变换本身不会减少数据体积，而是把数据从空间坐标域转换到频率域，起到分拣分类的作用。变换后，代表整体轮廓基调的低频系数集中在矩阵左上角，而代表细微噪点的高频系数分布在右下角，将人眼敏感与不敏感的信息彻底区分开。</li><li>量化（Quantization）：这是整个编码过程中唯一发生信息丢弃的有损压缩步骤。量化利用人眼对高频不敏感的特性，把频域矩阵里的每个数值除以量化步长 QP 并四舍五入取整：</li></ul><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>F</mi><mi>Q</mi><mo>=</mo><mtext>round</mtext><mrow><mo fence="true">(</mo><mfrac><mi>y</mi><mrow><mi>Q</mi><mi>P</mi></mrow></mfrac><mo fence="true">)</mo></mrow></mrow><annotation encoding="application/x-tex">FQ = \text{round}\left(\frac{y}{QP}\right)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="katex-base"><span class="katex-strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.1389em;">F</span><span class="mord mathnormal">Q</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="katex-base"><span class="katex-strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="mord text"><span class="mord">round</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1076em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1389em;">QP</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0359em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span></span></span></span></span><p>通过量化除法，那些数值微小、人眼又根本注意不到的高频系数，直接被除成了数字 0，从而安全剔除了视觉冗余，只保留核心的低频轮廓。QP 值越大除数越大，被置零的高频越多，体积越小但细节损失越大；QP 值越小保留细节越多但体积越大。</p><h3 id="4-5-消除编码冗余-熵编码"><a href="#4-5-消除编码冗余-熵编码" class="headerlink" title="4.5 消除编码冗余 熵编码"></a>4.5 消除编码冗余 熵编码</h3><p>经过量化后，残差矩阵变成了由极少数非零系数和大量 0 组成的稀疏矩阵。此时已经来到了比特级的最底层处理。</p><p>编码器先通过 ZigZag（之字形）扫描，把二维矩阵拉成一条一维数组。由于高频系数都在右下角且大多已被量化为 0，扫描后数组末尾会聚集大量连续的 0。</p><p>最后一步是对这条数组进行无损的熵编码：</p><ul><li>CAVLC（基于上下文的自适应可变长编码）：运算量小，所有设备均能支持。量化扫描后数组里绝大部分都是 0，CAVLC 的思路是不去硬存长串的 0，而是只抓几个关键特征查表压缩：<ul><li>TotalCoeffs：一共有几个非零数字。</li><li>TrailingOnes：末尾连着几个 ±1。</li><li>TotalZeros：所有非零数字前面一共夹了几个 0。</li><li>RunBefore：每个非零数字紧前面挨着几个 0。</li><li>自适应变量 nC：根据左边和上方邻居的情况动态换表，越常用的特征分配越短的码。<br>更细节的内容请参考<a href="https://cloud.tencent.com/developer/article/1612331?from=article.detail.1612330" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>编码原理（五）–熵编码–CAVLC</a>。</li></ul></li><li>CABAC（基于上下文的自适应二进制算术编码）：压缩效率更高，通常能比 CAVLC 再多压出 10%~15% 的空间，但计算量更大，常见于主流和高清档次。更细节的内容可以查看：<a href="https://lazybing.github.io/blog/2017/09/12/video-coding/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://lazybing.github.io/blog/2017/09/12/video-coding/</a></li></ul><h2 id="五、本地存储与网络传输"><a href="#五、本地存储与网络传输" class="headerlink" title="五、本地存储与网络传输"></a>五、本地存储与网络传输</h2><p>在压缩算法完成后，得到的是纯粹的数学数据。如何将这些数据标准化地包装起来，用于网络推流或写入文件？</p><h3 id="5-1-解耦算法与网络-VCL与NAL分层"><a href="#5-1-解耦算法与网络-VCL与NAL分层" class="headerlink" title="5.1 解耦算法与网络 VCL与NAL分层"></a>5.1 解耦算法与网络 VCL与NAL分层</h3><p>H264 在架构上清晰解耦为两层：</p><div class="markmap-wrap" style="height: 280px">      <script type="application/json">{"content":"H264","children":[{"content":"&#x7f51;&#x7edc;&#x63d0;&#x53d6;&#x5c42; NAL (I&#x3001;P&#x3001;B &#x6bcf;&#x4e00;&#x5e27;&#x5c31;&#x662f;&#x4e00;&#x5f20;&#x56fe;&#x7247;)","children":[{"content":"SPS(NALU): &#x5e8f;&#x5217;&#x53c2;&#x6570;&#x96c6;&#xff08;&#x4f5c;&#x7528;&#x4e8e;&#x4e00;&#x7cfb;&#x5217;&#x8fde;&#x7eed;&#x7f16;&#x7801;&#x56fe;&#x50cf;&#xff09;","children":[],"payload":{"tag":"li","lines":"6,7"}},{"content":"PPS(NALU): &#x56fe;&#x50cf;&#x53c2;&#x6570;&#x96c6;&#xff08;&#x4f5c;&#x7528;&#x4e8e;&#x7f16;&#x7801;&#x89c6;&#x9891;&#x5e8f;&#x5217;&#x4e2d;&#x4e00;&#x4e2a;&#x6216;&#x591a;&#x4e2a;&#x56fe;&#x50cf;&#xff09;","children":[],"payload":{"tag":"li","lines":"7,8"}},{"content":"I frame(NALU): 2 &#x79cd;&#x7c7b;&#x578b; I &#x5e27;&#xff0c;I / IDR&#xff08;&#x5373;&#x65f6;&#x89e3;&#x7801;&#x5237;&#x65b0;&#xff09;","children":[],"payload":{"tag":"li","lines":"8,9"}},{"content":"P frame(NALU)","children":[],"payload":{"tag":"li","lines":"9,10"}},{"content":"B frame(NALU)","children":[],"payload":{"tag":"li","lines":"10,11"}}],"payload":{"tag":"h2","lines":"5,6"}},{"content":"&#x89c6;&#x8baf;&#x7f16;&#x7801;&#x5c42; VCL","children":[],"payload":{"tag":"h2","lines":"11,12"}}],"payload":{"tag":"h1","lines":"4,5"}}</script>      <script type="application/json">{"colorFreezeLevel":2}</script>    </div><ul><li>VCL（Video Coding Layer，视频编码层）：负责前文讲述的所有核心压缩运算，只关注数学算法，输出未经封装的原始二进制数据。</li><li>NAL（Network Abstraction Layer，网络抽象层）：负责把 VCL 算出来的数据打包封装成统一格式的包裹（NALU），屏蔽底层网络介质的差异，适配不同的网络协议或文件容器。</li></ul><p>为了抗丢包，一帧图像通常不会打成一个死板的大包，而是被切分成一个或多个片（Slice）。每个 Slice 独立包含片头和片数据，各自封装成一个 NALU 单元发送：</p><div class="markmap-wrap" style="height: 360px">      <script type="application/json">{"content":"&#x4e00;&#x5e27;&#x56fe;","children":[{"content":"&#x5207;&#x7247; 1","children":[{"content":"&#x5207;&#x7247;&#x5934; + &#x5207;&#x7247;&#x6570;&#x636e;","children":[{"content":"&#x5b8f;&#x5757;","children":[{"content":"&#x5b8f;&#x5757;&#x7c7b;&#x578b;","children":[],"payload":{"tag":"li","lines":"8,9"}},{"content":"&#x9884;&#x6d4b;&#x7c7b;&#x578b;","children":[],"payload":{"tag":"li","lines":"9,10"}},{"content":"CBP","children":[],"payload":{"tag":"li","lines":"10,11"}},{"content":"QP","children":[],"payload":{"tag":"li","lines":"11,12"}},{"content":"&#x5b8f;&#x5757;&#x6570;&#x636e;","children":[{"content":"Y(16*16) &#x4eae;&#x5ea6;","children":[],"payload":{"tag":"li","lines":"13,14"}},{"content":"CB(8*8) &#x989c;&#x8272;","children":[],"payload":{"tag":"li","lines":"14,15"}},{"content":"CR(8*8) &#x989c;&#x8272;","children":[],"payload":{"tag":"li","lines":"15,16"}}],"payload":{"tag":"li","lines":"12,16"}}],"payload":{"tag":"li","lines":"7,16"}},{"content":"&#x5b8f;&#x5757;","children":[],"payload":{"tag":"li","lines":"16,17"}},{"content":"...","children":[],"payload":{"tag":"li","lines":"17,18"}}],"payload":{"tag":"h3","lines":"6,7"}}],"payload":{"tag":"h2","lines":"5,6"}},{"content":"&#x5207;&#x7247; 2","children":[],"payload":{"tag":"h2","lines":"18,19"}},{"content":"...","children":[],"payload":{"tag":"h2","lines":"19,20"}}],"payload":{"tag":"h1","lines":"4,5"}}</script>      <script type="application/json">{"colorFreezeLevel":3}</script>    </div><p><img src="https://image.skyforever.top/blog/2026/09/003d26e2124f169ded1135b5da379965.webp" alt="NAL层到宏块层的句法结构全景"><br><em>NAL层到宏块层的句法结构全景</em></p><p><img src="https://image.skyforever.top/blog/2026/09/157add20ea9f12eefdd612f2a46c430c.webp" alt="H264码流分层结构体系"><br><em>H264码流分层结构体系</em></p><h3 id="5-2-组装传输包裹-NALU打包结构"><a href="#5-2-组装传输包裹-NALU打包结构" class="headerlink" title="5.2 组装传输包裹 NALU打包结构"></a>5.2 组装传输包裹 NALU打包结构</h3><p>从底层计算数据到网络传输单元，需要经过一次流水线包装：</p><p><img src="https://image.skyforever.top/blog/2026/09/f6987d3f2347286f94fc7c20cf7232e1.webp" alt="SODB到NALU及字节流转换关系"><br><em>SODB到NALU及字节流转换关系</em></p><ol><li>SODB（String of Data Bits）：算法算出来的原始比特流，像散装散沙，只记录有效数据，位数不一定能凑齐整字节。</li><li>RBSP（Raw Byte Sequence Payload）：在尾部加上补齐位强行凑成整字节，相当于把散沙装进标准规格的箱子里。</li><li>NALU（NAL Unit）：在箱子外面贴上一个 1 字节的标签头（NAL Header），标明这箱装的是什么，装箱完毕即可用于传输。</li></ol><p>经过这三个步骤，即可讲视频编码层里的数据打包为可以方便网络传输的数据</p><figure class="highlight text"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">RBSP = SODB + 结尾字节对齐比特</span><br><span class="line">NALU = 1 字节 NAL Header + RBSP</span><br><span class="line">H264 码流 = 分隔标识 + NALU + 分隔标识 + NALU + ...</span><br></pre></td></tr></tbody></table></figure><p><img src="https://image.skyforever.top/blog/2026/09/2c856b63e59b4a38955d2922fd2f4abd.webp" alt="码流中起始码与NALU排布关系"><br><em>码流中起始码与NALU排布关系</em></p><p><img src="https://image.skyforever.top/blog/2026/09/ac7d91dfd6bbce27ba59bed0733a0e43.webp" alt="NALU头部与RBSP负载排布示意"><br><em>NALU头部与RBSP负载排布示意</em></p><p>NAL Header 包含 1 字节信息，其末尾 5 个 bit 决定了当前 NALU 的具体类型：</p><p><img src="https://image.skyforever.top/blog/2026/09/29869975bb7fd05798e959a4c9f1f25e.webp" alt="NALU头部类型定义表"><br><em>NALU头部类型定义表</em></p><p>开发中最常见的 NALU 类型包括：</p><ul><li>Type 1：非 IDR 图像的片（如普通的 P 帧、B 帧数据）。</li><li>Type 5：IDR 图像的片（关键帧数据）。</li><li>Type 7（SPS，序列参数集）：整部视频的总说明书，记录分辨率、帧率、Profile 等全局关键参数。</li><li>Type 8（PPS，图像参数集）：分章节说明书，记录局部画面所用的熵编码类型、初始量化参数等。</li></ul><p>解码端要正常播放视频，必须先拿到 SPS 和 PPS 说明书。解码器只有读懂了这些参数，才知道该开辟多大的内存、用什么规则去解后面的图像片，否则拿到了画面数据也无法还原。</p><h3 id="5-3-适配网络与本地存储-码流封包格式"><a href="#5-3-适配网络与本地存储-码流封包格式" class="headerlink" title="5.3 适配网络与本地存储 码流封包格式"></a>5.3 适配网络与本地存储 码流封包格式</h3><p>NALU 只是一个个独立的数据包裹，怎么把它们连续组合成一段完整的数据流？工程上有两种主流方案：</p><ul><li>Annex B 格式NALU 本身没有记录自己的长度。为了让接收端知道前一个包裹何时结束、下一个包裹何时开始，Annex B 在每个 NALU 前面硬塞一个起始码（<code>0x000001</code> 或 <code>0x00000001</code>）作为分界线。起始码就像每个包裹之间的分隔标志。但万一包裹里的正文数据碰巧也算出了 <code>00 00 01</code>，解码器就会看走眼，以为包裹提前结束了。为了防止误判，编码器在打包时凡是遇到 <code>00 00 00</code> 到 <code>00 00 03</code> 这类特征序列，就会在中间强行塞入一个 <code>0x03</code> 字节破坏特征（防竞争机制）；解码器收到后再把塞进去的 <code>03</code> 拔掉扔掉，恢复原始数据。Annex B 格式支持从任意关键帧位置切入解码，非常适合 RTSP/RTMP 实时直播推流以及 <code>.h264</code> 裸流文件。</li><li>AVCC 格式<br>不使用起始码和防竞争字节，而是在每个 NALU 前面直接固定用 4 个字节记录当前 NALU 的实际长度。SPS 和 PPS 参数集通常集中存放在外层文件头部。这种格式解析速度快且没有防竞争开销，主要用于 MP4、MKV、FLV 等本地封装容器。</li></ul><h2 id="参考引用"><a href="#参考引用" class="headerlink" title="参考引用"></a>参考引用</h2><ul><li>[1] <a href="https://blog.csdn.net/LuohenYJ/article/details/84957101" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>YUV图像处理入门1</a></li><li>[2] <a href="https://blog.51cto.com/u_15375308/4010325" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>H264编码(帧内预测)</a></li><li>[3] <a href="https://www.cnblogs.com/Lxk0825/p/9927757.html" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>H.264编码profile &amp; level控制</a></li><li>[4] <a href="https://blog.csdn.net/wuqingsen1/article/details/118030223" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>帧内压缩与帧间压缩</a></li><li>[5] <a href="https://www.cnblogs.com/Lxk0825/p/9925064.html" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>H.264分层结构与码流结构</a></li><li>[6] <a href="https://blog.csdn.net/Liu1314you/article/details/77185215" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>H.264中普通I帧和IDR帧究竟有什么区别</a></li><li>[7] <a href="https://www.cnblogs.com/AndyJee/p/3724917.html" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>运动补偿与运动估计</a></li><li>[8] <a href="http://www.elkpi.com/topics/2016/04/color-formats-equasys-gmbh.html" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>Color Formats – equasys GmbH</a></li><li>[9] <a href="http://blog.gitdns.org/2017/03/14/h264/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>h264</a></li><li>[10] <a href="https://yumichan.net/video-processing/video-compression/introduction-to-h264-2-sodb-vs-rbsp-vs-ebsp/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>Introduction to H.264: (2) SODB vs RBSP vs EBSP</a></li><li>[11] <a href="https://www.cnblogs.com/Lxk0825/p/9925041.html" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>H.264基本原理与编码流程</a></li><li>[12] <a href="https://blog.51cto.com/u_15077549/3366546" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>【知识点】H264, H265硬件编解码基础及码流分析</a></li><li>[13] <a href="https://pjchender.dev/webdev/webrtc-media-basic/#%E4%BB%80%E9%BA%BC%E6%98%AF%E7%B7%A8%E8%A7%A3%E7%A2%BC%E5%99%A8" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>影音傳輸-基礎知識_GOP/视频基础</a></li><li>[14] <a href="https://blog.51cto.com/u_15375308/5073333" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>深入讲解音视频编码原理，H264码流详解——手写H264编码器</a></li><li>[15] <a href="https://cloud.tencent.com/developer/article/1612330" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>编码原理（四）—ZIGZAG扫描</a></li><li>[16] <a href="https://blog.csdn.net/qq_42139383/article/details/118334630" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>一文搞懂H264量化原理以及计算过程</a></li><li>[17] <a href="https://www.erenship.com/posts/1db7.html" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>音视频笔记｜H264 基础原理介绍</a></li></ul><link rel="stylesheet" href="https://cdn.jsdmirror.com/npm/markmap-toolbar@0.18.10/dist/style.css"><script data-stellar-script="markmap" src="https://cdn.jsdmirror.com/npm/d3@7"></script><script data-stellar-script="markmap" src="https://cdn.jsdmirror.com/npm/markmap-view@0.18.10"></script><script data-stellar-script="markmap" src="https://cdn.jsdmirror.com/npm/markmap-toolbar@0.18.10"></script><link rel="stylesheet" href="/css/markmap.css"><script data-stellar-script="markmap" src="/js/markmap.js"></script>]]>
    </content>
    <id>https://blog.skyforever.top/posts/7607</id>
    <link href="https://blog.skyforever.top/posts/7607"/>
    <published>2026-09-15T15:18:00.000Z</published>
    <summary>从视频压缩冗余消除出发，全景解析 H.264 核心编解码原理。涵盖 I/P/B 帧与 GOP 刷新机制、YUV 色彩采样、宏块切分、帧内/帧间预测与运动补偿、DCT 变换与量化、CAVLC/CABAC 熵编码，以及 VCL 与 NALU 码流分层架构。</summary>
    <title>音视频笔记｜H264 基础原理介绍</title>
    <updated>2026-09-15T15:18:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="嵌入式开发" scheme="https://blog.skyforever.top/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/"/>
    <category term="OpenHarmony" scheme="https://blog.skyforever.top/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/OpenHarmony/"/>
    <category term="VSCode" scheme="https://blog.skyforever.top/tags/VSCode/"/>
    <category term="OpenHarmony" scheme="https://blog.skyforever.top/tags/OpenHarmony/"/>
    <category term="嵌入式开发" scheme="https://blog.skyforever.top/tags/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/"/>
    <category term="C/C++" scheme="https://blog.skyforever.top/tags/C-C/"/>
    <category term="Clangd" scheme="https://blog.skyforever.top/tags/Clangd/"/>
    <content>
      <![CDATA[<p>用 VS Code 写 OpenHarmony 代码时，经常会遇到智能提示极慢，比如跳转函数定义和实现要卡很久。</p><p>在中文互联网上基本搜不到直接的解答，参考<a href="https://kashima19960.github.io/2025/03/21/openharmony/%E8%A7%A3%E5%86%B3%E7%94%A8vscode%E7%BC%96%E5%86%99openharmony%E4%BB%A3%E7%A0%81%E6%97%B6%EF%BC%8C%E8%B7%B3%E8%BD%AC%E5%87%BD%E6%95%B0%E5%AE%9A%E4%B9%89%E5%92%8C%E5%AE%9E%E7%8E%B0%E6%97%B6%E9%97%B4%E8%BF%87%E9%95%BF/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>社区文章</a>以及 GitHub 和 Reddit 上的讨论，终于找到了根本原因和解决方案。</p><p>相关讨论链接：</p><ul><li><a href="https://www.reddit.com/r/vscode/comments/l5hz4i/c_intellisense_and_parsing_super_slow/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>C++ 智能感知和解析超级慢：r/vscode</a></li><li><a href="https://github.com/microsoft/vscode-cpptools/issues/12169" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>大工程中 C/C++ 智能感知极慢：Issue #12169 · microsoft/vscode-cpptools</a></li></ul><hr><h2 id="为什么会卡"><a href="#为什么会卡" class="headerlink" title="为什么会卡"></a>为什么会卡</h2><p>其实就是微软官方的 C/C++ 扩展在大型工程下的索引机制问题：</p><p><img src="https://image.skyforever.top/blog/2026/08/bbd2ae5ac4f17dd901bf599b97b4386e.png" alt="微软官方 C/C++ 扩展插件"></p><p>这个插件每次打开工程都会自动递归扫描所有头文件路径来建索引。对于小项目很方便，但 OpenHarmony 源码超过 20GB、包含几十万个文件，全量扫描会直接把磁盘 I/O 和 CPU 吃满，导致跳转时卡死。</p><hr><h2 id="第一步：生成编译数据库"><a href="#第一步：生成编译数据库" class="headerlink" title="第一步：生成编译数据库"></a>第一步：生成编译数据库</h2><p>解决卡顿的核心，就是给开发工具提供一个精准的 <code>compile_commands.json</code>（编译数据库）。</p><blockquote><p><strong>什么是 <code>compile_commands.json</code>？</strong></p><p>它记录了工程里每个源文件真实的编译命令、宏定义和头文件包含路径。有了它，插件直接按真实指令分析代码，不需要再无脑扫描整个 20GB 的源码目录。</p></blockquote><p>它长这样：</p><figure class="highlight json"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">[</span></span><br><span class="line">  <span class="punctuation">{</span></span><br><span class="line">    <span class="attr">"directory"</span><span class="punctuation">:</span> <span class="string">"/home/xxx/workspace/OpenHarmony-v3.1-Release/out/hispark_pegasus/wifiiot_hispark_pegasus"</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">"command"</span><span class="punctuation">:</span> <span class="string">"ccache riscv32-unknown-elf-gcc -D_XOPEN_SOURCE=700 -DOHOS_DEBUG -D__LITEOS__ -D__LITEOS_M__ -I../../../applications/sample/wifi-iot/app/loc_info_collector/gpsM_uart -I../../../kernel/liteos_m/components/cmsis/2.0 -c ../../../applications/sample/wifi-iot/app/loc_info_collector/mqtt/wb_ram.c -o obj/applications/sample/wifi-iot/app/loc_info_collector/mqtt/libmain_process.wb_ram.o"</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">"file"</span><span class="punctuation">:</span> <span class="string">"../../../applications/sample/wifi-iot/app/loc_info_collector/mqtt/wb_ram.c"</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">"output"</span><span class="punctuation">:</span> <span class="string">"obj/applications/sample/wifi-iot/app/loc_info_collector/mqtt/libmain_process.wb_ram.o"</span></span><br><span class="line">  <span class="punctuation">}</span></span><br><span class="line"><span class="punctuation">]</span></span><br></pre></td></tr></tbody></table></figure><h3 id="生成步骤"><a href="#生成步骤" class="headerlink" title="生成步骤"></a>生成步骤</h3><ol><li>进入 <code>build.ninja</code> 所在的目标构建目录：<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> out/hispark_pegasus/wifiiot_hispark_pegasus/</span><br></pre></td></tr></tbody></table></figure></li></ol><p><img src="https://image.skyforever.top/blog/2026/08/a7ed34cac5822d30a605050bc2abd8d5.png" alt="Ninja 构建文件所在目录"></p><ol start="2"><li><p>通过 ninja 的 <code>compdb</code> 工具导出编译数据库：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ninja -C ./ -t compdb cxx cc &gt; compile_commands.json</span><br></pre></td></tr></tbody></table></figure><blockquote><p>注：该命令本质上是将 <code>ninja -C ./ -t compdb cxx cc</code> 导出的编译信息重定向到 <code>compile_commands.json</code> 文件中。</p></blockquote></li><li><p>将生成的 <code>compile_commands.json</code> 移动到 OpenHarmony 源码根目录下：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mv</span> ./compile_commands.json ../../../</span><br></pre></td></tr></tbody></table></figure></li><li><p>编写自动化一键脚本（可选）：<br>在修改 OpenHarmony 模块结构或增删源文件时，<code>compile_commands.json</code> 需要重新生成。可将上述步骤封装为 Bash 脚本：</p></li></ol><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line">workspace=~/workspace/OpenHarmony-v3.1-Release/</span><br><span class="line">build_dir=<span class="variable">$workspace</span>/out/hispark_pegasus/wifiiot_hispark_pegasus/</span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> <span class="variable">$build_dir</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 1. 导出编译数据库</span></span><br><span class="line">ninja -C <span class="variable">$build_dir</span> -t compdb cxx cc &gt; compile_commands.json</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 移动到源码根目录</span></span><br><span class="line"><span class="built_in">mv</span> compile_commands.json <span class="variable">$workspace</span></span><br></pre></td></tr></tbody></table></figure><hr><h2 id="方案一：继续使用微软官方插件"><a href="#方案一：继续使用微软官方插件" class="headerlink" title="方案一：继续使用微软官方插件"></a>方案一：继续使用微软官方插件</h2><p>如果不想换插件，可以直接配置 <code>.vscode/c_cpp_properties.json</code>，让它读取编译数据库，不再自己扫描头文件：</p><figure class="highlight json"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line">  <span class="attr">"configurations"</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="punctuation">{</span></span><br><span class="line">      <span class="attr">"name"</span><span class="punctuation">:</span> <span class="string">"OpenHarmony"</span><span class="punctuation">,</span></span><br><span class="line">      <span class="comment">// 指定编译数据库路径，避免全局递归扫描</span></span><br><span class="line">      <span class="attr">"compileCommands"</span><span class="punctuation">:</span> <span class="string">"${workspaceFolder}/compile_commands.json"</span></span><br><span class="line">    <span class="punctuation">}</span></span><br><span class="line">  <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">"version"</span><span class="punctuation">:</span> <span class="number">4</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></tbody></table></figure><p>配置后插件直接通过编译数据库找头文件和宏定义，不会再在后台狂扫 20GB 源码，跳转速度会明显提升。</p><hr><h2 id="方案二：切换到-Clangd"><a href="#方案二：切换到-Clangd" class="headerlink" title="方案二：切换到 Clangd"></a>方案二：切换到 Clangd</h2><p>想要更极致的秒级跳转和更低的内存占用，推荐切换到 Clangd。</p><h3 id="1-本地安装后端"><a href="#1-本地安装后端" class="headerlink" title="1. 本地安装后端"></a>1. 本地安装后端</h3><p>VS Code 的 <code>clangd</code> 插件只是客户端，电脑本地需要先安装好后端程序：</p><ul><li><strong>官方预编译安装包</strong>：前往 <a href="https://github.com/clangd/clangd/releases" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>Clangd Releases 页面</a> 下载对应系统的压缩包（解压后将 <code>bin/clangd</code> 路径加入系统环境变量 <code>PATH</code> 即可）。</li><li><strong>通过包管理器安装</strong>：<ul><li><strong>Ubuntu / Debian</strong>：<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 安装 clangd 服务端</span></span><br><span class="line">sudo apt update &amp;&amp; sudo apt install clangd</span><br></pre></td></tr></tbody></table></figure></li><li><strong>macOS</strong>：<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 使用 Homebrew 安装</span></span><br><span class="line">brew install llvm</span><br></pre></td></tr></tbody></table></figure></li><li><strong>Windows</strong>：<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 使用 winget 安装，或者直接下载官方 zip 解压</span></span><br><span class="line">winget install LLVM.LLVM</span><br></pre></td></tr></tbody></table></figure></li></ul></li></ul><h3 id="2-插件搭配推荐"><a href="#2-插件搭配推荐" class="headerlink" title="2. 插件搭配推荐"></a>2. 插件搭配推荐</h3><p>Clangd 只负责代码分析，不带格式化和调试功能，建议按下面这套搭配：</p><ol><li><strong>clangd</strong>：负责代码补全、语法高亮和函数跳转。</li><li><strong>Clang-Format</strong>：负责代码格式化（style 可设为 <code>"WebKit"</code>）。</li><li><strong>CodeLLDB</strong>：负责 C/C++ 断点调试。</li></ol><p><img src="https://image.skyforever.top/blog/2026/08/973e5b6f3dc8c93b52cec38134aaf40d.png" alt="VS Code clangd 语言服务插件"></p><p><img src="https://image.skyforever.top/blog/2026/08/4b467a4983d7e54a5d64fb29702aec92.png" alt="Clang-Format 代码格式化插件"></p><h3 id="3-过滤-GCC-专有参数"><a href="#3-过滤-GCC-专有参数" class="headerlink" title="3. 过滤 GCC 专有参数"></a>3. 过滤 GCC 专有参数</h3><p>OpenHarmony 的编译命令里有一些 GCC/RISC-V 专用参数，Clangd 可能会报无法识别的警告。有两种解决方式：</p><h4 id="方式-A：使用-clangd-配置文件"><a href="#方式-A：使用-clangd-配置文件" class="headerlink" title="方式 A：使用 .clangd 配置文件"></a>方式 A：使用 .clangd 配置文件</h4><p>在 OpenHarmony 源码根目录下创建 <code>.clangd</code> 配置文件，clangd 会在索引时自动过滤这些不支持的参数：</p><figure class="highlight yaml"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 在工程根目录下创建 .clangd</span></span><br><span class="line"><span class="attr">CompileFlags:</span></span><br><span class="line">  <span class="comment"># 过滤 Clangd 无法识别的 GCC / RISC-V 专有编译选项</span></span><br><span class="line">  <span class="attr">Remove:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">-fno-optimize-strlen</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">-freorder-blocks-algorithm=simple</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">-mno-small-data-limit=0</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">-fno-aggressive-loop-optimizations</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">-msave-restore</span></span><br></pre></td></tr></tbody></table></figure><h4 id="方式-B：脚本清洗"><a href="#方式-B：脚本清洗" class="headerlink" title="方式 B：脚本清洗"></a>方式 B：脚本清洗</h4><p>也可以在导出 <code>compile_commands.json</code> 文件时用 <code>sed</code> 顺手把不兼容参数删掉：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line">workspace=~/workspace/OpenHarmony-v3.1-Release/</span><br><span class="line">build_dir=<span class="variable">$workspace</span>/out/hispark_pegasus/wifiiot_hispark_pegasus/</span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> <span class="variable">$build_dir</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 1. 导出编译数据库</span></span><br><span class="line">ninja -C <span class="variable">$build_dir</span> -t compdb cxx cc &gt; compile_commands.json</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 清洗 GCC 专有参数</span></span><br><span class="line">sed -i <span class="string">'s/-fno-optimize-strlen//g'</span> compile_commands.json</span><br><span class="line">sed -i <span class="string">'s/-freorder-blocks-algorithm=simple//g'</span> compile_commands.json</span><br><span class="line">sed -i <span class="string">'s/-mno-small-data-limit=0//g'</span> compile_commands.json</span><br><span class="line">sed -i <span class="string">'s/-fno-aggressive-loop-optimizations//g'</span> compile_commands.json</span><br><span class="line">sed -i <span class="string">'s/  / /g'</span> compile_commands.json</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 移动到工程根目录</span></span><br><span class="line"><span class="built_in">mv</span> compile_commands.json <span class="variable">$workspace</span></span><br></pre></td></tr></tbody></table></figure><h3 id="4-检查生效"><a href="#4-检查生效" class="headerlink" title="4. 检查生效"></a>4. 检查生效</h3><p>打开 VS Code，看底部状态栏的 <code>clangd: idle</code>，只要在转圈说明正在建索引。如果没反应，按 <code>Ctrl + Shift + P</code> 执行 <code>clangd: Restart language server</code> 重启即可。</p><p><img src="https://image.skyforever.top/blog/2026/08/6f0bd9812174568abbb79bf44587ccc3.png" alt="VS Code 底部状态栏 clangd 运行状态"></p>]]>
    </content>
    <id>https://blog.skyforever.top/posts/43921</id>
    <link href="https://blog.skyforever.top/posts/43921"/>
    <published>2026-07-21T12:12:00.000Z</published>
    <summary>解决用 VS Code 编写 OpenHarmony 代码时函数跳转慢的问题，详解 compile_commands.json 编译数据库生成与 Clangd 配置方法。</summary>
    <title>解决 VS Code 开发 OpenHarmony 代码跳转慢的问题</title>
    <updated>2026-07-21T12:12:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="安全工具" scheme="https://blog.skyforever.top/categories/%E5%AE%89%E5%85%A8%E5%B7%A5%E5%85%B7/"/>
    <category term="Python" scheme="https://blog.skyforever.top/categories/%E5%AE%89%E5%85%A8%E5%B7%A5%E5%85%B7/Python/"/>
    <category term="GitHub" scheme="https://blog.skyforever.top/tags/GitHub/"/>
    <category term="Python" scheme="https://blog.skyforever.top/tags/Python/"/>
    <category term="OSINT" scheme="https://blog.skyforever.top/tags/OSINT/"/>
    <category term="信息收集" scheme="https://blog.skyforever.top/tags/%E4%BF%A1%E6%81%AF%E6%94%B6%E9%9B%86/"/>
    <category term="安全工具" scheme="https://blog.skyforever.top/tags/%E5%AE%89%E5%85%A8%E5%B7%A5%E5%85%B7/"/>
    <category term="GhostTrack" scheme="https://blog.skyforever.top/tags/GhostTrack/"/>
    <content>
      <![CDATA[<p>这个开源项目，你丢一个名字/手机号/IP给它，就可以得到关联的社交媒体账号、归属地、地理位置信息。</p><p>在 GitHub 已获取 13.3k star。 项目地址 <a href="https://github.com/HunxByts/GhostTrack" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://github.com/HunxByts/GhostTrack</a></p><p>仅仅一个 Python 脚本，用来做 IP / 手机号 / 用户名的基础 OSINT 信息收集。</p><p>三个模块，覆盖常见情报场景：</p><ul><li><p>IP Tracker：输入目标 IP，可获取基础地理位置信息，也可以结合 Seeker 等工具做进一步关联分析（例如辅助反查真实 IP）</p></li><li><p>Phone Tracker：手机号归属地、运营商信息查询，属于 OSINT 中很常见的基础能力 </p></li><li><p>Username Tracker：输入用户名，跨多个平台搜索公开账号信息，把分散的社交媒体痕迹拼接起来</p></li></ul><p>这个脚本适合做渗透测试前期信息收集的安全工程师，学习 OSINT 方法论的安全方向学生， CTF 比赛中需要快速做信息侦察的选手，对信息安全和数据关联分析感兴趣的开发者</p><p>注意：该工具仅用于合法授权的安全研究与学习用途，禁止用于任何未经授权的个人追踪或隐私侵犯行为。</p>]]>
    </content>
    <id>https://blog.skyforever.top/posts/37648</id>
    <link href="https://blog.skyforever.top/posts/37648"/>
    <published>2026-05-26T14:45:23.000Z</published>
    <summary>介绍 GhostTrack，一个开源的 Python OSINT 信息收集脚本。支持 IP 地理位置追踪、手机号归属地查询、跨平台用户名搜索三大模块。</summary>
    <title>一个信息追踪 Python 脚本</title>
    <updated>2026-05-26T14:45:23.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="嵌入式" scheme="https://blog.skyforever.top/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F/"/>
    <category term="AI编程" scheme="https://blog.skyforever.top/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F/AI%E7%BC%96%E7%A8%8B/"/>
    <category term="嵌入式" scheme="https://blog.skyforever.top/tags/%E5%B5%8C%E5%85%A5%E5%BC%8F/"/>
    <category term="AI编程" scheme="https://blog.skyforever.top/tags/AI%E7%BC%96%E7%A8%8B/"/>
    <category term="Claude Code" scheme="https://blog.skyforever.top/tags/Claude-Code/"/>
    <category term="开发工具" scheme="https://blog.skyforever.top/tags/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/"/>
    <category term="PCB设计" scheme="https://blog.skyforever.top/tags/PCB%E8%AE%BE%E8%AE%A1/"/>
    <category term="物联网" scheme="https://blog.skyforever.top/tags/%E7%89%A9%E8%81%94%E7%BD%91/"/>
    <category term="MCU" scheme="https://blog.skyforever.top/tags/MCU/"/>
    <content>
      <![CDATA[<blockquote><p>如果你对大语言模型（LLM）、智能体（Agent）、上下文（Context）、RAG、MCP、Skill 等 AI 基础概念还不太清楚，建议先阅读前置概念解析文章：<a href="/posts/38247" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>解析各种AI概念</a>。理清这些技术名词背后的底层逻辑与工程本质，会让你更容易看懂本文的工具链架构。</p></blockquote><h2 id="1-AI-能给嵌入式开发带来什么"><a href="#1-AI-能给嵌入式开发带来什么" class="headerlink" title="1. AI 能给嵌入式开发带来什么"></a>1. AI 能给嵌入式开发带来什么</h2><p>做嵌入式开发的人，日常里有一大块时间花的不是”设计”，而是”操作”。</p><p>翻数据手册比对芯片参数、手动配编译链、等烧录、盯串口 log、反复试 PID 参数。这些事情不算难，但碎、耗时间、容易出错。一个变量溢出或者中断优先级搞反了，你可能要对bug找一下午。</p><p>AI 现在能把这些活接过去一部分。AI 不只是能写代码——而是你告诉它一个方向，它自己去编译、烧录、看 log、调参数，做完回来告诉你结果。你可以把精力放到系统架构和关键决策上，而不是被绑在”调一下、等三分钟、看一眼日志、再调一下”这种循环里。</p><p>2026 年的情况是：Agent 帮助 AI 调用 MCP 和读取 Skills，让 AI 直接操作硬件工具链。调 EDA 画板、ssh 上板子跑命令、GDB 分析崩溃现场。直接闭环完成一个目标，编译，运行，调试的步骤都可以交给 AI 来做。</p><p>只需要安装 Agent 工具并配置下面的这些工具，就可以让 AI 拥有闭环调试的能力。下面所有工具都是挂在 Agent 上用的，安装配置参考 <a href="/posts/52013" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>/posts/52013</a>。</p><h2 id="2-做方案和画板子"><a href="#2-做方案和画板子" class="headerlink" title="2. 做方案和画板子"></a>2. 做方案和画板子</h2><p><strong>NextBoard</strong></p><p><a href="https://github.com/LeoKemp223/NextBoard" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>LeoKemp223/NextBoard</a> 把硬件选型做成了一套 AI Agent 流水线。</p><p>你输入一个需求，例如”带 Wi-Fi 的温湿度采集器”，它自动做需求确认、芯片选型（给国产优先/混合折中/海外主流三套对比）、下载数据手册、算成本、出模块框图，最后还有独立评审 Agent 从成本和供应链风险角度打分。</p><p>安装：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 全局安装</span></span><br><span class="line">./scripts/install.sh --global --platform claude</span><br><span class="line"></span><br><span class="line"><span class="comment"># 或通过 marketplace</span></span><br><span class="line">claude plugin marketplace add LeoKemp223/NextBoard</span><br><span class="line">claude plugin install nextboard-hardware-solution</span><br></pre></td></tr></tbody></table></figure><p>装好后输入 <code>/hardware-solution</code> 即可启动该工作流。</p><p>但我得泼盆冷水。AI 做器件选型目前还不太靠谱。</p><p>推荐的芯片可能已经停产、价格虚高，或者根本没考虑你项目的实际情况，因为行情随时在变，需求随时在变，AI 无法直接考虑到这些（AI 的语料库只会在训练阶段更新）。更务实的做法是先去 <a href="https://oshwhub.com/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>立创开源平台</a> 搜类似方案，看看别人实际用了什么器件、布线怎么走的，心里有数之后再让 AI 帮你细化方案。现阶段做硬件选型还是人来做比较靠谱，AI 只能做辅助。</p><p><strong>嘉立创 EDA AI</strong></p><p>方案定了之后，落到原理图设计和 PCB 绘制上，可以用嘉立创官方最新推出的 Run API Gateway 扩展（详细教程可参考官方推文：<a href="https://mp.weixin.qq.com/s/GK3i3Q7fpCriDPQYoYmzgw" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>嘉立创EDA，能用AI了？！还能免费使用……</a>）。</p><p>该扩展为 AI 工具提供了完整的 WebSocket API 网关桥接，链路架构为：<br><code>Agent → easyeda-api Skill → Bridge Server (端口 49620-49629) → Run API Gateway 扩展 → 嘉立创EDA 专业版</code></p><p>它能调用嘉立创 EDA 绝大部分功能：根据你的自然语言指令调用元件库、生成电路模块、进行原理图修改与布局布线辅助。</p><h4 id="安装与配置步骤"><a href="#安装与配置步骤" class="headerlink" title="安装与配置步骤"></a>安装与配置步骤</h4><ol><li><p>EDA 侧安装扩展：<br>打开 <a href="https://pro.lceda.cn/editor" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>嘉立创EDA 专业版</a> → 顶部菜单【高级】→【扩展管理器】→ 搜索并安装 <a href="https://ext.lceda.cn/item/oshwhub/run-api-gateway" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>Run API Gateway</a>。安装后勾选「允许外部交互」与「显示在顶部菜单」，顶部出现 <code>API Gateway</code> 菜单。</p></li><li><p>安装 easyeda-api Skill：<br>在终端执行全局安装命令：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx clawhub@latest install easyeda-api --workdir <span class="string">"<span class="variable">$HOME</span>"</span> --<span class="built_in">dir</span> skills</span><br></pre></td></tr></tbody></table></figure><p>若网络受限或命令安装失败，可手动下载 <a href="https://image.lceda.cn/files/easyeda-api.zip" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>easyeda-api.zip</a>，解压到 <code>~/skills/easyeda-api/</code> 目录（确保 <code>SKILL.md</code> 位于该目录下，不要多层嵌套）。</p></li><li><p>AI 客户端准备：</p><ul><li>如果使用 Claude Code，确保配置中能读取全局 skills 目录；</li><li>如果使用 OpenCode，终端运行 <code>npm install -g opencode-ai</code> 安装，启动后输入 <code>/connect</code> 连接模型（支持绑定 API Key 或直接使用 OpenCode 免费模型）。</li></ul></li><li><p>一键启动连接：<br>在 AI 客户端（Claude Code 或 OpenCode）中直接输入：</p><figure class="highlight text"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">嘉立创EDA，启动！</span><br></pre></td></tr></tbody></table></figure><p>Skill 会自动启动本地 Bridge Server 并与 EDA 侧扩展完成握手验证。</p></li><li><p>验证与实战调用：<br>连接成功后，先发送只读验证指令：<code>请检查当前嘉立创EDA窗口是否连接成功，返回当前窗口状态</code>。链路通畅后，即可用自然语言下发具体硬件设计任务，例如：“生成 ESP32-C3 最小系统电路”、“给电源输入部分加上 ESD 保护电路”等。</p></li></ol><h2 id="3-编译、烧录、调试"><a href="#3-编译、烧录、调试" class="headerlink" title="3. 编译、烧录、调试"></a>3. 编译、烧录、调试</h2><p>嵌入式开发最烦人的不是写代码，是写完代码之后的事。编译调工具链，烧录配 OpenOCD 或 J-Link，调试开 GDB、接串口。每个操作单独看都不难，但换一个芯片平台就要重新学一遍。</p><p><a href="https://github.com/LeoKemp223/embed-ai-tool" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>LeoKemp223/embed-ai-tool</a> 干的事很简单：给 AI 装上操作这些工具链的能力。通过 23 个 Claude Code Skill，把原本割裂的开发环节串成一个自主闭环：</p><p><img src="https://image.skyforever.top/blog/2026/08/5d138155f054ff8700ad065b7dd31410.svg" alt="嵌入式开发 Agent 自主闭环"></p><p>整个工具链覆盖 5 大核心阶段：</p><ol><li>静态分析：代码规范检查与语法漏洞排查（cppcheck、clang-tidy、MISRA-C 规则集）</li><li>编译构建：自动识别工程类型并调用对应编译器（CMake、Keil、IAR、PlatformIO、ESP-IDF）</li><li>固件烧录：自动探测烧录器并写入固件（OpenOCD、J-Link、串口、Keil、PlatformIO、ESP-IDF）</li><li>在板调试：硬件在环断点排查与系统分析（GDB+OpenOCD、J-Link、FreeRTOS/RT-Thread/Zephyr 任务栈分析、ELF/map 内存解析）</li><li>外设与协议：实时交互与通信日志抓取（串口监控过滤、Modbus RTU/TCP、CAN 报文调试、SCPI 仪器联动）</li></ol><p><strong>这套能力最核心的价值在于“闭环”</strong>：AI 作为调度中枢，烧录完固件后会自动通过串口或 GDB 监控运行状态；一旦捕获到断点命中、内存越界、任务栈溢出或串口报错日志，会立即将信息回传给 AI 大脑，自动定位源码并重新修改，再次触发编译与验证，直到跑通。</p><p>安装：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 一键装全部</span></span><br><span class="line">npx skills add LeoKemp223/embed-ai-tool -g -y</span><br><span class="line"></span><br><span class="line"><span class="comment"># 或按需</span></span><br><span class="line">npx skills add LeoKemp223/embed-ai-tool --skill build-cmake --skill flash-openocd -g -y</span><br></pre></td></tr></tbody></table></figure><p>装完以后，日常开发只需下达宏观指令：</p><ul><li>“编译当前工程并烧录到板子”：AI 自己识别工程类型（Keil 的 <code>.uvprojx</code>、CMake 的 <code>CMakeLists.txt</code> 或 ESP-IDF），匹配工具链执行编译，检测烧录器并完成烧录；</li><li>“在 main.c 第 42 行设断点看 crc 值”：自动挂载 GDB 单步调试；</li><li>“打开串口监控，过滤 ERROR 行”：实时抓取异常日志；</li><li>“分析一下 FreeRTOS 任务栈，看看哪个任务溢出”：快速排查系统级死锁或越界。</li></ul><p>注意：它不帮你安装 Keil、IAR、gcc-arm-none-eabi 这些底层的物理编译器和驱动环境，这些环境依赖仍然需本地具备。它做的是充当你的自动化操作手，帮你省去频繁在各个软件间切换敲命令与手动排错的时间。</p><h2 id="4-针对-Linux-板子：让-AI-直接上板操作"><a href="#4-针对-Linux-板子：让-AI-直接上板操作" class="headerlink" title="4. 针对 Linux 板子：让 AI 直接上板操作"></a>4. 针对 Linux 板子：让 AI 直接上板操作</h2><p>embed-ai-tool 的调试能力侧重 MCU 侧（GDB + 串口 + RTOS），如果你的板子跑的是嵌入式 Linux，<a href="https://github.com/yolejee/bsp_board_mcp" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>yolejee/bsp_board_mcp</a> 更适合。</p><p>它是一个 MCP Server，让 Claude Code 通过 SSH、串口、ADB-USB、ADB-WiFi 直连 Linux 开发板。不需要你手动 ssh 上去复制粘贴。</p><p>安装：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> https://github.com/yolejee/bsp_board_mcp.git</span><br><span class="line"><span class="built_in">cd</span> bsp_board_mcp</span><br><span class="line">uv <span class="built_in">sync</span>    <span class="comment"># Windows 双击 setup.bat</span></span><br></pre></td></tr></tbody></table></figure><p>在项目根目录的 <code>.mcp.json</code> 中配置（SSH 为例）：</p><figure class="highlight json"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line">  <span class="attr">"mcpServers"</span><span class="punctuation">:</span> <span class="punctuation">{</span></span><br><span class="line">    <span class="attr">"linux-board-ssh"</span><span class="punctuation">:</span> <span class="punctuation">{</span></span><br><span class="line">      <span class="attr">"command"</span><span class="punctuation">:</span> <span class="string">"uv"</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">"args"</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="string">"--directory"</span><span class="punctuation">,</span> <span class="string">"/path/to/bsp_board_mcp"</span><span class="punctuation">,</span> <span class="string">"run"</span><span class="punctuation">,</span> <span class="string">"python"</span><span class="punctuation">,</span> <span class="string">"-m"</span><span class="punctuation">,</span> <span class="string">"linux_board_mcp"</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">"env"</span><span class="punctuation">:</span> <span class="punctuation">{</span></span><br><span class="line">        <span class="attr">"BOARD_TRANSPORT"</span><span class="punctuation">:</span> <span class="string">"ssh"</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">"BOARD_HOST"</span><span class="punctuation">:</span> <span class="string">"192.168.7.2"</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">"BOARD_USER"</span><span class="punctuation">:</span> <span class="string">"root"</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">"BOARD_KEY"</span><span class="punctuation">:</span> <span class="string">"/home/you/.ssh/board_rsa"</span></span><br><span class="line">      <span class="punctuation">}</span></span><br><span class="line">    <span class="punctuation">}</span></span><br><span class="line">  <span class="punctuation">}</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></tbody></table></figure><p>串口模式把 <code>BOARD_TRANSPORT</code> 改成 <code>serial</code>，填 <code>BOARD_SERIAL_PORT</code> 和波特率。ADB 模式改 <code>adb-usb</code>（填 <code>ADB_SERIAL</code>）或 <code>adb-wifi</code>（填 <code>ADB_WIFI_HOST</code>）。</p><p>配好之后直接对 Claude 说：”看看板子内存情况”、”查这个 GPIO 中断触发次数”、”加载 ko 驱动，看 dmesg 有没有报错”。只读操作（read_dmesg、read_sysfs、read_proc、run_shell 等）不需要每次确认，破坏性操作（install_module、write_sysfs、reboot_board）需要批准。</p><p>embed-ai-tool 的调试面向 MCU/RTOS/裸机场景，bsp_board_mcp 面向 Linux 板子。两者不互斥，你的项目该用哪个取决于板子上跑的是什么。</p><h2 id="5-闭环调参：让-AI-自己试，试对为止"><a href="#5-闭环调参：让-AI-自己试，试对为止" class="headerlink" title="5. 闭环调参：让 AI 自己试，试对为止"></a>5. 闭环调参：让 AI 自己试，试对为止</h2><p>有些任务不是”查个 log”就能解决的。PID 调参是典型——参数对不对，要跑起来看才知道。会调的人十几分钟搞定，不熟的可能耗一天。</p><p><a href="https://github.com/KINGSTON-115/llm-pid-tuner" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>KINGSTON-115/llm-pid-tuner</a> 让 LLM 自己闭环迭代。你告诉它”响应要快，但别超调”，它自己跑、自己看效果、自己调参数。</p><p>安装：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Windows：从 https://github.com/KINGSTON-115/llm-pid-tuner/releases/latest 下载 exe</span></span><br><span class="line"><span class="comment"># 源码：</span></span><br><span class="line">git <span class="built_in">clone</span> -b dev https://github.com/KINGSTON-115/llm-pid-tuner.git</span><br><span class="line"><span class="built_in">cd</span> llm-pid-tuner &amp;&amp; pip install -r requirements.txt</span><br></pre></td></tr></tbody></table></figure><p>连接方式：单片机通过串口跑 <code>firmware.cpp</code>，持续上报 CSV 格式的控制数据（时间戳、设定值、输入、PWM、误差、P/I/D 分量）。上位机读串口，调 LLM API 分析响应质量，生成新参数写回单片机。</p><p>LLM 配置（<code>config.json</code>），国内中转站用 <code>openai_claude</code> 协议：</p><figure class="highlight json"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line">  <span class="attr">"LLM_PROVIDER"</span><span class="punctuation">:</span> <span class="string">"openai_claude"</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">"LLM_API_BASE_URL"</span><span class="punctuation">:</span> <span class="string">"https://你的中转站/v1"</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">"LLM_MODEL_NAME"</span><span class="punctuation">:</span> <span class="string">"claude-sonnet-4-6"</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">"LLM_API_KEY"</span><span class="punctuation">:</span> <span class="string">"sk-xxx"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></tbody></table></figure><p>工作流：采数据 → LLM 分析（超调、稳态误差）→ 给新 P/I/D → 写入执行 → 观察。<br>变差了自动回退到历史最佳，连续几轮满足阈值自动停。</p><p>这和以前手动调参的区别在于：你只需要告诉它方向，AI 自己去闭环到收敛。</p><h2 id="6-板子没有现成工具怎么办"><a href="#6-板子没有现成工具怎么办" class="headerlink" title="6. 板子没有现成工具怎么办"></a>6. 板子没有现成工具怎么办</h2><p>上面这些工具覆盖的场景——STM32/ESP32、Linux 板子、PID 控制器——都有比较成熟的开发生态。<br>但做嵌入式的都知道，大量国产 MCU 开发生态不完善。</p><p>海思 Hi3863 就是这种情况。LiteOS 的编译和烧录是用脚本控制的。</p><p>我的做法是自己给 AI 写工具。</p><p>用 <a href="/posts/49583" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>Hi3863 LiteOS OTA 如何实现</a> 这个博客里的方法，在设备端搭建 TCP 服务端<br>电脑上编译好 OTA 升级固件、固件里实现自动写 Flash、校验、重启。然后写了个 Python 发送脚本（<code>tools/ota_sender.py</code>），Claude Code 改完代码后可以调用这个脚本把固件推到板子上：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">改代码 → 编译 → ota_sender.py 推固件 → 串口看结果 → 再改</span><br></pre></td></tr></tbody></table></figure><p>以前手动烧录，改一行代码要三五分钟才能看到效果；走 OTA 之后几十秒一个循环。</p><p>这不是说每个项目都要写 OTA 工具。核心思路是：在应用层开一扇门让 AI 能够到你的设备。串口协议、TCP 服务、简单的 CLI 都可以。哪怕只是一个能收发指令的串口小程序，也比每次手动复制粘贴强。</p><h2 id="7-真正值钱的是什么"><a href="#7-真正值钱的是什么" class="headerlink" title="7. 真正值钱的是什么"></a>7. 真正值钱的是什么</h2><p>以前做嵌入式，最怕的是那种不复杂但很难找的 bug。变量溢出、中断优先级搞反、DMA 缓冲区没对齐——表面现象可能毫无关联，你对着串口盯半天，脑力全耗在排查上。</p><p>现在这些活可以丢给 AI。不是”AI 帮你跑一个工具”——而是你给它一个方向，它自己去做闭环。写完代码自己编译、烧录、看串口、查 log、定位问题、修改、重来，直到跑通。</p><p>Claude Code 不和板子交互时，它是代码助手。加上 embed-ai-tool，它能编译烧录调试。加上 bsp_board_mcp，它能上 Linux 板子查日志。加上 llm-pid-tuner，它能连续调参。板子太偏门？自己写个桥接脚本让 AI 够到它。</p><p>但工具层面的事说完了，有个更深的问题绕不开。</p><h2 id="8-AI-写完了所有代码，然后呢"><a href="#8-AI-写完了所有代码，然后呢" class="headerlink" title="8. AI 写完了所有代码，然后呢"></a>8. AI 写完了所有代码，然后呢</h2><p>最近很多人问我同一个问题：用了 Claude Code 以后，客户提需求，几句提示词项目就出来了，代码都不用自己写，剩下就修修改改。他们问我——以后怎么办？还需要学编程吗？手写代码是不是已经变成”古法编程”了？</p><p>这个焦虑，用过 AI 的人应该都有。</p><h3 id="嵌入式开发的本质是”组装”"><a href="#嵌入式开发的本质是”组装”" class="headerlink" title="嵌入式开发的本质是”组装”"></a>嵌入式开发的本质是”组装”</h3><p>先说一个基本事实：嵌入式这个工种，本质就是组装。</p><p>你用的芯片不是你的，Flash 不是你的，RTOS 内核不是你的，协议栈也不是你写的。你的工作是买来这些积木，搭起来，调通，让它能卖。大一点讲，IT 行业做应用开发全是这样——没有哪行代码是你发明创造的，你做的就是整合资源。</p><p>以前整合一辆”汽车”，买预控、买存储、买外设，最后组装调试，中间要走很长的路。现在 Claude Code 把这条路压短了，一句话的事。但本质没变，还是组装。</p><p>只是有一个东西变了：<strong>公司还愿不愿意为组装的时间付钱。</strong></p><h3 id="公司到底在为什么付钱"><a href="#公司到底在为什么付钱" class="headerlink" title="公司到底在为什么付钱"></a>公司到底在为什么付钱</h3><p>一家嵌入式公司，对研发侧的花费，过去就两块：为劳动时间付钱，为经验付钱。</p><p>劳动时间是什么？就是你坐在那敲代码、调参数、盯串口。经验是什么？往下细分就多了——工程经验、管理经验、研发经验。</p><p>AI 来了以后，第一块直接归零。你跟 AI 比时间？一个人学会的东西不可能瞬间复制给另一个大脑，但 AI 的参数一旦更新，下一秒全世界的 AI 都能用。不要跟 AI 比劳动时间，这是一条断头路。</p><p><strong>但经验，公司还会付钱。</strong></p><p>工程经验是你踩过的坑。AI 能写出代码，但那东西离量产有距离。产品只有在真实生产环境里跑起来、卖出去的时候，才会告诉你哪里不对。你打完补丁，走完这个循环，得到的就是工程经验。公司愿意为这个买单——因为一个高级工程师配 20 个 AI，能把劳动时间压到极致，但量产要踩的坑一个都跳不过去。</p><p>管理经验也在变。以前产品经理管 20 个研发工程师，用敏捷开发、V 字流程、瀑布模型来排期同步。未来你可能管一个人加 20 个 Agent。管理对象变了，但”把所有人的工作在环测试、在环集成、前后有序”这个需求没变。以前是为管人付钱，以后是为管 Agent 付钱。你现在要学的，是 Agent 怎么组织。</p><p>研发经验又是另一回事。工程经验是”我知道做得出来”，研发经验是”我不知道能不能做出来，但我愿意试”。世界大模型能不能跑通？AI 能不能替代人类？科学界没有定论。研发可能血本无归，但大公司愿意为这个砸千亿美金。这不是工程人员的事，是研究人员的事。区别在哪？搞工程不会吵架，搞研发天天吵——因为谁都不知道答案。</p><h3 id="你要积累的是什么"><a href="#你要积累的是什么" class="headerlink" title="你要积累的是什么"></a>你要积累的是什么</h3><p>所以回到那个问题：还用学编程吗？手写代码还有意义吗？</p><p>零基础当然要写，原理都不懂，AI为了快速达到目的，骗你那不带眨眼的。</p><p>但过了那个阶段，你要卷的东西不再是”多快写完一个驱动”。你要攒的是方案——在某个行业里，市场验证过的、能快速上线的、可维护可裂变的方案。然后带着这个方案去下一家公司变现。</p><p>你能把四个月的项目周期压到一个月，公司多出来三个月去铺渠道、跑营销——这三个月可能创造 60 万的业绩。你问他要 5 万，他是闭着眼睛给的。</p><p>以后不会再有”辛苦的程序员”了，996 的日子真的到头了。不是因为它不好，是因为靠堆人力的公司自己会发现自己一直在亏。市场验证得很快。</p><p><strong>这就是未来的核心竞争力：把一个产品快速正确地组装出来，卖得出去，还能维护、还能复用到下一个产品。这件事的瓶颈不在代码，在你对架构的理解、你对 Agent 的掌控、你攒过的工程经验。</strong></p><p>过去市面上有两条路——靠铆时间拼 996，或者靠经验走到管理层。接下来不是了。普通工程师也可以做管理，只不过你管的不是人，是 Agent。把架构和 Agent 工程学好，开发出来的产品能快速上线、可维护、能裂变到不同产品线，你就已经走到了那个位置。</p><p>最后，推荐一本我认为至今最好的嵌入式软件架构入门书：<a href="https://zhaochengbo.github.io/zhaoming-embedded/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>兆明嵌入式——C 语言面向对象编程·嵌入式实战</a>。它把”怎么用 C 写出可复用、可维护的嵌入式架构”这件事讲透了，跟 AI 时代要攒的工程经验正好对口。</p><p>如果你已经有了c语言基础和嵌入式开发基础（例如STM32开发），想学架构设计，这本书是最好的起点。它的核心思想是”用 C 语言写面向对象的代码”，通过封装、抽象、模块化来提升代码的复用性和可维护性。无论是现在还是未来，这些都是嵌入式开发的核心能力。</p><p>另外推荐一个非常优质且实用的嵌入式设计模式开源项目：<a href="https://github.com/xuanlinzhu/DesignMode/tree/master" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>xuanlinzhu/DesignMode——设计模式-面向嵌入式软件开发</a>。它详细总结了单例、工厂、观察者、状态机等经典设计模式在 C 语言嵌入式系统中的工程实现，配合面向对象的架构思想阅读，能帮助你进一步打牢模块化、低耦合的系统设计内功。</p>]]>
    </content>
    <id>https://blog.skyforever.top/posts/46321</id>
    <link href="https://blog.skyforever.top/posts/46321"/>
    <published>2026-05-25T16:00:00.000Z</published>
    <summary>2026年，AI辅助嵌入式开发已经不只是&quot;帮你写代码&quot;了。从硬件方案选型、PCB设计、 固件编译烧录调试，到直接操控板子跑命令，再到自动调PID参数——本文串联一套完整的AI工具链， 展示嵌入式开发全流程如何被AI重塑。</summary>
    <title>2026年如何使用AI辅助做嵌入式开发</title>
    <updated>2026-05-25T16:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="嵌入式" scheme="https://blog.skyforever.top/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F/"/>
    <category term="物联网" scheme="https://blog.skyforever.top/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F/%E7%89%A9%E8%81%94%E7%BD%91/"/>
    <category term="嵌入式" scheme="https://blog.skyforever.top/tags/%E5%B5%8C%E5%85%A5%E5%BC%8F/"/>
    <category term="物联网" scheme="https://blog.skyforever.top/tags/%E7%89%A9%E8%81%94%E7%BD%91/"/>
    <category term="LiteOS" scheme="https://blog.skyforever.top/tags/LiteOS/"/>
    <category term="Hi3863" scheme="https://blog.skyforever.top/tags/Hi3863/"/>
    <category term="WiFi" scheme="https://blog.skyforever.top/tags/WiFi/"/>
    <category term="AP" scheme="https://blog.skyforever.top/tags/AP/"/>
    <category term="配网" scheme="https://blog.skyforever.top/tags/%E9%85%8D%E7%BD%91/"/>
    <category term="Captive Portal" scheme="https://blog.skyforever.top/tags/Captive-Portal/"/>
    <category term="强制门户" scheme="https://blog.skyforever.top/tags/%E5%BC%BA%E5%88%B6%E9%97%A8%E6%88%B7/"/>
    <category term="lwIP" scheme="https://blog.skyforever.top/tags/lwIP/"/>
    <content>
      <![CDATA[<p>这篇博客档总结我在 HiSpark WS63（LiteOS + lwIP）平台上实现 WiFi AP 配网（强制门户 | Captive Portal）的完整流程，以及开发过程中遇到的关键问题和解决方案。</p><hr><h2 id="1-什么是强制门户"><a href="#1-什么是强制门户" class="headerlink" title="1. 什么是强制门户"></a>1. 什么是强制门户</h2><p>Captive Portal（强制门户）是一种网络认证机制。当设备（手机/电脑）连接到一个新的 WiFi 热点时，操作系统会自动检测该网络是否需要额外认证。如果检测到”有网关在但无法访问互联网”，系统就会自动弹出一个窗口，引导用户访问配网页面。</p><p>iOS、Android、Windows 都有各自的检测 URL（如 <code>captive.apple.com</code>、<code>connectivitycheck.gstatic.com</code>、<code>msftconnecttest.com</code>），通过访问这些 URL 来判断网络状态。</p><p>在访问的时候，达到以下条件时，系统大概率会弹窗：</p><ol><li>连接到WiFi热点，拿到IP地址</li><li>DHCP中下发了网关（Router）和 DNS 服务器地址，两个地址和配网用的HTTP服务IP一致</li><li>访问检测URL时，手机DNS解析被开发板劫持到本地网关IP</li><li>HTTP请求被302重定向到配网页面</li></ol><hr><h2 id="2-整体架构"><a href="#2-整体架构" class="headerlink" title="2. 整体架构"></a>2. 整体架构</h2><p>进入 AP 模式后，代码架构和业务流程如下图所示</p><p><img src="https://image.skyforever.top/blog/2026/05/a49d1b67b70f83278ddc1534cd7024d7.webp" alt="流程图"></p><hr><h2 id="3-代码实现"><a href="#3-代码实现" class="headerlink" title="3. 代码实现"></a>3. 代码实现</h2><h3 id="3-1-强制启动-AP-模式"><a href="#3-1-强制启动-AP-模式" class="headerlink" title="3.1 强制启动 AP 模式"></a>3.1 强制启动 AP 模式</h3><p>在 <code>bsp_wifi.c</code> 中，实现<code>bsp_wifi_smart_init()</code> 启动 AP 模式</p><p>让开发板开个热点出来给手机：</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">bsp_wifi_smart_init</span><span class="params">(<span class="type">void</span>)</span> {</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"[WiFi] 强制启动 AP 模式，等待用户配网...\r\n"</span>);</span><br><span class="line">    <span class="keyword">return</span> bsp_wifi_init_ex(BSP_WIFI_MODE_AP);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>热点（AP） 配置参数可以定义在 <code>bsp_wifi.h</code>：</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> BSP_WIFI_AP_SSID     <span class="string">"WS63_Robot"</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> BSP_WIFI_AP_PASSWORD <span class="string">""</span>          <span class="comment">// 开放网络，无密码</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> BSP_WIFI_AP_CHANNEL  13</span></span><br></pre></td></tr></tbody></table></figure><h3 id="3-2-AP-网络接口配置"><a href="#3-2-AP-网络接口配置" class="headerlink" title="3.2 AP 网络接口配置"></a>3.2 AP 网络接口配置</h3><p>在<code>init_ap_mode()</code> 中设置静态 IP 并启动 DHCP 服务器</p><p>这样当手机连接开发版的时候，开发板可以给手机分配ip：</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">netif</span>* <span class="title">netif_p</span> =</span> netifapi_netif_find(<span class="string">"ap0"</span>);</span><br><span class="line"><span class="keyword">if</span> (netif_p) {</span><br><span class="line">    <span class="type">ip4_addr_t</span> ip, mask, gw;</span><br><span class="line">    IP4_ADDR(&amp;ip,   <span class="number">192</span>, <span class="number">168</span>, <span class="number">1</span>, <span class="number">1</span>);</span><br><span class="line">    IP4_ADDR(&amp;mask, <span class="number">255</span>, <span class="number">255</span>, <span class="number">255</span>, <span class="number">0</span>);</span><br><span class="line">    IP4_ADDR(&amp;gw,   <span class="number">192</span>, <span class="number">168</span>, <span class="number">1</span>, <span class="number">1</span>);</span><br><span class="line"></span><br><span class="line">    netifapi_netif_set_addr(netif_p, &amp;ip, &amp;mask, &amp;gw);</span><br><span class="line">    netifapi_dhcps_start(netif_p, <span class="literal">NULL</span>, <span class="number">0</span>);</span><br><span class="line">    g_wifi_status = BSP_WIFI_STATUS_GOT_IP;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h3 id="3-3-Captive-Portal-服务初始化"><a href="#3-3-Captive-Portal-服务初始化" class="headerlink" title="3.3 Captive Portal 服务初始化"></a>3.3 Captive Portal 服务初始化</h3><p>在主任务的初始化流程中调用自己实现的：</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">captive_portal_service_init();</span><br></pre></td></tr></tbody></table></figure><p>该函数创建 <code>captive_portal_task</code>，同时监听两个 socket：</p><ul><li><strong>UDP 53</strong>：DNS 查询</li><li><strong>TCP 80</strong>：HTTP 请求</li></ul><p>使用 <code>lwip_select</code> 实现单线程多路复用：</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">fd_set read_fds;</span><br><span class="line">FD_ZERO(&amp;read_fds);</span><br><span class="line">FD_SET(g_dns_socket, &amp;read_fds);</span><br><span class="line">FD_SET(g_http_socket, &amp;read_fds);</span><br><span class="line"><span class="type">int</span> max_fd = (g_dns_socket &gt; g_http_socket) ? g_dns_socket : g_http_socket;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (lwip_select(max_fd + <span class="number">1</span>, &amp;read_fds, <span class="literal">NULL</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>) &gt; <span class="number">0</span>) {</span><br><span class="line">    <span class="keyword">if</span> (FD_ISSET(g_dns_socket,  &amp;read_fds)) dns_server_handle();</span><br><span class="line">    <span class="keyword">if</span> (FD_ISSET(g_http_socket, &amp;read_fds)) handle_http_accept();</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h3 id="3-4-DNS-劫持"><a href="#3-4-DNS-劫持" class="headerlink" title="3.4 DNS 劫持"></a>3.4 DNS 劫持</h3><p>所有 DNS A 记录查询都返回 AP IP（<code>192.168.1.1</code>）</p><p>让手机的每个网络请求都指向开发板的配网页面（Http服务）：</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 解析 DNS 查询中的域名</span></span><br><span class="line"><span class="type">char</span> domain[<span class="number">64</span>] = {<span class="number">0</span>};</span><br><span class="line"><span class="comment">// ... 从 UDP 报文中提取域名 ...</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 构造 DNS 响应</span></span><br><span class="line"><span class="type">uint8_t</span> response[<span class="number">256</span>];</span><br><span class="line"><span class="built_in">memcpy</span>(response, dns_buf, <span class="number">2</span>);  <span class="comment">// 复制 Transaction ID</span></span><br><span class="line">response[<span class="number">2</span>] = <span class="number">0x81</span>; response[<span class="number">3</span>] = <span class="number">0x80</span>;  <span class="comment">// 标准响应，无错误</span></span><br><span class="line"><span class="comment">// ... 设置 Answer 数量、构造 A 记录 ...</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// IP 地址字段写入 192.168.1.1</span></span><br><span class="line">response[offset++] = <span class="number">192</span>;</span><br><span class="line">response[offset++] = <span class="number">168</span>;</span><br><span class="line">response[offset++] = <span class="number">1</span>;</span><br><span class="line">response[offset++] = <span class="number">1</span>;</span><br></pre></td></tr></tbody></table></figure><h3 id="3-5-HTTP-路由与-302-重定向"><a href="#3-5-HTTP-路由与-302-重定向" class="headerlink" title="3.5 HTTP 路由与 302 重定向"></a>3.5 HTTP 路由与 302 重定向</h3><p>这是强制门户（弹出配网页面）的核心代码。</p><p>当请求来到开发板ip的时候，需要让手机请求的地址转到 <code>192.168.1.1</code>，而不是直接返回网页内容。</p><p>实现上分为两步：</p><h4 id="第一步：Host-头检查"><a href="#第一步：Host-头检查" class="headerlink" title="第一步：Host 头检查"></a>第一步：Host 头检查</h4><p>只有直接访问小车 IP 的请求才走正常路由，其他一律 走302（重定向）：</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">bool</span> is_direct_ip = <span class="literal">false</span>;</span><br><span class="line"><span class="type">char</span> target_host[<span class="number">64</span>];</span><br><span class="line"><span class="built_in">snprintf</span>(target_host, <span class="keyword">sizeof</span>(target_host), <span class="string">"Host: %s"</span>, g_ap_ip_str);</span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">strstr</span>(buf, target_host) != <span class="literal">NULL</span>) {</span><br><span class="line">    is_direct_ip = <span class="literal">true</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (!is_direct_ip) {</span><br><span class="line">    <span class="type">char</span> redirect_resp[<span class="number">256</span>];</span><br><span class="line">    <span class="built_in">snprintf</span>(redirect_resp, <span class="keyword">sizeof</span>(redirect_resp),</span><br><span class="line">        <span class="string">"HTTP/1.1 302 Found\r\n"</span></span><br><span class="line">        <span class="string">"Location: http://%s/\r\n"</span></span><br><span class="line">        <span class="string">"Content-Length: 0\r\n"</span></span><br><span class="line">        <span class="string">"Connection: close\r\n\r\n"</span>,</span><br><span class="line">        g_ap_ip_str);</span><br><span class="line">    send_response_and_close(client_fd, redirect_resp);</span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h4 id="第二步：请求分发"><a href="#第二步：请求分发" class="headerlink" title="第二步：请求分发"></a>第二步：请求分发</h4><p>当手机访问开发板上的网页时，跳转到对应的api服务</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (is_get &amp;&amp; <span class="built_in">strcmp</span>(path, <span class="string">"/status"</span>) == <span class="number">0</span>) {</span><br><span class="line">    handle_status_request(client_fd);    <span class="comment">// JSON 状态</span></span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">if</span> (is_get &amp;&amp; <span class="built_in">strcmp</span>(path, <span class="string">"/"</span>) == <span class="number">0</span>) {</span><br><span class="line">    send_response_and_close(client_fd, s_html_page);  <span class="comment">// 配网页面</span></span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">if</span> (is_post &amp;&amp; <span class="built_in">strcmp</span>(path, <span class="string">"/config"</span>) == <span class="number">0</span>) {</span><br><span class="line">    handle_config_request(client_fd, buf);  <span class="comment">// 处理配网</span></span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">}</span><br><span class="line"><span class="comment">// 兜底：其他路径也返回配网页面</span></span><br><span class="line">send_response_and_close(client_fd, s_html_page);</span><br></pre></td></tr></tbody></table></figure><h3 id="3-6-配网页面与状态轮询"><a href="#3-6-配网页面与状态轮询" class="headerlink" title="3.6 配网页面与状态轮询"></a>3.6 配网页面与状态轮询</h3><p>内嵌在固件中的 HTML 页面包含：</p><ul><li>WiFi 名称（SSID）和密码输入框</li><li>“连接”按钮，通过 <code>POST /config</code> 提交</li><li>JavaScript 轮询 <code>GET /status</code> 获取连接状态</li></ul><p>连接状态由 <code>wifi_switch_task</code> 后台任务维护，通过全局变量 <code>g_captive_status</code> 暴露给 HTTP 服务。</p><h3 id="3-7-WiFi-模式切换"><a href="#3-7-WiFi-模式切换" class="headerlink" title="3.7 WiFi 模式切换"></a>3.7 WiFi 模式切换</h3><p>当手机完成网页操作，开发板通过手机发来的<code>POST /config</code> 请求接收 SSID 和密码后，程序会创建后台任务 执行网络切换，<strong>不阻塞 HTTP 服务</strong>：</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">static</span> <span class="type">void</span> <span class="title function_">wifi_switch_task</span><span class="params">(<span class="type">void</span>* arg)</span> {</span><br><span class="line">    <span class="comment">// 1. 关闭 AP 热点和 DHCP</span></span><br><span class="line">    wifi_softap_disable();</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">netif</span>* <span class="title">ap</span> =</span> netifapi_netif_find(<span class="string">"ap0"</span>);</span><br><span class="line">    <span class="keyword">if</span> (ap) netifapi_dhcps_stop(ap);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 2. 启用 STA 模式</span></span><br><span class="line">    <span class="keyword">if</span> (wifi_sta_enable() != ERRCODE_SUCC) {</span><br><span class="line">        <span class="comment">// 回退到 AP 模式</span></span><br><span class="line">        bsp_wifi_smart_init();</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 3. 连接目标 WiFi</span></span><br><span class="line">    <span class="keyword">if</span> (bsp_wifi_start_sta_with_timeout(ssid, password, <span class="number">15000</span>) != <span class="number">0</span>) {</span><br><span class="line">        wifi_sta_disable();</span><br><span class="line">        bsp_wifi_smart_init();  <span class="comment">// 失败回退</span></span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    }</span><br><span class="line">    <span class="comment">// 连接成功，状态更新为 CONNECTED</span></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><hr><h2 id="4-遇到的问题及解决方案"><a href="#4-遇到的问题及解决方案" class="headerlink" title="4. 遇到的问题及解决方案"></a>4. 遇到的问题及解决方案</h2><h3 id="问题-1：返回-HTTP-200，地址栏不跳转"><a href="#问题-1：返回-HTTP-200，地址栏不跳转" class="headerlink" title="问题 1：返回 HTTP 200，地址栏不跳转"></a>问题 1：返回 HTTP 200，地址栏不跳转</h3><p><strong>现象</strong>：手机访问 <code>baidu.com</code>，小车返回了 HTML 内容（HTTP 200），但地址栏仍显示 <code>baidu.com</code>，没有弹窗。</p><p><strong>原因</strong>：浏览器以为收到的 HTML 就是 <code>baidu.com</code> 的网页内容，自然不会跳转。</p><p><strong>解决</strong>：必须返回 <strong>302 Found</strong>，让浏览器主动跳转到小车的 IP 地址：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">HTTP/1.1 302 Found</span><br><span class="line">Location: http://192.168.1.1/</span><br></pre></td></tr></tbody></table></figure><h3 id="问题-2：DNS-劫持后，连直接访问-192-168-1-1-也被-302"><a href="#问题-2：DNS-劫持后，连直接访问-192-168-1-1-也被-302" class="headerlink" title="问题 2：DNS 劫持后，连直接访问 192.168.1.1 也被 302"></a>问题 2：DNS 劫持后，连直接访问 192.168.1.1 也被 302</h3><p><strong>现象</strong>：加了全局 302 后，用户在浏览器地址栏输入 <code>192.168.1.1</code> 也会触发重定向，页面无法显示。</p><p><strong>原因</strong>：没有区分”DNS 劫持过来的流量”和”用户直接访问小车 IP 的流量”。</p><p><strong>解决</strong>：检查 HTTP 请求头中的 <code>Host</code> 字段。只有当 <code>Host</code> 是小车 IP 时，才走正常路由：</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (<span class="built_in">strstr</span>(buf, <span class="string">"Host: 192.168.1.1"</span>) == <span class="literal">NULL</span>) {</span><br><span class="line">    <span class="comment">// 这是 DNS 劫持流量 → 302 重定向</span></span><br><span class="line">} <span class="keyword">else</span> {</span><br><span class="line">    <span class="comment">// 这是直接访问 → 正常处理</span></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h3 id="问题-3：DHCP-没有下发网关（最隐蔽）"><a href="#问题-3：DHCP-没有下发网关（最隐蔽）" class="headerlink" title="问题 3：DHCP 没有下发网关（最隐蔽）"></a>问题 3：DHCP 没有下发网关（最隐蔽）</h3><p><strong>现象</strong>：手机 WiFi 详情里”路由器/网关”显示 <code>0.0.0.0</code>，系统完全不发起 Captive Portal 探测。串口日志中没有 DNS 查询和 HTTP 请求。</p><p><strong>根因分析</strong>：</p><p>手机连接 WiFi 后，操作系统会检查：</p><ol><li>是否拿到了 IP 地址？</li><li>是否拿到了**网关（Router）**和 <strong>DNS</strong>？</li></ol><p>如果网关是 <code>0.0.0.0</code>，系统认为这是一个”没有互联网能力的局域网设备”，直接静默处理，<strong>绝不弹窗</strong>。</p><p>lwIP 的 DHCP 服务器默认<strong>不下发网关</strong>（<code>LWIP_DHCPS_GW</code> 默认为 0），导致 DHCP Offer/ACK 报文中没有 Router 选项。</p><p><strong>排查曲折</strong>：</p><ul><li><p>第一次：在 <code>bsp_wifi.c</code> 里加 <code>#define CONFIG_DHCPS_GW 1</code> → <strong>无效</strong><br>原因：C 宏只在定义它的 <code>.c</code> 编译单元内有效，<code>dhcps.c</code> 编译时看不到。</p></li><li><p>第二次：改到 <code>lwipopts.h</code> → <strong>仍无效</strong><br>原因：CMake 中 <code>LWIP_CONFIG_FILE</code> 被硬编码为 <code>"lwip/lwipopts_default.h"</code>，<code>lwipopts.h</code> 根本没被 lwIP 源文件包含。</p></li><li><p><strong>最终解决</strong>：在 <code>lwipopts_default.h</code> 中直接定义 <code>#define CONFIG_DHCPS_GW 1</code>。<br>这个文件是实际被 <code>LWIP_CONFIG_FILE</code> 指定的配置文件，所有 lwIP 源文件都能看到。</p></li></ul><p><strong><code>lwipopts_default.h</code> 中的关键逻辑</strong>：</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">if</span> defined (CONFIG_DHCPS_GW)</span></span><br><span class="line"><span class="meta">#<span class="keyword">ifndef</span> LWIP_DHCPS_GW</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> LWIP_DHCPS_GW 1    <span class="comment">// 下发网关</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">else</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">ifndef</span> LWIP_DHCPS_GW</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> LWIP_DHCPS_GW 0    <span class="comment">// 默认关闭</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br></pre></td></tr></tbody></table></figure><p>当 <code>LWIP_DHCPS_GW = 1</code> 后，<code>dhcps.c</code> 在构造 DHCP Offer/ACK 时就会加入 Router 选项（Option 3），地址为 AP 接口的 IP（<code>192.168.1.1</code>）。同时 <code>LWIP_DHCPS_DNS_OPTION</code> 会确保 DNS 服务器也下发为 <code>192.168.1.1</code>。</p><hr><h2 id="5-关键配置项汇总"><a href="#5-关键配置项汇总" class="headerlink" title="5. 关键配置项汇总"></a>5. 关键配置项汇总</h2><div class="md-table-scroll"><table><thead><tr><th>配置项</th><th>值</th><th>说明</th></tr></thead><tbody><tr><td><code>BSP_WIFI_AP_SSID</code></td><td><code>"WS63_Robot"</code></td><td>热点名称</td></tr><tr><td><code>BSP_WIFI_AP_PASSWORD</code></td><td><code>""</code></td><td>开放网络（无密码）</td></tr><tr><td><code>BSP_WIFI_AP_CHANNEL</code></td><td><code>13</code></td><td>WiFi 频道</td></tr><tr><td>AP 静态 IP</td><td><code>192.168.1.1</code></td><td>固定网关地址</td></tr><tr><td><code>CONFIG_DHCPS_GW</code></td><td><code>1</code></td><td>启用 DHCP 网关下发</td></tr><tr><td>DNS 端口</td><td><code>53</code></td><td>标准 DNS 端口</td></tr><tr><td>HTTP 端口</td><td><code>80</code></td><td>标准 HTTP 端口</td></tr><tr><td>DHCP 租约起始偏移</td><td><code>2</code></td><td>客户端 IP 从 <code>192.168.1.2</code> 开始分配</td></tr></tbody></table></div><hr><h2 id="6-调试技巧"><a href="#6-调试技巧" class="headerlink" title="6. 调试技巧"></a>6. 调试技巧</h2><h3 id="查看手机是否拿到网关"><a href="#查看手机是否拿到网关" class="headerlink" title="查看手机是否拿到网关"></a>查看手机是否拿到网关</h3><p>手机连接 <code>WS63_Robot</code> 后，在 WiFi 详情中查看：</p><ul><li><strong>路由器/网关</strong>：必须是 <code>192.168.1.1</code></li><li><strong>DNS</strong>：必须是 <code>192.168.1.1</code></li></ul><p>如果显示 <code>0.0.0.0</code>，说明 <code>LWIP_DHCPS_GW</code> 未生效，DHCP 配置有问题。</p><h3 id="串口日志观察点"><a href="#串口日志观察点" class="headerlink" title="串口日志观察点"></a>串口日志观察点</h3><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">[WiFi] AP 热点已启用: SSID=WS63_Robot, 开放网络(无密码), 频道=13</span><br><span class="line">[WiFi] AP 热点 IP: 192.168.1.1</span><br><span class="line">[Portal] DNS 查询: connectivitycheck.gstatic.com -&gt; 192.168.1.1</span><br><span class="line">[Portal] 客户端连接: 192.168.1.2</span><br><span class="line">[Portal] 302 重定向 -&gt; http://192.168.1.1/</span><br><span class="line">[Portal] 收到配网请求: SSID=MyHomeWiFi</span><br><span class="line">[WiFi] 正在连接 MyHomeWiFi...</span><br><span class="line">[WiFi] 已连接: MyHomeWiFi, 信号强度: -45</span><br></pre></td></tr></tbody></table></figure><p>如果没有看到 <code>[Portal] DNS 查询</code> 日志，说明手机根本没发起探测 → 检查 DHCP 网关。</p><h3 id="手动测试"><a href="#手动测试" class="headerlink" title="手动测试"></a>手动测试</h3><ol><li>手机连接热点后，<strong>不要等弹窗</strong>，直接在浏览器地址栏输入 <code>192.168.1.1</code></li><li>如果能看到配网页面，说明 HTTP 服务正常</li><li>如果看不到，检查串口是否有 <code>客户端连接</code> 日志</li><li>在浏览器里访问 <code>http://neverssl.com</code>，观察是否 302 跳转到 <code>192.168.1.1</code></li></ol><hr><h2 id="7-总结"><a href="#7-总结" class="headerlink" title="7. 总结"></a>7. 总结</h2><p>实现 Captive Portal 的关键不是”搭一个网页”，而是<strong>让操作系统”认为这个网络需要认证登陆”</strong>。这要求：</p><ol><li><strong>DNS 劫持</strong>：让所有域名解析到本地 IP</li><li><strong>302 重定向</strong>：把劫持流量引导到配置页面</li><li><strong>DHCP 网关下发</strong>：这是最容易被忽略的一点——手机必须拿到网关和 DNS，系统才会发起探测</li></ol><p>如果只做了前两点而第三点缺失，结果就是：手机静默连接，没有任何弹窗，用户必须手动打开浏览器输入 IP 才能配网——体验大打折扣。</p>]]>
    </content>
    <id>https://blog.skyforever.top/posts/52107</id>
    <link href="https://blog.skyforever.top/posts/52107"/>
    <published>2026-05-25T00:12:00.000Z</published>
    <summary>总结在 HiSpark WS63（LiteOS + lwIP）平台上实现 WiFi AP 配网（Captive Portal / 强制门户）的完整流程， 涵盖强制门户检测原理、整体架构、代码实现及开发过程中的关键问题与解决方案。</summary>
    <title>Hi3863 WiFi AP 配网实现方法</title>
    <updated>2026-05-25T00:12:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="嵌入式" scheme="https://blog.skyforever.top/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F/"/>
    <category term="物联网" scheme="https://blog.skyforever.top/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F/%E7%89%A9%E8%81%94%E7%BD%91/"/>
    <category term="嵌入式" scheme="https://blog.skyforever.top/tags/%E5%B5%8C%E5%85%A5%E5%BC%8F/"/>
    <category term="物联网" scheme="https://blog.skyforever.top/tags/%E7%89%A9%E8%81%94%E7%BD%91/"/>
    <category term="LiteOS" scheme="https://blog.skyforever.top/tags/LiteOS/"/>
    <category term="OpenHarmony" scheme="https://blog.skyforever.top/tags/OpenHarmony/"/>
    <category term="OTA" scheme="https://blog.skyforever.top/tags/OTA/"/>
    <category term="WS63" scheme="https://blog.skyforever.top/tags/WS63/"/>
    <category term="固件升级" scheme="https://blog.skyforever.top/tags/%E5%9B%BA%E4%BB%B6%E5%8D%87%E7%BA%A7/"/>
    <category term="UPG" scheme="https://blog.skyforever.top/tags/UPG/"/>
    <content>
      <![CDATA[<h2 id="0-LiteOS-OTA-实现方式概述"><a href="#0-LiteOS-OTA-实现方式概述" class="headerlink" title="0. LiteOS OTA 实现方式概述"></a>0. LiteOS OTA 实现方式概述</h2><p>在 LiteOS 生态中，常见的 OTA 实现方式主要有以下三种：</p><div class="md-table-scroll"><table><thead><tr><th align="left">方式</th><th align="left">适用场景</th><th align="left">核心机制</th></tr></thead><tbody><tr><td align="left"><strong>① UPG 模块模式</strong></td><td align="left">轻量级 MCU/SoC（如 WS63）</td><td align="left">芯片厂商封装 UPG 接口，应用层直接调用 API 写入 Flash，由 Bootloader 完成分区切换</td></tr><tr><td align="left"><strong>② IoT Link SDK 模式</strong></td><td align="left">物联网设备（NB-IoT 等）</td><td align="left">基于 LwM2M/PCP 协议与云平台交互，采用 Loader + App 双镜像架构，支持差分升级</td></tr><tr><td align="left"><strong>③ OpenHarmony 标准系统模式</strong></td><td align="left">富设备（RK3568、手机等）</td><td align="left">独立的 updater 分区与 misc 分区，uboot 引导进入 updater 模式，有完整 Linux 用户态升级流程</td></tr></tbody></table></div><p><strong>本文实现的是方式 ①</strong>：基于 WS63 芯片提供的 UPG 模块，在 LiteOS 应用层构建 TCP 局域网服务端，通过流式接收固件并调用 <code>uapi_upg_*</code> 系列接口完成升级。相比其他两种方式，这种方式最轻量、最直接，适合局域网快速烧录和调试场景。</p><p>无论哪种实现方式，OTA 的整体流程都可以概括为以下四个步骤：</p><p><img src="https://image.skyforever.top/blog/2026/05/70cded9a06ed069c7e0691f328a9a8ca.webp" alt="OTA主要流程"></p><p>本文按实际操作的先后顺序组织，共分为以下几个部分：</p><ol><li><strong>了解 UPG 接口</strong>：理解底层升级模块的工作原理和 API</li><li><strong>环境准备</strong>：生成签名密钥、全量编译并烧录底包（<strong>必须先完成，否则后续 OTA 校验会失败</strong>）</li><li><strong>代码实现</strong>：编写 OTA 服务代码</li><li><strong>OTA 升级与推送</strong>：生成升级包并远程推送到设备</li><li><strong>问题排查</strong>：常见问题及解决方法</li><li><strong>方案对比</strong>：LiteOS OTA 与 OpenHarmony 标准系统 OTA 的差异</li></ol><hr><h2 id="1-了解-LiteOS-OTA-相关接口"><a href="#1-了解-LiteOS-OTA-相关接口" class="headerlink" title="1. 了解 LiteOS OTA 相关接口"></a>1. 了解 LiteOS OTA 相关接口</h2><p>WS63 的 OTA 升级依赖于底层提供的 <strong>UPG (Upgrade) 模块</strong>。应用层只需要把接收到的固件包按顺序调用接口写入即可，底层的签名校验和 Flash 分区操作由 UPG 模块完成。</p><h3 id="UPG-内部工作流程"><a href="#UPG-内部工作流程" class="headerlink" title="UPG 内部工作流程"></a>UPG 内部工作流程</h3><p><img src="https://image.skyforever.top/blog/2026/05/a7d99933a2b91c869de4f5d1cbe99a99.webp" alt="UPG 内部工作流程"></p><h3 id="UPG-内部-Flash-分区与数据流向"><a href="#UPG-内部-Flash-分区与数据流向" class="headerlink" title="UPG 内部 Flash 分区与数据流向"></a>UPG 内部 Flash 分区与数据流向</h3><p>WS63 采用 <strong>AB 双分区</strong> 方案，Flash 整体布局如下图所示（总大小4MB）：</p><p><img src="https://image.skyforever.top/blog/2026/05/69a3505f36c1e652917121355f496d3f.webp" alt="WS63 整体 Flash 物理分区表"></p><p>上图中与 UPG 相关的区域划分定义在<br><code>build/config/target_config/ws63/param_sector/param_sector.json</code><br>中，分区 ID 枚举见<br><code>middleware/chips/ws63/partition/include/partition_resource_id.h</code>：</p><div class="md-table-scroll"><table><thead><tr><th align="left">区域</th><th align="left">分区名</th><th align="left">作用</th></tr></thead><tbody><tr><td align="left"><strong>A 区（运行区）</strong></td><td align="left"><code>PARTITION_APP_IMAGE</code></td><td align="left">当前正在运行的固件，起始地址 <code>0x030000</code>，大小 <code>0x240000</code>（约 2.25MB）</td></tr><tr><td align="left"><strong>B 区（FOTA 区）</strong></td><td align="left"><code>PARTITION_FOTA_DATA</code></td><td align="left">起始地址 <code>0x270000</code>，大小 <code>0x183000</code>（约 1.512MB）。前半部分存放接收到的升级包数据；后半部分为升级标记区（记录升级状态、包长度、镜像数量等）；最后 4KB 为 AB 配置区（记录当前从哪个分区启动）</td></tr></tbody></table></div><p>物理分区与 A/B 逻辑分区的映射关系如下图所示：</p><p><img src="https://image.skyforever.top/blog/2026/05/b14e26d1274abc50bc03806b1c4fcccd.webp" alt="物理分区与 A_B 逻辑分区映射关系"></p><p>物理上的 imageA (2.25M)+ fota data (1.5M)被从中问强行切分，变成了等大的两个1.93MB 区域，这也解释了为什么 fota_data 不仅仅是暂存区，它的前半部分其实是 B 区代码的运行空间。</p><p><strong>下载阶段（App 中）的数据流向：</strong></p><p>应用层调用 UPG 存储层接口（实现在<br> <code>middleware/utils/update/storage/upg_storage.c</code><br> ），将网络接收到的固件写入 Flash：</p><ol><li><code>uapi_upg_prepare()</code> —— 擦除 <code>PARTITION_FOTA_DATA</code> 分区，并在升级标记区写入 <code>head_magic</code> 和 <code>package_length</code></li><li><code>uapi_upg_write_package_sync()</code> —— 将网络接收到的固件数据按 offset 顺序写入 <strong>FOTA 区起始地址 + offset</strong>。实际的 Flash 读写由 <code>middleware/chips/ws63/update/common/upg_common_porting.c</code> 中的 <code>upg_flash_write()</code> 完成</li><li><code>uapi_upg_verify_file()</code> —— 对 FOTA 暂存区中的固件进行 ECDSA 签名 + SHA256 哈希校验</li><li><code>uapi_upg_request_upgrade(true)</code> —— 在升级标记区写入 <code>head_end_magic</code> 和 <code>firmware_num</code>，标记”升级包已就绪”，然后<strong>重启</strong></li></ol><p><strong>升级阶段（Bootloader 中）的数据流向：</strong></p><p>Bootloader 启动后（入口在<br><code>bootloader/flashboot_ws63/startup/main.c</code><br>的 <code>start_fastboot()</code>），调用 <code>ws63_upg_check()</code> 检测升级标记。若标记完整，自动调用 <code>uapi_upg_start()</code>（实现在 <code>middleware/utils/update/local_update/upg_process.c</code>）：</p><ol><li>从 <strong>FOTA 暂存区</strong> 读取升级包，逐个镜像处理（<code>upg_process_update()</code> → <code>upg_perform_image_task()</code>）</li><li>对于全镜像升级，调用 <code>middleware/utils/update/local_update/upg_upgrade.c</code> 中的 <code>uapi_upg_full_image_update()</code>，将 FOTA 区的数据读出，写入<strong>目标镜像分区</strong>（B 区或对应分区）</li><li>如果是 AB 模式，写入完成后调用 <code>middleware/chips/ws63/update/ab_upg/upg_ab.c</code> 中的 <code>upg_set_run_region()</code> <strong>切换启动分区</strong></li><li>设置 <code>complete_flag</code>，再次重启，此时从新的分区启动新固件</li></ol><p>OTA 动作与数据流向的整体过程如下图所示：</p><p>注意图片内容是假设当前系统正在A区运行</p><p><img src="https://image.skyforever.top/blog/2026/05/081a4ce3cb64b3c861fe7154a03b2752.webp" alt="OTA 动作与数据流向"></p><blockquote><p>回滚机制：AB 模式下，如果新固件连续验签失败达到阈值（3 次），Bootloader 会自动切换回另一个分区启动，实现失败回滚。</p></blockquote><p>核心头文件为 <code>include/middleware/utils/upg.h</code>，下面是此头文件里的相关接口说明，你也可以直接打开头文件查看内容：</p><div class="md-table-scroll"><table><thead><tr><th align="left">API 接口</th><th align="left">功能说明</th><th align="left">调用时机</th></tr></thead><tbody><tr><td align="left"><code>uapi_upg_init(const upg_func_t *funcs)</code></td><td align="left"><strong>初始化 UPG 模块</strong>。需要传入内存分配和串口打印的回调函数。</td><td align="left">系统启动后，OTA 服务启动前。</td></tr><tr><td align="left"><code>uapi_upg_reset_upgrade_flag(void)</code></td><td align="left"><strong>清除残留标志</strong>。防止上次失败的升级状态干扰本次 OTA。</td><td align="left">UPG 初始化后紧接着调用。</td></tr><tr><td align="left"><code>uapi_upg_prepare(upg_prepare_info_t *info)</code></td><td align="left"><strong>准备升级</strong>。告知底层即将接收的固件总大小，底层会做 Flash 空间检查。</td><td align="left">接收到网络传输的固件 Header 时调用。</td></tr><tr><td align="left"><code>uapi_upg_write_package_sync(offset, buf, len)</code></td><td align="left"><strong>同步写入数据块</strong>。将接收到的固件分块写入 UPG 暂存区。</td><td align="left">网络接收循环中，每收到一块数据时调用。</td></tr><tr><td align="left"><code>uapi_upg_verify_file(upg_package_header_t *hdr)</code></td><td align="left"><strong>固件校验</strong>。对写入完成的暂存区固件进行 ECDSA 签名和 SHA256 哈希校验。</td><td align="left">整个固件包接收完成后调用。</td></tr><tr><td align="left"><code>uapi_upg_request_upgrade(bool reboot)</code></td><td align="left"><strong>触发升级</strong>。通知 Bootloader 切换分区，并可选择是否立即重启。</td><td align="left"><code>verify</code> 校验通过（返回成功）后调用。</td></tr></tbody></table></div><h2 id="2-环境准备"><a href="#2-环境准备" class="headerlink" title="2. 环境准备"></a>2. 环境准备</h2><p>在开始编写 OTA 代码之前，必须先完成以下两项环境准备工作。否则后续生成的 OTA 升级包将无法通过设备端的签名校验。</p><h3 id="2-1-用脚本生成签名密钥"><a href="#2-1-用脚本生成签名密钥" class="headerlink" title="2.1 用脚本生成签名密钥"></a>2.1 用脚本生成签名密钥</h3><p>OTA 固件包必须经过签名，Bootloader 和 UPG 模块才会允许刷入。第一次开发或更换工程时，需要生成一套专属密钥。</p><p><strong>脚本位置</strong>：<code>build/config/target_config/ws63/sign_encry/gen_all_key.sh</code></p><ol><li>进入 SDK 的加密配置目录：<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> build/config/target_config/ws63/sign_encry</span><br></pre></td></tr></tbody></table></figure></li><li>执行一键生成密钥脚本：<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bash gen_all_key.sh</span><br></pre></td></tr></tbody></table></figure><em>注意：执行过程中提示旧密钥会被覆盖，输入 <code>Y</code> 确认。</em></li><li><strong>输出结果</strong>：脚本会在 <code>build/config/target_config/ws63/sign_config/</code> 目录下生成一系列 <code>.pem</code> 私钥文件（包含 Root、App、Bootloader 私钥等），后续打包脚本会自动调用这些文件。</li></ol><hr><h3 id="2-2-全量编译与本地烧录底包（极度重要）"><a href="#2-2-全量编译与本地烧录底包（极度重要）" class="headerlink" title="2.2 全量编译与本地烧录底包（极度重要）"></a>2.2 全量编译与本地烧录底包（极度重要）</h3><blockquote><p><strong>为什么必须有这一步？</strong><br>刚才生成的只是私钥。对应的<strong>公钥</strong>会被编译进 Bootloader 和设备的 efuse 中。如果只生成密钥而不做本地全量烧录，设备里的旧公钥将永远无法校验通过你用新私钥打包的 OTA 固件</p><p>（表现为 <code>uapi_upg_verify_file</code> 返回 <code>0x01</code> 或错误码）</p></blockquote><ol><li><p><strong>编译全量工程</strong>（回到 SDK 根目录）：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python build.py ws63-liteos-app</span><br></pre></td></tr></tbody></table></figure></li><li><p><strong>打包全量烧录包 (.fwpkg)</strong>：<br><em>(如果 build.py 没有自动生成，手动执行以下命令)</em><br><strong>脚本位置</strong>：<code>tools/pkg/packet.py</code></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python tools/pkg/packet.py ws63 ws63-liteos-app <span class="string">""</span></span><br></pre></td></tr></tbody></table></figure><p><strong>产物路径</strong>：<code>output/ws63/fwpkg/ws63-liteos-app/ws63-liteos-app_all.fwpkg</code></p></li><li><p><strong>本地物理烧录</strong>：<br>使用官方烧录工具（如 HiBurn 或 JLink），通过<strong>串口/USB线</strong>将 <code>ws63-liteos-app_all.fwpkg</code> 完整烧录到开发板中。<br><em>(完成这一步后，你的开发板就具备了接收后续 OTA 的最新公钥基础。)</em></p></li></ol><hr><h2 id="3-代码实现"><a href="#3-代码实现" class="headerlink" title="3. 代码实现"></a>3. 代码实现</h2><p>我们可以用Liteos的这套接口，在UPG外部实现完整的 OTA 相关代码</p><p><img src="https://image.skyforever.top/blog/2026/05/c105e29b76c3f7712f2c1d8c6485734c.webp" alt="工程 在 UPG外部 OTA 的代码实现"></p><p>本工程中的 OTA 服务实现位于以下文件：</p><ul><li><strong>接口文件</strong>：<code>application/samples/peripheral/smart_car/apps/robot_demo/services/ota_service.h</code></li><li><strong>实现文件</strong>：<code>application/samples/peripheral/smart_car/apps/robot_demo/services/ota_service.c</code></li><li><strong>主程序初始化</strong>：<code>application/samples/peripheral/smart_car/apps/robot_demo/core/robot_mgr.c</code></li></ul><h3 id="3-1-OTA-服务接口定义"><a href="#3-1-OTA-服务接口定义" class="headerlink" title="3.1 OTA 服务接口定义"></a>3.1 OTA 服务接口定义</h3><p><strong>文件位置</strong>：<br><code>application/samples/peripheral/smart_car/apps/robot_demo/services/ota_service.h</code></p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">ifndef</span> OTA_SERVICE_H</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> OTA_SERVICE_H</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdint.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdbool.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> OTA_TCP_PORT        8890</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> OTA_RECV_CHUNK_SIZE 4096</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> OTA_TCP_STACK_SIZE  16384</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> OTA_TCP_TASK_PRIORITY 23</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> OTA_MAGIC_LEN       4</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> OTA_MAGIC_STR       <span class="string">"OTAx"</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">enum</span> {</span></span><br><span class="line">    OTA_STATE_IDLE,       <span class="comment">// 空闲</span></span><br><span class="line">    OTA_STATE_WAITING,    <span class="comment">// TCP 监听中</span></span><br><span class="line">    OTA_STATE_RECEIVING,  <span class="comment">// 接收数据中</span></span><br><span class="line">    OTA_STATE_VERIFYING,  <span class="comment">// UPG 校验中</span></span><br><span class="line">    OTA_STATE_UPGRADING,  <span class="comment">// 已请求升级，即将重启</span></span><br><span class="line">    OTA_STATE_FAILED      <span class="comment">// 失败</span></span><br><span class="line">} <span class="type">ota_state_t</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> {</span></span><br><span class="line">    <span class="type">ota_state_t</span> state;</span><br><span class="line">    <span class="type">uint8_t</span>     progress_percent;</span><br><span class="line">    <span class="type">uint32_t</span>    received_size;</span><br><span class="line">    <span class="type">uint32_t</span>    total_size;</span><br><span class="line">} <span class="type">ota_status_t</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">ota_service_init</span><span class="params">(<span class="type">void</span>)</span>;</span><br><span class="line"><span class="type">bool</span> <span class="title function_">ota_service_start</span><span class="params">(<span class="type">uint32_t</span> expected_size)</span>;</span><br><span class="line"><span class="type">void</span> <span class="title function_">ota_service_cancel</span><span class="params">(<span class="type">void</span>)</span>;</span><br><span class="line"><span class="type">bool</span> <span class="title function_">ota_service_is_active</span><span class="params">(<span class="type">void</span>)</span>;</span><br><span class="line"><span class="type">void</span> <span class="title function_">ota_service_get_status</span><span class="params">(<span class="type">ota_status_t</span> *out)</span>;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span> <span class="comment">/* OTA_SERVICE_H */</span></span></span><br></pre></td></tr></tbody></table></figure><h3 id="3-2-OTA-服务核心实现"><a href="#3-2-OTA-服务核心实现" class="headerlink" title="3.2 OTA 服务核心实现"></a>3.2 OTA 服务核心实现</h3><p><strong>文件位置</strong>：<br><code>application/samples/peripheral/smart_car/apps/robot_demo/services/ota_service.c</code></p><p>核心逻辑分为 7 个阶段：</p><h4 id="阶段-A：UPG-初始化"><a href="#阶段-A：UPG-初始化" class="headerlink" title="阶段 A：UPG 初始化"></a>阶段 A：UPG 初始化</h4><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">ota_service_init</span><span class="params">(<span class="type">void</span>)</span></span><br><span class="line">{</span><br><span class="line">    <span class="type">static</span> <span class="type">const</span> <span class="type">upg_func_t</span> s_upg_funcs = {</span><br><span class="line">        .<span class="built_in">malloc</span> = fota_upg_malloc,      <span class="comment">// osal_kmalloc</span></span><br><span class="line">        .<span class="built_in">free</span>   = fota_upg_free,        <span class="comment">// osal_kfree</span></span><br><span class="line">        .serial_putc = fota_upg_serial_putc  <span class="comment">// uapi_uart_write</span></span><br><span class="line">    };</span><br><span class="line">    uapi_upg_init(&amp;s_upg_funcs);</span><br><span class="line">    uapi_upg_reset_upgrade_flag();  <span class="comment">// 清除残留升级标志</span></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h4 id="阶段-B：TCP-服务端启动"><a href="#阶段-B：TCP-服务端启动" class="headerlink" title="阶段 B：TCP 服务端启动"></a>阶段 B：TCP 服务端启动</h4><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">bool</span> <span class="title function_">ota_service_start</span><span class="params">(<span class="type">uint32_t</span> expected_size)</span></span><br><span class="line">{</span><br><span class="line">    g_ota_task_handle = osal_kthread_create(</span><br><span class="line">        (osal_kthread_handler)ota_tcp_server_task, <span class="literal">NULL</span>,</span><br><span class="line">        <span class="string">"ota_tcp_task"</span>, OTA_TCP_STACK_SIZE);</span><br><span class="line">    osal_kthread_set_priority(g_ota_task_handle, OTA_TCP_TASK_PRIORITY);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h4 id="阶段-C：接收-8-字节-Header"><a href="#阶段-C：接收-8-字节-Header" class="headerlink" title="阶段 C：接收 8 字节 Header"></a>阶段 C：接收 8 字节 Header</h4><p>这个Header由 魔术字+包大小 组成</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[4 bytes] Magic: "OTAx" (0x4F 0x54 0x41 0x78)</span><br><span class="line">[4 bytes] Total firmware size (uint32_t, big-endian)</span><br></pre></td></tr></tbody></table></figure><h4 id="阶段-D：UPG-预准备"><a href="#阶段-D：UPG-预准备" class="headerlink" title="阶段 D：UPG 预准备"></a>阶段 D：UPG 预准备</h4><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">errcode_t</span> ret = uapi_upg_prepare(&amp;prepare_info);</span><br><span class="line"><span class="comment">/* prepare_info.package_len = total_size */</span></span><br></pre></td></tr></tbody></table></figure><h4 id="阶段-E：流式接收并写入-UPG"><a href="#阶段-E：流式接收并写入-UPG" class="headerlink" title="阶段 E：流式接收并写入 UPG"></a>阶段 E：流式接收并写入 UPG</h4><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">while</span> (offset &lt; total_size) {</span><br><span class="line">    n = recv_all(conn_fd, recv_buf, chunk_size, <span class="number">30000</span>);</span><br><span class="line">    ret = uapi_upg_write_package_sync(offset, recv_buf, (<span class="type">uint16_t</span>)n);</span><br><span class="line">    offset += n;</span><br><span class="line">    <span class="comment">/* 每 4KB 回复 1 byte ACK: 0x00 = OK */</span></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h4 id="阶段-F：UPG-校验"><a href="#阶段-F：UPG-校验" class="headerlink" title="阶段 F：UPG 校验"></a>阶段 F：UPG 校验</h4><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ret = uapi_upg_read_package(<span class="number">0</span>, (<span class="type">uint8_t</span> *)&amp;hdr, <span class="keyword">sizeof</span>(hdr));</span><br><span class="line">ret = uapi_upg_verify_file(&amp;hdr);  <span class="comment">// 签名+哈希校验</span></span><br></pre></td></tr></tbody></table></figure><h4 id="阶段-G：请求升级并重启"><a href="#阶段-G：请求升级并重启" class="headerlink" title="阶段 G：请求升级并重启"></a>阶段 G：请求升级并重启</h4><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ret = uapi_upg_request_upgrade(<span class="literal">true</span>);  <span class="comment">// true = 立即重启</span></span><br></pre></td></tr></tbody></table></figure><h3 id="3-3-主程序初始化"><a href="#3-3-主程序初始化" class="headerlink" title="3.3 主程序初始化"></a>3.3 主程序初始化</h3><p><strong>文件位置</strong>：<br><code>application/samples/peripheral/smart_car/apps/robot_demo/core/robot_mgr.c</code></p><p>在 <code>robot_mgr_init()</code> 中 <code>udp_service_init()</code> 之后添加：</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">"../services/ota_service.h"</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">robot_mgr_init</span><span class="params">(<span class="type">void</span>)</span></span><br><span class="line">{</span><br><span class="line">    <span class="comment">/* ... 其他初始化 ... */</span></span><br><span class="line">    udp_service_init();</span><br><span class="line">    ota_service_init();  <span class="comment">// &lt;-- OTA 服务初始化</span></span><br><span class="line">    <span class="comment">/* ... */</span></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><hr><h2 id="4-OTA-升级与推送"><a href="#4-OTA-升级与推送" class="headerlink" title="4. OTA 升级与推送"></a>4. OTA 升级与推送</h2><p>完成环境准备和代码编写后，即可开始制作 OTA 升级包并推送到设备进行验证。</p><h3 id="4-1-生成-OTA-升级包-Pkg"><a href="#4-1-生成-OTA-升级包-Pkg" class="headerlink" title="4.1 生成 OTA 升级包 (Pkg)"></a>4.1 生成 OTA 升级包 (Pkg)</h3><p>现在你的设备已经跑起来了，假设你需要修复一个 Bug 并通过 OTA 推送。</p><ol><li><p><strong>修改代码</strong>：<br>在应用代码中做一些改动，比如修改版本号打印：<code>printf("OTA Version V2.0\r\n");</code></p></li><li><p><strong>重新编译代码</strong>：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python build.py ws63-liteos-app</span><br></pre></td></tr></tbody></table></figure></li><li><p><strong>获取 OTA 产物</strong>：<br><strong>产物路径</strong>：<code>output/ws63/upgrade/update.fwpkg</code></p><p>注意区分，这个包通常只有 1MB 左右，比全量包小很多。</p></li><li><p><strong>执行 OTA 升级包打包脚本</strong>：<br><strong>脚本位置</strong>：<code>build/config/target_config/ws63/build_ws63_update.py</code></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python build/config/target_config/ws63/build_ws63_update.py --pkt app</span><br></pre></td></tr></tbody></table></figure><p>该脚本会提取上一步编译出的 <code>.bin</code> 文件，使用【2.1】生成的私钥进行 ECDSA 签名，并打包成 UPG 格式。</p></li></ol><p><strong>验证方法：</strong> 可以在代码中加入明显的版本标记（如 <code>printf("[FIRMWARE] OTA_TEST_BUILD_V2\r\n")</code>），OTA 重启后观察串口是否出现该标记，即可确认固件已更新。</p><hr><h3 id="4-2-远程-OTA-推送"><a href="#4-2-远程-OTA-推送" class="headerlink" title="4.2 远程 OTA 推送"></a>4.2 远程 OTA 推送</h3><p>最后一步，通过网络将 <code>update.fwpkg</code> 发送给处于局域网内的开发板。</p><p>这个脚本是我自己写的，可以根据我的代码实现一个自己的脚本</p><p>在我的工程里，脚本位置是：<code>tools/ota_sender.py</code></p><ol><li>确保开发板已连接 Wi-Fi，且你编写的网络 OTA 服务端（第3节的代码）处于监听状态。</li><li>使用配套的 Python 发送端脚本推送固件：<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 格式：python ota_sender.py &lt;目标开发板IP&gt; &lt;OTA包路径&gt;</span></span><br><span class="line">python tools/ota_sender.py 192.168.111.20 output/ws63/upgrade/update.fwpkg</span><br></pre></td></tr></tbody></table></figure></li><li><strong>观察设备端反应</strong>：<ul><li>设备端开始接收数据，串口打印接收进度。</li><li>接收完成后，触发 <code>uapi_upg_verify_file</code> 校验。</li><li>串口输出类似 <code>[UPG] verify success!</code>。</li><li>设备<strong>自动重启</strong>，此时底层 Bootloader 会接管，将暂存区的新固件覆盖到主分区。</li><li>再次开机，看到你修改的 <code>OTA Version V2.0</code> 打印，说明完整 OTA 流程大功告成。</li></ul></li></ol><hr><h3 id="4-3-日常操作流程"><a href="#4-3-日常操作流程" class="headerlink" title="4.3 日常操作流程"></a>4.3 日常操作流程</h3><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Step 1: 修改代码（如 robot_mgr.c 等）</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Step 2: 重新编译（必须！生成OTA升级包的脚本不会自动编译）</span></span><br><span class="line">python build.py ws63<span class="literal">-liteos-app</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Step 3: 生成 OTA 升级包</span></span><br><span class="line">python build\config\target_config\ws63\build_ws63_update.py <span class="literal">--pkt</span> app</span><br><span class="line"></span><br><span class="line"><span class="comment"># Step 4: 远程推送 OTA</span></span><br><span class="line">python tools\ota_sender.py <span class="number">192.168</span>.<span class="number">111.20</span> output\ws63\upgrade\update.fwpkg</span><br><span class="line"></span><br><span class="line"><span class="comment"># Step 5: 观察串口，确认新固件已生效</span></span><br></pre></td></tr></tbody></table></figure><p><img src="https://image.skyforever.top/blog/2026/05/16975780f21be31519eae33a1f99c192.webp" alt="完成代码后的操作流程"></p><h2 id="5-可能遇到的问题"><a href="#5-可能遇到的问题" class="headerlink" title="5. 可能遇到的问题"></a>5. 可能遇到的问题</h2><div class="md-table-scroll"><table><thead><tr><th>现象</th><th>原因</th><th>解决</th></tr></thead><tbody><tr><td>TCP 连接失败</td><td>OTA 任务未启动 / 防火墙 / 网络不通</td><td>检查设备是否正常运行，确认 IP 地址和端口</td></tr><tr><td>Header ACK 错误</td><td>固件大小为 0 / Magic 不匹配</td><td>检查 <code>update.fwpkg</code> 是否完整</td></tr><tr><td>UPG write 失败</td><td>空间不足 / Flash 错误</td><td>检查 UPG 分区大小，确认 Flash 正常</td></tr><tr><td>校验失败 (0x01)</td><td><strong>签名密钥不匹配</strong></td><td>重新运行 <code>gen_all_key.sh</code>，重新全量烧录 <code>.fwpkg</code></td></tr><tr><td>设备未重启</td><td>UPG request_upgrade 失败</td><td>检查 <code>uapi_upg_verify_file()</code> 返回值</td></tr><tr><td>OTA 成功但固件没变化</td><td><strong>修改代码后没有重新编译</strong></td><td>打包脚本只读取已编译的 <code>.bin</code>，不会自动编译。必须先执行 <code>python build.py ws63-liteos-app</code></td></tr></tbody></table></div><h3 id="校验失败详细排查"><a href="#校验失败详细排查" class="headerlink" title="校验失败详细排查"></a>校验失败详细排查</h3><p>如果最终 ACK 返回 <code>0x01</code>（校验失败），串口日志会打印类似：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[OTA] uapi_upg_verify_file failed, ret=0x800030xx (UPG_XXX)</span><br></pre></td></tr></tbody></table></figure><p>常见错误码：</p><ul><li><code>0x80003040</code>: UPG_NOT_INIT — UPG 未初始化</li><li><code>0x80003044</code>: UPG_INVALID_IMAGE_ID — 镜像 ID 不匹配</li><li><code>0x80003048</code>: UPG_FLASH_ERASE_ERROR — Flash 擦除错误</li><li><code>0x80003051</code>: UPG_NO_ENOUGH_SPACE — 空间不足</li></ul><p><strong>最可能的原因：Bootloader 公钥与新私钥不匹配。</strong></p><p>确认步骤：</p><ol><li>检查 <code>fota.cfg</code> 中的 <code>RootKeyFile</code> 和 <code>SubKeyFile</code> 路径是否正确</li><li>确认 <code>sign_config/</code> 下的 <code>.pem</code> 文件是最新生成的</li><li><strong>重新全量烧录</strong> <code>ws63-liteos-app_all.fwpkg</code>（这是最关键的步骤）</li><li>重新生成 <code>update.fwpkg</code></li><li>再次 OTA 推送</li></ol><hr><h2 id="6-LiteOS-OTA-与-OpenHarmony-OTA-的对比"><a href="#6-LiteOS-OTA-与-OpenHarmony-OTA-的对比" class="headerlink" title="6. LiteOS OTA 与 OpenHarmony OTA 的对比"></a>6. LiteOS OTA 与 OpenHarmony OTA 的对比</h2><h3 id="6-1-相同点"><a href="#6-1-相同点" class="headerlink" title="6.1 相同点"></a>6.1 相同点</h3><div class="md-table-scroll"><table><thead><tr><th align="left">相同点</th><th align="left">说明</th></tr></thead><tbody><tr><td align="left"><strong>签名校验</strong></td><td align="left">都需要使用公私钥对升级包进行签名，设备端用公钥校验，防止刷入非法固件</td></tr><tr><td align="left"><strong>分区备份机制</strong></td><td align="left">都有分区/镜像备份的概念，升级失败时可以回滚到旧版本</td></tr><tr><td align="left"><strong>四步基本流程</strong></td><td align="left">都遵循”制作升级包 → 下载/推送 → 校验 → 重启生效”的基本流程</td></tr><tr><td align="left"><strong>全量升级支持</strong></td><td align="left">都支持全量升级，这是最基础的升级方式</td></tr></tbody></table></div><h3 id="6-2-不同点"><a href="#6-2-不同点" class="headerlink" title="6.2 不同点"></a>6.2 不同点</h3><div class="md-table-scroll"><table><thead><tr><th align="left">对比项</th><th align="left">LiteOS OTA（本文实现）</th><th align="left">OpenHarmony 标准系统 OTA</th></tr></thead><tbody><tr><td align="left"><strong>操作系统</strong></td><td align="left">LiteOS（轻量级实时操作系统）</td><td align="left">OpenHarmony 标准系统（类 Linux 多进程系统）</td></tr><tr><td align="left"><strong>系统架构</strong></td><td align="left">单进程/单任务，应用直接操作硬件</td><td align="left">多进程、多服务，有 init、SA、IPC 等机制</td></tr><tr><td align="left"><strong>升级入口</strong></td><td align="left">C 语言直接调用 UPG 接口</td><td align="left">JS API → update_service SA → 系统安装服务</td></tr><tr><td align="left"><strong>分区设计</strong></td><td align="left">Flash 划分为 Running / Backup / Download / Flag 等区域</td><td align="left">独立的 updater 分区、misc 分区，与主系统隔离</td></tr><tr><td align="left"><strong>启动流程</strong></td><td align="left">Bootloader 直接切换分区并跳转</td><td align="left">uboot 读取 misc 分区指令，加载 updater.img 进入升级模式</td></tr><tr><td align="left"><strong>网络协议</strong></td><td align="left">由应用层自行实现（本文为方便采用 TCP 局域网推送）</td><td align="left">内置 HTTPS 下载，对接厂商 OTA 服务器</td></tr><tr><td align="left"><strong>差分升级</strong></td><td align="left">本文实现不支持（UPG 模块本身不处理差分）</td><td align="left">支持（bsdiff/imgdiff 差分算法）</td></tr><tr><td align="left"><strong>UI 界面</strong></td><td align="left">无</td><td align="left">有升级进度 UI 界面</td></tr><tr><td align="left"><strong>服务器依赖</strong></td><td align="left">局域网 Python 推送脚本即可</td><td align="left">需要搭建搜包服务器 + 下载服务器</td></tr><tr><td align="left"><strong>适用设备</strong></td><td align="left">资源受限的 MCU、模组</td><td align="left">富设备、开发板、手机等</td></tr></tbody></table></div><p>下图展示了 OpenHarmony 标准系统 updater 模式的启动流程，可以看到其需要 uboot 读取 misc 分区指令、加载 updater.img、启动 init 服务等一系列步骤：</p><p><img src="https://image.skyforever.top/blog/2026/05/35f937b6e69795a063f9ee4624fb7acb.webp" alt="标准系统镜像启动流程"></p><p>下图则是 OpenHarmony 标准系统升级子系统的整体架构，包含了 updater_service、updater、公共库、三方库等多个层级，远比本文的 UPG 轻量接口复杂：</p><p><img src="https://image.skyforever.top/blog/2026/05/cf220298fc2ca2ed6029c896dc0bf8c5.webp" alt="标准系统升级子系统架构"></p><hr><h2 id="参考文章"><a href="#参考文章" class="headerlink" title="参考文章"></a>参考文章</h2><div class="md-table-scroll"><table><thead><tr><th align="left">文章</th><th align="left">链接</th><th align="left">说明</th></tr></thead><tbody><tr><td align="left">[经验分享] OTA升级开发指导</td><td align="left"><a href="https://forums.openharmony.cn/forum.php?mod=viewthread&amp;tid=900&amp;extra=page=1&amp;mobile=no" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://forums.openharmony.cn/forum.php?mod=viewthread&amp;tid=900&amp;extra=page%3D1&amp;mobile=no</a></td><td align="left">OpenHarmony 标准系统 updater 模式适配指南</td></tr><tr><td align="left">OTA升级 - openharmony官方文档</td><td align="left"><a href="https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-ota-guide.md#%E7%94%9F%E6%88%90%E5%85%AC%E7%A7%81%E9%92%A5%E5%AF%B9" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-ota-guide.md#%E7%94%9F%E6%88%90%E5%85%AC%E7%A7%81%E9%92%A5%E5%AF%B9</a></td><td align="left">官方文档，覆盖标准系统与轻量/小型系统</td></tr><tr><td align="left">如何实现OpenHarmony的OTA升级?</td><td align="left"><a href="https://cloud.tencent.com/developer/article/2516696" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://cloud.tencent.com/developer/article/2516696</a></td><td align="left">基于 RK3568 的标准系统 OTA 实践</td></tr><tr><td align="left">漫谈LiteOS之OTA 方案概述</td><td align="left"><a href="https://bbs.huaweicloud.com/blogs/180966" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://bbs.huaweicloud.com/blogs/180966</a></td><td align="left">LiteOS IoT Link SDK 的 OTA 方案（HDIFFPATCH + LZMA）</td></tr><tr><td align="left">漫谈LiteOS-Huawei_IoT_Link_SDK_OTA 开发指导</td><td align="left"><a href="https://www.cnblogs.com/hwiot/p/12745773.html" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://www.cnblogs.com/hwiot/p/12745773.html</a></td><td align="left">LiteOS 基于 LwM2M 的 FOTA/SOTA 开发指南</td></tr></tbody></table></div>]]>
    </content>
    <id>https://blog.skyforever.top/posts/49583</id>
    <link href="https://blog.skyforever.top/posts/49583"/>
    <published>2026-05-18T16:00:00.000Z</published>
    <summary>基于 WS63 芯片的 LiteOS OTA 升级完整实现指南，详解 UPG 模块接口原理、环境准备、 TCP 服务端代码实现、升级包推送及常见问题排查。</summary>
    <title>Hi3863 LiteOS OTA 如何实现</title>
    <updated>2026-05-18T16:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="嵌入式" scheme="https://blog.skyforever.top/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F/"/>
    <category term="嵌入式" scheme="https://blog.skyforever.top/tags/%E5%B5%8C%E5%85%A5%E5%BC%8F/"/>
    <category term="单片机" scheme="https://blog.skyforever.top/tags/%E5%8D%95%E7%89%87%E6%9C%BA/"/>
    <category term="多任务" scheme="https://blog.skyforever.top/tags/%E5%A4%9A%E4%BB%BB%E5%8A%A1/"/>
    <category term="状态机" scheme="https://blog.skyforever.top/tags/%E7%8A%B6%E6%80%81%E6%9C%BA/"/>
    <category term="裸机" scheme="https://blog.skyforever.top/tags/%E8%A3%B8%E6%9C%BA/"/>
    <category term="调度器" scheme="https://blog.skyforever.top/tags/%E8%B0%83%E5%BA%A6%E5%99%A8/"/>
    <category term="低功耗" scheme="https://blog.skyforever.top/tags/%E4%BD%8E%E5%8A%9F%E8%80%97/"/>
    <category term="RTOS" scheme="https://blog.skyforever.top/tags/RTOS/"/>
    <category term="协程" scheme="https://blog.skyforever.top/tags/%E5%8D%8F%E7%A8%8B/"/>
    <content>
      <![CDATA[<blockquote><p>本文内出现的例程基本都是伪代码，不确保能直接运行</p></blockquote><h3 id="一、简易多任务"><a href="#一、简易多任务" class="headerlink" title="一、简易多任务"></a>一、简易多任务</h3><h4 id="1、前后台-if-else-标志位轮询"><a href="#1、前后台-if-else-标志位轮询" class="headerlink" title="1、前后台 if else 标志位轮询"></a>1、前后台 if else 标志位轮询</h4><p>如果你需要实现两个不同频率的 led 闪烁任务，那么就不能使用阻塞 delay 了，此时可以考虑使用前后台。</p><p>例如下面这段代码，前台主循环不断轮询标志位，后台中断触发标志位，从而实现两个互不干扰的不同周期 led 闪烁任务</p><figure class="highlight cpp"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 任务标志位</span></span><br><span class="line"><span class="type">uint8_t</span> flag_led1 = <span class="number">0</span>;</span><br><span class="line"><span class="type">uint8_t</span> flag_led2 = <span class="number">0</span>;</span><br><span class="line"><span class="type">uint8_t</span> flag_button = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">(<span class="type">void</span>)</span></span>{</span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>){</span><br><span class="line">        <span class="comment">// led1 闪烁任务，100ms 翻转一次</span></span><br><span class="line">        <span class="keyword">if</span>(flag_led1){</span><br><span class="line">            <span class="comment">// 翻转引脚电平</span></span><br><span class="line">            <span class="built_in">gpio_toggle</span>(led1_pin);</span><br><span class="line">            <span class="comment">// 清除标志位</span></span><br><span class="line">            flag_led1 = <span class="number">0</span>;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">// led2 闪烁任务，20ms 翻转一次</span></span><br><span class="line">        <span class="keyword">if</span>(flag_led2){</span><br><span class="line">            <span class="comment">// 翻转引脚电平</span></span><br><span class="line">            <span class="built_in">gpio_toggle</span>(led2_pin);</span><br><span class="line">            <span class="comment">// 清除标志位</span></span><br><span class="line">            flag_led2 = <span class="number">0</span>;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 按键检测任务</span></span><br><span class="line">        <span class="keyword">if</span>(flag_button){</span><br><span class="line">            <span class="comment">// 打印按键状态变化</span></span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">"Button state change\n"</span>);</span><br><span class="line">            <span class="comment">// 其他操作</span></span><br><span class="line">            <span class="comment">// ...</span></span><br><span class="line">            </span><br><span class="line">            <span class="comment">// 清除标志位</span></span><br><span class="line">            flag_button = <span class="number">0</span>;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 其他任务</span></span><br><span class="line">        <span class="comment">// ...</span></span><br><span class="line">    }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="type">uint64_t</span> systick_counter = <span class="number">0</span>;</span><br><span class="line"><span class="comment">// 系统嘀嗒中断，1ms 中断一次</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">systick_handler</span><span class="params">(<span class="type">void</span>)</span></span>{</span><br><span class="line"></span><br><span class="line">    systick_counter ++;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span>(systick_counter % <span class="number">100</span> == <span class="number">0</span>){ <span class="comment">// led1 100ms 翻转一次</span></span><br><span class="line">        flag_led1 = <span class="number">1</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span>(systick_counter % <span class="number">20</span> == <span class="number">0</span>){ <span class="comment">// led2 20ms 翻转一次</span></span><br><span class="line">        flag_led2 = <span class="number">1</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 其他任务</span></span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 按键边沿中断</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">exti_0_handler</span><span class="params">(<span class="type">void</span>)</span></span>{</span><br><span class="line">    flag_button = <span class="number">1</span>;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h3 id="二、多定时器（multi-timer-）"><a href="#二、多定时器（multi-timer-）" class="headerlink" title="二、多定时器（multi timer ）"></a>二、多定时器（multi timer ）</h3><h4 id="1、硬件多定时器"><a href="#1、硬件多定时器" class="headerlink" title="1、硬件多定时器"></a>1、硬件多定时器</h4><p>对于前面这种需要不同周期执行的任务，如果你的硬件资源足够丰富，那么完全可以配置多个硬件定时器，在硬件定时器中断服务函数里执行相应的操作，而且还能配置优先级抢占，处理好资源竞争实时性完全不输 rtos</p><figure class="highlight scss"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">int <span class="selector-tag">main</span>(void){</span><br><span class="line">    <span class="comment">// 初始化硬件定时器</span></span><br><span class="line">    <span class="built_in">timer_init</span>(&amp;timer1, <span class="number">100</span>, <span class="number">0</span>); <span class="comment">// 100ms 周期，优先级 0</span></span><br><span class="line">    <span class="built_in">timer_init</span>(&amp;timer2, <span class="number">20</span>, <span class="number">1</span>); <span class="comment">// 20ms 周期，优先级 1</span></span><br><span class="line">    <span class="comment">// ...其他任务</span></span><br><span class="line"></span><br><span class="line">    <span class="built_in">while</span>(<span class="number">1</span>){ <span class="comment">// 主循环就相当于 rtos 的空闲（idle）任务</span></span><br><span class="line">        <span class="comment">// 这里还可以直接进入低功耗休眠，等中断唤醒</span></span><br><span class="line">        <span class="built_in">system_sleep_until_interrupt</span>();</span><br><span class="line">    }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 定时器1 中断服务函数，100ms 进入一次</span></span><br><span class="line">void <span class="built_in">timer1_handler</span>(void){</span><br><span class="line">    <span class="built_in">gpio_toggle</span>(led1_pin); <span class="comment">// 翻转 led1 引脚</span></span><br><span class="line">}</span><br><span class="line"><span class="comment">// 定时器2 中断服务函数，20ms 进入一次</span></span><br><span class="line">void <span class="built_in">timer2_handler</span>(void){</span><br><span class="line">    <span class="built_in">gpio_toggle</span>(led2_pin); <span class="comment">// 翻转 led2 引脚</span></span><br><span class="line">    <span class="comment">// 中断内执行耗时操作也没关系，因为会被更高优先级的中断打断</span></span><br><span class="line">}</span><br><span class="line"><span class="comment">// ...其他任务</span></span><br></pre></td></tr></tbody></table></figure><h4 id="2、软件多定时器"><a href="#2、软件多定时器" class="headerlink" title="2、软件多定时器"></a>2、软件多定时器</h4><p>现实是，你根本没那么多的硬件资源，以及硬件定时器灵活性和可移植性会差一点，你可能要套好几个 if else 才能实现一些效果。<br>所以接下来介绍这个非常常用的软件多定时器方案</p><p>对周期任务进行抽象，可以提取出下面这几个基本成员：</p><blockquote><p>抽象：主体从客体身上抽取主体能够理解的意象。在互联网用语上，抽象=难懂的/怪的东西。</p></blockquote><ul><li>周期/重载值</li><li>当前值/计数值</li><li>任务标志位</li><li>任务回调函数</li></ul><p>其实设置这些成员变量就像是在配置一个硬件定时器一样，我们只要每次在 systick 中断中将当前值减一，直到减到零，就重置为重载值，并且把标志位置一。主循环不断轮询所有任务的标志位，一旦检测到某个标志位为一，那么就调用它的回调函数来执行相应任务</p><p>代码可以写成这样：</p><figure class="highlight cpp"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> <span class="title class_">task_stu</span> {</span><br><span class="line">    <span class="type">uint32_t</span> period;    <span class="comment">// 周期/重载值</span></span><br><span class="line">    <span class="type">uint32_t</span> val;       <span class="comment">// 当前值</span></span><br><span class="line">    <span class="type">uint8_t</span> flag;       <span class="comment">// 任务标志位</span></span><br><span class="line"></span><br><span class="line">    <span class="built_in">void</span> (*task_callback_function)(<span class="keyword">struct</span> task_stu *self); <span class="comment">// 任务回调函数</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">struct</span> <span class="title class_">task_stu</span> *next; <span class="comment">// 链表 next 指针</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// void *data; // 私有数据</span></span><br><span class="line">};</span><br></pre></td></tr></tbody></table></figure><p>把每个周期任务配置好后就可以通过数组或者链表进行管理和轮询</p><figure class="highlight cpp"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> <span class="title class_">task_stu</span> {</span><br><span class="line">    <span class="type">uint32_t</span> period;    <span class="comment">// 周期/重载值</span></span><br><span class="line">    <span class="type">uint32_t</span> val;       <span class="comment">// 当前值</span></span><br><span class="line">    <span class="type">uint8_t</span> flag;       <span class="comment">// 任务标志位</span></span><br><span class="line"></span><br><span class="line">    <span class="built_in">void</span> (*task_callback_function)(<span class="keyword">struct</span> task_stu *self); <span class="comment">// 任务回调函数</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">struct</span> <span class="title class_">task_stu</span> *next; <span class="comment">// 链表 next 指针</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// void *data; // 私有数据</span></span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="comment">// 链表头</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">task_stu</span> _task_head = {.next = <span class="literal">NULL</span>};</span><br><span class="line"></span><br><span class="line"><span class="comment">// led1 闪烁任务</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">task_cb_led1</span><span class="params">(<span class="keyword">struct</span> task_stu *self)</span></span>;</span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">task_stu</span> task_led1 = {</span><br><span class="line">    .period = <span class="number">100</span>;</span><br><span class="line">    .val = <span class="number">100</span>;</span><br><span class="line">    .flag = <span class="number">0</span>;</span><br><span class="line">    </span><br><span class="line">    .task_callback_function = task_cb_led1;</span><br><span class="line"></span><br><span class="line">    .next = <span class="literal">NULL</span>;</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="comment">// led2 闪烁任务</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">task_cb_led2</span><span class="params">(<span class="keyword">struct</span> task_stu *self)</span></span>;</span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">task_stu</span> task_led1 = {</span><br><span class="line">    .period = <span class="number">20</span>;</span><br><span class="line">    .val = <span class="number">20</span>;</span><br><span class="line">    .flag = <span class="number">0</span>;</span><br><span class="line">    </span><br><span class="line">    .task_callback_function = task_cb_led2;</span><br><span class="line"></span><br><span class="line">    .next = <span class="literal">NULL</span>;</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">(<span class="type">void</span>)</span></span>{</span><br><span class="line"></span><br><span class="line">    <span class="built_in">task_add</span>(&amp;task_led1); <span class="comment">// 将任务一添加到链表中</span></span><br><span class="line">    <span class="built_in">task_add</span>(&amp;task_led2); <span class="comment">// 将任务二添加到链表中</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">struct</span> <span class="title class_">task_stu</span> *pTask = _task_head.next;</span><br><span class="line">    <span class="keyword">while</span>(pTask != <span class="literal">NULL</span>){</span><br><span class="line">        <span class="keyword">if</span>(pTask-&gt;flag){</span><br><span class="line">            pTask-&gt;flag = <span class="number">0</span>; <span class="comment">// 运行标志位置零</span></span><br><span class="line">            </span><br><span class="line">            <span class="keyword">if</span>(pTask-&gt;task_callback_function != <span class="literal">NULL</span>){</span><br><span class="line">                <span class="comment">// 调用任务回调函数</span></span><br><span class="line">                pTask-&gt;<span class="built_in">task_callback_function</span>(pTask);</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        pTask = pTask-&gt;next;</span><br><span class="line">    }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// led1 闪烁任务</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">task_cb_led1</span><span class="params">(<span class="keyword">struct</span> task_stu *self)</span></span>{</span><br><span class="line">    <span class="built_in">gpio_toggle</span>(led1_pin);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// led2 闪烁任务</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">task_cb_led2</span><span class="params">(<span class="keyword">struct</span> task_stu *self)</span></span>{</span><br><span class="line">    <span class="built_in">gpio_toggle</span>(led2_pin);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// systick 中断</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">systick_handler</span><span class="params">(<span class="type">void</span>)</span></span>{</span><br><span class="line">    <span class="keyword">struct</span> <span class="title class_">task_stu</span> *pTask = _task_head.next;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 给链表中的每个节点当前计时值减一，判断是否需要运行</span></span><br><span class="line">    <span class="keyword">while</span>(pTask != <span class="literal">NULL</span>){</span><br><span class="line">        <span class="keyword">if</span>(-- pTask-&gt;val == <span class="number">0</span>){</span><br><span class="line">            pTask-&gt;val = pTask-&gt;period; <span class="comment">// 将当前值重置为重载值</span></span><br><span class="line">            pTask-&gt;flag = <span class="number">1</span>; <span class="comment">// 运行标志位置一</span></span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        pTask = pTask-&gt;next;</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>这样就可以把每个任务放在各自的回调里进行执行，代码更加分明</p><p>有些教程会用数组去进行管理，会带来一些局限性，比如不好删除和新增任务，当然，在增删链表节点的时候需要开关中断来保证原子操作</p><h3 id="三、-switch-case-状态机"><a href="#三、-switch-case-状态机" class="headerlink" title="三、 switch case 状态机"></a>三、 switch case 状态机</h3><p>软件定时器已经可以解决大部分 项目 ，但是依然不够全面，很多任务并不一定是固定周期执行的，比如下面这个每秒读取温度的任务：</p><figure class="highlight cpp"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">(<span class="type">void</span>)</span></span>{</span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>){</span><br><span class="line">        <span class="built_in">temp_trans</span>(&amp;my_temp_sensor); <span class="comment">// 让温度传感器开始进行温度转换</span></span><br><span class="line"></span><br><span class="line">        <span class="built_in">delay_ms</span>(<span class="number">20</span>); <span class="comment">// 温度转换需要 20ms</span></span><br><span class="line"></span><br><span class="line">        <span class="type">float</span> temp_val = <span class="built_in">temp_read</span>(&amp;my_temp_sensor); <span class="comment">// 读取温度</span></span><br><span class="line">        <span class="built_in">display_temp</span>(temp_val); <span class="comment">// 显示更新后的温度</span></span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">"temp update: %f\n"</span>, temp_val); <span class="comment">// 打印更新后的温度</span></span><br><span class="line"></span><br><span class="line">        <span class="built_in">delay_ms</span>(<span class="number">980</span>); <span class="comment">// 下一秒再次更新温度</span></span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>这个时候，就可以通过状态机来实现这个功能，代码如下：</p><figure class="highlight cpp"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">uint32_t</span> <span class="title">get_systick</span><span class="params">(<span class="type">void</span>)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="type">float</span> temp_val = <span class="number">25.0</span>;</span><br><span class="line"><span class="type">uint8_t</span> flag_temp_read_over = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 温度检测任务</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">task1_get_temp</span><span class="params">(<span class="type">void</span>)</span></span>{</span><br><span class="line">    <span class="type">static</span> <span class="type">uint32_t</span> last_tick = <span class="number">0</span>;</span><br><span class="line">    <span class="type">static</span> <span class="type">uint8_t</span> step = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">switch</span>(step){</span><br><span class="line">        <span class="keyword">case</span> <span class="number">0</span>: <span class="comment">// 发起温度转换</span></span><br><span class="line">            <span class="built_in">temp_trans</span>(&amp;my_temp_sensor); <span class="comment">// 让温度传感器开始进行温度转换</span></span><br><span class="line">            step = <span class="number">1</span>; <span class="comment">// 进入转换等待状态</span></span><br><span class="line">            last_tick = <span class="built_in">get_systick</span>(); <span class="comment">// 设置计时起始值</span></span><br><span class="line"></span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// delay_ms(20);</span></span><br><span class="line">        <span class="keyword">case</span> <span class="number">1</span>: <span class="comment">// 等待转换完成，相当于非阻塞延迟 20ms</span></span><br><span class="line">            <span class="keyword">if</span>(<span class="built_in">get_systick</span>() - last_tick &gt; <span class="number">20</span>){ <span class="comment">// 转换需要 20ms</span></span><br><span class="line">                step = <span class="number">2</span>; <span class="comment">// 进入数据读取状态</span></span><br><span class="line">            }</span><br><span class="line"></span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">case</span> <span class="number">2</span>: <span class="comment">// 转换完成</span></span><br><span class="line">            <span class="comment">// 读取转换好的温度</span></span><br><span class="line">            temp_val = <span class="built_in">temp_read</span>(&amp;my_temp_sensor);</span><br><span class="line">            flag_temp_read_over ++; <span class="comment">// 温度读取完成，发布</span></span><br><span class="line">            last_tick = <span class="built_in">get_systick</span>(); <span class="comment">// 设置计时起始值</span></span><br><span class="line">            step = <span class="number">3</span>; <span class="comment">// 进入数据读取状态</span></span><br><span class="line">            </span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// delay_ms(980);</span></span><br><span class="line">        <span class="keyword">case</span> <span class="number">3</span>: <span class="comment">// 1s 后发起下一次转换，这里相当于非阻塞 delay 980ms</span></span><br><span class="line">            <span class="keyword">if</span>(<span class="built_in">get_systick</span>() - last_tick &gt; <span class="number">980</span>){ <span class="comment">// 每秒发起一次温度读取</span></span><br><span class="line">                step = <span class="number">0</span>; <span class="comment">// 进入发起温度转换状态</span></span><br><span class="line">            }</span><br><span class="line"></span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">    }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">task2_display</span><span class="params">(<span class="type">void</span>)</span></span>{</span><br><span class="line">    <span class="type">static</span> <span class="type">uint8_t</span> last_flag_temp_read_over = <span class="number">0</span>;</span><br><span class="line">    <span class="comment">// ...其他显示内容</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span>(last_flag_temp_read_over != flag_temp_read_over){ <span class="comment">// 温度读取计数变化</span></span><br><span class="line">        <span class="comment">// 更新显示温度</span></span><br><span class="line">        <span class="built_in">display_temp</span>(temp_val);</span><br><span class="line">        last_flag_temp_read_over = flag_temp_read_over;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ...其他显示内容</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">task3_print</span><span class="params">(<span class="type">void</span>)</span></span>{</span><br><span class="line">    <span class="type">static</span> <span class="type">uint8_t</span> last_flag_temp_read_over = <span class="number">0</span>;</span><br><span class="line">    <span class="comment">// ...其他打印内容</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span>(last_flag_temp_read_over != flag_temp_read_over){ <span class="comment">// 温度读取计数变化</span></span><br><span class="line">        <span class="comment">// 打印新温度值</span></span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">"temp update: %f\n"</span>, temp_val);</span><br><span class="line">        last_flag_temp_read_over = flag_temp_read_over;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ...其他打印内容</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">(<span class="type">void</span>)</span></span>{</span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>){</span><br><span class="line">        <span class="built_in">task1_get_temp</span>();   <span class="comment">// 每秒读取温度任务</span></span><br><span class="line">        <span class="built_in">task2_display</span>();    <span class="comment">// 显示数据任务</span></span><br><span class="line">        <span class="built_in">task3_print</span>();      <span class="comment">// 打印数据任务</span></span><br><span class="line">        <span class="comment">// ...其他任务</span></span><br><span class="line">    }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="type">uint32_t</span> systick;</span><br><span class="line"><span class="comment">// systick 中断，1ms 一次</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">systick_handler</span><span class="params">(<span class="type">void</span>)</span></span>{</span><br><span class="line">    systick ++;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">uint32_t</span> <span class="title">get_systick</span><span class="params">(<span class="type">void</span>)</span></span>{</span><br><span class="line">    <span class="keyword">return</span> systick;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>这里面的 case 1 和 case 3 分别相当于 <code>delay_ms(20)</code> 和 <code>delay_ms(980)</code>，不过并不是阻塞的，它每次进入都会判断时间有没有到，没有到则 break 退出状态机让其他任务执行，到了再切换状态。</p><p>或者也可以与软件定时器结合起来实现这个效果，也就是修改软件定时器的周期和计数值：</p><figure class="highlight objectivec"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> task_stu task_get_temp = {</span><br><span class="line">    .period = <span class="number">1000</span>, <span class="comment">// 每秒发起一次温度检测</span></span><br><span class="line">    .val = <span class="number">1000</span>,</span><br><span class="line">    .flag = <span class="number">0</span>,</span><br><span class="line"></span><br><span class="line">    .task_callback_function = task2_get_temp;</span><br><span class="line"></span><br><span class="line">    .next = <span class="literal">NULL</span>,</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="comment">// 温度检测任务</span></span><br><span class="line"><span class="type">void</span> task2_get_temp(<span class="keyword">struct</span> task_stu *<span class="keyword">self</span>){</span><br><span class="line">    <span class="keyword">static</span> uint32_t last_tick = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">static</span> uint8_t step = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">switch</span>(step){</span><br><span class="line">        <span class="keyword">case</span> <span class="number">0</span>: <span class="comment">// 每秒发起一次温度读取</span></span><br><span class="line">            temp_trans(&amp;my_temp_sensor); <span class="comment">// 让温度传感器开始进行温度转换</span></span><br><span class="line">            <span class="comment">// 将软件定时器的周期改为 20ms</span></span><br><span class="line">            <span class="keyword">self</span>-&gt;period = <span class="number">20</span>;</span><br><span class="line">            <span class="keyword">self</span>-&gt;val = <span class="number">20</span>;</span><br><span class="line">            step = <span class="number">1</span>; <span class="comment">// 20ms 后会进入转换完成状态</span></span><br><span class="line"></span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">case</span> <span class="number">1</span>: <span class="comment">// 转换完成</span></span><br><span class="line">            <span class="comment">// 读取转换好的温度</span></span><br><span class="line">            temp_val = temp_read(&amp;my_temp_sensor);</span><br><span class="line">            temp_read_over(); <span class="comment">// 温度读取完成，发布</span></span><br><span class="line">            <span class="comment">// 将软件定时器的周期改为 980ms</span></span><br><span class="line">            <span class="keyword">self</span>-&gt;period = <span class="number">980</span>;</span><br><span class="line">            <span class="keyword">self</span>-&gt;val = <span class="number">980</span>;</span><br><span class="line">            step = <span class="number">0</span>; <span class="comment">// 1s 后会进入发起温度转换状态</span></span><br><span class="line">            </span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">    }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> main(<span class="type">void</span>){</span><br><span class="line">    <span class="comment">//...</span></span><br><span class="line">    task_add(&amp;task_get_temp);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>){</span><br><span class="line">        <span class="comment">//...轮询</span></span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h3 id="四、事件驱动框架"><a href="#四、事件驱动框架" class="headerlink" title="四、事件驱动框架"></a>四、事件驱动框架</h3><p>上面的状态机也能算事件驱动，只有温度更新了才去打印和显示，这样就不会反复打印旧温度，事件驱动的底层就是 if else，所以这里更强调的是事件驱动的“框架”，通过构建框架，可以提供更高的灵活性和更清晰的程序结构。</p><h4 id="1、osal-operating-system-abstraction-layer-，操作系统抽象层"><a href="#1、osal-operating-system-abstraction-layer-，操作系统抽象层" class="headerlink" title="1、osal(operating system abstraction layer ，操作系统抽象层)"></a>1、osal(operating system abstraction layer ，操作系统抽象层)</h4><p>直接看源码，osal 会给每个 task 分配一个 uint16 的事件集变量，每一位可以配置为一个事件，如果某个 task 有事件触发，也就是这个变量某一位不为 0，那么就会执行这个任务，以下是 osal 的部分源码：</p><figure class="highlight cpp"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// task 对象结构体</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span> <span class="title class_">OSALTaskREC</span></span><br><span class="line">{</span><br><span class="line">    <span class="keyword">struct</span>  <span class="title class_">OSALTaskREC</span>  *next;</span><br><span class="line">    pTaskInitFn          pfnInit;<span class="comment">// 任务初始化函数指针</span></span><br><span class="line">    pTaskEventHandlerFn  pfnEventProcessor;    <span class="comment">// 任务事件处理函数指针</span></span><br><span class="line">    uint8                taskID;<span class="comment">// 任务ID</span></span><br><span class="line">    uint8                taskPriority;    <span class="comment">// 任务优先级</span></span><br><span class="line">    uint16               events;<span class="comment">// 任务事件集</span></span><br><span class="line">} OsalTadkREC_t;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 可以通过 api 对某个任务设置事件</span></span><br><span class="line"><span class="function">uint8 <span class="title">osal_set_event</span><span class="params">( byte task_id, uint16 event_flag )</span></span>;</span><br><span class="line"><span class="function">uint8 <span class="title">osal_clear_event</span><span class="params">( uint8 task_id, uint16 event_flag )</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="function">OsalTadkREC_t *<span class="title">osalNextActiveTask</span><span class="params">( <span class="type">void</span> )</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line">  OsalTadkREC_t  *TaskSech;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// Start at the beginning</span></span><br><span class="line">  TaskSech = TaskHead;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// When found or not</span></span><br><span class="line">  <span class="keyword">while</span> ( TaskSech ) </span><br><span class="line">{</span><br><span class="line">        <span class="keyword">if</span> ( TaskSech-&gt;events )</span><br><span class="line">        {</span><br><span class="line">  <span class="comment">// task is highest priority that is ready</span></span><br><span class="line">          <span class="keyword">return</span>  TaskSech;</span><br><span class="line">      }</span><br><span class="line">      TaskSech =  TaskSech-&gt;next;</span><br><span class="line">  }</span><br><span class="line">  <span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">osal_start_system</span><span class="params">( <span class="type">void</span> )</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line">    uint16 events;</span><br><span class="line">    uint16 retEvents;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 这里就是 osal 的主循环</span></span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>){</span><br><span class="line">        <span class="comment">// 不断获取活跃任务</span></span><br><span class="line">        TaskActive = <span class="built_in">osalNextActiveTask</span>();</span><br><span class="line">        <span class="keyword">if</span> ( TaskActive ){</span><br><span class="line">            <span class="built_in">HAL_ENTER_CRITICAL_SECTION</span>();</span><br><span class="line">            events = TaskActive-&gt;events;</span><br><span class="line">            <span class="comment">// Clear the Events for this task</span></span><br><span class="line">            TaskActive-&gt;events = <span class="number">0</span>;</span><br><span class="line">            <span class="built_in">HAL_EXIT_CRITICAL_SECTION</span>();</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 如果这个任务的事件集不为 0</span></span><br><span class="line">            <span class="keyword">if</span> ( events != <span class="number">0</span> ){</span><br><span class="line">                <span class="comment">// Call the task to process the event(s)</span></span><br><span class="line">                <span class="keyword">if</span> ( TaskActive-&gt;pfnEventProcessor ){</span><br><span class="line">                    <span class="comment">// 调用任务回调函数</span></span><br><span class="line">                    retEvents = (TaskActive-&gt;pfnEventProcessor)(TaskActive-&gt;taskID, events);</span><br><span class="line"></span><br><span class="line">                    <span class="comment">// Add back unprocessed events to the current task</span></span><br><span class="line">                    <span class="built_in">HAL_ENTER_CRITICAL_SECTION</span>();</span><br><span class="line">                    TaskActive-&gt;events |= retEvents;</span><br><span class="line">                    <span class="built_in">HAL_EXIT_CRITICAL_SECTION</span>();</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>这个 osal 个人认为非常清晰明了，它里面还有一些软件定时器和消息组件等等，比较推荐大家使用</p><p>下面这个是他人 fork 在 github 的带中文注释版本的 osal 源码：</p><ul><li>github: <a href="https://github.com/mcuwty/osal" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>mcuwty/osal</a></li></ul><p>下面这个视频是 osal 的相关教程：<br><img src="https://image.skyforever.top/blog/2026/05/f8ee5f49559da78b7daaba6496bd6867.webp" alt="osal教程"></p><p><a href="https://www.bilibili.com/video/BV1ajsJecEmq" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>【Bilibili】@三林渡口 - 【架构分析】嵌入式祼机事件驱动框架_01_任务实现</a></p><h4 id="2、ltx-裸机调度器"><a href="#2、ltx-裸机调度器" class="headerlink" title="2、ltx 裸机调度器"></a>2、ltx 裸机调度器</h4><p>ltx 裸机调度器是由软件多定时器发展过来的，除了软件定时器，还有两个基本组件，分别为闹钟和话题。本人最近几个 开源项目 使用的都是 ltx 裸机调度器，因为这个 ltx 就是我写的。<br>ltx 中的话题就是一个单标志位的事件，只要话题被发布，那么订阅这个话题的所有订阅者都会被调用，例如下面这个中断按键消抖功能：</p><p>每次产生边沿中断，都会将消抖闹钟的倒计时重置，直到不抖动 15ms 之后，调用回调，发布事件</p><p><img src="https://image.skyforever.top/blog/2026/05/9d44789e64aa30f31b19ce0deddb9639.webp" alt="闹钟消抖中断按键"></p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 按键边沿中断</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">exti_0_handler</span>(<span class="params"><span class="keyword">void</span></span>){</span><br><span class="line">    <span class="comment">// 每次进中断都将闹钟倒计时重置</span></span><br><span class="line">    <span class="title function_">ltx_Alarm_add</span>(&amp;alarm_debounce, <span class="number">15</span>); <span class="comment">// 添加闹钟，如果存在则不会重复添加</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 消抖闹钟回调，按键不抖动 15ms 后会被调用</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">alarm_cb_debounce</span>(<span class="params"><span class="keyword">void</span> *param</span>){</span><br><span class="line">    <span class="comment">// 按键消抖完成</span></span><br><span class="line">    <span class="comment">// 发布按键变化事件</span></span><br><span class="line">    <span class="title function_">ltx_Topic_publish</span>(&amp;topic_debounce_over);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 按键变化打印，订阅按键消抖完成话题</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">subscriber_cb_1</span>(<span class="params"><span class="keyword">void</span> *param</span>){</span><br><span class="line">    <span class="title function_">printf</span>(<span class="string">"button change to: %d\n"</span>, <span class="title function_">gpio_read</span>(key1));</span><br><span class="line">}</span><br><span class="line"><span class="comment">// 按键变化后改变 led 引脚状态为按键状态</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">subscriber_cb_2</span>(<span class="params"><span class="keyword">void</span> *param</span>){</span><br><span class="line">    <span class="title function_">gpio_write</span>(led1, <span class="title function_">gpio_read</span>(key1));</span><br><span class="line">}</span><br><span class="line"><span class="comment">// 其他需要按键变化响应的订阅者回调</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">subscriber_cb_3</span>(<span class="params"><span class="keyword">void</span> *param</span>){</span><br><span class="line">    <span class="comment">//...</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 脚本也可以订阅话题</span></span><br></pre></td></tr></tbody></table></figure><p>我之前开源的 1us 低延迟反应力测试器项目就是通过闹钟对中断按键进行消抖的。</p><p>ltx 源码主循环中也是不断在对话题链表和闹钟链表进行轮询，一旦标志位不为零，那么就依次调用所有订阅者回调</p><p>以下是 ltx 源码发布页：</p><ul><li>github: <a href="https://github.com/TiX233/ltx" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>TiX233/ltx</a></li><li>gitee: <a href="https://gitee.com/TiX233/ltx" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>TiX233/ltx</a></li></ul><h4 id="3、qp-c-框架"><a href="#3、qp-c-框架" class="headerlink" title="3、qp/c 框架"></a>3、qp/c 框架</h4><p>这是一个体量稍大一点的事件驱动框架。和一般的状态机不同，它更强调层次状态机，也就是状态机套状态机，这个框架更适合管理那种父状态机套着子状态机的上下文，比如一些 gui 场景或者大型项目，层次状态机对于事件的派发会更直观一点。如果想要详细了解的话，它有配套的书籍和比较多的例程可以参考，站内也有一些教程视频：</p><p><img src="https://image.skyforever.top/blog/2026/05/ba4ae77d7982152a783dde6fcb94c63f.webp" alt="qpc"></p><p><a href="https://www.bilibili.com/video/BV125YQecETw" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>【Bilibili】QP状态机嵌入式编程</a></p><p><img src="https://image.skyforever.top/blog/2026/05/b48c3d8e95812ee91f3cc6c760bef58b.webp" alt="qpc教程1"></p><p><a href="https://www.bilibili.com/video/BV1YV3ve3EHf" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>【Bilibili】@__MF - 事件驱动型编程和 QP/C 框架</a></p><p><img src="https://image.skyforever.top/blog/2026/05/7dfdc7aabe88ebb72e5d646f9bd0ba04.webp" alt="qpc教程2"></p><p><a href="https://www.bilibili.com/video/BV1RaxvzBEPu" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>【Bilibili】@心明可现 - 事件驱动编程05——逐行硬核解析QP/C源码，让编程水平上升一个level！</a></p><p>qpc 源码发布页：</p><ul><li>github：<a href="https://github.com/QuantumLeaps/qpc" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>QuantumLeaps/qpc</a></li></ul><h3 id="五、协程"><a href="#五、协程" class="headerlink" title="五、协程"></a>五、协程</h3><h4 id="1、什么是协程"><a href="#1、什么是协程" class="headerlink" title="1、什么是协程"></a>1、什么是协程</h4><p>其实你知道它的全称就能了解个大概了，协作式多线程，任务间是相互协作的，由每个任务自己决定什么时候出让 cpu，而相对的，rtos 里的线程，则能实现抢占式多线程。<br>如果任务设计得当，协程可以比线程快很多，因为它不需要保存任务上下文，切换开销很低。</p><p>推荐观看这个视频，看完便能理解无栈协程的底层逻辑：<br><img src="https://image.skyforever.top/blog/2026/05/8b68079ddc198cbfa6e0d49653c0f575.webp" alt="协程"></p><p><a href="https://www.bilibili.com/video/BV1dv4y127YT" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>【Bilibili】@等疾风 - 【协程革命】实现篇！无栈协程 有手就行？！ 全程字幕</a></p><p>接下来介绍几种单片机里的协程方案</p><h4 id="2、protothreads-pt-thread-宏-协程"><a href="#2、protothreads-pt-thread-宏-协程" class="headerlink" title="2、protothreads (pt-thread) 宏 协程"></a>2、protothreads (pt-thread) 宏 协程</h4><p>和上面推荐的视频里的无栈协程非常类似，这个宏协程其实就是对 switch case 进行了一层封装，让你能够更优雅地进行出让。他可以将 label 或者行号作为 case，经过宏封装过后的代码看起来会比普通的 switch case 更清晰，甚至看起来都不像是在写裸机程序</p><figure class="highlight cpp"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">static</span> <span class="type">int</span> protothread2_flag = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">protothread1</span><span class="params">(<span class="keyword">struct</span> pt *pt)</span></span>{</span><br><span class="line"></span><br><span class="line">    <span class="built_in">PT_BEGIN</span>(pt);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>) {</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">"Protothread 1 step1\n"</span>);</span><br><span class="line">        <span class="built_in">PT_YIELD</span>(pt); <span class="comment">// 出让 cpu</span></span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">"Protothread 1 step2\n"</span>);</span><br><span class="line">        <span class="built_in">PT_YIELD</span>(pt); <span class="comment">// 出让 cpu</span></span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">"Protothread 1 step3\n"</span>);</span><br><span class="line">        protothread2_flag = <span class="number">1</span>;</span><br><span class="line">        <span class="built_in">PT_YIELD</span>(pt); <span class="comment">// 出让 cpu</span></span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="built_in">PT_END</span>(pt);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">protothread2</span><span class="params">(<span class="keyword">struct</span> pt *pt)</span></span>{</span><br><span class="line"></span><br><span class="line">    <span class="built_in">PT_BEGIN</span>(pt);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>) {</span><br><span class="line">        protothread2_flag = <span class="number">0</span>;</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 出让 cpu，直到条件为真再继续执行下面的内容</span></span><br><span class="line">        <span class="built_in">PT_WAIT_UNTIL</span>(pt, protothread1_flag != <span class="number">0</span>);</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">"Protothread 2 running\n"</span>);</span><br><span class="line">        </span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="built_in">PT_END</span>(pt);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="type">static</span> <span class="keyword">struct</span> <span class="title class_">pt</span> pt1, pt2;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">(<span class="type">void</span>)</span></span>{</span><br><span class="line">    </span><br><span class="line">    <span class="built_in">PT_INIT</span>(&amp;pt1);</span><br><span class="line">    <span class="built_in">PT_INIT</span>(&amp;pt2);</span><br><span class="line">  </span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>) {</span><br><span class="line">        <span class="built_in">protothread1</span>(&amp;pt1);</span><br><span class="line">        <span class="built_in">protothread2</span>(&amp;pt2);</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>将其中宏进行展开：</p><figure class="highlight cpp"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">protothread1</span><span class="params">(<span class="keyword">struct</span> pt *pt)</span></span>{</span><br><span class="line"></span><br><span class="line">    <span class="comment">// PT_BEGIN(pt);</span></span><br><span class="line">    <span class="type">char</span> PT_YIELD_FLAG = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">switch</span>(pt-&gt;lc){ </span><br><span class="line">        <span class="keyword">case</span> <span class="number">0</span>:</span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>) {</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">"Protothread 1 step1\n"</span>);</span><br><span class="line">        <span class="comment">// PT_YIELD(pt);</span></span><br><span class="line">        PT_YIELD_FLAG = <span class="number">0</span>;</span><br><span class="line">        pt-&gt;lc = __LINE__; <span class="keyword">case</span> __LINE__:</span><br><span class="line">        <span class="keyword">if</span>(PT_YIELD_FLAG == <span class="number">0</span>) {</span><br><span class="line">            <span class="keyword">return</span> PT_YIELDED;</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">"Protothread 1 step2\n"</span>);</span><br><span class="line">        <span class="built_in">PT_YIELD</span>(pt);</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">"Protothread 1 step3\n"</span>);</span><br><span class="line">        protothread2_flag = <span class="number">1</span>;</span><br><span class="line">        <span class="built_in">PT_YIELD</span>(pt);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// PT_END(pt);</span></span><br><span class="line">    }</span><br><span class="line">    PT_YIELD_FLAG = <span class="number">0</span>;</span><br><span class="line">    pt-&gt;lc = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">return</span> PT_ENDED;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">protothread2</span><span class="params">(<span class="keyword">struct</span> pt *pt)</span></span>{</span><br><span class="line"></span><br><span class="line">    <span class="built_in">PT_BEGIN</span>(pt);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>) {</span><br><span class="line">        protothread2_flag = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">        <span class="built_in">PT_WAIT_UNTIL</span>(pt, protothread1_flag != <span class="number">0</span>);</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">"Protothread 2 running\n"</span>);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="built_in">PT_END</span>(pt);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>以下是源码发布页：<br><a href="https://dunkels.com/adam/pt/download.html" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>pt-thread</a></p><p>他人 fork 在 github 的带中文注释的源码：</p><ul><li>github：<a href="https://github.com/Akagi201/protothreads" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>Akagi201/protothreads</a></li></ul><p>以下是搜到的两个教程视频：</p><p><img src="https://image.skyforever.top/blog/2026/05/e655dd6d74891e291c249041016f9eb4.webp" alt="pt1"></p><p><a href="https://www.bilibili.com/video/BV1sd4y1b7Rs" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>【Bilibili】@峻德的 - 单片机 嵌入式 protothreads (pt-thread) 协程源码分析</a></p><p><img src="https://image.skyforever.top/blog/2026/05/afd6ac8e8ac0b50025965dbbfc78faab.webp" alt="pt2"></p><p><a href="https://www.bilibili.com/video/BV1CM411H7JJ" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>【Bilibili】@我和我的妹妹雯雯 - 单片机宏协程，介于状态机和RTOS之间的选择，三行代码零资源实现丝滑的多任务切换</a></p><h4 id="3、ltx-脚本组件"><a href="#3、ltx-脚本组件" class="headerlink" title="3、ltx 脚本组件"></a>3、ltx 脚本组件</h4><p>其实单单对 switch case 进行封装还是不够优雅，因为你还是要在 switch case 里面插入额外的倒计时轮询步骤。</p><p>所以接下来介绍 ltx 的脚本组件。<br>先看效果，打眼一看，其实还是 switch case，但是每个 case 之间可以设置非阻塞的延时时间，并且还可以设置下一个 case 等待某个事件并设置超时时间。<br>这一切都是依赖 ltx 调度器实现的，即便是协程，也是需要一个调度器的，宏协程的调度器其实就是最外层的 while(1)，所以只能靠每个任务内部自己轮询 tick 和 flag，而 ltx 脚本组件是对 ltx 基础组件的封装拓展（话题与闹钟），所以对时间和事件的轮询会交给 ltx 调度器（主循环）。</p><p>下面是一个脚本回调的样例：</p><figure class="highlight cpp"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">script_cb_test</span><span class="params">(<span class="keyword">struct</span> ltx_Script_stu *script)</span></span>{</span><br><span class="line">    <span class="keyword">if</span>(<span class="built_in">ltx_Script_get_triger_type</span>(script) == SC_TRIGER_RESET){</span><br><span class="line">        <span class="comment">// 外部要求此脚本复位，可在此处做释放资源等操作</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> ;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">switch</span>(script-&gt;step_now){</span><br><span class="line">        <span class="keyword">case</span> <span class="number">0</span>:</span><br><span class="line">            <span class="comment">// 步骤0</span></span><br><span class="line"></span><br><span class="line">            <span class="comment">// ...需要执行的内容...</span></span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">"This is step0 running...\n"</span>);</span><br><span class="line">            </span><br><span class="line">            <span class="comment">// 设置下一步骤为延时一段时间后再执行</span></span><br><span class="line">            <span class="built_in">ltx_Script_next_step_delay</span>(script,      <span class="comment">// 脚本指针</span></span><br><span class="line">                                       <span class="number">1</span>,           <span class="comment">// 下一个步骤编号</span></span><br><span class="line">                                       <span class="number">200</span>);        <span class="comment">// 延迟时间为 200ms</span></span><br><span class="line">            <span class="comment">// break 退出 step0，200ms 后会进入 step1</span></span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">case</span> <span class="number">1</span>:</span><br><span class="line">            <span class="comment">// 步骤1</span></span><br><span class="line"></span><br><span class="line">            <span class="comment">// ...需要执行的内容...</span></span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">"This is step1 running...\n"</span>);</span><br><span class="line">            </span><br><span class="line">            <span class="comment">// 设置下一步骤为延时一段时间后再执行</span></span><br><span class="line">            <span class="built_in">ltx_Script_next_step_delay</span>(script,      <span class="comment">// 脚本指针</span></span><br><span class="line">                                       <span class="number">2</span>,           <span class="comment">// 下一个步骤编号</span></span><br><span class="line">                                       <span class="number">0</span>);          <span class="comment">// 延迟时间为 0ms</span></span><br><span class="line">            <span class="comment">// 因为设置的步骤间延时为 0，所以会在 break 后短暂出让一次 cpu 给其他任务执行机会，然后立即进入 step2</span></span><br><span class="line">            <span class="comment">// 具体来讲就是把当前脚本加入就绪任务队列的末尾</span></span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">case</span> <span class="number">2</span>:</span><br><span class="line">            <span class="comment">// 步骤2</span></span><br><span class="line"></span><br><span class="line">            <span class="comment">// ...需要执行的内容...</span></span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">"This is step2 running...\n"</span>);</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 设置下一步骤为等待某个事件产生或者超时再执行</span></span><br><span class="line">            <span class="built_in">ltx_Script_next_step_topic</span>(script,      <span class="comment">// 脚本指针</span></span><br><span class="line">                                       <span class="number">3</span>,           <span class="comment">// 下一个步骤编号</span></span><br><span class="line">                                       <span class="number">100</span>,         <span class="comment">// 事件等待超时时间为 100ms</span></span><br><span class="line">                                       &amp;topic_button_click); <span class="comment">// 需要等待的事件的指针</span></span><br><span class="line">            <span class="comment">// 按键单击事件触发或者超时 100ms 会进入 step3</span></span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">case</span> <span class="number">3</span>:</span><br><span class="line">            <span class="comment">// 步骤3，会在步骤3订阅的事件发生后调用，或者超时也会调用</span></span><br><span class="line">            <span class="keyword">if</span>(<span class="built_in">ltx_Script_get_triger_type</span>(script) == SC_TRIGER_TIMEOUT){ <span class="comment">// 因为超时而调用</span></span><br><span class="line">                <span class="built_in">printf</span>(<span class="string">"Step3 wait topic timeout!\n"</span>);</span><br><span class="line">            }<span class="keyword">else</span> { <span class="comment">// 因为事件触发而调用</span></span><br><span class="line">                <span class="built_in">printf</span>(<span class="string">"Step3 get topic\n"</span>);</span><br><span class="line">            }</span><br><span class="line">            <span class="comment">// ...设置下一步骤...</span></span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ...</span></span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>效果和 rtos 等待信号量并设置超时时间比较类似，使用起来也比较直观</p><h4 id="4、longjmp-协程"><a href="#4、longjmp-协程" class="headerlink" title="4、longjmp 协程"></a>4、longjmp 协程</h4><p>我想几乎不太会有人在单片机里用这个，你可以通过 setjmp 保存当前位置上下文，在其他地方可以用 longjmp 跳回来，可以理解为一种跨函数的 goto 。</p><p>不太推荐这种做法，所以不做详细展开，想要详细了解可以看一下下面这个视频：<br><img src="https://image.skyforever.top/blog/2026/05/08ec9b4b703ed696ab9a419a34e86311.webp" alt="longjmp"></p><p><a href="https://www.bilibili.com/video/BV1VC4y1w7BZ" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>【Bilibili】@阿布编程 - CPU眼里的：setjmp | longjmp</a></p><h3 id="六、裸机多任务与-rtos-多任务的区别总结"><a href="#六、裸机多任务与-rtos-多任务的区别总结" class="headerlink" title="六、裸机多任务与 rtos 多任务的区别总结"></a>六、裸机多任务与 rtos 多任务的区别总结</h3><h4 id="1、非阻塞延时"><a href="#1、非阻塞延时" class="headerlink" title="1、非阻塞延时"></a>1、非阻塞延时</h4><p>裸机的一大痛点就是不能 <strong>直接</strong> 实现非阻塞 delay，一般需要把任务切分再通过轮询来实现</p><p>接下来是几种裸机里面的实现方法总结：</p><p><strong>a、状态机：</strong></p><p>例如前面提及的温度检测任务，我们不希望温度转换的 20ms 阻塞系统，那么就需要专门插入一个等待延时完成步骤给状态机。</p><p><strong>b、直接修改软件定时器倒计时：</strong></p><p>还是前面提及的温度检测任务，对于软件定时器方案，可以把时间轮询交给外部，比如可以直接修改软件定时器的重载值来实现非阻塞延时。</p><p><strong>c、ltx 脚本组件</strong></p><p>ltx 脚本组件可以设置步骤间非阻塞延时时间。</p><h4 id="2、高优先级抢占"><a href="#2、高优先级抢占" class="headerlink" title="2、高优先级抢占"></a>2、高优先级抢占</h4><p>优先级抢占可以给产品带来更高的响应性，即便是耗时任务操作，rtos 也可以将其打断切换到其他任务。<br>单片机作为微控制器其实一般的情况下一个任务不会有太多耗时操作，比如 led 闪烁也就是翻转一下 led 电平，大部分时间都在 delay。cpu 耗时操作一般都体现在计算上面，比如画显存什么的，但是对于这些耗时计算任务，你依然可以手工对其进行切片，把一个 case 切成几个 case，case 之间相当于出让一次 cpu，比如你一个 case 画全屏改为一个 case 画十分之一屏或者更细分。<br>当然，如果你自己写代码倒是可以对任务进行手动切分，但是如果用一些耗时的闭源的库可能就不好切分了，只能上 rtos 让它来帮你切分。</p><p>裸机显然是没办法直接实现高优先级抢占了，但是依然有如下几种能够提高任务响应能力的方案：</p><p><strong>a、任务排序：</strong></p><p><img src="https://image.skyforever.top/blog/2026/05/4badfe0cce3855168be4b6ff72e6f8e6.webp" alt="排序"></p><p>这就是 osal 的实现方法，使用 osal 框架创建任务的时候，需要给任务设置一个唯一 id，这个 id 还承载着优先级的功能，按照这个 id 来将任务插入到链表的特定位置。<br>这样，在遍历的时候，高优先级的任务可以先执行，执行完后再从任务链表头遍历而不是继续遍历。这样可以提供一定的优先级能力，但依然没办法在低优先级任务执行的时候被高优先级任务打断</p><p><strong>b、systick 抢占</strong></p><p>有一些软件多定时器调度教程会额外增加一个优先级变量，一旦这个高优先级任务到时间，那么就直接在 systick 中断里执行，而不是在主循环，这倒是切切实实实现了抢占，不过只能实现两个优先级，以及可能带来资源竞争问题，需要关开中断来实现原子操作</p><p><strong>c、硬件定时器抢占</strong></p><p>也就是第二节提到的硬件多定时器方案。</p><h4 id="3、可移植性"><a href="#3、可移植性" class="headerlink" title="3、可移植性"></a>3、可移植性</h4><p>这里谈的不是业务的可移植性，而是框架的可移植性。<br>大部分裸机调度框架基本只需要你在 systick 中断服务函数里调用一个系统嘀嗒，然后把调度器扔到主循环里就行了，不用太担心硬件平台的差异，而 rtos 就要麻烦一点了，毕竟不同 架构 的 mcu 的寄存器什么的是不一样的，尤其是一些新出的 risc-v 的例程少的 mcu 会让你比较痛苦。</p><h4 id="4、资源竞争"><a href="#4、资源竞争" class="headerlink" title="4、资源竞争"></a>4、资源竞争</h4><p>裸机的一大优势就是几乎不用考虑资源竞争问题，毕竟任务间不能相互打断，数据直接扔到全局变量里就能交换与通信，也不太需要拷贝，而 rtos 就需要队列或者其他组件来传递数据</p><h4 id="5、空闲低功耗"><a href="#5、空闲低功耗" class="headerlink" title="5、空闲低功耗"></a>5、空闲低功耗</h4><p>举个例子，你有两个 led，第一个 100ms 闪一下，第二个 20ms 闪一下，那么你的系统其实大部分时间都在轮询这个时间到没到，你完全可以让系统睡 20ms 再起来翻转一下电平然后接着睡</p><p>在 rtos 里，一般会提供一个空闲（idle）任务，你可以在空闲任务里进入休眠模式，等到下一次 systick 或者其他中断唤醒系统后触发任务调度跳出 idle</p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 空闲任务</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">task_idle</span>(<span class="params"><span class="keyword">void</span> *param</span>){</span><br><span class="line">    <span class="comment">// 进入休眠</span></span><br><span class="line">    <span class="title function_">system_sleep_until_interrupt</span>();</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>在裸机里面，似乎不是很好办？因为裸机里提供不了空闲任务，空闲的时候系统会一直轮询有没有什么任务的事件触发，当然，硬件多定时器那个除外。<br>以 osal 为例，你可能需要修改他的源码，比如他的获取活跃任务，会通过 if 进行判断是否为空，你可以加一个 else，也就是没有活跃任务，此时便直接进入休眠</p><figure class="highlight rust"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// osal 主循环</span></span><br><span class="line">void <span class="title function_ invoke__">osal_start_system</span>( void )</span><br><span class="line">{</span><br><span class="line">    uint16 events;</span><br><span class="line">    uint16 retEvents;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 这里就是 osal 的主循环</span></span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>){</span><br><span class="line">        <span class="comment">// 不断获取活跃任务</span></span><br><span class="line">        TaskActive = <span class="title function_ invoke__">osalNextActiveTask</span>();</span><br><span class="line">        <span class="keyword">if</span> ( TaskActive ){</span><br><span class="line">            <span class="title function_ invoke__">HAL_ENTER_CRITICAL_SECTION</span>();</span><br><span class="line">            events = TaskActive<span class="punctuation">-&gt;</span>events;</span><br><span class="line">            <span class="comment">// Clear the Events for this task</span></span><br><span class="line">            TaskActive<span class="punctuation">-&gt;</span>events = <span class="number">0</span>;</span><br><span class="line">            <span class="title function_ invoke__">HAL_EXIT_CRITICAL_SECTION</span>();</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 如果这个任务的事件集不为 0</span></span><br><span class="line">            <span class="keyword">if</span> ( events != <span class="number">0</span> ){</span><br><span class="line">                <span class="comment">// Call the task to process the event(s)</span></span><br><span class="line">                <span class="keyword">if</span> ( TaskActive<span class="punctuation">-&gt;</span>pfnEventProcessor ){</span><br><span class="line">                    <span class="comment">// 调用任务回调函数</span></span><br><span class="line">                    retEvents = (TaskActive<span class="punctuation">-&gt;</span>pfnEventProcessor)(TaskActive<span class="punctuation">-&gt;</span>taskID, events);</span><br><span class="line"></span><br><span class="line">                    <span class="comment">// Add back unprocessed events to the current task</span></span><br><span class="line">                    <span class="title function_ invoke__">HAL_ENTER_CRITICAL_SECTION</span>();</span><br><span class="line">                    TaskActive<span class="punctuation">-&gt;</span>events |= retEvents;</span><br><span class="line">                    <span class="title function_ invoke__">HAL_EXIT_CRITICAL_SECTION</span>();</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">        }<span class="keyword">else</span> { <span class="comment">// ！自己修改源码添加的 else，当没有活跃 task 会进入这个 else</span></span><br><span class="line">            <span class="comment">// 这里执行空闲任务</span></span><br><span class="line">            <span class="comment">// 风险：TaskActive 判空后和 system_sleep_until_interrupt() 执行前可能产生中断</span></span><br><span class="line">            <span class="comment">// 但是执行完中断后回到主循环接下来系统会进入休眠</span></span><br><span class="line">            <span class="comment">// 所以这个中断产生的事件不会被处理</span></span><br><span class="line">            <span class="comment">// 只有下次其他中断唤醒系统才会一起处理</span></span><br><span class="line">            <span class="title function_ invoke__">system_sleep_until_interrupt</span>(); <span class="comment">// 等待中断唤醒</span></span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>但是这样会带来风险，比如说在获取 TaskActive 为空后，但是进入 <code>system_sleep_until_interrupt()</code> 前，此时产生了一个中断的话，比如按下了一个按键，系统不会去获取新的 TaskActive，那么这次中断事件就得到下一次其他中断唤醒系统后才能响应了。那加入开关中断呢？</p><figure class="highlight rust"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// osal 主循环</span></span><br><span class="line">void <span class="title function_ invoke__">osal_start_system</span>( void )</span><br><span class="line">{</span><br><span class="line">    uint16 events;</span><br><span class="line">    uint16 retEvents;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 这里就是 osal 的主循环</span></span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>){</span><br><span class="line">        <span class="comment">// 不断获取活跃任务</span></span><br><span class="line">        __irq_disable(); <span class="comment">// ！！修改源码加入关闭中断</span></span><br><span class="line">        TaskActive = <span class="title function_ invoke__">osalNextActiveTask</span>();</span><br><span class="line">        <span class="keyword">if</span> ( TaskActive ){</span><br><span class="line">            __irq_enable(); <span class="comment">// ！！修改源码加入打开中断</span></span><br><span class="line"></span><br><span class="line">            <span class="title function_ invoke__">HAL_ENTER_CRITICAL_SECTION</span>();</span><br><span class="line">            events = TaskActive<span class="punctuation">-&gt;</span>events;</span><br><span class="line">            <span class="comment">// Clear the Events for this task</span></span><br><span class="line">            TaskActive<span class="punctuation">-&gt;</span>events = <span class="number">0</span>;</span><br><span class="line">            <span class="title function_ invoke__">HAL_EXIT_CRITICAL_SECTION</span>();</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 如果这个任务的事件集不为 0</span></span><br><span class="line">            <span class="keyword">if</span> ( events != <span class="number">0</span> ){</span><br><span class="line">                <span class="comment">// Call the task to process the event(s)</span></span><br><span class="line">                <span class="keyword">if</span> ( TaskActive<span class="punctuation">-&gt;</span>pfnEventProcessor ){</span><br><span class="line">                    <span class="comment">// 调用任务回调函数</span></span><br><span class="line">                    retEvents = (TaskActive<span class="punctuation">-&gt;</span>pfnEventProcessor)(TaskActive<span class="punctuation">-&gt;</span>taskID, events);</span><br><span class="line"></span><br><span class="line">                    <span class="comment">// Add back unprocessed events to the current task</span></span><br><span class="line">                    <span class="title function_ invoke__">HAL_ENTER_CRITICAL_SECTION</span>();</span><br><span class="line">                    TaskActive<span class="punctuation">-&gt;</span>events |= retEvents;</span><br><span class="line">                    <span class="title function_ invoke__">HAL_EXIT_CRITICAL_SECTION</span>();</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">        }<span class="keyword">else</span> { <span class="comment">// ！！自己修改源码添加的 else，当没有活跃 task 会进入这个 else</span></span><br><span class="line">            <span class="comment">// 这里执行空闲任务</span></span><br><span class="line">            <span class="comment">// 进入休眠，虽然还没有开启中断，但是只是不能进中断服务函数而已，还是能唤醒系统</span></span><br><span class="line">            <span class="title function_ invoke__">system_sleep_until_interrupt</span>(); <span class="comment">// 等待中断唤醒</span></span><br><span class="line">            <span class="comment">// 一定要先调用休眠再调用开中断，否则还是有空窗期</span></span><br><span class="line">            __irq_enable(); <span class="comment">// ！！修改源码加入打开中断</span></span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>但是这并不完美，关闭中断期间调用的 <code>osalNextActiveTask()</code> 内部其实是在遍历 task 链表，他的时间复杂度是 O(N)，所以会比较耗时，会导致响应性变差以及判空效率低。</p><p>ltx V1 和 osal 一样，都是对任务链表的所有任务进行事件轮询，时间复杂度是 O(N)，所以 V2 对话题进行了修改，不再直接使用链表，而是修改为链表队列，事件产生不再是置位标志位，而是把话题指针加入这个队列，主循环不断弹出话题并执行即可，不用轮询所有话题，所以时间复杂度是 O(1)，提高了调度器的响应能力，以及获得了更快的空闲判定。</p><p>如果你想要一个真正的空闲任务，那么你可以通过抬升调度器优先级来实现，也就是让调度器跑在一个最低优先级的软中断里，比如 <code>PendSV</code>，此时的主循环就是最低优先级的空闲任务，有事件就触发软中断的标志位让调度器执行，没有任务就退出调度器。ltx V2+ 专门提供了这种能力，更便于实现空闲任务与空闲钩子。</p><h4 id="6、tickless"><a href="#6、tickless" class="headerlink" title="6、tickless"></a>6、tickless</h4><p><img src="https://image.skyforever.top/blog/2026/05/29282d700b9f58fec6b05fd20bd0a577.webp" alt="tickless"><br>因为 systick 中断的存在，上面的 idle 休眠会 1ms 被 systick 中断唤醒一次，但是醒来后调度器发现没有要做的事就又进入休眠，我们更期望系统能完整睡完 N 毫秒再醒过来，所以你可以通过获取最近一个阻塞任务的延时时间然后修改 systick 的重载值，让他 N 毫秒后再触发中断，然后在唤醒时将 systick 的倒计时更新为下一个任务的到来时间就可以实现 tickless 的效果。</p><p>不过一般的裸机框架的 systick 都需要每个 tick 遍历所有定时器的计数值减一，那么获取最近一个需要执行的任务的时间也需要对所有定时器进行遍历，效率会比较低，也会拖慢裸机的响应性。</p><p><img src="https://image.skyforever.top/blog/2026/05/d128cdde780c8ee1885e50202cc8e243.webp" alt="裸机遍历systick"></p><p>所以可以仿照一些 rtos 的实现方法对你的裸机框架进行爆改，也就是不能按照传统裸机的每毫秒进一次 systick 去递减所有定时器 tick 计数值，而是根据定时器的倒计时进行顺序插入，每个定时器存储自身与前一个定时器的时间差，那么 systick 只需弹出首(几)个闹钟节点即可，且进行 tickless 操作时只需要获取首个节点的倒计时就行，效率更高。</p><p><img src="https://image.skyforever.top/blog/2026/05/eab03193933b2d16431cea9aaf315d65.webp" alt="差分定时器链表示意"><br>走到这里，已经接近于手搓一个 rtos 了，如果不想自己手搓，那么可以直接使用 ltx V3，其内建空闲任务与 tickless 支持。</p>]]>
    </content>
    <id>https://blog.skyforever.top/posts/53927</id>
    <link href="https://blog.skyforever.top/posts/53927"/>
    <published>2026-05-11T16:00:00.000Z</published>
    <summary>总结单片机裸机环境下多任务与低功耗的实现方案，涵盖前后台、软件定时器、状态机、OSAL、ltx调度器、QP/C、协程等，并与RTOS进行对比</summary>
    <title>单片机裸机多任务与低功耗方案总结</title>
    <updated>2026-05-11T16:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <content>
      <![CDATA[<p>我平时重度依赖 Claude Code，踩了不少坑，也摸索出了一些能切实提高效率的习惯。</p><p>今天整理了 15 个我最常用的技巧，有些是自己折腾出来的，有些是看别人操作学到的。直接上干货。</p><h4 id="0-使用新出的自动模式"><a href="#0-使用新出的自动模式" class="headerlink" title="0.使用新出的自动模式"></a>0.使用新出的自动模式</h4><p>Claude Code 最近新出了个自动模式，能让它自己根据上下文判断什么时候需要权限，什么时候不需要权限，什么时候需要开子代理，什么时候不需要开子代理，什么时候需要切 Plan 模式，什么时候不需要切 Plan 模式。</p><p>自动模式不是简单的一刀切，把所有权限确认全关掉，而是走了一个更灵活的路子，在真正执行动作前，先让一个分类器模型过一遍，判断这个操作是不是安全、是不是符合你的任务意图。</p><p>像大规模删文件、把敏感数据发到外部、危险命令执行、超出任务范围的异常操作，都会被重点拦截。</p><p>如果分类器觉得不对劲，Claude 会先换办法，不行再回来找你确认。</p><p>但也别高兴太早，Auto mode 并不是 100% 安全，相比 –dangerously-skip-permissions 虽然降低了风险，但并不能完全消除风险，官方仍然建议还是在隔离环境中使用。</p><p>官方说它还会增加一点延迟和额外消耗，而且如果连续拦截太多次，最后还是会退回人工确认。</p><p>说白了，默认模式太谨慎，裸奔模式太激进，Auto mode 就是卡是一种折中的方案。<br>目前官方写的是：Team 先用，Enterprise 和 API 正在陆续放开，需要 Claude Sonnet 4.6 或 Claude Opus 4.6，像 Claude 3、Haiku、Bedrock、Vertex、Foundry 这些暂时还不支持。</p><p>CLI 开启方式是：</p><p>claude –enable-auto-mode</p><p>进入会话后，可以按 Shift + Tab 切换到 Auto 模式。</p><h4 id="1-绕过权限弹窗并设置别名"><a href="#1-绕过权限弹窗并设置别名" class="headerlink" title="1. 绕过权限弹窗并设置别名"></a><strong>1. 绕过权限弹窗并设置别名</strong></h4><p>每次跑脚本都要点确认很烦。最省事的做法是直接在 shell 里配个别名：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">alias</span> c-d=<span class="string">"claude --dangerously-skip-permissions"</span></span><br></pre></td></tr></tbody></table></figure><p>或者去编辑 <code>~/.claude/settings.json</code> 文件（注意加这行 <code>skipDangerousModePermissionPrompt: true</code>）：</p><figure class="highlight json"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line">  <span class="attr">"permissions"</span><span class="punctuation">:</span> <span class="punctuation">{</span></span><br><span class="line">    <span class="attr">"defaultMode"</span><span class="punctuation">:</span> <span class="string">"bypassPermissions"</span></span><br><span class="line">  <span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">"skipDangerousModePermissionPrompt"</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></tbody></table></figure><p>搞定后下一次直接输入<code>c-d</code>拉起最高权限实例，清净很多。</p><h4 id="2-用-claude-init-初始化-CLAUDE-md"><a href="#2-用-claude-init-初始化-CLAUDE-md" class="headerlink" title="2. 用 claude init 初始化 CLAUDE.md"></a><strong>2. 用 <code>claude init</code> 初始化 CLAUDE.md</strong></h4><p>接手老项目，别指望 AI 自己能瞬间领悟。直接在终端敲 <code>claude init</code>，它会自己摸索代码库并生成初版 <code>CLAUDE.md</code>（这是它分析出来的代码库基本情况，方便ClaudeCode快速上手）。</p><p>就像你在公司带一个新人，你不是直接让他干活，而是先给新人一段时间去了解工作情况，这个功能就是让ai自己先去了解代码库，了解你代码的业务情况</p><p>拿到ai理解的初版内容后一定要手动精简。保留项目简述、启动测试命令即可；编码规范用 <code>@</code> 引入外部规则文件。<br>最重要的是核心备忘——那些一旦删了 AI 就会写出报错代码的潜规则，保留到CLAUDE.md里。文档越短，效果越好。</p><h4 id="3-告别纯命令行，用-UI-客户端"><a href="#3-告别纯命令行，用-UI-客户端" class="headerlink" title="3. 告别纯命令行，用 UI 客户端"></a><strong>3. 告别纯命令行，用 UI 客户端</strong></h4><p>终端里敲字费劲可以试试带 UI 的客户端。除了 VS Code 官方插件，最近我发现个非常有意思的 Web 看板项目<a href="https://github.com/BloopAI/vibe-kanban/tree/main" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>Vibe Kanban</a>。<br>你可以把任务分成“进行中、已完成、Review”，直接拖拽过去开启对应的 Claude Code 实例，让 Claude Code 多线并行操作非常直观。</p><h4 id="4-连续按两次-ESC-快速回滚"><a href="#4-连续按两次-ESC-快速回滚" class="headerlink" title="4. 连续按两次 ESC 快速回滚"></a><strong>4. 连续按两次 ESC 快速回滚</strong></h4><p>发现代码改乱了，连按两次 ESC 可以直接触发回滚。</p><p>另外，关闭实例后终端会吐出一串恢复命令（类似 <code>claude -r &lt;会话名&gt;</code>）。</p><p>下次直接跑这串命令，就能无缝回到上一次对话的最后状态，上下文都在。</p><p><img src="https://image.skyforever.top/blog/2026/04/ba3de548854c7ead238f866c197fb1f2.webp" alt="回到上次对话的命令"></p><h4 id="5-别只给需求，给“反馈链路”"><a href="#5-别只给需求，给“反馈链路”" class="headerlink" title="5. 别只给需求，给“反馈链路”"></a><strong>5. 别只给需求，给“反馈链路”</strong></h4><p>没有反馈链路的提问方法:</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">帮我做一个邮箱密码登录功能</span><br></pre></td></tr></tbody></table></figure><p>这么给 Claude Code 说，Claude Code 往往丢几行代码就觉得搞定，实际上根本跑不起来。</p><p>但有反馈链路的提问方法:</p><figure class="highlight text"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">帮我做一个邮箱密码登录功能。</span><br><span class="line">做完后请自己测试这个流程：</span><br><span class="line">- 错误输入要有提示</span><br><span class="line">- 正确登录后使用 Chrome MCP 跳转到 dashboard</span><br><span class="line">- 未登录访问 dashboard 要跳回 login</span><br><span class="line">如果测试失败，请继续修复，直到这条链路跑通再告诉我完成。</span><br></pre></td></tr></tbody></table></figure><p>把单次对话变成一套循环闭环，让Claude Code自己跑闭环测试，他就知道他写的代码是否能达到效果，自己给代码多次迭代，可用性直接大大提高。</p><h4 id="6-装上针对语言的-LSP-插件"><a href="#6-装上针对语言的-LSP-插件" class="headerlink" title="6. 装上针对语言的 LSP 插件"></a><strong>6. 装上针对语言的 LSP 插件</strong></h4><p>一定要装代码智能插件（LSP）。它能让文件一保存就自动诊断语法错误或包遗漏，不用等到最后编译才发现死胡同。</p><p>在 Claude Code 里输入</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/plugin</span><br></pre></td></tr></tbody></table></figure><p>在插件的Discover（发现）页面搜索 LSP ,即可给 Claude Code 安装常用编程语言的分析工具，帮助 Claude Code 写出更正确的代码</p><p><img src="https://image.skyforever.top/blog/2026/04/8d17b53a47060ddf3113e73646d41b26.webp" alt="给claudecode安装LSP"></p><h4 id="7-尽可能多用优质技能（Skills）"><a href="#7-尽可能多用优质技能（Skills）" class="headerlink" title="7. 尽可能多用优质技能（Skills）"></a><strong>7. 尽可能多用优质技能（Skills）</strong></h4><p>技能就是封装好的标准化工作流说明书。做架构设计或者前端 UI 只要挂上对应的技能，模型就会老老实实按既定规范走，极大减少盲盒概率。</p><p>除了内置的，用命令一键去市场装现成的也很方便。</p><p>可以在这个网站找到合适的Skills：<a href="https://skillsmp.com/zh" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://skillsmp.com/zh</a></p><h4 id="8-没思路时，切-Plan-模式"><a href="#8-没思路时，切-Plan-模式" class="headerlink" title="8. 没思路时，切 Plan 模式"></a><strong>8. 没思路时，切 Plan 模式</strong></h4><p>遇到复杂需求不知道从哪下手，按下 <code>Shift + Tab</code> 切到 Claude Code 内置的 Plan 模式。</p><p>它会先探索代码库、跟你反复对齐思路，定好计划再动手写代码。前期对齐逻辑，后面基本不会跑偏。</p><h4 id="9-抛弃“二手翻译”，直接喂报错日志"><a href="#9-抛弃“二手翻译”，直接喂报错日志" class="headerlink" title="9. 抛弃“二手翻译”，直接喂报错日志"></a><strong>9. 抛弃“二手翻译”，直接喂报错日志</strong></h4><p>用自己的解释漏掉了原始的信息：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">登录跳转有问题，应该是token 没存上，你帮我修一下,</span><br></pre></td></tr></tbody></table></figure><p>一旦这么说，大模型很容易顺着你的错觉钻牛角尖。</p><p>最稳妥的做法：把第一手报错日志原封不动砸给它。</p><p>你可以加上你怀疑的方向，但必须有原始信息，让它自己去排查所有可能性。</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">这是登录相关的控制台报错和接口返回，我怀疑是 token 存储或者路由守卫的问题，你先从这个方向排查，但也请结合日志判断真实原因。</span><br><span class="line">- 日志信息</span><br><span class="line">- 其他信息</span><br></pre></td></tr></tbody></table></figure><h4 id="10-卡死的时候，果断-clear"><a href="#10-卡死的时候，果断-clear" class="headerlink" title="10. 卡死的时候，果断 /clear"></a><strong>10. 卡死的时候，果断 <code>/clear</code></strong></h4><p>如果你现在的任务和上一个任务毫无关联，就用 <code>/clear</code> 清空上下文。或者直接新开个对话，上下文堆积太多必定会导致模型变蠢。清空 AI 的脑子重来往往有奇效。</p><p>在实际开发中，很多时候你开发新功能的时候不需要再了解之前的功能实现，不需要把你实现的部分给同事再说一边，和 ai 打交道也是同理</p><h4 id="11-用子代理（Sub-agent）隔离污染"><a href="#11-用子代理（Sub-agent）隔离污染" class="headerlink" title="11. 用子代理（Sub-agent）隔离污染"></a><strong>11. 用子代理（Sub-agent）隔离污染</strong></h4><p>子代理是独立的上下文，在整个运行过程中不影响主代理的上下文</p><p>使用 Claude Code 自带的子代理<br>1、explore 搜索代码<br>2、plan 生成计划<br>3、General-purpose 复杂任务</p><p>什么情况下要去使用自定义子代理?<br>1、你要进行的价务时间比较长且和当前主代理没有多大关系，主代理更关心的是这个子代理的结果<br>比如code-review<br>主代理需要的是 codereview 的结果进行优化，至于过程完全不在意</p><h4 id="12-用-btw-随时开小差"><a href="#12-用-btw-随时开小差" class="headerlink" title="12. 用 /btw 随时开小差"></a><strong>12. 用 <code>/btw</code> 随时开小差</strong></h4><p>英文是<strong>by the way</strong>，它在 Claude Code 中的功能非常实用，可以让你在不打断 AI 主任务的前提下，快速插入一个分支问题。</p><p>以前你让Claude Code重构一个大模块，干着干着你突然想到一个问题，比如”诶那个测试文件在哪个目录来着”，你一问，Claude停下来回答你，然后上下文窗口里就多了一段完全不相关的对话，它重新开始干活的时候可能就跑偏了。</p><p>这就是所谓的上下文污染，用Claude Code时间长的人应该都被坑过。</p><p>要不然就是呆呆的，等到整个任务跑完，再去问，但是其实也是污染。</p><p>现在打/btw，然后说一个问题，比如我在执行过程中，突然想知道现在我这个项目的抓取流程是啥，我就可以直接敲/btw。</p><p><img src="https://image.skyforever.top/blog/2026/09/d3b573798d83115c4b29a7d3a356699a.webp" alt="img"></p><p>你再敲一下空格，就可以直接在后面写问题了，然后发送。</p><p><img src="https://image.skyforever.top/blog/2026/09/53a5313968020fba2573116ef3f9ac38.webp" alt="img"></p><p>这个回答，完全不会中断你之前发送的任务，上下两个进程，是纯粹的并行状态。</p><p>回答完以后，哦我知道了，那这段就没用了，你就可以按空格或者回车，直接把这一段消除掉。</p><p><img src="https://image.skyforever.top/blog/2026/09/1d139e49129d6f8935ecf979e9657e73.webp" alt="img"></p><p>之前的Claude的任务还是该干嘛继续干嘛，对话历史里干干净净，跟什么都没发生一样。</p><p>而且几乎不费token，因为复用了当前的提示缓存。</p><h4 id="13-用-worktree-开启多核并行"><a href="#13-用-worktree-开启多核并行" class="headerlink" title="13. 用 --worktree 开启多核并行"></a><strong>13. 用 <code>--worktree</code> 开启多核并行</strong></h4><p>如果你同时要修几个不相关的 Bug或者并行写不同的功能，又怕每个功能写完之后会相互冲突，用 <code>claude --worktree &lt;分支名&gt;</code> 启动。它会直接拉出一个隔离的 Git 工作区副本，几条线并行跑完全互不干扰。只要你脑子转得过来，这就是效率杀器。</p><p>本身 git 的这个功能就是给多人编程团队写作用的，现在是一个人控制多个 AI 并行开发</p><p>具体使用用法可以查看：<a href="https://zhuanlan.zhihu.com/p/2026589961529357680" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>Claude Code CLI支持Worktree实现多分支并行独立工作</a></p><h4 id="14-挂载少而精的-MCP-工具"><a href="#14-挂载少而精的-MCP-工具" class="headerlink" title="14. 挂载少而精的 MCP 工具"></a><strong>14. 挂载少而精的 MCP 工具</strong></h4><p>有了技能后，MCP 没必要装一堆花里胡哨的，留几个痛点级的就行。比如装一个 MySQL MCP，查数据落库时让它直接走协议查表，比手写脚本再去跑要快得多。或者装一个Chrome MCP,让ai自动点击网页上的按钮做测试。</p><h4 id="15-用-精准投喂文件"><a href="#15-用-精准投喂文件" class="headerlink" title="15. 用 @ 精准投喂文件"></a><strong>15. 用 <code>@</code> 精准投喂文件</strong></h4><p>别让大模型自己海搜代码，费时又烧 Token。只要你大概知道逻辑在哪个目录，直接 <code>@</code> 把相关文件拽进去。指哪打哪才是最高效的用法。</p>]]>
    </content>
    <id>https://blog.skyforever.top/posts/51722</id>
    <link href="https://blog.skyforever.top/posts/51722"/>
    <published>2026-04-15T16:07:28.000Z</published>
    <summary>
      <![CDATA[<p>我平时重度依赖 Claude Code，踩了不少坑，也摸索出了一些能切实提高效率的习惯。</p>
<p>今天整理了 15 个我最常用的技巧，有些是自己折腾出来的，有些是看别人操作学到的。直接上干货。</p>
<h4 id="0-使用新出的自动模式"><a href="#0-]]>
    </summary>
    <title>15条高频实用的ClaudeCode技巧</title>
    <updated>2026-04-15T16:07:28.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="AI技术" scheme="https://blog.skyforever.top/categories/AI%E6%8A%80%E6%9C%AF/"/>
    <category term="AI编程" scheme="https://blog.skyforever.top/categories/AI%E6%8A%80%E6%9C%AF/AI%E7%BC%96%E7%A8%8B/"/>
    <category term="教程" scheme="https://blog.skyforever.top/tags/%E6%95%99%E7%A8%8B/"/>
    <category term="AI编程" scheme="https://blog.skyforever.top/tags/AI%E7%BC%96%E7%A8%8B/"/>
    <category term="Agent" scheme="https://blog.skyforever.top/tags/Agent/"/>
    <category term="Skill" scheme="https://blog.skyforever.top/tags/Skill/"/>
    <category term="AI" scheme="https://blog.skyforever.top/tags/AI/"/>
    <category term="Prompt" scheme="https://blog.skyforever.top/tags/Prompt/"/>
    <content>
      <![CDATA[<p>最近网上有个词很火，叫“龙虾”。有人说它代表未来，啥都能干；有人说它是妥妥的智商税。</p><p>有人说它代表着未来。有人499上门帮你安装，有人299上门帮你卸载。但是我想告诉你，所有这些说法都不准确。因为事情的重点根本就不在龙虾这只这个软件本身上</p><p>其实，所有的争论都不在点子上。今天，我直接带你从最底层的代码原理看清它的本质。即使你没写过代码，跟着我的思路，也绝对能看懂。 我会用最简单的方式让你看到本质</p><p>在看透了 Agent 的底层循环机制后，我还会分享一个我的私人实战干货：我是如何利用这套思路，配合Agent程序加速我工作的。</p><hr><h2 id="一、-Agent-是什么？"><a href="#一、-Agent-是什么？" class="headerlink" title="一、 Agent 是什么？"></a>一、 Agent 是什么？</h2><p>忘掉各种高大上的名词，让我们回到最初的起点：大语言模型。大模型本质上就是一个只会一问一答的单纯机器。在网页上你能和它聊天，在程序里，我们需要用 API。</p><h3 id="第一步：最基础的单次对话"><a href="#第一步：最基础的单次对话" class="headerlink" title="第一步：最基础的单次对话"></a>第一步：最基础的单次对话</h3><p>以目前极具性价比的 <strong>DeepSeek</strong> 为例，我们只需要把<a href="https://api-docs.deepseek.com/zh-cn/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>官方文档的实例</a>粘贴过来，填一下 api 密钥，就能得到一个最简单的“提问-回答”程序：</p><hr><div class="tag-plugin tabs" align="center" id="tab_1"><div class="nav-tabs"><div class="tab active"><a href="#tab_1-1">流程图</a></div><div class="tab"><a href="#tab_1-2">代码块</a></div></div><div class="tab-content"><div class="tab-pane active" id="tab_1-1"><pre class="mermaid">flowchart TD    A([开始]) --&gt; B[初始化 API 客户端<br>并将问题写死在代码中]    B --&gt; C[调用 API<br>打印输出 AI 回复]    C --&gt; D([结束])</pre></div><div class="tab-pane" id="tab_1-2"><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Please install OpenAI SDK first: `pip3 install openai`</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">from</span> openai <span class="keyword">import</span> OpenAI</span><br><span class="line"></span><br><span class="line">client = OpenAI(api_key=os.environ.get(<span class="string">'DEEPSEEK_API_KEY'</span>),base_url=<span class="string">"https://api.deepseek.com"</span>)</span><br><span class="line"></span><br><span class="line">response = client.chat.completions.create(</span><br><span class="line">    model=<span class="string">"deepseek-chat"</span>,</span><br><span class="line">    messages=[  <span class="comment"># 消息列表，包含系统提示词和用户问题</span></span><br><span class="line">        {<span class="string">"role"</span>: <span class="string">"user"</span>, <span class="string">"content"</span>: <span class="string">"你好"</span>},</span><br><span class="line">    ],</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(response.choices[<span class="number">0</span>].message.content)</span><br><span class="line"></span><br></pre></td></tr></tbody></table></figure></div></div></div><p>运行后，你能得到 Ai 回复的一句问候语。但这样调用AI,问题写死在代码里，我们无法自主输入。</p><h3 id="第二步：加入“用户输入”"><a href="#第二步：加入“用户输入”" class="headerlink" title="第二步：加入“用户输入”"></a>第二步：加入“用户输入”</h3><p>为了让程序活起来，我们引入 <code>input()</code> 函数。我们在发请求前，<strong>加入一行读取用户键盘输入的代码</strong>，替换掉刚才写死的问题。</p><hr><div class="tag-plugin tabs" align="center" id="tab_2"><div class="nav-tabs"><div class="tab active"><a href="#tab_2-1">流程图</a></div><div class="tab"><a href="#tab_2-2">代码块</a></div></div><div class="tab-content"><div class="tab-pane active" id="tab_2-1"><pre class="mermaid">flowchart TD    A([开始]) --&gt; B[初始化 API 客户端]    B --&gt; C[/等待并读取用户键盘输入/]    C --&gt; D[将用户输入传入 API<br>打印输出 AI 回复]    D --&gt; E([结束])</pre></div><div class="tab-pane" id="tab_2-2"><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Please install OpenAI SDK first: `pip3 install openai`</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">from</span> openai <span class="keyword">import</span> OpenAI</span><br><span class="line"></span><br><span class="line">client = OpenAI(api_key=os.environ.get(<span class="string">'DEEPSEEK_API_KEY'</span>),base_url=<span class="string">"https://api.deepseek.com"</span>)</span><br><span class="line">user_input = <span class="built_in">input</span>(<span class="string">"请输入你的问题："</span>)  <span class="comment"># 从用户输入获取问题</span></span><br><span class="line"></span><br><span class="line">response = client.chat.completions.create(</span><br><span class="line">    model=<span class="string">"deepseek-chat"</span>,</span><br><span class="line">    messages=[  <span class="comment"># 消息列表</span></span><br><span class="line">        {<span class="string">"role"</span>: <span class="string">"user"</span>, <span class="string">"content"</span>: user_input},</span><br><span class="line">    ],</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(response.choices[<span class="number">0</span>].message.content)</span><br><span class="line"></span><br></pre></td></tr></tbody></table></figure></div></div></div><p>现在程序运行后会停住，等待用户在黑框里敲字提问，敲回车后 AI 会给出对应的回答。<br>这样写依然是“一次性”的，回答完一个问题，程序还是会立刻结束。</p><h3 id="第三步：加入“死循环”"><a href="#第三步：加入“死循环”" class="headerlink" title="第三步：加入“死循环”"></a>第三步：加入“死循环”</h3><p>为了让对话可以一直持续下去，我们在刚才“输入+调用API”的代码外面，<strong>套上一个 <code>while True</code> 的无限循环</strong>。</p><hr><div class="tag-plugin tabs" align="center" id="tab_3"><div class="nav-tabs"><div class="tab active"><a href="#tab_3-1">流程图</a></div><div class="tab"><a href="#tab_3-2">代码块</a></div></div><div class="tab-content"><div class="tab-pane active" id="tab_3-1"><pre class="mermaid">flowchart TD    A([开始]) --&gt; B[初始化 API 客户端]    B --&gt; C{While 循环}    C -- 循环体 --&gt; D[读取用户键盘输入<br>调用 API 并打印输出回复]    D --&gt; C</pre></div><div class="tab-pane" id="tab_3-2"><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Please install OpenAI SDK first: `pip3 install openai`</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">from</span> openai <span class="keyword">import</span> OpenAI</span><br><span class="line"></span><br><span class="line">client = OpenAI(api_key=os.environ.get(<span class="string">'DEEPSEEK_API_KEY'</span>),base_url=<span class="string">"https://api.deepseek.com"</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span> <span class="literal">True</span>:  <span class="comment"># 【新增】死循环，让对话可以一直进行</span></span><br><span class="line">  user_input = <span class="built_in">input</span>(<span class="string">"请输入你的问题："</span>)  <span class="comment"># 从用户输入获取问题</span></span><br><span class="line">  response = client.chat.completions.create(</span><br><span class="line">    model=<span class="string">"deepseek-chat"</span>,</span><br><span class="line">    messages=[</span><br><span class="line">      {<span class="string">"role"</span>: <span class="string">"user"</span>, <span class="string">"content"</span>: user_input},</span><br><span class="line">    ],</span><br><span class="line">  )</span><br><span class="line"></span><br><span class="line">  <span class="built_in">print</span>(response.choices[<span class="number">0</span>].message.content)</span><br><span class="line"></span><br></pre></td></tr></tbody></table></figure></div></div></div><p>现在你可以自由地一直提问了！比如你问“1+1等于几”，它回答2。<br>但当你紧接着追问“再加1等于几呢？”时，它通常会乱答。因为在上面的代码中，每次循环都只把“当前这句”传给了大模型，<strong>大模型本身没有记忆</strong>，不知道你之前给他说了什么。</p><h3 id="第四步：加入“记忆系统”"><a href="#第四步：加入“记忆系统”" class="headerlink" title="第四步：加入“记忆系统”"></a>第四步：加入“记忆系统”</h3><p>怎么让它拥有记忆呢？非常简单：我们在循环外面建一个全局的消息列表（messages），<strong>把每次你的提问和 Ai 的回答，都塞进这个列表里。</strong> 每次请求时，把整个列表发过去。同时增加一个“退出”指令来结束程序。</p><hr><div class="tag-plugin tabs" align="center" id="tab_4"><div class="nav-tabs"><div class="tab active"><a href="#tab_4-1">流程图</a></div><div class="tab"><a href="#tab_4-2">代码块</a></div></div><div class="tab-content"><div class="tab-pane active" id="tab_4-1"><pre class="mermaid">flowchart TD    A([开始]) --&gt; B[初始化客户端<br>初始化全局消息列表]    B --&gt; C{While 循环}    C -- 等待交互 --&gt; D[/读取输入/]    D -- 退出 --&gt; F([结束])    D -- 正常输入 --&gt; E[将提问追加到消息列表<br>调用 API 传入完整列表并打印回复<br>将 AI 回复追加到消息列表]    E --&gt; C</pre></div><div class="tab-pane" id="tab_4-2"><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Please install OpenAI SDK first: `pip3 install openai`</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">from</span> openai <span class="keyword">import</span> OpenAI</span><br><span class="line"></span><br><span class="line">client = OpenAI(api_key=os.environ.get(<span class="string">'DEEPSEEK_API_KEY'</span>),base_url=<span class="string">"https://api.deepseek.com"</span>)</span><br><span class="line">messages=[]</span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span> <span class="literal">True</span>: </span><br><span class="line">  user_input = <span class="built_in">input</span>(<span class="string">"请输入你的问题："</span>)  <span class="comment"># 从用户输入获取问题</span></span><br><span class="line">  messages.append({<span class="string">"role"</span>: <span class="string">"user"</span>, <span class="string">"content"</span>: user_input}) <span class="comment"># 追加用户消息到消息列表</span></span><br><span class="line">  response = client.chat.completions.create(</span><br><span class="line">    model=<span class="string">"deepseek-chat"</span>,</span><br><span class="line">    messages=messages,</span><br><span class="line">  )</span><br><span class="line">  reply = response.choices[<span class="number">0</span>].message.content</span><br><span class="line">  <span class="built_in">print</span>(response.choices[<span class="number">0</span>].message.content)</span><br><span class="line">  messages.append({<span class="string">"role"</span>: <span class="string">"assistant"</span>, <span class="string">"content"</span>: reply})  <span class="comment"># 追加助手消息</span></span><br><span class="line">  </span><br></pre></td></tr></tbody></table></figure></div></div></div><p>再次运行，问“1+1等于几”，答2；追问“再加1呢”，完美回答3。甚至问“刚才我们聊了什么”它也能总结。<br>恭喜你，这个几十行的程序，<strong>跟市面上各种网页版的 AI 聊天工具在底层逻辑上已经没有任何区别了！</strong> 但它此时还只是个陪聊工具。</p><h3 id="第五步：见证奇迹的时刻——进化为-Agent"><a href="#第五步：见证奇迹的时刻——进化为-Agent" class="headerlink" title="第五步：见证奇迹的时刻——进化为 Agent"></a>第五步：见证奇迹的时刻——进化为 Agent</h3><p>现在的 Ai 只会聊天。如果我想让它帮我下载视频或者创建文件，它只会给你一堆文字步骤。<br>如何让它自动化？<strong>我们在提示词里规定一个严格的“命令格式”，并加一层“内循环”：一旦检测到 AI 回复了特定命令，代码就去执行，并把执行结果丢回给 AI 看。</strong></p><hr><div class="tag-plugin tabs" align="center" id="tab_5"><div class="nav-tabs"><div class="tab active"><a href="#tab_5-1">流程图</a></div><div class="tab"><a href="#tab_5-2">代码块</a></div></div><div class="tab-content"><div class="tab-pane active" id="tab_5-1"><pre class="mermaid">flowchart TD    A([开始]) --&gt; B[初始化客户端与消息列表<br>设定提示词要求特定输出格式]    B --&gt; C{外层循环:<br>与用户交互}    C -- 等待 --&gt; D[/读取输入/]    D -- 退出 --&gt; J([结束])    D -- 提问 --&gt; E[追加提问到列表]    E --&gt; F{内层循环: <br>自动执行任务}    F -- AI思考 --&gt; G[调用 API 并追加回复到列表]    G -- 判断结果 --&gt; H{回复以'完成:'开头?}    H -- 是-任务结束 --&gt; C    H -- 否-发现命令 --&gt; I[提取命令并在本地系统执行<br>将执行结果追加到消息列表反馈给AI]    I --&gt; F</pre></div><div class="tab-pane" id="tab_5-2"><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Please install OpenAI SDK first: `pip3 install openai`</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">from</span> openai <span class="keyword">import</span> OpenAI</span><br><span class="line"></span><br><span class="line">client = OpenAI(api_key=os.environ.get(<span class="string">'DEEPSEEK_API_KEY'</span>),base_url=<span class="string">"https://api.deepseek.com"</span>)</span><br><span class="line">messages = [{<span class="string">"role"</span>: <span class="string">"system"</span>, <span class="string">"content"</span>: <span class="string">"如果需要操作电脑请回复'命令: xxx'，如果完成任务请回复'完成: xxx'"</span>}]</span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">  user_input = <span class="built_in">input</span>(<span class="string">"请输入你的问题："</span>)</span><br><span class="line">  messages.append({<span class="string">"role"</span>: <span class="string">"user"</span>, <span class="string">"content"</span>: user_input})</span><br><span class="line"></span><br><span class="line">  <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">    response = client.chat.completions.create(</span><br><span class="line">      model=<span class="string">"deepseek-chat"</span>,</span><br><span class="line">      messages=messages,</span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">    reply = response.choices[<span class="number">0</span>].message.content</span><br><span class="line">    <span class="built_in">print</span>(reply)</span><br><span class="line">    messages.append({<span class="string">"role"</span>: <span class="string">"assistant"</span>, <span class="string">"content"</span>: reply})</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> reply.strip().startswith(<span class="string">"完成:"</span>):<span class="comment"># 如果ai说完成，就结束对话</span></span><br><span class="line">      <span class="keyword">break</span></span><br><span class="line">    <span class="keyword">elif</span> reply.strip().startswith(<span class="string">"命令:"</span>):<span class="comment"># 如果ai说命令，就执行命令并反馈结果</span></span><br><span class="line">      cmd = reply.split(<span class="string">"命令:"</span>)[<span class="number">1</span>].strip()</span><br><span class="line">      result = os.popen(cmd).read()</span><br><span class="line">      messages.append({<span class="string">"role"</span>: <span class="string">"user"</span>, <span class="string">"content"</span>: <span class="string">f"执行结果反馈: <span class="subst">{result}</span>"</span>})</span><br><span class="line">    <span class="keyword">else</span>: <span class="comment"># 如果ai既不说命令也不说完成，就继续对话</span></span><br><span class="line">      <span class="keyword">continue</span></span><br></pre></td></tr></tbody></table></figure></div></div></div><p>当你输入：“创建一个txt文件”。</p><ol><li>大模型输出：<code>命令：touch hello.txt</code></li><li>程序检测到 <code>命令:</code> 这几个字，内层循环拦截了回复，静默调用系统执行了创建，并告诉 Ai “文件已创建”。</li><li>Ai 评估任务结束，输出 <code>完成: hello.txt 已创建成功</code>，跳出内循环。</li></ol><p><strong>这就是 Agent！</strong><br>短短几十行代码，揭示了可以完成各种复杂操作的 Agent 的本质：<strong>大模型负责做决策并按格式输出文本，外部代码负责拦截文本并驱动真正的工具（如 shell、API）执行。</strong><br>市面上很多智能体（例如Openclaw小龙虾），其实就是把这个干瘪的 <code>os.popen</code> 换成了各种精致的函数，并套了个漂亮的前端 UI 而已。<br>对于Agent程序来说，他根本不知道大模型输出的是什么内容，他只负责按照规则去拦截和执行。</p><blockquote><p>通过上面的代码你能看出，如果不加安全拦截，大模型输出 <code>命令: rm -rf /</code> 这种全局删除命令时程序也会毫不犹豫地执行。如果用户的提示词是教唆 AI 去删库，就会引发灾难，这就是目前 Agent 面临的极大安全隐患。</p></blockquote><hr><h2 id="二、-什么是-Skill-？"><a href="#二、-什么是-Skill-？" class="headerlink" title="二、 什么是 Skill ？"></a>二、 什么是 Skill ？</h2><p>既然大模型只是调度员，那如果它不知道该用什么命令怎么办？<br>比如我想让它找个新闻，它可能一本正经地胡说八道。</p><p>这就引出了 <strong>Skill（技能）</strong>。<br>所谓 Skill，其实就是<strong>给 Agent 程序看的“说明书”</strong>。</p><p>我们可以新建一个叫 <code>skill.md</code> 的纯文本文件，里面写上：</p><blockquote><p>【搜索新闻技能】：如果你需要搜索新闻，请不要自己编，请输出命令：<code>python search_news.py [关键词]</code></p></blockquote><p>然后，我们在上面的 Python 代码启动前，把这个 <code>skill.md</code> 文件的内容读取出来，全部塞进最开始的 <code>system_prompt</code>（系统提示词）里。</p><p>大模型看到说明书，瞬间就“学会”了这项技能！所谓给 Ai 拓展能力，根本不是重新训练大模型，而只是你在提示词里多塞了一张操作说明书。<br>或者换句话来说，就是提前把相关操作用skill这种方式提前给大模型说了而已<br>这就是为什么有些人的agent程序啥都不会，有些人给agent程序装了一堆skill之后就能干一大堆活的原因了。<br>和之前一样，不是ai很厉害，而是你厉害。是你把你的思路和想法以skill这种形式教会了ai。</p><p>所以为什么我文章开头我说网上各种关于小龙虾的讨论都不准确呢？因为大部分讨论都陷入了两种极端。<br>比如说agent能执行shell命令，有人就说龙虾是万能的，什么都能干。因为任何操作都能转化成shell命令，没什么毛病。<br>但是有人也说龙虾啥也干不了。比如说搜索新闻那个任务，我本地没有相关工具给他，他不知道这个命令怎么用，那也完成不了这个任务。<br>所以真正的答案往往是比较中庸的，无聊的</p><p>ai的相关能力都是软件工程师或者你自己赋予的</p><p>但是往往是极端的言论。容易获得更大的流量。</p><p>大部分Agent程序的这个架构范式肯定是没有问题的。但是关键的核心在于我们这个世界是否已经足够的命令化接口化。<br>这就需要一个漫长的演化过程，而且也涉及到各方利益的权衡，要不然的话豆包手机早就成了。<br>不过非要说一点的话，我认为龙虾的出现最重要的一点就是可以促进我们这个世界的操作命令化、接口化的速度。<br>假如我们这个电脑上的所有操作都能被做成一个个清晰的命令，整个物理世界的所有操作也都被开放成一个清晰的接口。<br>那么这个时候龙虾或者说agent才能大展拳脚。但同时风险和危险也随之到来了。</p><hr><h2 id="三、-实战：我如何用-Agent-Skill-来简化工作-？"><a href="#三、-实战：我如何用-Agent-Skill-来简化工作-？" class="headerlink" title="三、 实战：我如何用 Agent+Skill 来简化工作 ？"></a>三、 实战：我如何用 Agent+Skill 来简化工作 ？</h2><p>看懂了上面这段无聊但硬核的代码循环，你就会明白：<strong>一切皆可 Agent 化，一切皆可命令化</strong>。</p><p>接下来，分享我是如何把这个底层逻辑迁移到“写教材”这件事上的。</p><p>很多人让 Ai 写书，都是在对话框里发一句：“帮我写一本关于 Python 的教材”，结果 Ai 吐出来一堆极度空洞的大纲和废话。<br>我的做法完全不同，我写了一个**“教材生成 Agent”**，并给它配了详细的 Skill 说明书。</p><h3 id="1-编写“写书-Skill”说明书（核心心法）"><a href="#1-编写“写书-Skill”说明书（核心心法）" class="headerlink" title="1. 编写“写书 Skill”说明书（核心心法）"></a>1. 编写“写书 Skill”说明书（核心心法）</h3><p>不要试图让 Ai 一次性干完所有工作。我在我的 <code>skill.md</code> 里，为大模型规定了严格的工作流：</p><ul><li><strong>第一步：需求分析。</strong> 根据我给的资料，先输出这本教材的受众是谁，重点难点是什么。</li><li><strong>第二步：任务拆解与排序。</strong> 不要直接写正文！先写出包含 50 个小节的详细树状大纲，并将每个小节定义为一个独立的“Task（任务）”。</li><li><strong>第三步：按顺序执行 Task。</strong> Agent 每次只读取一个 Task（例如：编写 1.1 章节），并结合我提前给到的参考资料生成内容。</li></ul><h3 id="2-自动循环执行"><a href="#2-自动循环执行" class="headerlink" title="2. 自动循环执行"></a>2. 自动循环执行</h3><p>就跟前面我们写的那个带 <code>os.popen</code> 的代码一模一样：<br>大模型拿到拆解的任务列表后，程序开始进入循环。</p><ul><li>发送指令：“请根据参考资料，生成 1.1 章节”。</li><li>大模型返回文本。</li><li>Python 脚本截获文本，自动在本地 <code>C盘/教材/</code> 目录下生成 <code>1.1.md</code> 文件。</li><li>程序进入下一个循环，生成 <code>1.2.md</code> …</li></ul><p>我就只需要喝杯茶，看着文件夹里的文件一个个自动冒出来，拼成一本十几万字的教材。</p><h3 id="3-为什么要拆解任务？"><a href="#3-为什么要拆解任务？" class="headerlink" title="3. 为什么要拆解任务？"></a>3. 为什么要拆解任务？</h3><p>为什么要一步一步来，而不是让它一次写完？<br><strong>因为 Ai 有“上下文限制”（Context Window）。</strong><br>程序的一个变量都有存储范围限制，ai也不例外。</p><p>虽然现在的大模型动辄支持百万字上下文，但在实际干活时，如果你一次性塞给它太多要求，它的注意力就会被分散。</p><p>让它一次写 2 万字，后面 1 万字大概率是车轱辘话。</p><p>通过 Skill 把任务拆解开，把每一次生成的长度控制在一个“文字限度”内，写完一节清空一下无关的短期记忆，这是保证 Ai 长时间输出质量的唯一解。</p><h3 id="4-为什么我坚持全流程使用-Markdown-md-？"><a href="#4-为什么我坚持全流程使用-Markdown-md-？" class="headerlink" title="4. 为什么我坚持全流程使用 Markdown (.md)？"></a>4. 为什么我坚持全流程使用 Markdown (.md)？</h3><p>在写教材时，我的工作流始终是：<br><strong>资料转为 MD -&gt; Ai 生成 MD -&gt; 脚本转换 MD 为 PPT/Word。</strong></p><p>为什么不让 Ai 用 Python 直接生成 Word 格式文档？<br><strong>因为大语言模型它原生只支持“纯文本”！</strong> Markdown 就是一种带有排版标记的纯文本。</p><p>让 Ai 处理和输出 MD，没有任何工具转换的损耗，它的脑力 100% 都在内容创作上。</p><p>等所有 Markdown 完美生成后，再用 <code>Pandoc</code> 或者 <code>python-docx</code> 这样的脚本工具，瞬间把几十个 MD 文件批量转换成排版精美的 Word 或 PPT。</p><p><strong>让 Ai 干文本的活，让脚本干转换的活，这才是王道。</strong></p><hr><h2 id="四、-触类旁通：重塑你的生产力"><a href="#四、-触类旁通：重塑你的生产力" class="headerlink" title="四、 触类旁通：重塑你的生产力"></a>四、 触类旁通：重塑你的生产力</h2><p>讲到这里，你应该理解了。大语言模型的实力，绝不是只停留在那个一问一答的网页对话框里！</p><p><strong>只要是支持文字输入的地方，只要能获取或输入纯文本，Ai 都可以大显身手。</strong></p><ul><li><strong>各种开源项目的命令行本身</strong>：你不需要死记硬背 Git、Docker 或者 ffmpeg 的几百个参数，现阶段你只需要知道这些工具是大概怎么用地，把它们的说明书喂给 Ai，你的 Agent 程序就能替你组装出最复杂的指令。</li><li><strong>浏览器里的 JS 脚本</strong>：把网页的 HTML 纯文本抓下来给 Ai，让它提取关键信息，再生成一段 JS 脚本帮你自动填表单。</li><li><strong>Word / Excel 的宏脚本（VBA）</strong>：你只需要用文字描述你想怎么整理报表，让 Ai 吐出纯文本的 VBA 代码，贴进去运行，繁琐的表格瞬间处理完毕。</li></ul><p>这个世界正在快速演化。现在很多程序正在被重写为专门给ai调用的形式（MCP,Skill），当物理世界和软件世界的所有操作，都抽象成一个个清晰的命令行或 API 接口（纯文本）的时候，挂载了各种 Skill 说明书的 Ai Agent，必将接管我们的大部分繁琐工作。</p><p>希望通过这篇文章和这些亲自手搓的代码，能让你真正理解 Agent，并把它用在你的工作流中！只要能想象得到的地方，Ai 都能来帮你。</p><p>帮你做一些长线执行的，繁琐的活</p>]]>
    </content>
    <id>https://blog.skyforever.top/posts/41826</id>
    <link href="https://blog.skyforever.top/posts/41826"/>
    <published>2026-03-19T02:30:00.000Z</published>
    <summary>从底层循环机制出发，讲清楚什么是 Agent、为什么 Agent 能执行任务、如何真正用好 Agent， 以及如何编写高质量的 Skill.md 来提升 AI 协作效率。</summary>
    <title>什么是Agent，怎么用好Agent，怎么写Skill</title>
    <updated>2026-03-19T02:30:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="AI技术" scheme="https://blog.skyforever.top/categories/AI%E6%8A%80%E6%9C%AF/"/>
    <category term="概念解析" scheme="https://blog.skyforever.top/categories/AI%E6%8A%80%E6%9C%AF/%E6%A6%82%E5%BF%B5%E8%A7%A3%E6%9E%90/"/>
    <category term="Agent" scheme="https://blog.skyforever.top/tags/Agent/"/>
    <category term="AI" scheme="https://blog.skyforever.top/tags/AI/"/>
    <category term="LLM" scheme="https://blog.skyforever.top/tags/LLM/"/>
    <category term="RAG" scheme="https://blog.skyforever.top/tags/RAG/"/>
    <category term="MCP" scheme="https://blog.skyforever.top/tags/MCP/"/>
    <category term="Function Calling" scheme="https://blog.skyforever.top/tags/Function-Calling/"/>
    <category term="概念解析" scheme="https://blog.skyforever.top/tags/%E6%A6%82%E5%BF%B5%E8%A7%A3%E6%9E%90/"/>
    <category term="人工智能" scheme="https://blog.skyforever.top/tags/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/"/>
    <content>
      <![CDATA[<p>LLM、Prompt、Agent、RAG、Function Calling、MCP、LangChain……最近这几年，你是不是也被这些层出不穷的AI新词儿搞得头晕脑胀？</p><p>如果你一个都不认识，或者觉得它们高深莫测，那么恭喜你，来对地方了。</p><p>一个没有太多技术含量的行业，最终都会走向包装概念，让人感觉很高大上来让投资者投资。很多听起来神乎其神的新技术，如果把它们身上的“科技外衣”一层层剥开，你会看到一个非常接地气、甚至有点搞笑的现实：</p><p>看起来高大上的“智能体（Agent）”，本质上并不是AI变聪明了，而是工程师在AI外围套上了一层“制度和枷锁”。</p><hr><h2 id="看懂大模型与智能体的原理"><a href="#看懂大模型与智能体的原理" class="headerlink" title="看懂大模型与智能体的原理"></a>看懂大模型与智能体的原理</h2><p>在探讨复杂的架构前，我们可以通过两个通俗生动的科普视频，快速看清大语言模型（LLM）与智能体（Agent）的最底层真相。</p><h3 id="1-什么是大语言模型（LLM）？"><a href="#1-什么是大语言模型（LLM）？" class="headerlink" title="1. 什么是大语言模型（LLM）？"></a>1. 什么是大语言模型（LLM）？</h3><p>大语言模型（LLM）是当前生成式 AI 的核心。官方的教科书定义通常是：<em>“一种基于深度神经网络的人工智能模型，通过分析海量文本数据进行训练……”</em>。</p><p>如果用大白话来解释，它其实并没有真正的“主观思维”，而是一个在海量文本数据中计算字词概率的预测模型（文字接龙）。</p><p>B站UP主【闪客】在科普视频中用极接地气的方式讲透了这一底层逻辑：</p><div class="tag-plugin video-player" style="aspect-ratio:1.7777777777777777;max-width:100%;">    <iframe src="https://player.bilibili.com/player.html?bvid=BV1y7DXBEEUp&amp;autoplay=false" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true">    </iframe>    </div>    <div class="tag-plugin colorful note" color="blue"><div class="title"><strong><p>视频内容要点总结</p></strong></div><div class="body"><ul><li>统计概率猜词本质：大模型并不真正理解题目背后的数理逻辑，而是把全网海量文本作为“题库”，统计字词间极高的共现规律来猜下一个字，本质是个准确率极高的“文字接龙/蒙题机器”。</li><li>符号主义 vs 深度学习：从早期死记公式严密推导（符号主义）的上限受限，到后来靠海量数据统计概率找规律（深度学习）的暴力破解，正是“找规律”让大模型在海量场景中实现了智能涌现。</li><li>能力惊艳但伴随局限：因为底层是概率拟合而非真正逻辑，模型在复杂任务中表现出色的同时，也常在数手指、数字母等确定性问题上犯常识错误（幻觉），因此需要外围工程加以约束。</li></ul></div></div><p>我们可以把大语言模型当作一个黑箱：我们给这个黑箱输入单次的内容（Prompt / 提问），然后这个黑箱通过内部的统计概率计算，输出大概率正确的内容（单次预测回复）。</p><p><img src="https://image.skyforever.top/blog/2026/08/dd09f579a69230c7be79111f584c0a4a.svg" alt="大语言模型黑箱模型"></p><hr><h3 id="2-什么是智能体（Agent）？"><a href="#2-什么是智能体（Agent）？" class="headerlink" title="2. 什么是智能体（Agent）？"></a>2. 什么是智能体（Agent）？</h3><p>单纯的大语言模型只有“一问一答”的对话能力，而且本身没有任何记忆（我们感知到的多轮对话，都是外围程序把历史记录打包发给它）。</p><p>为了让 AI 能够自主调用工具、多步规划并自动完成复杂任务，工程师在其外围构建了智能体（Agent）。</p><p>UP主【闪客】用 20 行极简 Python 代码彻底拆解了从“伪造记忆”到“Agent 自动化执行”的底层逻辑：</p><div class="tag-plugin video-player" style="aspect-ratio:1.7777777777777777;max-width:100%;">    <iframe src="https://player.bilibili.com/player.html?bvid=BV19hwTzwETF&amp;autoplay=false" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true">    </iframe>    </div>    <div class="tag-plugin colorful note" color="green"><div class="title"><strong><p>视频内容要点总结</p></strong></div><div class="body"><ul><li>上下文（Context）与记忆真相：AI 本身是“秒忘”的，我们感知到的多轮对话记忆，纯粹是外围程序在每次发起请求时，把历史聊天记录打包（Context）一同塞给模型。</li><li>Agent 的本质是 While 循环：Agent 并没有神秘魔法，核心就是通过一个 <code>while</code> 循环不断调用大模型 API，并规定模型输出特定格式的命令（如 <code>命令: ...</code>）。</li><li>外围代跑腿与技能扩展：外围程序充当“跑腿秘书”，负责识别命令并在本地执行系统指令（Shell 命令），把执行结果回传给大模型，循环往复直至任务完成；配合 <code>skill.md</code> 说明书即可随时教会 AI 调用新工具。</li></ul></div></div><p>从上面的视频里我们可以清晰地了解到：大模型本身是秒忘的，程序员写了一段代码把每次和 AI 的聊天记录存下来。每一次交互，依然是我们给黑箱输入一些内容（单次用户输入 + Agent 保存的历史对话记录），然后这个黑箱输出大概率正确的内容（比如一段调用工具的命令）。外围程序代跑腿执行该命令后，再把执行结果存入聊天记录，形成一个自动循环。</p><p><img src="https://image.skyforever.top/blog/2026/08/3586398f732e2af7e416aad43074eea1.svg" alt="智能体循环机制"></p><hr><h2 id="构建“可靠的”-AI-系统"><a href="#构建“可靠的”-AI-系统" class="headerlink" title="构建“可靠的” AI 系统"></a>构建“可靠的” AI 系统</h2><p>看清了底层大模型（概率预测）与智能体（While 循环跑腿）的真相后，我们再来看看工程师们是如何在这个并不靠谱的小人外围，搭建起一整套严密的工业级控制体系的。</p><h3 id="3-什么是检索增强生成（RAG）？"><a href="#3-什么是检索增强生成（RAG）？" class="headerlink" title="3. 什么是检索增强生成（RAG）？"></a>3. 什么是检索增强生成（RAG）？</h3><p>因为 AI 的知识只停留在它被训练好的那一刻，所以它有两个致命毛病：</p><ol><li>信息滞后：不知道今天刚发生的新闻。</li><li>产生幻觉：当记不清某些知识时，为了完成文字接龙，会极度自信地胡说八道。</li></ol><p>为了让 AI 能够基于最新的真实数据回答问题，工程师给它配了外部小抄：</p><ul><li>联网搜索：AI 想看新闻时，跑腿秘书立刻去网上抓取最新的网页递给它。</li><li>RAG（检索增强生成）：公司把自己的内部资料库做成一个“向量字典”。AI 一问到内部业务，跑腿秘书就去字典里把最相关的几页检索出来拍在 AI 眼前，让 AI 基于正确资料回答。</li></ul><p>这就相当于给 AI 开了开卷考试的作弊器，在它开始瞎编之前先看一眼标准答案，回答的准确率自然大幅提高。</p><hr><h3 id="4-什么是-Function-Calling-与-MCP？"><a href="#4-什么是-Function-Calling-与-MCP？" class="headerlink" title="4. 什么是 Function Calling 与 MCP？"></a>4. 什么是 Function Calling 与 MCP？</h3><p>随着 AI 想管的事情越来越多——关智能家居的灯、做 PPT、控制工业设备，每个工具的接线口长得千奇百怪。为了不让 AI 抓狂，行业内搞了两次“普通话大统一”：</p><h4 id="1-Function-Calling（规范-AI-说话的格式）"><a href="#1-Function-Calling（规范-AI-说话的格式）" class="headerlink" title="1. Function Calling（规范 AI 说话的格式）"></a>1. Function Calling（规范 AI 说话的格式）</h4><p>大模型厂商对 AI 进行了专门训练，规定它想用工具时，必须输出死板、严谨的 JSON 结构化格式（类似标准填空题表格），外围程序就能 100% 稳定解析。</p><h4 id="2-MCP（规范工具插座的万能协议）"><a href="#2-MCP（规范工具插座的万能协议）" class="headerlink" title="2. MCP（规范工具插座的万能协议）"></a>2. MCP（规范工具插座的万能协议）</h4><p>如果说 Function Calling 规范了 AI 的嘴巴，那么 MCP（Model Context Protocol）规范的就是外部工具的通用插座。</p><p><img src="https://image.skyforever.top/blog/2026/02/2eaf3cf1dda224892bb0a66a2ffc06e3.webp" alt="MCP 协议图"></p><p>在 MCP 协议下，不管你是智能台灯、Excel 软件还是数据库，都换上同一种“万能三头插座”。Agent 程序不再需要为每个新工具单独写适配代码，直接插进 MCP 接口，AI 就能一秒控制新工具。</p><hr><h3 id="5-调用-AI-的四种方式"><a href="#5-调用-AI-的四种方式" class="headerlink" title="5. 调用 AI 的四种方式"></a>5. 调用 AI 的四种方式</h3><p>为了让 AI 稳定听话地干活，人类在程序架构里设计了四种调用与管理模式：</p><ol><li>直接编程派（LangChain）——“死板的老板”：<br>完全不给 AI 自由发挥的空间。在程序里写死：第一步调用什么模型，第二步必须把结果传给哪个函数，呆板但胜在绝对可控。</li><li>低代码工作流（Workflow）——“画好的流水线”：<br>把工作步骤做成图形化连线图（如 Coze、Dify 等平台）。AI 就像流水线上的工人，只能顺着传送带一步步往下流转。</li><li>按需加载派（Skill/技能目录）——“按需发说明书”：<br>如果外部工具太多，把几千页工具说明书一次性塞给 AI 会爆掉上下文，甚至导致注意力分散。程序将工具封装成独立的“技能包（Skill）”，只有当 AI 遇到特定任务时，才把对应的说明书递给它。</li><li>外包分工派（SubAgent/子智能体）——“套娃包工头”：<br>当任务极其庞大时，主 AI 会通过多线程分发创建几个一模一样的子智能体，把大任务拆解并分发给分身去执行，各分身汇报结果后用完即弃，大幅降低单点上下文过载风险。</li></ol><p>看清了这一层，你就会明白：<strong>无论是 RAG 查资料小抄、MCP 接入工具万能插座，还是 Skill 技能说明书，其本质依然是改变黑箱输入的内容（用户提问 + RAG 知识 + MCP 数据 + Skill 规范），然后让黑箱输出大概率正确的高质量内容。</strong></p><p><img src="https://image.skyforever.top/blog/2026/08/b4643907747dbf326dde6e4971e8897d.svg" alt="RAG/MCP/Skill 的本质：改变黑箱输入"></p><hr><h3 id="6-为什么-Agent-容易出错？"><a href="#6-为什么-Agent-容易出错？" class="headerlink" title="6. 为什么 Agent 容易出错？"></a>6. 为什么 Agent 容易出错？</h3><p>你可能会问：既然人类设计了这么完美的管理制度、万能插座和小抄，为什么现实中 AI 智能体干活时间越长、步骤越多，就越容易跑偏、胡言乱语？</p><p>最核心的原因在于：<strong>我们无法在推理使用阶段改变黑箱本身（因为大模型只有在训练阶段才能改变输出概率，使用时只能改变黑箱的输入）。</strong></p><p>因为无法改变黑箱内部固定的概率特性，一旦生成庞大复杂的内容，错误就会像滚雪球一样呈指数级放大，而且在推演过程中即使出错，AI 自身也无法发觉，反而会把错误当成事实继续推演。</p><p>拿写代码来举例：<br>当你给大模型输入一个宏观开发指令时，它会输出很多个代码文件。<br>每次生成单份代码文件时，其正确概率几乎是固定的（假设高达 90%）。<br>但一个庞大的系统由数十个代码文件组合而成，这些文件组合起来的系统整体正确率，是所有代码文件的正确率连乘累积的（<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0.9</mn><mo>×</mo><mn>0.9</mn><mo>×</mo><mn>0.9...</mn></mrow><annotation encoding="application/x-tex">0.9 \times 0.9 \times 0.9...</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="katex-base"><span class="katex-strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">0.9</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="katex-base"><span class="katex-strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">0.9</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="katex-base"><span class="katex-strut" style="height:0.6444em;"></span><span class="mord">0.9...</span></span></span></span>）。随着文件数量增加，整体可用率会急剧暴跌趋近于 0！</p><p><img src="https://image.skyforever.top/blog/2026/08/4ded7254d4d713ca0ca95365bd2f514d.svg" alt="多文件概率累乘雪崩"></p><p>所以，<strong>必须要有工程师能挑出 AI 写的代码里的错误</strong>，否则由 AI 独立堆砌的大型系统大概率会越来越不可靠。</p><p>为了对抗这个“错误雪崩”规律，现代 AI 工程演进出了最新的阶段：系统护栏（Harness Engineering）。人类不再寄希望于 AI 自己不犯错，而是在外围装上密密麻麻的自动化测试、校验规则与质检员：</p><ul><li>不让 AI 自己当裁判：AI 写完的代码，外围程序自动运行单元测试。</li><li>用报错反馈逼迫重试：一旦测试不通过，程序把报错信息直接反馈给 AI 强制修正。</li><li>严密的边界限制：限制单次执行权限与活动范围，防止脱缰。</li></ul><hr><h3 id="7-总结"><a href="#7-总结" class="headerlink" title="7. 总结"></a>7. 总结</h3><p>看清了“概率模型”与“错误雪崩”的本质，你就会明白：<strong>没有人类搭建的外围控制系统与质检护栏，AI 自己产出的东西很快就会退化为不可用的垃圾。</strong></p><p>AI 极大解放了生产力，但它并没有消灭工程师，反而带来了极其庞大的系统设计与工程治理需求。</p><blockquote><p>根据2026年初最新的行业数据：全球软件工程的职位空缺数量近期已经突破了 6.7 万个，比两年前的低谷期几乎翻了一番。（<a href="https://www.businessinsider.com/ai-isnt-killing-software-coding-jobs-booming-trueup-2026-4" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>原文地址</a>/<a href="https://finance.sina.com.cn/tech/discovery/2026-04-08/doc-inhtuqhe1582051.shtml" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>国内转载</a>）</p></blockquote><p><img src="https://image.skyforever.top/blog/2026/08/bf8701c4d032c2a3482b387b6cfe1954.jpg" alt="真正懂底层与框架的工程师，用AI降维打击只会提示词的人"></p><p>这背后的逻辑非常清晰：企业需要的不再是只会盲目敲代码的人，而是能够驯服这匹不稳定的“野马”、把概率模型转化为确定性业务价值的人。</p><p>那么，究竟怎样才能让 AI 输出的内容真正可靠？对于人类使用者来说，主要有以下两种方式：</p><ol><li>作为 AI 这匹马的“掌控者（骑手）”：敏锐观察 AI 的推演与输出，一旦看到 AI 的前进方向是错误的，能凭借专业能力及时把它纠正回来，借助 AI 极快的速度成倍加速自己的工作；</li><li>作为系统的“架构设计师”：为 AI 设计一套合理的流水线，把各个 AI 放在流水线上各司其职。配合严密的质检与容错机制，AI 在这个系统中即使出了一点小错误，系统也能自动调整与纠偏，完全不影响整个系统的稳定运转。</li></ol><p>工程师的价值并没有消失，只是发生了转移：<strong>从“自己动手写代码/干活的人”，变成了“设计系统、让 AI 乖乖干活的人”。</strong> 给刚入职的天才（大模型），配上严密的规范文档（上下文）、审批流程（反馈循环）和绩效考核（护栏）。</p><p>所以，关掉那些为了流量贩卖焦虑的短视频吧。<br>在这个被新词汇包裹的“名词诈骗”时代里，看透底牌的你不需要恐慌。大模型只是那个只会找规律蒙题的偏科生，而你，才是那个制定试卷、把控流程、并最终拍板的主考官。</p>]]>
    </content>
    <id>https://blog.skyforever.top/posts/38247</id>
    <link href="https://blog.skyforever.top/posts/38247"/>
    <published>2026-02-27T06:00:00.000Z</published>
    <summary>用通俗直白的语言，深入解析Agent、RAG、MCP、Function Calling、LangChain、Skill等AI领域的热门概念。 揭示这些看似高大上的名词背后的本质，帮助读者建立统一的AI概念认知框架。</summary>
    <title>解析各种AI概念</title>
    <updated>2026-02-27T06:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="开发工具" scheme="https://blog.skyforever.top/categories/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/"/>
    <category term="AI编程" scheme="https://blog.skyforever.top/categories/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/AI%E7%BC%96%E7%A8%8B/"/>
    <category term="教程" scheme="https://blog.skyforever.top/tags/%E6%95%99%E7%A8%8B/"/>
    <category term="AI编程" scheme="https://blog.skyforever.top/tags/AI%E7%BC%96%E7%A8%8B/"/>
    <category term="Claude Code" scheme="https://blog.skyforever.top/tags/Claude-Code/"/>
    <category term="开发工具" scheme="https://blog.skyforever.top/tags/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/"/>
    <category term="Anthropic" scheme="https://blog.skyforever.top/tags/Anthropic/"/>
    <content>
      <![CDATA[<p>最近 AI 编程工具界最火的莫过于 Anthropic 官方推出的 Claude Code。但国内因为网络和高昂的 API 费用，很多开发者望而却步。</p><p>今天这篇文章，我将带你用<strong>一杯奶茶钱（7.9 元）<strong>搞定原本遥不可及的顶级 AI 编程体验，并扒一扒 Claude Code 内部隐藏的</strong>子代理机制</strong>——很多人因为不懂这个机制，白白浪费了大量 Token 和上下文！</p><hr><h2 id="一、什么是-Claude-Code？"><a href="#一、什么是-Claude-Code？" class="headerlink" title="一、什么是 Claude Code？"></a>一、什么是 Claude Code？</h2><p>与网页版的聊天对话框不同，Claude Code 是一个运行在终端（CLI）的<strong>具备工程上下文、权限控制和执行能力的开发协作系统</strong>。</p><p>它的核心特点是：</p><ol><li><strong>直接在终端可用</strong>：无需来回切换窗口。</li><li><strong>能动手的工程师</strong>：可以自主读取代码、编写文件、执行 Git 提交，甚至运行测试命令。</li><li><strong>按量计费（API 模式）</strong>：本地不吃算力，全部通过 API 调用云端模型。</li></ol><p>简单来说，它不是一个“聊天机器人”，而是一个直接坐在你终端里的“高级外包程序员”。</p><blockquote><p><strong>官方文档参考</strong>：<a href="https://code.claude.com/docs/zh-CN/overview" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>Claude Code Overview</a></p></blockquote><hr><h2 id="二、算力平台选择：先搞定-API-密钥"><a href="#二、算力平台选择：先搞定-API-密钥" class="headerlink" title="二、算力平台选择：先搞定 API 密钥"></a>二、算力平台选择：先搞定 API 密钥</h2><p>官方的 Claude 4.7 接口价格非常昂贵（百万 Token 动辄几十美元），且国内无法直连。我们的核心原则是：<strong>API 提供商本质只是一个算力中转，既然功能一样，哪家便宜稳定就买哪家！</strong></p><p>在下载任何工具之前，我们需要先去云厂商那里注册并获取 API Key。</p><p>下面提供三种方案，可以根据自己的需求点击切换查看：</p><div class="tag-plugin tabs" align="center" id="tab_6"><div class="nav-tabs"><div class="tab active"><a href="#tab_6-1">付费推荐（首选）</a></div><div class="tab"><a href="#tab_6-2">英伟达（免费）</a></div><div class="tab"><a href="#tab_6-3">OpenRouter（免费）</a></div></div><div class="tab-content"><div class="tab-pane active" id="tab_6-1"><p>如果你追求稳定、快速的 Claude Code 体验，可以考虑付费方案。在付费方案中随便选择一个购买就行，关键看自己的预算和需求。</p><ul><li><strong>国外付费</strong>：模型能力通常更强（如 Claude 官方 API），但需要配置上网环境，国内访问不便。</li><li><strong>国内付费</strong>：便宜、稳定、量大、好用，且无需翻墙，<strong>推荐优先选择国内付费方案</strong>。目前各家价格相差不大，找个最便宜的用就行。</li></ul><p>关于国内外的codingplan计费方式，可用模型和速度等信息，可以通过以下链接快速获取最新的价格信息：</p><p><a href="https://coding-plan.xyz/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>Coding Plan一站通 - 最全、最及时的AI套餐信息</a></p><p>购买套餐后，进入对应平台的 API Key 控制台获取密钥。各个平台的密钥获取请参考各自官方文档。</p><p>得到密钥后即可通过cc-switch配置claudecode,进而使用对应平台的模型服务</p><p><strong>以阿里云为例，演示付费平台的完整接入流程：</strong></p><p><strong>1. 购买套餐</strong></p><p>前往 <a href="https://www.aliyun.com/benefit/scene/ai-discount" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>阿里云 AI 编程套餐活动页</a> 完成购买。</p><p>找到下面的购买入口进行购买：</p><p><img src="https://image.skyforever.top/blog/2026/02/ed1eacf9b7bf9fc2adc8858d8a2f8793.webp" alt="阿里云AI编程套餐购买入口"></p><p><strong>2. 获取密钥</strong></p><p>购买后进入 <a href="https://bailian.console.aliyun.com/cn-beijing/?tab=model#/api-key" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>百炼 API Key 控制台</a>，在左侧找到订阅套餐的选项，将 API Key <strong><code>&lt;u&gt;</code>复制保存好 <code>&lt;/u&gt;</code></strong>。</p><p><img src="https://image.skyforever.top/blog/2026/02/445b99037a697f16bd9c378d847c5c76.webp" alt="百炼API Key控制台"></p><p><strong>3. 记录接口地址</strong></p><p>根据 <a href="https://bailian.console.aliyun.com/cn-beijing/?spm=a2c6h.12873639.article-detail.8.632438beNFVBFl&amp;source_channel=zhihedoc&amp;tab=doc#/doc/?type=model&amp;url=3005961" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>官方文档</a>，阿里的专属后端调用地址为：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://coding.dashscope.aliyuncs.com/apps/anthropic</span><br></pre></td></tr></tbody></table></figure></div><div class="tab-pane" id="tab_6-2"><p><strong>英伟达免费 API 一年（12 个月）使用权</strong>，可以直接调用 GLM 5.1、Gemma 4、MiniMax 等 193 款主流大模型，这羊毛必须薅！</p><p><strong>1. 访问官方网站</strong></p><p>打开浏览器，访问 <a href="https://build.nvidia.com/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://build.nvidia.com/</a>，点击注册账号。</p><p><strong>2. 账号登录与验证</strong></p><p>按照页面提示完成注册。验证环节支持 <strong>+86 手机号</strong> 接收验证码，非常方便。</p><p><strong>3. 创建 API Key</strong></p><p>访问 <a href="https://build.nvidia.com/settings/api-keys" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>API Keys 管理页面</a>，创建新的密钥。</p><blockquote><p><strong>注意</strong>：Expiration（有效期）请选择 <strong>Never Expire</strong>（永不过期），避免后续麻烦。</p></blockquote><p><strong>4. 接口配置</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># API Base URL</span></span><br><span class="line">https://integrate.api.nvidia.com/v1/chat/completions</span><br><span class="line"></span><br><span class="line"><span class="comment"># 可用模型示例</span></span><br><span class="line">z-ai/glm-4.7</span><br><span class="line">z-ai/glm-5.1</span><br><span class="line">minimaxai/minimax-m2.7</span><br><span class="line">google/gemma-4-27b-it</span><br></pre></td></tr></tbody></table></figure><blockquote><p><strong>热门模型高峰时期使用可能会有卡顿</strong><br><strong>建议</strong></p><ol><li><strong>当成备用 / 开发测试用</strong>：写代码、生成长文本、Agent 实验都很香。</li><li><strong>错峰使用</strong>：国内凌晨或上午通常会快很多。</li><li><strong>多备几个模型</strong>：在客户端里把 GLM + MiniMax + Nemotron 都加进去，哪个快用哪个。</li><li><strong>客户端优化</strong>：cc-switch、Cherry Studio 等支持自动 fallback 的工具能自动跳过卡住的模型。</li></ol></blockquote></div><div class="tab-pane" id="tab_6-3"><p>通过 OpenRouter 上的免费模型，配合 cc-switch 这款可视化管理工具，一键切换 API 提供商，可以实现 <strong>完全免费的 AI 编程体验</strong>。</p><p><strong>Base URL</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://openrouter.ai/api/v1</span><br></pre></td></tr></tbody></table></figure><p><strong>推荐模型</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">inclusionai/ling-2.6-1t:free</span><br></pre></td></tr></tbody></table></figure><p>最近很火的模型，出自蚂蚁百灵大模型，知识储备充足，思考维度更深，输出的回答质量更高、精准度更强，但响应速度相对缓慢，更适配复杂且重要的工作任务。</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ling-2.6-flash</span><br></pre></td></tr></tbody></table></figure><p>类似快枪手，核心优势是反应速度快，作答内容满足基础使用需求即可，不会过度追求完美，整体工作效率出色，能够快速批量处理事务，适合应用于简单、需要即时响应的各类任务。</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Nemotron 3 Super (free)</span><br></pre></td></tr></tbody></table></figure><p>超长上下文、多智能体推理、高吞吐量，适合长文档分析、跨文档推理、科学计算等场景。</p><blockquote><p><strong>小技巧</strong>：建议在 cc-switch 中多配置几个模型方便快速切换。配置好一个之后直接复制，然后编辑，粘贴模型 Id，点击模型映射 <strong>“一键设置”</strong> 即可。</p></blockquote><p><img src="https://image.skyforever.top/blog/2026/09/d2697326c3c91de4398b664dc4c8f850.webp" alt="OpenRouter 多模型配置示例"></p><blockquote><p><strong>PS</strong>：OpenRouter 充值如果想要使用 <strong>支付宝或微信</strong>，勾选 “Use checkout page” 后即可在出现的页面选择对应支付方式。详细教程：<a href="https://zhuanlan.zhihu.com/p/1902150269241893722" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>参阅这篇知乎文章</a>。</p></blockquote></div></div></div><hr><h2 id="三、安装-Claude-Code"><a href="#三、安装-Claude-Code" class="headerlink" title="三、安装 Claude Code"></a>三、安装 Claude Code</h2><p>虽然各家云厂商都提供了复杂的官方配置文档，但作为开发者，我们有更优雅的通用解法：使用开源工具 <strong>cc-switch</strong>。</p><p>无论你买的是阿里云、智谱还是其他家，配置流程只有简单的三步：<strong>复制、粘贴、启用</strong>。</p><h3 id="1-安装环境和程序本体"><a href="#1-安装环境和程序本体" class="headerlink" title="1. 安装环境和程序本体"></a>1. 安装环境和程序本体</h3><h4 id="1-1-安装运行环境-Node-js"><a href="#1-1-安装运行环境-Node-js" class="headerlink" title="1.1 安装运行环境(Node.js):"></a>1.1 安装运行环境(Node.js):</h4><p>因为 Claude Code 是由 JavaScript 编写的程序，所以需要先安装 Node.js。</p><p>Node.js 是一个开源、跨平台的 JavaScript 运行环境，它让电脑能够运行像 Claude Code 这样的命令行工具。</p><p>下载地址：<a href="https://nodejs.org/zh-cn/download" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://nodejs.org/zh-cn/download</a></p><p>下载 Node.js的<strong>Windows 安装程序 (.msi)</strong>。下载后就像安装微信一样，双击运行并一路点击 ‘Next’（下一步）直到 ‘Finish’（完成）即可。</p><p><img src="https://image.skyforever.top/blog/2026/02/59c3c9fb491621cb49e3327454902458.webp" alt="Node.js下载指示"></p><h4 id="1-2-安装-运行依赖-（Git）"><a href="#1-2-安装-运行依赖-（Git）" class="headerlink" title="1.2 安装 运行依赖 （Git）"></a>1.2 安装 运行依赖 （Git）</h4><p>Claude Code 的底层运行依赖 Bash 环境，这是 Windows不支持的。</p><p>因此必须安装 Git，利用其附带的 <strong>Git Bash</strong> 工具来模拟类 Linux 环境，Claude Code 才能正常工作。</p><p>下载地址：<a href="https://git-scm.com/install/windows" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://git-scm.com/install/windows</a></p><p>下载<strong>Git for Windows/x64 Setup</strong>。下载后就像安装微信一样，双击运行，保持默认安装选项一路点击 ‘Next’（下一步）直到 ‘Finish’（完成）即可。</p><p><img src="https://image.skyforever.top/blog/2026/02/e355cc0b8730840d27428cae8bbaf3ac.webp" alt="Git for Windows下载页面"></p><h4 id="1-3-安装-Claude-Code"><a href="#1-3-安装-Claude-Code" class="headerlink" title="1.3 安装 Claude Code"></a>1.3 安装 Claude Code</h4><p>安装好前面的两个环境后，按下键盘上的win+r，在里面输入cmd，点击确定以打开cmd命令行窗口</p><p><img src="https://image.skyforever.top/blog/2026/03/11682306e70bef01e47d366ddfa7bc3f.png" alt="Win+R 运行窗口输入 cmd 打开命令行"></p><p>在你的cmd终端执行以下命令即可实现安装：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g @anthropic-ai/claude-code</span><br></pre></td></tr></tbody></table></figure><p><img src="https://image.skyforever.top/blog/2026/02/5b2c6a966baaaefb3bb93461d35ba823.webp" alt="通过npm安装Claude Code"></p><h3 id="2-下载并安装-cc-switch"><a href="#2-下载并安装-cc-switch" class="headerlink" title="2. 下载并安装 cc-switch"></a>2. 下载并安装 cc-switch</h3><p>这是一个专为 Claude Code 等工具设计的可视化配置切换器。</p><p>前往 <a href="https://github.com/farion1231/cc-switch/releases" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>cc-switch GitHub Releases</a> 下载对应操作系统的安装包。</p><p>往下翻，找到 <code>CC-Switch-v3.11.0-Windows.msi</code>，下载安装，安装时一路下一步即可</p><p><img src="https://image.skyforever.top/blog/2026/02/84f5ead1fa24b9869e51857f00ce55ff.webp" alt="cc-switch GitHub Releases下载页面"></p><h3 id="3-配置-API"><a href="#3-配置-API" class="headerlink" title="3. 配置 API"></a>3. 配置 API</h3><p><strong>第一步：复制你的 KEY</strong></p><p>不同平台获取 API Key 的入口略有不同，找到对应平台的控制台复制保存好：</p><div class="tag-plugin tabs" align="center" id="tab_7"><div class="nav-tabs"><div class="tab active"><a href="#tab_7-1">阿里云</a></div><div class="tab"><a href="#tab_7-2">英伟达</a></div><div class="tab"><a href="#tab_7-3">OpenRouter</a></div></div><div class="tab-content"><div class="tab-pane active" id="tab_7-1"><p>进入 <a href="https://bailian.console.aliyun.com/cn-beijing/?tab=model#/api-key" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>百炼 API Key 控制台</a>，在左侧找到订阅套餐的选项，将 API Key <code>&lt;u&gt;</code>复制保存好 <code>&lt;/u&gt;</code>。</p><p><img src="https://image.skyforever.top/blog/2026/02/445b99037a697f16bd9c378d847c5c76.webp" alt="百炼API Key控制台"></p></div><div class="tab-pane" id="tab_7-2"><p>访问 <a href="https://build.nvidia.com/settings/api-keys" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>NVIDIA API Keys 管理页面</a>，创建新的密钥，并将 API Key <code>&lt;u&gt;</code>复制保存好 <code>&lt;/u&gt;</code>。</p><blockquote><p><strong>注意</strong>：Expiration（有效期）请选择 <strong>Never Expire</strong>（永不过期），避免后续麻烦。</p></blockquote><p><img src="https://image.skyforever.top/blog/2026/05/c54af5c5e7163cc919442579e9f6b97a.webp" alt="点击复制key"></p></div><div class="tab-pane" id="tab_7-3"><p>访问 <a href="https://openrouter.ai/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>OpenRouter</a> 注册账号，然后在 Keys 页面创建 API Key，并将 API Key <code>&lt;u&gt;</code>复制保存好 <code>&lt;/u&gt;</code>。</p></div></div></div><p><strong>第二步：在 cc-switch 中填写 API Key 和后端地址</strong></p><p>打开 cc-switch 桌面端，点击右上角的加号添加配置：</p><ul><li>如果你使用的是<strong>常用平台</strong>（阿里云、英伟达、OpenRouter、智谱、Kimi 等），选择对应的<strong>厂商预设</strong>。</li><li>如果你使用的是不常用平台例如讯飞、百度等，选择<strong>自定义</strong>。</li></ul><p><img src="https://image.skyforever.top/blog/2026/02/04a7ffd9742354a0cb1d7845c9431cd3.webp" alt="cc-switch添加新配置"></p><p>然后根据不同平台填写对应的信息：</p><div class="tag-plugin tabs" align="center" id="tab_8"><div class="nav-tabs"><div class="tab active"><a href="#tab_8-1">付费配置（阿里云示例）</a></div><div class="tab"><a href="#tab_8-2">英伟达</a></div><div class="tab"><a href="#tab_8-3">OpenRouter</a></div></div><div class="tab-content"><div class="tab-pane active" id="tab_8-1"><p><img src="https://image.skyforever.top/blog/2026/02/edaa226dc7779af9123704eb7a150da1.webp" alt="选择阿里云厂商配置"><br>往下翻，将 API Key 和后端地址粘贴进去：</p><p>阿里云的后端地址为：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://coding.dashscope.aliyuncs.com/apps/anthropic</span><br></pre></td></tr></tbody></table></figure><p><img src="https://image.skyforever.top/blog/2026/02/aa25538a9e933707dfda4d208600a64b.webp" alt="配置阿里云API Key和接口地址"></p><blockquote><p>其他付费平台的后端地址请参考各自官方文档，通常在 API Key 管理页面或开发文档中可以找到。</p></blockquote><p>点击”保存”（或添加）即可。</p></div><div class="tab-pane" id="tab_8-2"><p><img src="https://image.skyforever.top/blog/2026/05/80c498e31c7693ef19637f9ba1c704c1.webp" alt="选择英伟达配置"></p><p>往下翻，将 API Key 和后端地址粘贴进去：</p><ul><li><p><strong>后端地址</strong>：<code>https://integrate.api.nvidia.com/v1/chat/completions</code></p></li><li><p><strong>API Key</strong>：粘贴刚才创建的 NVIDIA API Key</p></li><li><p><strong>模型名称</strong>：填入你想使用的模型 ID，例如：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">z-ai/glm-4.7</span><br><span class="line">z-ai/glm-5.1</span><br><span class="line">minimaxai/minimax-m2.7</span><br><span class="line">google/gemma-4-27b-it</span><br></pre></td></tr></tbody></table></figure></li></ul><p>具体选择什么模型，可以查看英伟达的<a href="https://build.nvidia.com/models?filters=nimType:nim_type_preview" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>模型列表</a>页面查看有哪些免费模型</p><p><img src="https://image.skyforever.top/blog/2026/05/28345afb80cae25d954b8d4fb740e984.webp" alt="选择查看免费模型"></p><p>配置好后，点击”添加”即可。</p><p>注意<strong>热门模型高峰时期可能会有卡顿</strong>，建议多配置几个模型作为备用。</p></div><div class="tab-pane" id="tab_8-3"><p>填写以下信息：</p><ul><li><strong>Base URL</strong>：<code>https://openrouter.ai/api/v1</code></li><li><strong>API Key</strong>：粘贴你的 OpenRouter API Key</li><li><strong>模型名称</strong>：填入免费模型 ID，例如：<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">inclusionai/ling-2.6-1t:free</span><br><span class="line">ling-2.6-flash</span><br><span class="line">Nemotron 3 Super (free)</span><br></pre></td></tr></tbody></table></figure></li></ul><p>点击”保存”即可。</p><blockquote><p><strong>小技巧</strong>：建议多配置几个免费模型方便切换。配置好一个后直接复制，编辑模型 ID，点击”一键设置”即可快速添加其他模型。</p></blockquote><blockquote><p><strong>PS</strong>：OpenRouter 充值如需支付宝或微信，勾选 “Use checkout page”。详细教程可以<a href="https://zhuanlan.zhihu.com/p/1902150269241893722" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>参阅这篇知乎文章</a>。</p></blockquote></div></div></div><h3 id="4-开始使用"><a href="#4-开始使用" class="headerlink" title="4.开始使用"></a>4.开始使用</h3><p>大功告成！</p><p>现在你在之前的终端里输入 <code>claude</code>，就可以直接起飞了。</p><p>可以在对话框里随便输入一些文字来测试是否配置成功</p><p><img src="https://image.skyforever.top/blog/2026/02/19af532d600edd488f26118ddb38ca6c.webp" alt="Claude Code启动成功界面"></p><p>在使用之前，建议做一些基础配置<br>在claudecode对话框里输入</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/config</span><br></pre></td></tr></tbody></table></figure><p>进入配置界面，往下翻，找到 <code>Language</code>的选项，按下空格</p><p><img src="https://image.skyforever.top/blog/2026/05/5cd5be0f09dcc9b6f2145a3c393f34a0.webp" alt="选择语言配置选项"></p><p>输入Chinese,注意C要大写</p><p><img src="https://image.skyforever.top/blog/2026/05/c7ff064d961bde6a36646369f70c49ab.webp" alt="配置为中文"></p><p>这样设置后，claudecode虽然界面还是英文，但他的思考和回答都会变成中文，这样方便我们看懂claudecode的思考内容，并且在一些细节上程序会对对中文场景做优化</p><p>如果想自定义这个页面的其他设置，可以参考<a href="https://code.claude.com/docs/zh-CN/settings" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>ClaudeCode 官方文档</a>里面的描述</p><hr><h2 id="四、用“文件整理”搞懂三大子代理模式"><a href="#四、用“文件整理”搞懂三大子代理模式" class="headerlink" title="四、用“文件整理”搞懂三大子代理模式"></a>四、用“文件整理”搞懂三大子代理模式</h2><p><strong>这是新手最容易踩坑的地方！</strong></p><p>很多新手打开 Claude Code 后，无论干什么都在主对话里直接输入。这会导致一个致命问题：<strong>主对话的上下文越来越长，反应越来越慢，Token 消耗极快！</strong></p><p>其实，Claude Code 内部有一套极其精密的<strong>交互模式</strong>和<strong>子代理</strong>（Subagent）机制。你可以把“子代理”理解为运行在<strong>独立上下文窗口</strong>中的专用 AI 工具人。把特定任务交给它们，<strong>就不会污染你的主对话上下文</strong>。</p><p>一般情况下，它在终端会自动切换，如果你用 VS Code 插件，也可以手动切换：</p><p><img src="https://image.skyforever.top/blog/2026/02/9314e63ffa8a2b7ca642f7fd246ee8b2.png" alt="Claude Code交互模式切换界面"></p><p>为了让你秒懂这三大模式的作用（Ask、Plan、Edit），我们直接结合一个非程序员也极其需要的日常痛点来实战：<strong>让 Claude Code 帮我们整理一个乱七八糟的文件夹</strong>。</p><blockquote><p><strong>注意</strong>：让 AI 整理文件前，请确保不要在包含超多文件或核心系统盘的目录执行，避免误删重要数据。</p></blockquote><h3 id="0-先进入需要整理的文件夹"><a href="#0-先进入需要整理的文件夹" class="headerlink" title="0. 先进入需要整理的文件夹"></a>0. 先进入需要整理的文件夹</h3><p>在文件管理器里找到你需要整理文件的位置，例如我这里要整理我的博客，就打开博客文件夹</p><p>点击我箭头指向的这个位置</p><p><img src="https://image.skyforever.top/blog/2026/03/53a56b53bf71d279fa4fcb085fbc4fc2.png" alt="317d8969d47c300256a56a44fa0e9489"></p><p>往里面输出cmd，然后回车确认</p><p><img src="https://image.skyforever.top/blog/2026/03/0cd69ef91905278ccbe8b25d6b723854.png" alt="运行窗口输入 cmd 打开终端命令行"></p><p>在新开的终端窗口中，输入 <code>claude</code>即可启动 <code>ClaudeCode</code></p><p><img src="https://image.skyforever.top/blog/2026/03/bece9f495b6455e696e46c8399d1d440.png" alt="终端输入 claude 成功启动 Claude Code"></p><h3 id="1-Ask-模式，先看不动手"><a href="#1-Ask-模式，先看不动手" class="headerlink" title="1. Ask 模式，先看不动手"></a>1. Ask 模式，先看不动手</h3><p>打开此工具默认以Ask（询问）模式启动</p><p>此模式做只读分析。它会调用速度快、成本低的模型，分出多个人来同时读取文件</p><p>只拥有读取权限，<strong>绝对不改文件</strong>。</p><p>面对一堆不知道装了什么的乱七八糟的文件，我们先用探索模式去摸底。</p><ul><li><p><strong>触发关键词</strong>：“探索”、“帮我看看”、“分析一下”</p></li><li><p>实战：<br>在终端中输入：</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">帮我探索一下当前文件夹，告诉我里面都有哪些类型的文件？</span><br></pre></td></tr></tbody></table></figure><p>此时它会派出几个小兵快速翻阅目录，并向你汇报他的分析结果：</p><p><img src="https://image.skyforever.top/blog/2026/03/297fe7be89179f01b797f90b38237504.png" alt="Ask 模式下快速浏览目录与汇报分析结果"></p></li></ul><h3 id="2-Plan-模式，规划后再行动"><a href="#2-Plan-模式，规划后再行动" class="headerlink" title="2. Plan 模式，规划后再行动"></a>2. Plan 模式，规划后再行动</h3><p>Plan（计划）模式依然不改文件，只负责在独立上下文中收集信息，并给你一份详细的实施步骤。</p><p>摸清文件夹底细后，我们需要制定分类规则，防止 AI 瞎整理。</p><ul><li><p><strong>触发关键词</strong>：“帮我做个规划”、“出个整理方案”</p></li><li><p>实战：<br>继续在终端输入：</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">进入 计划 模式。基于刚才看到的文件，帮我制定一个文件夹分类整理方案，按文件类型和日期列出具体的新建文件夹名称，并给出你的移动规则。</span><br></pre></td></tr></tbody></table></figure><p>此时，AI 会给你输出一份 Markdown 列表。</p><p><img src="https://image.skyforever.top/blog/2026/03/3929b7c1ed518c2ccbbc2db93ebfdb02.png" alt="Plan 模式下生成的实施步骤规划列表"></p><p>你可以看看ai给出的整理方案合不合理，你可以反复和ai沟通来确认实施方案，只有你自己和ai磨合好了之后，AI才能做出对你有帮助的动作</p><p>界面会给你这四个选项，你可以根据你的需要来选择他执行此计划还是重新计划：</p><p><img src="https://image.skyforever.top/blog/2026/03/df67093977d1693970c10a3aed8f0828.png" alt="计划确认界面的多项选择操作提示"></p><p>翻译后的内容：</p><p><img src="https://image.skyforever.top/blog/2026/03/c827c75549d13db5059419e180a7a28e.png" alt="c827c75549d13db5059419e180a7a28e"></p><p>例如我这里说：</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">我觉得不太合理</span><br><span class="line"><span class="number">1</span>.你不能动我的git，应该由我自己判断是否提交记录</span><br><span class="line">      <span class="number">2</span>.我这里image文件夹下压根就没有多少图片，不需要整理</span><br><span class="line">      <span class="number">3</span>.你只能修改_posts文件夹，按照你说的用年份分类，还有各种脚本放到同一个文件夹内</span><br></pre></td></tr></tbody></table></figure><p>输入后，ai就会按照你的指导重新给出方案，直到你满意为止</p><p><img src="https://image.skyforever.top/blog/2026/03/de9891bfe8aeb339602768982489e201.png" alt="针对用户反馈调整后的计划建议"></p><p>看，ai重新给了我一个方案，这次就比较合理，我们选择第一个选项，让他开始进入编辑模式干活</p><p><img src="https://image.skyforever.top/blog/2026/03/115136796864ee937dc09696578fbbbe.png" alt="确认并批准最终实施计划"></p></li></ul><h3 id="3-Edit-模式，开始干活"><a href="#3-Edit-模式，开始干活" class="headerlink" title="3. Edit 模式，开始干活"></a>3. Edit 模式，开始干活</h3><p>这是 <code>ClaudeCode</code> 真正动手的全能模式。会定位文件、执行命令（如新建文件夹、移动文件）、生成差异，并直接自动编写文件。</p><p>最好是在方案确认无误后，下达最终执行指令来使用此模式。</p><ul><li><p><strong>触发关键词</strong>：“修改”、“执行”</p><p><em>刚刚确认方案，它就会自动调用系统命令，新建文件夹并唰唰唰地把文件全部归类整齐！</em></p></li></ul><p><img src="https://image.skyforever.top/blog/2026/03/08ed704851ef2c92d9f676095a066ff8.png" alt="Edit 模式自动执行命令与整理归类文件"></p><hr><h2 id="五、对非编程人员推荐的基础用法"><a href="#五、对非编程人员推荐的基础用法" class="headerlink" title="五、对非编程人员推荐的基础用法"></a>五、对非编程人员推荐的基础用法</h2><p>很多人认为 Claude Code 只能写代码，这其实极大地低估了它的潜力。由于它具备 <strong>文件读写权限、终端执行能力以及多模态视觉</strong>，它本质上是一个<strong>接管了你操作系统的 AI Agent</strong>。</p><h3 id="查找和生成本地文档"><a href="#查找和生成本地文档" class="headerlink" title="查找和生成本地文档"></a>查找和生成本地文档</h3><p>首先是 Claude Code 本身支持搜索，你可以让他搜索指定内容给你写成 MarkDown 文档，也可以对你本身的 MarkDown 文档进行编辑。</p><p>注意因为我们用的是阿里的ClaudeCode套餐，无法调用Claude官方搜索工具，所以我们需要配置阿里的搜索MCP</p><p>根据<a href="https://help.aliyun.com/zh/model-studio/web-search-for-coding-plan" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>阿里云官方文档</a>的教程，我们需要进入阿里的<a href="https://bailian.console.aliyun.com/cn-beijing/?spm=a2c4g.11186623.0.0.35b1771960A1gf&amp;tab=app#/mcp-market" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>MCP广场</a>，找到联网搜索MCP服务并开通</p><p>我下面画框的这两个开通</p><blockquote><p>除开推荐的MCP服务外，也可以自行安装其他服务来尝试其他功能，例如接入支付MCP让AI在淘宝帮你下单，接入高德地图MCP让AI帮你规划行程</p></blockquote><p><img src="https://image.skyforever.top/blog/2026/02/61bcefd191c6317bddcde86d636220aa.webp" alt="阿里云MCP广场界面"></p><p>然后，此服务需要单独创建APIKEY<br>进入此网址：<a href="https://bailian.console.aliyun.com/cn-beijing/?spm=a2c4g.11186623.0.0.5de85ec6kTTcXJ&amp;tab=model#/api-key" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://bailian.console.aliyun.com/cn-beijing/?spm=a2c4g.11186623.0.0.5de85ec6kTTcXJ&amp;tab=model#/api-key</a></p><p>点击创建APIKEY</p><p><img src="https://image.skyforever.top/blog/2026/02/43912fe3102bf015983d73e0b914d8a3.webp" alt="创建MCP服务APIKEY界面"></p><p>创建成功后，将下列命令中的 YOUR_API_KEY 替换为开通联网搜索MCP时使用的阿里云百炼 API Key，并放在终端里执行：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">claude mcp add WebSearch https://dashscope.aliyuncs.com/api/v1/mcps/WebSearch/mcp -t http -H <span class="string">"Authorization: Bearer YOUR_API_KEY"</span></span><br></pre></td></tr></tbody></table></figure><p>终端返回 <code>Added HTTP MCP server xx</code> 即表示添加成功。</p><p>可以再添加下面这个MCP服务方便claudecode解析网页：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">claude mcp add WebParser https://dashscope.aliyuncs.com/api/v1/mcps/WebParser/sse -t sse -H <span class="string">"Authorization: Bearer YOUR_API_KEY"</span></span><br></pre></td></tr></tbody></table></figure><p>接着，执行以下命令进入 Claude Code。</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">claude</span><br></pre></td></tr></tbody></table></figure><p>在对话框执行 <code>/mcp</code>命令，确认 <code>websearch</code>的状态为 connected。首次添加可能需要等待状态从 connecting 变成 connected。</p><p><img src="https://image.skyforever.top/blog/2026/02/e81b44ddea1ce9c0acf3cefbe7e2591d.webp" alt="Claude Code MCP服务状态界面"></p><p>按 Esc 退出 MCP 列表后，发送提问 <code>用websearch MCP搜索鸿蒙最新的新闻</code>即可看到搜索结果。</p><blockquote><p>为了避免和其他工具混淆，建议提问时明确提及 websearch MCP。</p></blockquote><p><img src="https://image.skyforever.top/blog/2026/02/7b75f2f11d8766ca2b0800dd7839579a.webp" alt="使用websearch MCP搜索结果示例"></p><p>返回搜索结果即大功告成，接下来就可以让他搜索归藏的信息并且整理一个介绍文档。</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">请使用搜索功能，查找关于‘Openharmony <span class="number">3863</span>’的资料，阅读我本地 D:\OpenHarmony 目录下的相关文档，然后为我生成一份 Markdown 格式的综合报告，并存为 星闪概念介绍及<span class="number">3863</span>开发板星闪使用方法.md。</span><br></pre></td></tr></tbody></table></figure><p><img src="https://image.skyforever.top/blog/2026/02/eb8130f18c7a9ff23a0490e99e3f3492.webp" alt="Claude Code生成技术文档示例"></p><p>你也可以让他分析你保存在本地的文章之后进行改写，生成新的文章。</p><p>比如我这里就让他把 星闪 的软件相关 文章改写成适合发布的博客文章，同时生成对应的微信发布版本，也可以对于会议总结之类的文档进行分析和处理。</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">读取我刚才录音转写的会议纪要 meeting_notes.txt，总结出关键决策点，并识别出分配给我的所有待办事项，将它们以任务列表的形式添加到我的 todo.md 文件中。</span><br></pre></td></tr></tbody></table></figure><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">根据你刚刚生成的 hi3863芯片星闪使用方法，将其改写成一篇约 <span class="number">800</span>字的博客文章，风格要轻松有趣。然后，为这篇文章生成 <span class="number">3</span> 个适合在 小红书 上发布的内容版本，并附上 <span class="comment">#AI #Tech 标签</span></span><br></pre></td></tr></tbody></table></figure><h3 id="图片分析和处理"><a href="#图片分析和处理" class="headerlink" title="图片分析和处理"></a>图片分析和处理</h3><p>由于我们给 Claude Code 接入的是多模态的大模型，所以你的图片也可以让他帮忙处理。</p><p>比如我打开了一个全是图片的文件夹，里面的图片名字乱七八糟的，这时候就可以让他分析图片内容之后根据图片内容给图片重新命名。</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">分析我当前文件夹下的所有图片内容，基于图片内容批量对图片进行重新命名。</span><br></pre></td></tr></tbody></table></figure><p>这个东西的应用场景很多，例如财务人员可以用ClaudeCode整理发票</p><p><img src="https://image.skyforever.top/blog/2026/02/59ea2e02cd2d0a02b1fb53a5fd5532a1.webp" alt="Claude Code批量重命名图片功能演示"></p><h3 id="辅助做数据标注"><a href="#辅助做数据标注" class="headerlink" title="辅助做数据标注"></a>辅助做数据标注</h3><p>在重新命名之后我们也不能浪费他分析的图片内容。</p><p>我们都知道在训练图像模型或者 Lora 的时候需要对图像进行标注，大部分训练工具都是把标注放在一个跟图片命名一样的文本文件里，现在我们就可以让 Claude Code来做这件事了。</p><p>可以看到他执行的非常完美，以往这些你还得找对应的工具，而且不好自定义要求，现在直接提问就行。</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">分析图像内容，生成对图像的详细描述，除了内容还有风格，然后将这些描述放在跟图像名称一样的文本文件中。</span><br></pre></td></tr></tbody></table></figure><p>我们最近在做一些AI训练，可以用这个方法让ai做数据标注，方便我们训练一些针对性的小模型用于嵌入式设备</p><p><img src="https://image.skyforever.top/blog/2026/02/70608f52415cdc0d041dcdff5dbb6a6d.webp" alt="Claude Code图像内容分析和标注功能"></p><h3 id="修改系统设置"><a href="#修改系统设置" class="headerlink" title="修改系统设置"></a>修改系统设置</h3><p>Claude Code除了可以读取文件和修改文件外，也是可以控制系统设置的。</p><p>比如我们就可以写好自己日常对于软件和系统设置在不同工作时间的喜好，需要的时候一键完成所有操作的更改。</p><p>这里我就让他给我关掉浏览器，然后打开 VScode，开启 Windows 的专注助手（勿扰模式），直接进入工作模式。</p><p>更进一步让他把操作写成 PowerShell 脚本，之后你就可以直接右键运行脚本完成系统设置了。</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Claude，帮我创建一个名为 deep_work.ps1 的 PowerShell 脚本。这个脚本需要：</span><br><span class="line"><span class="number">1</span>. 启动 VScode。</span><br><span class="line"><span class="number">2</span>. 强制关闭 Edge/Chrome 浏览器和微信等通讯软件。</span><br><span class="line"><span class="number">3</span>. 开启 Windows 的‘专注助手（勿扰模式）’。</span><br><span class="line"><span class="number">4</span>. 播放我本地 D:\music\ 文件夹里的音乐。</span><br></pre></td></tr></tbody></table></figure><h2 id="Claude-Code-的高级使用方法"><a href="#Claude-Code-的高级使用方法" class="headerlink" title="Claude Code 的高级使用方法"></a>Claude Code 的高级使用方法</h2><p>上面都是些基本用法，你最近可能也看到了一些。</p><p>但是我发现结合一些本地软件，Claude Code能实现对各种文件更加高级的处理，比如视频转 gif、youtube 视频下载、加水印、文档格式转换等。</p><p>这些就非常牛皮了，而且我们日常内容创作大部分都非常需要。</p><h3 id="为本地文档生成PPT"><a href="#为本地文档生成PPT" class="headerlink" title="为本地文档生成PPT"></a>为本地文档生成PPT</h3><p>前面我们有了文档了，但是很多时候演示的时候总不能真给人看 Markdown 文档吧，能不能生成 PPT 呢？</p><p>可以的，朋友，必须可以，比如我这里就把前面我那个 MCP 索引文档的内容直接转换为 PPT 了。</p><p>这个依赖一个叫 Slidev 的项目，它可以用类似 Markdown 文档的格式将内容变成带有丰富样式的 PPT。</p><p>你不需要知道这个项目的细节，直接用我下面的提示词生成文件之后，复制文件到这个页面（<a href="https://stackblitz.com/github/slidevjs/new?file=slides.md%EF%BC%89%E9%A2%84%E8%A7%88%E5%B0%B1%E8%A1%8C%E3%80%82" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://stackblitz.com/github/slidevjs/new?file=slides.md）预览就行。</a></p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">帮我基于刚才总结的那个 hi3863芯片星闪使用方法 文章用 Slidev 这个专门用来用 Markdown 格式生成幻灯片的工具语法写一个对应的 PPT，用 Slidev 的语法美化一下</span><br></pre></td></tr></tbody></table></figure><p>上面的 Slidev 不需要本地安装直接预览就行，接下来我们介绍一些需要本地安装的项目。这些本地的软件非常强大，但是由于本身他们是没有界面的（纯命令行），阻碍了大量 Windows 用户使用。</p><p>但是有了 Claude Code 之后一切都解决了，提示词可以直接转换为驱动他们的命令行，也可以用提示词直接安装他们，你直接用就行。</p><p>生成效果还不错对吧，关键是这样生成支持二次编辑</p><p><img src="https://image.skyforever.top/blog/2026/03/b7ca6a926409929e6424ad79ae14338d.webp" alt="PPT生成效果"></p><h3 id="用-ffmpeg-帮助处理视频"><a href="#用-ffmpeg-帮助处理视频" class="headerlink" title="用 ffmpeg 帮助处理视频"></a>用 ffmpeg 帮助处理视频</h3><p>首先先介绍一下 ffmpeg 这个项目，基于它你可以实现非常强的视频编辑能力，理论上剪映之类的视频编辑软件底层都是基于类似技术完成的。</p><p>你可以对本地的视频进行拼接、剪辑、增加文字、转换格式、转换分辨率、增加音乐，基本上你能想到的视频编辑能力他都能做到。</p><p>首先我们需要打开你需要处理视频的的文件夹，然后启动 Claude Code。</p><p>我们直接让ClaudeCode来帮我们安装和配置软件</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">帮我在电脑上安装 ffmpeg，并确认已配置好环境变量</span><br></pre></td></tr></tbody></table></figure><p>看到没，跟其它教程里那些乱七八糟的下载和配置路径要求都没关系，你只需要说两句话，就全部安装了。</p><p>然后我们就可以爽用了，先给我们指定的视频加个水印试试。</p><p>可以看到新的视频右上角果然有了一个水印，这种言出法随的感觉谁不喜欢，你不需要了解原理，你就只需要知道所有的视频编辑他都能帮你搞定。</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">帮我将此目录下视频用 ffmpeg 打上一个 <span class="number">10</span>% 透明度的水印在右上角，水印内容为此目录下的png图片，然后存储为新视频。</span><br></pre></td></tr></tbody></table></figure><p><img src="https://image.skyforever.top/blog/2026/03/ea67f480b690625530b6be466f47b58a.png" alt="用ffmpeg添加视频水印效果"></p><p>然后我想要给视频配乐也可以，你只需要告诉他视频文件和音乐文件的名字就行，我甚至让他给音乐加上了淡入和淡出。</p><p>他先是获取了一下视频的时长，然后就开始操作了，然后搞定了，非常完美，严丝合缝，淡入淡出也加上了，可以看剪映界面预览的频谱。</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">帮我将 XXX 这个视频用 ffmpeg 将它和 XXX 音频合并为一个新的视频，音频的长度需要跟视频一样长并且加上淡入淡出。</span><br></pre></td></tr></tbody></table></figure><p>我们很多时候需要把视频转换为序列帧，然后拿其中一帧进行处理，或者处理所有的帧，以前你是不是还得到处找这种工具，而且转换效果不一定好。</p><p>Claude Code一句话就能搞定，处理的又快又好，而且节省了用网页工具上传下载的时间。</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">帮我将 XXXX 这个视频用 ffmpeg 转换为 png 序列帧放在一个新的文件夹里面。</span><br></pre></td></tr></tbody></table></figure><p><img src="https://image.skyforever.top/blog/2026/03/c5bdb490b1c56b11f2d0a678989e08a9.png" alt="用ffmpeg转换视频为序列帧"></p><p>另一个常见的任务就是视频转 gif，尤其公众号有视频大小限制，很多时候迫不得已得转成 gif 发布。</p><p>Claude Code 捕捉到了高品质这个关键词还制作了调色板保证颜色还原度，最后处理的非常完美。</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">帮我将当前文件夹中的第一个视频用 ffmpeg 转换为一个高品质 gif</span><br></pre></td></tr></tbody></table></figure><p><img src="https://image.skyforever.top/blog/2026/03/9a268f65af6dbd99ec51ab696e0b909d.png" alt="用ffmpeg转换视频为高品质GIF"></p><h3 id="利用-yt-dlp-下载视频"><a href="#利用-yt-dlp-下载视频" class="headerlink" title="利用 yt-dlp 下载视频"></a>利用 yt-dlp 下载视频</h3><p>像 ffmpeg 这种宝藏项目还有很多，比如 yt-dlp 这个项目跟 ffmpeg 配合几乎可以下载你能想到的所有视频平台的视频。</p><p>我们还是可以让 Claude Code帮我们安装 yt-dlp。</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">帮我在电脑上安装 yt<span class="literal">-dlp</span> 并配置环境变量</span><br></pre></td></tr></tbody></table></figure><p>然后直接提供视频链接他就会帮你下载，甚至可以批量下载多个视频或者一起连封面和视频一起下载，再也不需要忍受那些满是广告的下载工具了。</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">帮我用 yt<span class="literal">-dlp</span> 和 ffmpeg 下载这个平台的视频和它的封面：XXX 链接</span><br></pre></td></tr></tbody></table></figure><p><img src="https://image.skyforever.top/blog/2026/03/a559a1bb140e9976e5cf998c21c2b325.png" alt="用yt-dlp下载视频和封面"></p><h3 id="利用-ImageMagick-处理图片"><a href="#利用-ImageMagick-处理图片" class="headerlink" title="利用 ImageMagick 处理图片"></a>利用 ImageMagick 处理图片</h3><p>处理视频我们有 ffmpeg 这种项目，当然图片也有。</p><p>ImageMagick 是一个极其强大的工具集，你可以用它来转换格式、缩放、裁剪、旋转、添加滤镜、组合图片等等。</p><p>依然是老一套，先让 Claude Code 帮我们安装：</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">帮我在我电脑上安装 ImageMagick，并确保配置好环境变量，命令行可用</span><br></pre></td></tr></tbody></table></figure><p><img src="https://image.skyforever.top/blog/2026/02/3823c1e1c56c9633f2c72af6e6d52ef1.webp" alt="用winget安装ImageMagick"></p><p>先来一个常见任务，我们设计师做外包经常用，在没结款之前给甲方低分辨率和带水印的图片，现在就可以直接批量完成。</p><p>这里我让他把所有图片宽边调整为 800 PX，然后统一加上带“内部资料”文字的水印。</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">帮我用ImageMagick把文件夹下的所有图片的宽边尺寸统一调整为宽度 <span class="number">800</span> 像素，并给它们加上一个<span class="number">10</span>%透明度的灰色水印，水印文字是‘内部资料’，放在新的文件夹里面</span><br></pre></td></tr></tbody></table></figure><p>由于 Windows 字体编码原因，中文的水印有时会显示方块，可以让他改成英文（或者让 Claude 自己去调取系统里的中文字体如微软雅黑），而且出错之后他自己开始用多模态能力检查修改后的图像了，发现 10% 不透明度的文字不明显，又自己重新改了一下，太聪明了。</p><p><img src="https://image.skyforever.top/blog/2026/02/6e4c15dc95f6015724270abf67847b8b.webp" alt="用ImageMagick批量处理图片"></p><p>然后再来一个常见的图像拼接需求，这种在媒体上发消息的时候经常需要，尤其是发推文或者小红书。</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">将加过水印的图片用ImageMagick拼合成一张四宫格图片，中间有白色分隔</span><br></pre></td></tr></tbody></table></figure><p>搞得不错，这几张图比例不同，所以没有对齐，可以在命令上加上统一比例这种要求就行。</p><p><img src="https://image.skyforever.top/blog/2026/02/a95e0ea67d80cb9f4eed2000a36e0bb9.webp" alt="用ImageMagick拼接图片为四宫格"></p><h3 id="利用-Pandoc-进行文档转换"><a href="#利用-Pandoc-进行文档转换" class="headerlink" title="利用 Pandoc 进行文档转换"></a>利用 Pandoc 进行文档转换</h3><p>文档格式转换也是常见的需求，相当多的公司工作文档还是 Word (.docx)，很多时候我发过去 .md 文件那边都不知道怎么办。</p><p>首先还是让 Claude Code 帮我们在 Windows 上安装。</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">帮我在我电脑上安装 Pandoc</span><br></pre></td></tr></tbody></table></figure><p>这个时候我们就可以利用 Pandoc 这个项目进行各种文档格式之间的互相转换，当然批量转换也是可以的。</p><figure class="highlight powershell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">将 hi3863芯片星闪使用方法 这个 Markdown 文档用Pandoc转换为 word (.docx) 文档</span><br></pre></td></tr></tbody></table></figure><p>可以看到转的很好，Markdown 几乎所有格式也都迁移了，不管是加粗还是无序列表有序列表。</p><p><img src="https://image.skyforever.top/blog/2026/02/3f71e25b5177eec6f30ceb764c184000.webp" alt="用Pandoc转换文档格式"></p><hr><h2 id="六、我的日常开发方法论与-AI-避坑指南"><a href="#六、我的日常开发方法论与-AI-避坑指南" class="headerlink" title="六、我的日常开发方法论与 AI 避坑指南"></a>六、我的日常开发方法论与 AI 避坑指南</h2><p>我用过几款主流的 AI 编程工具（如 Cursor、Trae 等），但在日常的嵌入式和底层开发中，我主要使用的还是 Claude Code。整体感觉是：<strong>它现在已经是一个可以深度协作的工程助手。</strong></p><p>结合 Claude Code 的特性，我总结了一套自己的方法论与避坑原则：</p><h3 id="6-1-深度协作方法论（结合子代理）"><a href="#6-1-深度协作方法论（结合子代理）" class="headerlink" title="6.1 深度协作方法论（结合子代理）"></a>6.1 深度协作方法论（结合子代理）</h3><ol><li><strong>拒绝上来就写</strong>：接手复杂模块时，先用 <code>Explore</code> 探索代码库，生成核心架构文档；再用 <code>Plan</code> 制定实现流程。只有当你和ai理解一致后，产出才会高质量。</li><li><strong>控制上下文污染</strong>：每个独立的开发任务务必开启新对话（<code>/reset</code>），并提供清晰的需求背景和硬件约束。</li><li><strong>勤删废弃代码</strong>：旧代码和冗余注释会严重误导 AI，增加上下文噪音，长期不清理会直接影响协作效率。</li><li><strong>坚守人工底线</strong>：<ul><li>AI 生成的代码之后<strong>必须人工 Review</strong>。</li><li>关键的底层逻辑（如中断处理、时序控制）必要时自己重写。</li><li>核心路径必须做真机压测和边界测试。</li></ul></li></ol><h3 id="6-2-警惕过度依赖带来的三大风险"><a href="#6-2-警惕过度依赖带来的三大风险" class="headerlink" title="6.2 警惕过度依赖带来的三大风险"></a>6.2 警惕过度依赖带来的三大风险</h3><ol><li><strong>技术能力退化</strong>：习惯让 AI 看 Log，自身对硬件底层原理、指针异常的理解变浅，甚至失去对“优雅代码”的判断力。</li><li><strong>架构失控</strong>：AI 往往急于实现功能，容易导致硬件驱动与业务逻辑严重耦合，引入技术债务。</li><li><strong>一致性被破坏</strong>：不同对话生成的代码风格、命名规范可能完全割裂。</li></ol><h3 id="6-3-未来-3-年工程师的核心竞争力"><a href="#6-3-未来-3-年工程师的核心竞争力" class="headerlink" title="6.3 未来 3 年工程师的核心竞争力"></a>6.3 未来 3 年工程师的核心竞争力</h3><p>AI 时代，竞争的关键不再是“产出速度”。结合系统开发领域，我认为未来工程师的核心竞争力将转向以下维度：</p><ol><li><strong>系统架构与设计能力</strong>：单模块交给 AI，但系统级设计（HAL 与业务层解耦、RTOS 权衡、内存防碎片化）仍需人类主导。</li><li><strong>复杂业务与状态建模能力</strong>：将规则转化为可执行的设计。例如复杂的<a href="https://blog.skyforever.top/posts/63520/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>状态机设计</a>，以及软硬件交互边界划分。</li><li><strong>性能与稳定性治理能力</strong>：嵌入式设备资源极其受限，精细化内存管理、中断延迟优化、Watchdog 策略，必须通过真机抓包、示波器验证，AI 暂时还没有具生智能的能力，无法替代工程师。</li><li><strong>驾驭 AI 的协作能力</strong>：精通 Prompt 工程，懂得拆解问题，敏锐判断 AI 产出代码的潜在漏洞。</li></ol><h2 id="七、实战演练：让-Claude-Code-融入工程化"><a href="#七、实战演练：让-Claude-Code-融入工程化" class="headerlink" title="七、实战演练：让 Claude Code 融入工程化"></a>七、实战演练：让 Claude Code 融入工程化</h2><p>理论与方法论讲完了，接下来我们进入真刀真枪的代码实战阶段。</p><h3 id="1-对鸿蒙北向开发赋能"><a href="#1-对鸿蒙北向开发赋能" class="headerlink" title="1.对鸿蒙北向开发赋能"></a>1.对鸿蒙北向开发赋能</h3><p>对于前后端项目（北向项目）开发，我建议可以开两到三个ClaudeCode窗口，一个开发前端，一个开发后端，让后让后端输出api文档给前端，让前端做api适配。具体的前后端AI使用教程可以查看 <a href="https://ai.codefather.cn/library/1936010874183520257" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>鱼皮的AI知识库</a>，他的VibeCoding教程相对来说比较完整，且文档在Github上开源（<a href="https://github.com/liyupi/ai-guide" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>开源地址</a>）。</p><h3 id="2-对鸿蒙南向开发赋能"><a href="#2-对鸿蒙南向开发赋能" class="headerlink" title="2.对鸿蒙南向开发赋能"></a>2.对鸿蒙南向开发赋能</h3><p>很多开发者觉得 AI 写前端还行，遇到嵌入式（C/C++、硬件时序、RTOS）就歇菜了。核心原因在于：<strong>嵌入式开发需要极强的架构思维，并且硬件环境 AI 是“看”不到的。</strong></p><p>在我的日常开发中，面对复杂的嵌入式需求，我总结了一套**“Ask 摸底 -&gt; Plan 架构 -&gt; 软硬分离执行”**的闭环开发范式。</p><p>我们以一个典型且前沿的实战需求为例：<strong>为 Hi3863 平台（LiteOS 环境）编写 W25Q128FV 外部 Flash 驱动</strong>。看看顶级开发者是如何驱使 Claude Code 把复杂的芯片底层变得井井有条的。</p><h4 id="阶段一：用-Ask-模式“摸清底细”（Explore）"><a href="#阶段一：用-Ask-模式“摸清底细”（Explore）" class="headerlink" title="阶段一：用 Ask 模式“摸清底细”（Explore）"></a>阶段一：用 Ask 模式“摸清底细”（Explore）</h4><p>在引入新驱动前，面对 Hi3863 庞大的 SDK 目录，我绝不会直接让 AI 写代码，而是先派 <code>Explore</code> 子代理去摸清当前工程的底牌。</p><p>在终端中启动 Claude Code，明确要求它只探索，不修改：</p><blockquote><p><strong>提示词</strong>：<code>进入探索模式（Ask）。请帮我阅读当前项目下 Hi3863 的工程目录，重点分析现有的 SPI/QSPI 外设底层的 HAL 层接口是如何封装的，以及当前 LiteOS 的临界区保护、互斥锁和中断管理的接口规范是什么，看完后给我一个简单的总结。</code></p></blockquote><p>这一步是为了让 AI 建立起<strong>本地工程上下文</strong>，确保它后面生成的代码风格能完美融入 Hi3863 的原生框架，而不是瞎编一套不通用的底层 API。</p><h4 id="阶段二：用-Plan-模式“运筹帷幄”（架构设计）"><a href="#阶段二：用-Plan-模式“运筹帷幄”（架构设计）" class="headerlink" title="阶段二：用 Plan 模式“运筹帷幄”（架构设计）"></a>阶段二：用 Plan 模式“运筹帷幄”（架构设计）</h4><p>探索完毕后，进入最核心的规划环节。<strong>在这个环节，我们要把 AI 当作资深架构师，和它反复磨合，直到 <code>Plan</code> 子代理输出的设计文档与你的构想完全一致。</strong></p><p>我会下达一段非常详细的架构设计需求。你可以参考我日常使用的这段<strong>高阶 Prompt</strong>：</p><figure class="highlight text"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">进入规划模式（Plan）。我想为 Hi3863 平台编写一个 W25Q128FV 的驱动程序。请帮我输出一份详细的架构设计和分步实施计划，不要直接写代码。</span><br><span class="line"></span><br><span class="line">【架构设计要点】：</span><br><span class="line">1. 抽象分层：需要设计一个 Flash 抽象层，在 Per 接口层对接 W25Q128 的驱动。</span><br><span class="line">2. 多设备管理：考虑到系统未来可能挂载多个外部 Flash 芯片，需要使用 Builder（生成器）模式实现多个设备的统一管理，通过 Handler 层进行统一调度。</span><br><span class="line">3. 接口适配（配置模式）：不同 Flash 芯片可能使用不同通信接口（SPI/QSPI），采用配置模式对不同接口进行选配，实现灵活性。</span><br><span class="line">4. 依赖注入与可移植：驱动需具备良好的跨芯片移植能力（哪怕以后换成其他星闪芯片）。必须通过依赖注入方式，注入 Handler 所需的依赖（如 Hi3863 的 SPI 通信接口函数指针、中断处理、OS 临界区保护等）。</span><br><span class="line">5. 工厂模式封装：为了简化应用层的调用，采用工厂模式实现 Flash 对象的自动构建，向用户屏蔽 W25Q 系列的详细构建过程。</span><br><span class="line">6. 存储管理切换（策略模式）：Flash 管理策略未来会变化（如接入 LittleFS 文件系统或特定 Flash 均衡算法），采用策略模式设计内存管理层的动态切换机制。</span><br><span class="line">7. 测试闭环：需要在 Hi3863 平台上设计单元测试和电仿真测试用例，确保 Driver、Handler、依赖注入等模块对上提供的 API 能够快速验证。</span><br><span class="line"></span><br><span class="line">请根据以上要求，给我一份模块划分图（用文本表示）和 TODO 列表。</span><br></pre></td></tr></tbody></table></figure><blockquote><p>注意！</p><p>AI 给出的第一版 Plan 可能在某些细节（比如依赖注入的函数指针定义方式）上不符合你的要求。<strong>不要将就！</strong> 继续在 Plan 模式下指出它的问题（例如：<em>“工厂模式那一块的设计太重了，在 IoT 芯片上浪费内存，改成轻量级的静态预分配”</em>），直到它的 TODO List 完美契合你的心意。</p></blockquote><h4 id="阶段三：步步为营，软硬分离（Edit-执行）"><a href="#阶段三：步步为营，软硬分离（Edit-执行）" class="headerlink" title="阶段三：步步为营，软硬分离（Edit 执行）"></a>阶段三：步步为营，软硬分离（Edit 执行）</h4><p>Plan 敲定后，终于到了让 <code>Edit</code> 子代理（通用模型）写代码的阶段。</p><p>在嵌入式开发中，我坚守一个原则：<strong>先写硬件逻辑，再写软件逻辑；软件逻辑分控制线和存储线。</strong> 千万不要让 AI 一次性把从底层 SPI 到上层文件系统全写完，那样一旦出错，在 Hi3863 这种高频复杂芯片上连去哪抓 Bug 都不知道。</p><p>按照之前定好的 TODO 列表，我们一步步下达指令：</p><ol><li><p><strong>先调通硬件层（Driver）</strong>：</p><blockquote><p>“现在开始执行计划的第一步，只写最底层的 SPI 读写和时序依赖注入部分。写完后生成一个基础的寄存器读取测试函数（用来读取 W25Q128 的 Device ID）。”<br><em>（人工介入：把代码编译烧入 Hi3863 开发板，接上逻辑分析仪或看串口打印，确保读到了正确的 ID <code>0xEF4018</code>。硬件调通，心里才有底。）</em></p></blockquote></li><li><p><strong>再写核心逻辑（Handler &amp; 控制线）</strong>：</p><blockquote><p>“硬件层 ID 验证通过。现在执行第二步，利用工厂模式实现 Flash Handler 的对象构建，把前面的底层接口注入进去，实现基本的擦除、页写、连读功能。”</p></blockquote></li><li><p><strong>最后写策略层（存储线）</strong>：</p><blockquote><p>“执行第三步，利用策略模式接入之前说的 LittleFS 接口适配，向 OpenHarmony 框架侧提供标准的 VFS 挂载点。保持高内聚低耦合。”</p></blockquote></li></ol><h4 id="阶段四：测试用例覆盖（闭环验证）"><a href="#阶段四：测试用例覆盖（闭环验证）" class="headerlink" title="阶段四：测试用例覆盖（闭环验证）"></a>阶段四：测试用例覆盖（闭环验证）</h4><p>最后，别忘了利用 Claude Code 的代码生成能力，为你构建坚固的测试护城河。</p><blockquote><p>“基于我们刚刚完成的驱动，在 <code>test</code> 目录下生成对应的单元测试。通过 Mock 调用 Hi3863 的底层 SPI 接口，在纯软环境下验证工厂模式构建的对象是否正确，以及多设备管理 Handler 在越界读写时的保护逻辑。”</p></blockquote><p>你看，通过上面这四个阶段，我们并没有亲手敲击几行 C 代码，但整个工程的**灵魂（架构模式、软硬分离、依赖注入）**依然是我们赋予的。</p><p>Claude Code 充当了不知疲倦的高级打字员、UML 转换器和测试工程师。<strong>我们把主要精力从“查阅 W25Q128 手册的指令集对应关系”转移到了“把控系统复杂度与接口设计”上。</strong></p><p>在这个时代，AI 写出的代码或许能跑，但只有融合了人类工程思维、设计模式和物理世界硬件认知的系统，才是真正健壮的工业级产品。而 Claude Code，正是连接这两种力量的最强桥梁。</p><h2 id="八、从哪里获取最新的AI信息"><a href="#八、从哪里获取最新的AI信息" class="headerlink" title="八、从哪里获取最新的AI信息"></a>八、从哪里获取最新的AI信息</h2><p>正在爆肝编写中</p><h2 id="九、总结"><a href="#九、总结" class="headerlink" title="九、总结"></a>九、总结</h2><p>好了 教程到这里就结束了。</p><p>你可以用 Claude Code控制这些已经非常成熟的命令行项目，基本上你所有的需求都能找到对应的项目。</p><p>不是只有 MCP 才能做 Agent，这些传统工具在有了 LLM 加持之后会更加强大。</p><p>看到这里，你可能会突然意识到：原来那些让我们望而却步的专业工具，其实一直都在那里等着我们。</p><p>史蒂夫·乔布斯说过的一句话：”技术应该是隐形的。” 今天的 Claude Code，正是让那些强大的命令行工具变得”隐形”——你不需要理解它们在 Windows 下复杂的配置原理，不需要去配环境变量，只需要说出你的需求。</p><p>更重要的是，这种改变不仅仅是效率的提升，而是创作门槛的彻底消失。</p><p>所以，如果你还在犹豫要不要试试 Claude Code，我想说：别让”我不会编程”成为你探索新世界的借口。 因为在这个新世界里，你需要的不是编程能力，而是想象力。</p><p>那些曾经高高在上的专业工具，现在都在静静等待着你的一句话。而你要做的，就是勇敢地说出你的需求。</p><p>因为最好的工具，是让你忘记它是工具的工具。</p>]]>
    </content>
    <id>https://blog.skyforever.top/posts/52013</id>
    <link href="https://blog.skyforever.top/posts/52013"/>
    <published>2026-02-27T04:00:00.000Z</published>
    <summary>详细介绍如何在国内使用 Claude Code 这一顶级AI编程工具。涵盖API平台选择、cc-switch一键配置、子代理机制详解， 以及基于子代理的高效开发方法论与避坑指南。</summary>
    <title>Claude Code 使用指南</title>
    <updated>2026-02-27T04:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="极客DIY" scheme="https://blog.skyforever.top/categories/%E6%9E%81%E5%AE%A2DIY/"/>
    <category term="硬件评测" scheme="https://blog.skyforever.top/categories/%E6%9E%81%E5%AE%A2DIY/%E7%A1%AC%E4%BB%B6%E8%AF%84%E6%B5%8B/"/>
    <category term="教程" scheme="https://blog.skyforever.top/tags/%E6%95%99%E7%A8%8B/"/>
    <category term="3D打印" scheme="https://blog.skyforever.top/tags/3D%E6%89%93%E5%8D%B0/"/>
    <category term="FDM" scheme="https://blog.skyforever.top/tags/FDM/"/>
    <category term="拓竹" scheme="https://blog.skyforever.top/tags/%E6%8B%93%E7%AB%B9/"/>
    <category term="创想三维" scheme="https://blog.skyforever.top/tags/%E5%88%9B%E6%83%B3%E4%B8%89%E7%BB%B4/"/>
    <category term="建模" scheme="https://blog.skyforever.top/tags/%E5%BB%BA%E6%A8%A1/"/>
    <category term="切片软件" scheme="https://blog.skyforever.top/tags/%E5%88%87%E7%89%87%E8%BD%AF%E4%BB%B6/"/>
    <content>
      <![CDATA[<p>这两三年，3D打印技术真正从“极客玩具”走进了大众生活。从孩子的益智玩具、教学用具，到家里的定制收纳盒、花瓶，甚至修复家电的缺损零件，它都能搞定。在定制化需求日益增长的今天，拥有一台3D打印机就像拥有了一座微型工厂。</p><p>很多朋友可能还在犹豫：<strong>由于预算、占地面积、建模门槛、空气污染</strong>等问题不敢下手。别急，这篇保姆级指南将为你从头梳理，带你避开新手村的每一个坑。</p><hr><h3 id="一、起步：打印机类型的选择"><a href="#一、起步：打印机类型的选择" class="headerlink" title="一、起步：打印机类型的选择"></a><strong>一、起步：打印机类型的选择</strong></h3><p>市面上核心的3D打印机分为两大阵营，新手选购前必须明确自己的需求：</p><h4 id="1-FDM（熔融沉积成型）——-新手首选"><a href="#1-FDM（熔融沉积成型）——-新手首选" class="headerlink" title="1. FDM（熔融沉积成型）——  新手首选"></a><strong>1. FDM（熔融沉积成型）——  新手首选</strong></h4><ul><li><strong>原理</strong>：类似热熔胶枪，将塑料丝加热融化后，一层层挤出堆叠成型。</li><li><strong>优势</strong>：<ul><li>机器耐造，维护成本低。</li><li>生态圈极其成熟，耗材便宜且选择多。</li><li><strong>多色打印</strong>技术已非常成熟（如拓竹AMS）。</li><li>使用PLA耗材时基本无毒，适合家庭环境。</li></ul></li><li><strong>注意</strong>：虽然PLA污染轻，但打印ABS/ASA等工程塑料时仍有气味，建议配合空气净化器，或置于通风处（尽量不放在卧室）。</li></ul><h4 id="2-光固化（SLA-DLP-LCD）——-新手慎入"><a href="#2-光固化（SLA-DLP-LCD）——-新手慎入" class="headerlink" title="2. 光固化（SLA/DLP/LCD）—— 新手慎入"></a><strong>2. 光固化（SLA/DLP/LCD）—— 新手慎入</strong></h4><ul><li><strong>原理</strong>：利用紫外线照射液态光敏树脂，使其逐层固化。</li><li><strong>劝退点</strong>：<ul><li><strong>后处理极繁琐</strong>：打印完需要用酒精清洗、二次固化。</li><li><strong>环境要求高</strong>：树脂有化学毒性和强烈刺激性气味。</li><li><strong>操作风险</strong>：液态树脂难清理，容易弄脏皮肤和家具。</li></ul></li><li><strong>适用人群</strong>：<strong>非重度手办玩家或涂装大神，不建议作为第一台机器。</strong></li></ul><p><img src="https://image.skyforever.top/blog/2026/02/1bfd3f3a7b89da32ed586d128286bb95.webp" alt="FDM与光固化对比图"></p><hr><h3 id="二、硬件推荐：新手该买哪一款？"><a href="#二、硬件推荐：新手该买哪一款？" class="headerlink" title="二、硬件推荐：新手该买哪一款？"></a><strong>二、硬件推荐：新手该买哪一款？</strong></h3><p>针对目前主流市场，我们总结了以下几款适合不同需求新手的FDM机型：</p><h4 id="1-闭眼入系列：拓竹-A1-Combo-带AMS多色系统"><a href="#1-闭眼入系列：拓竹-A1-Combo-带AMS多色系统" class="headerlink" title="1. 闭眼入系列：拓竹 A1 Combo (带AMS多色系统)"></a><strong>1. 闭眼入系列：拓竹 A1 Combo (带AMS多色系统)</strong></h4><ul><li><strong>参考价格</strong>：约 2300元 (参考国补价)</li><li><strong>特点</strong>：打印质量极稳，运行噪音小，256×256mm 尺寸满足90%日常需求。</li><li><strong>必选理由</strong>：<strong>AMS lite（多色系统）</strong>。它不仅是为了打彩色模型，更重要的是<strong>自动进退料</strong>。相信我，一旦体验过自动换料的便捷，你绝对不想再手动捅耗材了。</li></ul><h4 id="2-高性价比平替：拓竹-A1-Mini"><a href="#2-高性价比平替：拓竹-A1-Mini" class="headerlink" title="2. 高性价比平替：拓竹 A1 Mini"></a><strong>2. 高性价比平替：拓竹 A1 Mini</strong></h4><ul><li><strong>特点</strong>：180×180mm 尺寸，除了小一点，核心功能与A1一致。不占桌面，极具性价比，适合作为入门体验机或第二台补充机。</li></ul><h4 id="3-进阶-工程系列：拓竹-P1系列"><a href="#3-进阶-工程系列：拓竹-P1系列" class="headerlink" title="3. 进阶/工程系列：拓竹 P1系列"></a><strong>3. 进阶/工程系列：拓竹 P1系列</strong></h4><ul><li><strong>适合人群</strong>：进阶玩家、需要打印ABS/ASA等高温材料的用户（P2S带封闭箱体）。</li><li><strong>选购建议</strong>：如果有预算，<strong>一定要上AMS</strong>。</li></ul><blockquote><p><strong>主流机型参数对比表</strong></p><div class="md-table-scroll"><table><thead><tr><th align="left">项目</th><th align="left">拓竹 A1 mini Combo</th><th align="left">拓竹 A1 Combo</th><th align="left">拓竹 P2S Combo</th><th align="left">创想 K1C/K2C</th><th align="left">起迪 Q1 Pro</th><th align="left">纵维立方 S1 Combo</th></tr></thead><tbody><tr><td align="left"><strong>图片</strong></td><td align="left"><img src="https://image.skyforever.top/blog/2026/02/5083f823b72ca8f4c619d384a3483f60.webp" alt="微信图片_2026-02-06_201635_415"></td><td align="left"><img src="https://image.skyforever.top/blog/2026/02/f576e82bcad0dd443b40f72c9bc12ed8.webp" alt="Snipaste_2026-02-06_20-19-29"></td><td align="left"><img src="https://image.skyforever.top/blog/2026/02/8549cf32bc120e6e1ad9a74c2b1cc47d.webp" alt="Snipaste_2026-02-06_20-20-07"></td><td align="left"><img src="https://image.skyforever.top/blog/2026/02/4652e5ab837bf40e24cc5f9bcd5af3c9.webp" alt="Snipaste_2026-02-06_20-21-35"></td><td align="left"><img src="https://image.skyforever.top/blog/2026/02/dbb25e4f64ad332df2b9b6548179a1be.webp" alt="Snipaste_2026-02-06_20-22-21"></td><td align="left"><img src="https://image.skyforever.top/blog/2026/02/e18d0968d5ad1d80c2e715a051542997.webp" alt="Snipaste_2026-02-06_20-22-44"></td></tr><tr><td align="left"><strong>参考价</strong></td><td align="left">¥1650+</td><td align="left">¥1880+</td><td align="left">¥3770+</td><td align="left">¥2360+</td><td align="left">¥2290+</td><td align="left">¥2090+</td></tr><tr><td align="left"><strong>尺寸</strong></td><td align="left">180³ mm</td><td align="left">256³ mm</td><td align="left">256³ mm</td><td align="left">260³ mm</td><td align="left"><strong>270×270×256</strong></td><td align="left">250³ mm</td></tr><tr><td align="left"><strong>最高温</strong></td><td align="left">300°C</td><td align="left">300°C</td><td align="left">300°C</td><td align="left">300°C</td><td align="left"><strong>370°C</strong></td><td align="left">320°C</td></tr><tr><td align="left"><strong>热床</strong></td><td align="left">80°C</td><td align="left">100°C</td><td align="left">110°C</td><td align="left">120°C</td><td align="left">120°C</td><td align="left">120°C</td></tr><tr><td align="left"><strong>亮点</strong></td><td align="left">小巧、静音、性价比</td><td align="left">流量补偿、多色、静音</td><td align="left">封闭箱体、高速、稳定</td><td align="left">全金属框架、AI摄像</td><td align="left">主动腔温加热(工程料神器)</td><td align="left">支持边烘干边打印</td></tr><tr><td align="left"><strong>建议</strong></td><td align="left"><strong>入门首选</strong>适合儿童/纯新手</td><td align="left"><strong>家用主力</strong>平台大、体验好</td><td align="left"><strong>进阶全能</strong>适合打ABS等</td><td align="left"><strong>性价比</strong>适合改机党</td><td align="left"><strong>工程专业</strong>适合高温材料</td><td align="left"><strong>功能整合</strong>适合需烘干环境</td></tr></tbody></table></div><p><em><strong>备注</strong>：价格参考自2025年10月22日京东商城，88vip叠加国补优惠后价格；售价可能随营销策略、电商促销和市场变化调整。</em></p></blockquote><hr><h3 id="三、耗材避坑：材料选得好，打印没烦恼"><a href="#三、耗材避坑：材料选得好，打印没烦恼" class="headerlink" title="三、耗材避坑：材料选得好，打印没烦恼"></a><strong>三、耗材避坑：材料选得好，打印没烦恼</strong></h3><p>3D打印的成败一半取决于机器，另一半就在耗材。对于新手来说，<strong>选对材料就是成功的一半</strong>。</p><h4 id="1-新手天花板：PLA系列"><a href="#1-新手天花板：PLA系列" class="headerlink" title="1. 新手天花板：PLA系列"></a><strong>1. 新手天花板：PLA系列</strong></h4><p>PLA（聚乳酸）是目前最环保、最容易打印的材料，<strong>强烈建议新手在前3个月只用PLA</strong>。</p><ul><li><strong>PLA (标准版)</strong>：首选。好打、收缩率极低、不翘边，刚性和细节表现均衡。</li><li><strong>PLA+ / PLA Tough</strong>：配方改良版，比普通PLA更抗摔，韧性更好，适合打有卡扣结构的件。</li><li><strong>PLA-CF / Matte</strong>：添加碳纤维或哑光处理。<strong>质感极佳</strong>，能完美隐藏层纹，打印件看起来像注塑成品，高级感拉满。</li><li><strong>Silk PLA (丝绸)</strong>：自带金属光泽，反光强烈，适合打印花瓶、摆件等观赏品。</li><li><strong>PLA Marble/Wood</strong>：仿大理石或木质纹理，质感特殊。</li></ul><h4 id="2-进阶材料（新手慎入）"><a href="#2-进阶材料（新手慎入）" class="headerlink" title="2. 进阶材料（新手慎入）"></a><strong>2. 进阶材料（新手慎入）</strong></h4><ul><li><strong>PETG</strong>：虽然韧性好、耐温稍高，但<strong>非常容易拉丝</strong>，且容易把PEI打印板粘坏（粘接力过强）。</li><li><strong>ABS / ASA</strong>：耐高温、强度高，但<strong>打印时有毒气味</strong>，且<strong>极易翘边</strong>。没有封闭箱体的机器（如A1 mini）千万别轻易尝试。</li></ul><h4 id="3-核心避坑-TIPS"><a href="#3-核心避坑-TIPS" class="headerlink" title="3. 核心避坑 TIPS"></a><strong>3. 核心避坑 TIPS</strong></h4><ul><li><strong>品牌推荐</strong>：Polymaker、三绿 (Sunlu)、K+、eSUN (易生)、兰博等主流品牌均可。无需迷信原厂高溢价耗材，第三方往往更具性价比。</li><li><strong>操作禁忌</strong>：<strong>千万不要在有料盘时剪断新耗材的固定扎带！</strong> 耗材线像弹簧一样蓄着力，一旦松开会瞬间“炸”成一团乱麻，你将不得不花费数小时重新绕线。</li><li><strong>硬件损耗</strong>：打印含纤维材料（带 <strong>CF</strong> 或 <strong>GF</strong> 后缀）时，<strong>必须更换硬化钢喷嘴和挤出机齿轮</strong>！普通的黄铜喷嘴打不到半卷就会被磨秃。</li></ul><h4 id="4-全耗材特性详细对比表"><a href="#4-全耗材特性详细对比表" class="headerlink" title="4. 全耗材特性详细对比表"></a><strong>4. 全耗材特性详细对比表</strong></h4><div class="md-table-scroll"><table><thead><tr><th align="left">材料名</th><th align="left">材料特性</th><th align="left">打印和使用须知</th></tr></thead><tbody><tr><td align="left"><strong>PLA</strong></td><td align="left">基础耗材</td><td align="left">不太耐摔，韧性较差</td></tr><tr><td align="left"><strong>PLA+</strong></td><td align="left">增韧耗材</td><td align="left">韧性有所提升，日常用材料</td></tr><tr><td align="left"><strong>PLA哑光</strong></td><td align="left">拥有哑光质感</td><td align="left">层粘较差，不建议Z向受大负载</td></tr><tr><td align="left"><strong>PLA丝绸</strong></td><td align="left">拥有丝绸反光质感</td><td align="left">打印速度越慢反光越好，层粘较差；不建议作为受力件使用</td></tr><tr><td align="left"><strong>PLA木质</strong></td><td align="left">添加木粉，木香、木质感</td><td align="left">吸水强，注意干燥，强度较低</td></tr><tr><td align="left"><strong>ABS</strong></td><td align="left">抗冲击性强，耐温较高</td><td align="left">封箱+喷胶防止翘边；打印挥发有毒气体，注意通风和人员避让</td></tr><tr><td align="left"><strong>PETG</strong></td><td align="left">透明度好，韧性好</td><td align="left">充分干燥，容易拉丝，适度加回抽</td></tr><tr><td align="left"><strong>PC</strong></td><td align="left">透明度好，综合性能强，耐高温</td><td align="left">充分干燥，关闭冷却风扇防止影响层粘；综合性能较强</td></tr><tr><td align="left"><strong>ASA</strong></td><td align="left">抗冲击性强，耐紫外线</td><td align="left">封箱+喷胶防止翘边；适合打印户外要承受紫外线的用品</td></tr><tr><td align="left"><strong>TPU</strong></td><td align="left">常见的弹性体材料</td><td align="left">充分干燥，慢速打印，微调流量比</td></tr><tr><td align="left"><strong>PEBA</strong></td><td align="left">高回弹性柔性材料</td><td align="left">充分干燥，慢速打印，微调流量比</td></tr><tr><td align="left"><strong>PLA夜光</strong></td><td align="left">夜光特性</td><td align="left">层粘较差，只建议做摆件</td></tr><tr><td align="left"><strong>PLA大理石</strong></td><td align="left">添加石粉，大理石纹理</td><td align="left">喷嘴不宜过小，防止堵头</td></tr><tr><td align="left"><strong>PLA Lite</strong></td><td align="left">廉价耗材</td><td align="left">添加廉价材料，性能差，不建议</td></tr><tr><td align="left"><strong>PLA-CF</strong></td><td align="left">添加短切碳纤维，磨砂表面，XY方向性能更强</td><td align="left">层粘弱于不加碳纤维的材料；喷嘴不宜过小，防止堵头</td></tr><tr><td align="left"><strong>PA</strong></td><td align="left">韧性好，耐高温，强度高</td><td align="left">充分干燥，封箱+喷胶防止翘边；尽量避免打印大面积平面物体</td></tr><tr><td align="left"><strong>PA6-CF/GF</strong></td><td align="left">刚性和强度均很高</td><td align="left">充分干燥，纤维含量较高建议适当给XY加负补偿，防止配合出现问题；建议打印完后打磨去毛刺</td></tr><tr><td align="left"><strong>PA12-CF</strong></td><td align="left">刚性和强度均很高，密度较低，适合无人机机架等</td><td align="left">同上（注：原文“适合打印无人机机架等”）</td></tr><tr><td align="left"><strong>PET-CF/GF</strong></td><td align="left">耐高温，抗蠕变，较光滑</td><td align="left">充分干燥，封箱+喷胶防止翘边</td></tr><tr><td align="left"><strong>PETG-CF/GF</strong></td><td align="left">成本低，韧性好，磨砂质感，Z强度高于PLA-CF</td><td align="left">充分干燥</td></tr><tr><td align="left"><strong>ABS-GF/CF</strong></td><td align="left">抗冲击性强，强度较高</td><td align="left">同ABS，但没那么容易翘边</td></tr></tbody></table></div><hr><h3 id="四、必备配件与工具"><a href="#四、必备配件与工具" class="headerlink" title="四、必备配件与工具"></a><strong>四、必备配件与工具</strong></h3><p>除了机器，这三样小东西能极大提升幸福感：</p><ol><li><strong>优质水口钳</strong>：用于剪断耗材、拆除模型支撑（推荐田宫金牌剪的平替款）。</li><li><strong>胶水喷雾 / PVP胶棒</strong>：涂在打印板上，防止模型翘边，同时在冷却后更容易取下模型。（<em>注意：取出打印板再喷，勿喷到机器丝杆导轨上</em>）。</li><li><strong>专用冷打板 (Cool Plate)</strong>：对PLA粘性极佳，可降低热床温度（省电），极大减少翘边概率。</li></ol><hr><h3 id="五、软件与流程：从模型到实物"><a href="#五、软件与流程：从模型到实物" class="headerlink" title="五、软件与流程：从模型到实物"></a><strong>五、软件与流程：从模型到实物</strong></h3><p>打印流程很简单：<strong>找模型/建模型 → 切片 → 传输 → 打印</strong>。</p><h4 id="1-第一阶段：模型去哪找？"><a href="#1-第一阶段：模型去哪找？" class="headerlink" title="1. 第一阶段：模型去哪找？"></a><strong>1. 第一阶段：模型去哪找？</strong></h4><p>新手不必急着学建模，先下载现成模型练手，熟悉机器脾气：</p><ul><li><strong>拓竹 MakerWorld</strong>：<a href="https://makerworld.com.cn/zh" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>国内站</a> | <a href="https://makerworld.com/zh" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>国际站</a> （生态体验最好，支持一键打印）</li><li><strong>创想云</strong>：<a href="https://www.crealitycloud.com/zh" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://www.crealitycloud.com/zh</a></li><li><strong>Printables</strong>：<a href="https://www.printables.com/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://www.printables.com/</a> (全球高质量社区)</li><li><strong>Thingiverse</strong>：<a href="https://www.thingiverse.com/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://www.thingiverse.com/</a> (老牌模型库)</li></ul><h4 id="2-第二阶段：为什么要自己建模？"><a href="#2-第二阶段：为什么要自己建模？" class="headerlink" title="2. 第二阶段：为什么要自己建模？"></a><strong>2. 第二阶段：为什么要自己建模？</strong></h4><p>买来打印机，大部分人做的第一件事是下载别人的模型。但**“玩转”3D打印的核心，在于将你脑海中的想法变成实物**。<br>试想一下，亲手设计一个严丝合缝的抽屉隔板、修复家里断裂的卡扣，或者复刻动漫里的道具。这种从0到1的创造力，才是3D打印的灵魂。</p><ul><li><strong>参数化生成器</strong>：MakerWorld等平台自带“参数化模型”，只需输入长宽高等数值，就能生成定制的收纳盒、名牌，<strong>无需建模基础</strong>。</li><li><strong>建模流派选择</strong>：<ul><li><strong>“搭积木”派 (推荐)</strong>：通过长方体、圆柱体组合。适合尺寸精准的零件。代表软件：Fusion 360, <strong>SketchUp</strong>。</li><li><strong>“捏橡皮泥”派</strong>：随意拉扯变形，适合做手办、生物。代表软件：Blender, ZBrush。</li></ul></li></ul><p><img src="https://image.skyforever.top/blog/2026/02/dcca06c15c87e3a9c248e1fb499b96e3.webp" alt="多款建模软件的对比"></p><hr><h3 id="六、建模实战：5分钟上手-SketchUp-草图大师"><a href="#六、建模实战：5分钟上手-SketchUp-草图大师" class="headerlink" title="六、建模实战：5分钟上手 SketchUp (草图大师)"></a><strong>六、建模实战：5分钟上手 SketchUp (草图大师)</strong></h3><p>对于DIY玩家，我强烈推荐 <strong>SketchUp</strong>。它直觉极强，不像工业软件那样需要定义复杂的约束。画个框，一拉就是柱子，非常适合做机箱、支架等结构件。</p><p>资源地址：<a href="https://www.ghxi.com/sketchup2022.html" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>SketchUp草图大师 2022 v22.0.354 绿色修改版 - 果核剥壳</a></p><h4 id="1-软件初始化设置"><a href="#1-软件初始化设置" class="headerlink" title="1. 软件初始化设置"></a><strong>1. 软件初始化设置</strong></h4><ul><li><p><strong>版本</strong>：建议安装2018-2022版本。</p></li><li><p><strong>模板</strong>：首次打开选择“建筑-毫米”。</p><p><img src="https://image.skyforever.top/blog/2026/02/c42e2822a786741f2ba3a3581a05c555.webp" alt="SketchUp 首次启动选择建筑毫米模板"></p></li><li><p><strong>工具栏</strong>：顶部空白处右键 -&gt; 勾选“大工具集”、“视图”、“样式”。</p><p><img src="https://image.skyforever.top/blog/2026/02/c4cfb5f9d00f006c4d35a1fa564a9071.webp" alt="勾选开启大工具集、视图与样式工具栏"></p></li><li><p><strong>视角修正</strong>：点击“相机”菜单 -&gt; 选择**“平行投影”**（）。</p><p><img src="https://image.skyforever.top/blog/2026/02/2d56432877ab2e4cb87fe4eb3a054585.webp" alt="相机菜单中切换为平行投影视角"></p></li></ul><blockquote><p>注：选择平行投影是为了取消近大远小的透视形变，方便对齐<br><img src="https://image.skyforever.top/blog/2026/02/462fca24ec8572aa01e648f13b2418e7.webp" alt="透视和平行显示对比"></p></blockquote><ul><li><p><strong>精度设置</strong>：窗口 -&gt; 模型信息</p><p><img src="https://image.skyforever.top/blog/2026/02/0108fbe6f8e55f85ff40c47bc39a963a.webp" alt="打开窗口菜单中的模型信息设置"></p><p>单位 -&gt; 精度设为 <code>0.0000</code></p><p><img src="https://image.skyforever.top/blog/2026/02/6892729a1da07a7297bdb96d8858e186.webp" alt="单位设置中将小数精度设为最高"></p></li><li><p><strong>线条优化</strong>：右侧面板 -&gt; 样式 -&gt; 编辑 -&gt; 将“轮廓线”从2改为1（让模型看起来不脏）</p><p><img src="https://image.skyforever.top/blog/2026/02/3f8b025c9c8e058208a6d9800d479642.webp" alt="样式编辑中将轮廓线粗细调整为 1"></p></li></ul><h4 id="2-常用操作速查表"><a href="#2-常用操作速查表" class="headerlink" title="2. 常用操作速查表"></a><strong>2. 常用操作速查表</strong></h4><p>左侧常用工具集：</p><p><img src="https://image.skyforever.top/blog/2026/02/df4472c33e66a6df6d8732bec22458e5.webp" alt="左侧常用工具集"></p><p>对应快捷键：</p><div class="md-table-scroll"><table><thead><tr><th align="left">功能</th><th align="left">快捷键</th><th align="left">作用</th></tr></thead><tbody><tr><td align="left"><strong>矩形</strong></td><td align="left"><code>R</code></td><td align="left">绘制平面</td></tr><tr><td align="left"><strong>推拉</strong></td><td align="left"><code>P</code></td><td align="left"><strong>核心功能</strong>：将平面拉伸为立体</td></tr><tr><td align="left"><strong>偏移</strong></td><td align="left"><code>F</code></td><td align="left">制作壁厚/边框</td></tr><tr><td align="left"><strong>输入尺寸</strong></td><td align="left">键盘直接敲数字</td><td align="left">比如<code>100,100</code> 回车</td></tr><tr><td align="left"><strong>视图旋转</strong></td><td align="left">按住鼠标中键(滚轮)</td><td align="left">360度观察</td></tr></tbody></table></div><h4 id="3-案例：做一个精准的收纳盒"><a href="#3-案例：做一个精准的收纳盒" class="headerlink" title="3. 案例：做一个精准的收纳盒"></a><strong>3. 案例：做一个精准的收纳盒</strong></h4><ol><li><p><strong>画底面</strong>：按 <code>R</code> (矩形)，点击起点，松开鼠标，键盘输入 <code>100,100</code> (注意切换英文输入法)，回车。</p></li><li><p><strong>变立体</strong>：按 <code>P</code> (推拉)，点击正方形面，向上移动鼠标，输入 <code>100</code>，回车。-&gt; 得到正方体。</p></li><li><p><strong>做壁厚</strong>：按 <code>F</code> (偏移)，点击顶面，向内移动，输入 <code>5</code>，回车。</p></li><li><p><strong>掏空</strong>：按 <code>P</code> (推拉)，点击中间的小方块，向下推，输入 <code>95</code>，回车。</p><p><em>恭喜！你刚刚设计了一个壁厚5mm、底厚5mm的收纳盒！</em></p><p><img src="https://image.skyforever.top/blog/2026/02/9cb5a675f69fc81331fde4b65d8db60c.webp" alt="在 SketchUp 中完成简易收纳盒建模"></p></li></ol><h4 id="4-导出打印文件"><a href="#4-导出打印文件" class="headerlink" title="4. 导出打印文件"></a><strong>4. 导出打印文件</strong></h4><ul><li><code>文件</code> -&gt; <code>导出</code> -&gt; <code>三维模型</code> -&gt; 选择 <strong>.stl</strong> 格式。</li></ul><hr><h3 id="七、关键步骤：切片"><a href="#七、关键步骤：切片" class="headerlink" title="七、关键步骤：切片"></a><strong>七、关键步骤：切片</strong></h3><p>模型文件(.stl)不能直接打印，需要通过切片软件如<code>Bambu Studio</code>转换成机器能读懂的代码(.gcode)。</p><p>Bambu Studio下载链接：<a href="https://bambulab.com/zh/download/studio" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://bambulab.com/zh/download/studio</a></p><p>像刚刚的模型比较简单，可以直接打印，不需要做切片处理，但</p><p><strong>核心参数建议 (以 Bambu Studio 为例)：</strong></p><p><img src="https://image.skyforever.top/blog/2026/02/e556bc43cd3c42722335d19c675d5b4f.webp" alt="Bambu Studio 切片软件主界面与参数面板"></p><ol><li><p><strong>摆放方向</strong>：<strong>大平面朝下</strong>贴紧底板，这是成功的基础。</p><p><img src="https://image.skyforever.top/blog/2026/02/5af7287de0551a44c68cbb6cc0abf123.webp" alt="调整方向"></p></li><li><p><strong>尺寸缩放</strong>：可以手动调整模型尺寸到合适大小</p><p><img src="https://image.skyforever.top/blog/2026/02/cfdeebd52fe72805d3a38a04f5208951.webp" alt="切片软件中进行模型尺寸等比缩放"></p></li><li><p>如果有很多模型需要批量打印，可以使用分盘打印的选项分批打印</p><p><img src="https://image.skyforever.top/blog/2026/02/b6e91db7f05e1cbcb990be2cd9f92d0f.webp" alt="多零件模型自动分盘排版打印"></p></li><li><p><strong>墙层数</strong>：默认2层较薄，<strong>建议改为 3-4 层</strong>，极大增加模型强度。</p></li><li><p><strong>填充</strong>：</p><ul><li>受力件：30%-50%（推荐“自适应立方体”或“以太网”）。</li><li>外观件：10%-15% 即可。</li></ul></li><li><p><strong>支撑 (Support)</strong>：</p><ul><li><p><strong>树状支撑 (Tree)</strong>：<strong>强烈推荐</strong>。好拆，接触面小，对模型表面损伤小。</p><p><img src="https://image.skyforever.top/blog/2026/02/ae91fa7bb218db6c49709bbc93b823a5.webp" alt="切片参数中启用树状支撑效果"></p></li></ul></li><li><p><strong>Brim (裙边)</strong>：打印接触面小的细高模型时务必开启，增加抓地力防倒塌。</p><p><img src="https://image.skyforever.top/blog/2026/02/3890455e237dbfaf1b8e4d638f59dbd4.webp" alt="启用 Brim 裙边增强底板附着力"></p></li></ol><blockquote><p><strong>更多教程</strong>：<a href="https://wiki.bambulab.com/zh/software/bambu-studio/studio-quick-start" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>Bambu Studio 官方快速上手指南</a></p></blockquote><hr><h3 id="结语"><a href="#结语" class="headerlink" title="结语"></a><strong>结语</strong></h3><p>3D打印的细节虽多，但入门真的不难。<strong>你最需要做的就是迈出第一步</strong>。</p><p>不用担心变成“炒面大师”（指打印失败成一团乱丝），这是每个新手的必经之路，也是乐趣的一部分。现在的社区资源极其丰富，遇到问题随时都能搜到答案。</p><p>如果你已经入手了，欢迎在评论区分享你的第一个打印作品！</p><blockquote><p><em>注：本文部分经验整理自B站UP主“<a href="https://www.bilibili.com/video/BV1QUsGzvEX1" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>喵星考拉</a>”，“<a href="https://www.bilibili.com/video/BV1xA4tzuE58" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>万事屋小玩</a>”及开源社区，更多动态可关注原作者。</em></p></blockquote>]]>
    </content>
    <id>https://blog.skyforever.top/posts/25562</id>
    <link href="https://blog.skyforever.top/posts/25562"/>
    <published>2026-02-06T08:00:00.000Z</published>
    <summary>本文汇集了科班UP主的3D打印入坑经验，从FDM与光固化的选择、拓竹与创想机型推荐，到耗材避坑、切片参数设置，手把手带你走进3D打印的世界。</summary>
    <title>3D打印入门指南</title>
    <updated>2026-02-06T08:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="嵌入式开发" scheme="https://blog.skyforever.top/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/"/>
    <category term="调试工具" scheme="https://blog.skyforever.top/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/%E8%B0%83%E8%AF%95%E5%B7%A5%E5%85%B7/"/>
    <category term="STM32" scheme="https://blog.skyforever.top/tags/STM32/"/>
    <category term="单片机" scheme="https://blog.skyforever.top/tags/%E5%8D%95%E7%89%87%E6%9C%BA/"/>
    <category term="J-Link" scheme="https://blog.skyforever.top/tags/J-Link/"/>
    <category term="RTT" scheme="https://blog.skyforever.top/tags/RTT/"/>
    <category term="嵌入式开发" scheme="https://blog.skyforever.top/tags/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/"/>
    <category term="调试技巧" scheme="https://blog.skyforever.top/tags/%E8%B0%83%E8%AF%95%E6%8A%80%E5%B7%A7/"/>
    <content>
      <![CDATA[<p>不知道大家在单片机开发时，是不是跟我一样觉得特别烦：每次开始调试，不仅要插下载器（J-Link/ST-Link），还得再找个 USB 转 TTL 模块接串口看打印信息。</p><p><strong>这就导致板子上挂着一堆线，电脑的 USB 口经常不够用，桌面上乱糟糟的。</strong></p><p>其实，既然我们已经插了 J-Link 下载器，为什么不能直接用它来看打印信息呢？完全可以！今天就来介绍一下如何利用 <strong>J-Link 的 RTT 功能</strong>，扔掉串口线，<strong>真正实现“一根线”搞定下载和调试</strong>。</p><h2 id="1-J-Link-仿真调试器"><a href="#1-J-Link-仿真调试器" class="headerlink" title="1. J-Link 仿真调试器"></a>1. J-Link 仿真调试器</h2><p>下载器五花八门，但我现在最常用 J-Link，原因很简单：<strong>省事</strong>。</p><p>相比于又要接 SWD 下载口、又要额外接 GND/TX/RX 串口线的传统方式，J-Link 只需要原本的那四根线（VCC, GND, SWDIO, SWCLK），就能同时完成<strong>程序下载</strong>和<strong>日志打印</strong>。体积小，接线少，简直是强迫症福音，YYDS！</p><p><img src="https://image.skyforever.top/blog/2025/12/51276d74e41bc4be6dac74b171160529.png" alt="J-Link OB ARM 仿真调试器"></p><h2 id="2-安装-J-Link-驱动"><a href="#2-安装-J-Link-驱动" class="headerlink" title="2. 安装 J-Link 驱动"></a>2. 安装 J-Link 驱动</h2><p><strong>下载链接</strong>：<a href="https://www.segger.com/downloads/jlink/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://www.segger.com/downloads/jlink/</a></p><p>买回来 J-Link 后，一般卖家都会提供驱动程序，驱动安装完成后就可以下载调试程序了。</p><p><img src="https://image.skyforever.top/blog/2025/12/407bbbbdfa6acb784c15f53f37fed135.png" alt="J-Link 驱动下载页面"></p><p>当然我们现在要使用 J-Link 的 <strong>RTT 功能 (Real Time Transfer，实时传输，可不是 RT-Thread 操作系统啊)</strong>，就需要在官网下载完整的 J-Link 包。最新版本的是 V8.92，当然旧版本通常也可以</p><p>下载完成后直接安装即可</p><h2 id="3-移植-RTT"><a href="#3-移植-RTT" class="headerlink" title="3. 移植 RTT"></a>3. 移植 RTT</h2><p>以前的教程说 RTT 源码包就在安装目录里，但我发现现在的安装包里没有这个文件了。查看 <a href="https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>官方文档</a> 发现源码包放在了 GitHub 上：</p><ul><li><strong>源码地址</strong>：<a href="https://github.com/SEGGERMicro/RTT" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>https://github.com/SEGGERMicro/RTT</a></li></ul><p>将这个源码包克隆或者下载下来</p><p><img src="https://image.skyforever.top/blog/2025/12/1521d0fe95d125ca0736993eb80a43a7.png" alt="RTT GitHub 源码页面"></p><p>然后将 <code>RTT</code> 文件夹复制到我们编写程序的工程文件夹中：</p><p><img src="https://image.skyforever.top/blog/2025/12/06ba955b4b403a4104f27f6b22cc6352.png" alt="RTT 文件夹结构"></p><p><img src="https://image.skyforever.top/blog/2025/12/6dd2ba69a47afcd5feea3127a5858d0f.png" alt="RTT 工程文件夹结构"></p><p>注意config文件夹里面的文件也要放到RTT文件夹</p><p><img src="https://image.skyforever.top/blog/2025/12/a42be084603163424d939b2b53735912.png" alt="RTT Config 文件夹结构"></p><p>接着在 IDE 项目中（如 Keil）新建一个 <code>RTT</code> 分组，并将 <code>RTT</code> 文件夹中的两个 <code>.c</code> 文件添加进来：</p><ul><li><code>SEGGER_RTT.c</code></li><li><code>SEGGER_RTT_printf.c</code></li></ul><p><img src="https://image.skyforever.top/blog/2025/12/980de73aea08fd73f58d1219e86686d4.png" alt="Keil 添加 RTT 源文件"></p><p>添加 <code>RTT</code> 的头文件路径。</p><p><img src="https://image.skyforever.top/blog/2025/12/c81839b4a71f6c18e48bad38baf629f5.png" alt="Keil 添加 RTT 头文件路径"></p><p>到这里基本就移植成功了，是不是很简单？就是把 RTT 的源码添加到工程中即可，完全不需要修改别的操作。</p><h2 id="4-RTT-打印输出"><a href="#4-RTT-打印输出" class="headerlink" title="4. RTT 打印输出"></a>4. RTT 打印输出</h2><p>接下来就可以在代码中进行打印输出了。</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">"stm32f4xx.h"</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">"delay.h"</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">"usart.h"</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">"led.h"</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">"SEGGER_RTT.h"</span> <span class="comment">// 引入头文件</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">(<span class="type">void</span>)</span></span><br><span class="line">{</span><br><span class="line">    delay_init();                     <span class="comment">// 初始化延时函数</span></span><br><span class="line">    LED_Init();                       <span class="comment">// 初始化LED</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>)</span><br><span class="line">    {</span><br><span class="line">        <span class="comment">// 通道0是默认通道</span></span><br><span class="line">        SEGGER_RTT_printf(<span class="number">0</span>, <span class="string">"hello world\r\n"</span>);</span><br><span class="line">        delay_ms(<span class="number">500</span>);</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>编译无误后，连接好下载器。</p><ol><li><strong>连接硬件</strong>：确保 SWD 接口（CLK, DIO, GND, VCC）连接正确。</li><li><strong>打开查看器</strong>：打开 J-Link 安装目录下的 <code>JLinkRTTViewer.exe</code>。</li></ol><p><img src="https://image.skyforever.top/blog/2025/12/7e653c9f5284b02604babdb1acc713ea.png" alt="软件位置示例"></p><p>按照如下配置（选择对应的芯片型号和接口方式）：</p><p><img src="https://image.skyforever.top/blog/2025/12/b583ec0681f2f1226757154e8dd881cb.png" alt="配置界面"></p><p>将代码下载到单片机中，就可以在软件界面看到完美的打印输出了。</p><p><img src="https://image.skyforever.top/blog/2025/12/391c32b3a9252341b2a2f140849b089d.png" alt="J-Link RTT Viewer 输出界面"></p><h2 id="5-RTT-的使用技巧"><a href="#5-RTT-的使用技巧" class="headerlink" title="5. RTT 的使用技巧"></a>5. RTT 的使用技巧</h2><h3 id="5-1-修改-RTT-缓冲大小"><a href="#5-1-修改-RTT-缓冲大小" class="headerlink" title="5.1 修改 RTT 缓冲大小"></a>5.1 修改 RTT 缓冲大小</h3><p>有时候我们发现信息不能完全打印出来，可能是因为缓冲不够。默认缓冲区大小是 1K (1024) 字节，如果不够可以在 <code>SEGGER_RTT_Conf.h</code> 中改大一点。</p><p><img src="https://image.skyforever.top/blog/2025/12/d7c1bfcf25470c90455ef84d9576edc1.png" alt="RTT 缓冲区配置"></p><h3 id="5-2-多虚拟端口使用"><a href="#5-2-多虚拟端口使用" class="headerlink" title="5.2 多虚拟端口使用"></a>5.2 多虚拟端口使用</h3><p>RTT 支持向不同的虚拟端口（Terminal）中打印信息，使用方法如下。</p><p>首先在 RTT Viewer 软件中分别打开三个虚拟端口：</p><p><img src="https://image.skyforever.top/blog/2025/12/a2f04282eddba03af3346fd77b99f3f0.png" alt="多虚拟终端"></p><p>编写代码：</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">while</span> (<span class="number">1</span>) {</span><br><span class="line">    SEGGER_RTT_SetTerminal(<span class="number">0</span>);</span><br><span class="line">    SEGGER_RTT_printf(<span class="number">0</span>, <span class="string">"hello world, SEGGER RTT Terminal 0!\r\n"</span>);</span><br><span class="line"></span><br><span class="line">    SEGGER_RTT_SetTerminal(<span class="number">1</span>);</span><br><span class="line">    SEGGER_RTT_printf(<span class="number">0</span>, <span class="string">"hello world, SEGGER RTT Terminal 1!\r\n"</span>);</span><br><span class="line"></span><br><span class="line">    SEGGER_RTT_SetTerminal(<span class="number">2</span>);</span><br><span class="line">    SEGGER_RTT_printf(<span class="number">0</span>, <span class="string">"hello world, SEGGER RTT Terminal 2!\r\n"</span>);</span><br><span class="line"></span><br><span class="line">    delay_ms(<span class="number">1000</span>);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>编译、链接、下载，观察现象：</p><ul><li><strong>窗口 0</strong>：显示 Terminal 0 的信息</li><li><strong>窗口 1</strong>：显示 Terminal 1 的信息</li><li><strong>窗口 2</strong>：显示 Terminal 2 的信息</li></ul><p><img src="https://image.skyforever.top/blog/2025/12/adb2bb8fccbb12da4200ef35f29f5556.png" alt="RTT 多终端显示效果"></p><h3 id="5-3-修改打印字符颜色"><a href="#5-3-修改打印字符颜色" class="headerlink" title="5.3 修改打印字符颜色"></a>5.3 修改打印字符颜色</h3><p>RTT 支持不同颜色的字符显示，这对于区分报警信息非常有用。</p><p><img src="https://image.skyforever.top/blog/2025/12/d357fa83d387a398eaa52eef166092ff.png" alt="RTT 彩色字符宏定义"></p><p>使用时，在字符串前面加上对应颜色的宏定义即可。</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">while</span> (<span class="number">1</span>) {</span><br><span class="line">    SEGGER_RTT_SetTerminal(<span class="number">0</span>);</span><br><span class="line">    SEGGER_RTT_printf(<span class="number">0</span>, RTT_CTRL_TEXT_RED <span class="string">"Error: System Fault!\r\n"</span>);</span><br><span class="line"></span><br><span class="line">    SEGGER_RTT_SetTerminal(<span class="number">1</span>);</span><br><span class="line">    SEGGER_RTT_printf(<span class="number">0</span>, RTT_CTRL_TEXT_GREEN <span class="string">"Info: System Normal.\r\n"</span>);</span><br><span class="line"></span><br><span class="line">    SEGGER_RTT_SetTerminal(<span class="number">2</span>);</span><br><span class="line">    SEGGER_RTT_printf(<span class="number">0</span>, RTT_CTRL_TEXT_BLUE <span class="string">"Debug: Value = 100.\r\n"</span>);</span><br><span class="line"></span><br><span class="line">    delay_ms(<span class="number">1000</span>);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h3 id="5-4-使用-printf-重定向"><a href="#5-4-使用-printf-重定向" class="headerlink" title="5.4 使用 printf 重定向"></a>5.4 使用 printf 重定向</h3><p>项目中使用 <code>printf</code> 的地方非常多，如果可以直接修改 <code>printf</code> 重定向到 RTT 组件，则会非常方便（无需修改原有代码中的打印语句）。</p><p>方法是直接使用 RTT 提供的 API 实现 <code>fputc</code>。</p><p><strong>重定义 fputc 函数：</strong></p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 重定义 fputc 函数</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">fputc</span><span class="params">(<span class="type">int</span> ch, FILE *f)</span> {</span><br><span class="line">    SEGGER_RTT_PutChar(<span class="number">0</span>, ch);</span><br><span class="line">    <span class="keyword">return</span> ch;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>替换之前的代码，直接使用 printf：</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">while</span> (<span class="number">1</span>) {</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"hello world, printf via SEGGER RTT!\r\n"</span>);</span><br><span class="line">    delay_ms(<span class="number">1000</span>);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>编译、链接、下载，效果与使用 <code>SEGGER_RTT_printf</code> 一致</p><hr><p><strong>结语</strong>：<br>虽然串口（UART）调试是经典做法，但对于我们这种追求效率（图省事）的开发者来说，RTT 简直是神技。</p><p><strong>自从用了 RTT，我的 USB 转 TTL 模块就可以去吃灰了。</strong></p><ul><li><strong>不需要</strong>单独接串口线；</li><li><strong>不需要</strong>担心占用单片机的 UART 硬件资源；</li><li><strong>不需要</strong>担心波特率设置不对导致乱码。</li></ul><p>如果你也想少插一根线，还原一个清爽的开发桌面，强烈建议试一试这个方法！</p>]]>
    </content>
    <id>https://blog.skyforever.top/posts/41626</id>
    <link href="https://blog.skyforever.top/posts/41626"/>
    <published>2025-12-08T11:57:17.000Z</published>
    <summary>详细介绍如何在单片机开发中，利用 J-Link 调试器的 RTT (Real Time Transfer) 功能代替传统串口打印。涵盖驱动安装、源码移植、多终端打印及 printf 重定向等实用技巧。</summary>
    <title>基于 J-Link RTT 的单片机调试打印指南</title>
    <updated>2025-12-08T11:57:17.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Skyforever</name>
    </author>
    <category term="嵌入式开发" scheme="https://blog.skyforever.top/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/"/>
    <category term="技术教程" scheme="https://blog.skyforever.top/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/%E6%8A%80%E6%9C%AF%E6%95%99%E7%A8%8B/"/>
    <category term="教程" scheme="https://blog.skyforever.top/tags/%E6%95%99%E7%A8%8B/"/>
    <category term="嵌入式" scheme="https://blog.skyforever.top/tags/%E5%B5%8C%E5%85%A5%E5%BC%8F/"/>
    <category term="单片机" scheme="https://blog.skyforever.top/tags/%E5%8D%95%E7%89%87%E6%9C%BA/"/>
    <category term="C语言" scheme="https://blog.skyforever.top/tags/C%E8%AF%AD%E8%A8%80/"/>
    <category term="裸机开发" scheme="https://blog.skyforever.top/tags/%E8%A3%B8%E6%9C%BA%E5%BC%80%E5%8F%91/"/>
    <category term="多任务" scheme="https://blog.skyforever.top/tags/%E5%A4%9A%E4%BB%BB%E5%8A%A1/"/>
    <category term="状态机" scheme="https://blog.skyforever.top/tags/%E7%8A%B6%E6%80%81%E6%9C%BA/"/>
    <content>
      <![CDATA[<p>以下内容为阅读书籍《从单片机基础到程序框架（2019版）》作者：吴坚鸿<br><a href="/data/ES/硬件/两大核心框架理论（四区一线，switch外加定时中断）/" target="_blank" data-md-link=""><span class="md-link-icon ui-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><g fill="currentColor"><g opacity=".5"><path d="M19.7388 4.26118C17.0572 1.57961 12.7095 1.57961 10.0279 4.26118L9.30707 4.98203C9.01418 5.27492 9.01418 5.7498 9.30707 6.04269C9.59997 6.33558 10.0748 6.33558 10.3677 6.04269L11.0886 5.32184C13.1844 3.22605 16.5823 3.22605 18.6781 5.32184C20.7739 7.41763 20.7739 10.8156 18.6781 12.9114L17.9573 13.6322C17.6644 13.9251 17.6644 14.4 17.9573 14.6929C18.2502 14.9858 18.725 14.9858 19.0179 14.6929L19.7388 13.972C22.4203 11.2905 22.4203 6.94276 19.7388 4.26118Z"></path><path d="M6.04269 9.30707C6.33558 9.59997 6.33558 10.0748 6.04269 10.3677L5.32184 11.0886C3.22605 13.1844 3.22605 16.5823 5.32184 18.6781C7.41763 20.7739 10.8156 20.7739 12.9114 18.6781L13.6322 17.9573C13.9251 17.6644 14.4 17.6644 14.6929 17.9573C14.9858 18.2501 14.9858 18.725 14.6929 19.0179L13.972 19.7388C11.2905 22.4203 6.94276 22.4203 4.26118 19.7388C1.57961 17.0572 1.57961 12.7095 4.26118 10.0279L4.98203 9.30707C5.27492 9.01418 5.7498 9.01418 6.04269 9.30707Z"></path></g><path d="M14.6933 9.30707C14.9862 9.59997 14.9862 10.0748 14.6933 10.3677L10.3682 14.6928C10.0753 14.9857 9.60045 14.9857 9.30756 14.6928C9.01467 14.3999 9.01467 13.9251 9.30756 13.6322L13.6327 9.30707C13.9255 9.01418 14.4004 9.01418 14.6933 9.30707Z"></path></g></svg></span>第88章</a>内容至第91章内容的观后感</p><h3 id="问题的起点：罪恶的Delay"><a href="#问题的起点：罪恶的Delay" class="headerlink" title="问题的起点：罪恶的Delay()"></a>问题的起点：罪恶的<code>Delay()</code></h3><p>在单片机编程的入门阶段，我们几乎都写过这样的代码来让LED闪烁：</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">while</span>(<span class="number">1</span>) {</span><br><span class="line">  LED_On();</span><br><span class="line">  Delay(<span class="number">500</span>); <span class="comment">// CPU在此空转，等待500毫秒</span></span><br><span class="line">  LED_Off();</span><br><span class="line">  Delay(<span class="number">500</span>);</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>这段代码简单直观，却隐藏着一个致命缺陷：<code>Delay()</code>函数是<strong>阻塞式</strong>的。在CPU空等的这500毫秒内，它无法响应按键、处理串口数据或执行任何其他任务。系统被完全“冻结”了。</p><p>要构建一个能同时处理多项事务的健壮系统，我们必须消灭<code>Delay()</code>。原作者通过一个“跑马灯”案例，展示实现高效并发的编程框架。</p><h3 id="第一重境界：阻塞式移位"><a href="#第一重境界：阻塞式移位" class="headerlink" title="第一重境界：阻塞式移位"></a>第一重境界：阻塞式移位</h3><p>这是最直接的跑马-灯实现。利用C语言的位移操作，结合<code>Delay()</code>，让灯光依次流动。</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">LedTask</span><span class="params">(<span class="type">void</span>)</span> {</span><br><span class="line">  <span class="type">static</span> <span class="type">uint8_t</span> led_mask = <span class="number">0x01</span>;</span><br><span class="line">  </span><br><span class="line">  P0 = ~led_mask; <span class="comment">// 灌电流点亮，所以取反</span></span><br><span class="line">  Delay(<span class="number">100000</span>);  <span class="comment">// 阻塞延时，系统“假死”</span></span><br><span class="line">  </span><br><span class="line">  led_mask &lt;&lt;= <span class="number">1</span>; <span class="comment">// 左移一位</span></span><br><span class="line">  <span class="keyword">if</span> (led_mask == <span class="number">0</span>) {</span><br><span class="line">    led_mask = <span class="number">0x01</span>;</span><br><span class="line">  }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><ul><li><strong>优点</strong>：代码逻辑简单。</li><li><strong>缺点</strong>：阻塞式，无法实现多任务并行。</li></ul><h3 id="第二重境界：非阻塞式移位"><a href="#第二重境界：非阻塞式移位" class="headerlink" title="第二重境界：非阻塞式移位"></a>第二重境界：非阻塞式移位</h3><p>用定时器中断驱动的“软件定时器”取代<code>Delay()</code>。任务函数不再等待，而是每次被调用时检查时间是否到达。</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 在定时器中断服务函数中 (例如每1ms一次):</span></span><br><span class="line"><span class="comment">// volatile uint16_t timer_tick = 0;</span></span><br><span class="line"><span class="comment">// timer_tick++;</span></span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">LedTask</span><span class="params">(<span class="type">void</span>)</span> {</span><br><span class="line">  <span class="type">static</span> <span class="type">uint16_t</span> last_time = <span class="number">0</span>;</span><br><span class="line">  <span class="type">static</span> <span class="type">uint8_t</span> led_mask = <span class="number">0x01</span>;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 检查自上次执行以来是否已过去200ms</span></span><br><span class="line">  <span class="keyword">if</span> (timer_tick - last_time &gt;= <span class="number">200</span>) {</span><br><span class="line">    last_time = timer_tick; <span class="comment">// 更新时间戳</span></span><br><span class="line">    </span><br><span class="line">    P0 = ~led_mask;</span><br><span class="line">    led_mask &lt;&lt;= <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">if</span> (led_mask == <span class="number">0</span>) {</span><br><span class="line">      led_mask = <span class="number">0x01</span>;</span><br><span class="line">    }</span><br><span class="line">  }</span><br><span class="line">  <span class="comment">// 如果时间没到，函数立刻返回</span></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><ul><li><strong>优点</strong>：非阻塞，CPU被释放出来，可以<code>while(1)</code>中调用其他任务。</li><li><strong>缺点</strong>：逻辑依然僵化。它强依赖于连续的IO口（P0口），且难以实现复杂的、非线性的亮灯逻辑。</li></ul><h3 id="第三重境界：状态机思维的升华"><a href="#第三重境界：状态机思维的升华" class="headerlink" title="第三重境界：状态机思维的升华"></a>第三重境界：状态机思维的升华</h3><p>这正是作者思想的精华所在。他彻底抛弃了“移位”这种面向过程的具象思维，转向一种更抽象、更强大的<strong>状态机</strong>思维。跑马灯的每一步，都被封装成一个独立的、自管理的任务函数。</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 任务一：跑马灯A</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">LedTask_A</span><span class="params">(<span class="type">void</span>)</span> {</span><br><span class="line">  <span class="type">static</span> <span class="type">uint16_t</span> last_time = <span class="number">0</span>;</span><br><span class="line">  <span class="type">static</span> <span class="type">uint8_t</span> step = <span class="number">0</span>; <span class="comment">// 状态机A的状态变量</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (IsTimerExpired(&amp;last_time, <span class="number">200</span>) == <span class="literal">false</span>) {</span><br><span class="line">    <span class="keyword">return</span>; <span class="comment">// 时间未到，立即返回，让出CPU</span></span><br><span class="line">  }</span><br><span class="line"></span><br><span class="line">  <span class="keyword">switch</span> (step) {</span><br><span class="line">    <span class="keyword">case</span> <span class="number">0</span>:</span><br><span class="line">      P0 = <span class="number">0b11111110</span>; <span class="comment">// 点亮第0个灯</span></span><br><span class="line">      step = <span class="number">1</span>;       <span class="comment">// 切换到下一个状态</span></span><br><span class="line">      <span class="keyword">break</span>;</span><br><span class="line">    <span class="comment">// ... 其他状态 ...</span></span><br><span class="line">    <span class="keyword">case</span> <span class="number">7</span>:</span><br><span class="line">      P0 = <span class="number">0b11101111</span>; <span class="comment">// 点亮第4个灯</span></span><br><span class="line">      step = <span class="number">0</span>;       <span class="comment">// 回到初始状态</span></span><br><span class="line">      <span class="keyword">break</span>;</span><br><span class="line">  }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>初看之下，我们只是将一个任务用<code>switch-case</code>重写了。但作者真正的意图远不止于此。<br>现在<br>这个<code>LedTask_A</code>函数本身，就是一个<strong>独立的、可轮询的“微型进程”</strong>。</p><h3 id="手动时间片：while-1-循环的真正威力"><a href="#手动时间片：while-1-循环的真正威力" class="headerlink" title="手动时间片：while(1)循环的真正威力"></a>手动时间片：while(1)循环的真正威力</h3><p>现在，想象我们有第二个、第三个任务，比如另一个速度不同的跑马灯<code>LedTask_B</code>，和一个按键扫描任务<code>KeyTask</code>。我们同样将它们各自封装成独立的状态机函数。</p><p>此时，<code>main</code>函数里的<code>while(1)</code>循环就展现了它真正的威力：</p><figure class="highlight c"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">main</span><span class="params">(<span class="type">void</span>)</span> {</span><br><span class="line">  <span class="comment">// ... 初始化 ...</span></span><br><span class="line">  <span class="keyword">while</span>(<span class="number">1</span>) {</span><br><span class="line">    <span class="comment">// 手动进行“时间片”轮转</span></span><br><span class="line">    LedTask_A(); <span class="comment">// 给任务A一个执行机会</span></span><br><span class="line">    LedTask_B(); <span class="comment">// 立即给任务B一个执行机会</span></span><br><span class="line">    KeyTask();   <span class="comment">// 立即给任务C一个执行机会</span></span><br><span class="line">  }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>这才是整个框架的核心！<strong>主循环变成了一个永不停歇的高速调度器</strong></p><p>它以极快的速度，一遍又一遍地“轮询”每一个任务函数。而每一个状态机任务都必须遵守一个原则：<strong>快速执行，快速返回</strong>。它们只在自己的时间片内（即函数被调用的瞬间）检查条件、执行一个微小的步骤，然后立刻退出，将CPU控制权交还给主循环，以便下一个任务可以被调用。</p><p>这就相当于我们**<u>手动地将CPU时间切成了一个个微小的“时间片”</u>**，并依次分配给了每一个任务。由于切换速度极快（远超人眼感知），在宏观上，所有任务看起来就像在同时运行。</p><h3 id="终极挑战：在“时间片”内处理“长时任务”"><a href="#终极挑战：在“时间片”内处理“长时任务”" class="headerlink" title="终极挑战：在“时间片”内处理“长时任务”"></a>终极挑战：在“时间片”内处理“长时任务”</h3><p>这个手动调度模型有一个前提：每个任务的“时间片”必须极短。如果<code>KeyTask</code>的某一步需要执行1秒钟，那么<code>任务_A</code>和<code>任务_B</code>都会因此卡顿1微秒。</p><p>那么，如何用这个框架处理播放音频、请求网络这种看似耗时很长的任务呢？</p><p>答案依然是<strong>分解</strong>。我们的目标，是<strong>确保任何任务的任何一个<code>case</code>状态，都是一个能在微秒级完成的“微操作”</strong>。CPU的角色是**“管理者”<strong>，而非</strong>“劳工”**。</p><h4 id="案例1：播放音频（I-O密集型任务）"><a href="#案例1：播放音频（I-O密集型任务）" class="headerlink" title="案例1：播放音频（I/O密集型任务）"></a>案例1：播放音频（I/O密集型任务）</h4><p>CPU的工作不是逐点播放音频数据，而是将数据分批“喂”给能自动工作的硬件（如DMA+DAC）。状态机只在关键时间点介入：</p><ul><li><strong><code>STATE_START</code></strong>: <strong>动作(瞬间)</strong>：配置并启动DMA播放第一个数据块。切换到<code>STATE_WAIT</code>。</li><li><strong><code>STATE_WAIT</code></strong>: <strong>检查(瞬间)</strong>：查询DMA中断标志。若缓冲区将空，则启动下一个数据块的填充和DMA重定向。</li></ul><p>CPU从不参与“播放”这个持续的过程，它只在需要“换弹夹”时，做一个“瞬间”的搬运工。</p><h4 id="案例2：请求网络（等待密集型任务）"><a href="#案例2：请求网络（等待密集型任务）" class="headerlink" title="案例2：请求网络（等待密集型任务）"></a>案例2：请求网络（等待密集型任务）</h4><p>网络请求的本质是“<strong>发送指令 -&gt; 漫长等待 -&gt; 接收数据</strong>”。状态机将此过程拆分：</p><ul><li><strong><code>STATE_SEND</code></strong>: <strong>动作(瞬间)</strong>：通过串口向WiFi模块发送HTTP请求指令。切换到<code>STATE_WAIT</code>。</li><li><strong><code>STATE_WAIT</code></strong>: <strong>检查(瞬间)</strong>：轮询串口接收缓冲区。有数据吗？有，就读一点分析一下；没有，就立即返回。</li></ul><p>CPU将等待的“锅”甩给了网络，自己只负责在每个时间片里做一次快速的“检查”，绝不原地空等。</p><p><u>当然，这些步骤又自己从头实现着实没必要，这种情况最好还是引入操作系统，例如<strong>RTOS</strong></u></p><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>读完吴坚鸿老师的这几章，有一种豁然开朗的感觉。这本书教授的不仅仅是一种编程技巧（术），更是一种解决复杂问题的系统化思想（道）。</p><p>这个框架的本质，就是<strong>用状态机将每个任务“切片”，再用主循环将CPU时间“切片”</strong>。通过这两层“切片”，我们就在裸机上构建了一个高效、稳定、资源占用极低的<strong>合作式多任务调度系统</strong>。</p><p>它虽然不如RTOS（实时操作系统）的抢占式调度来得强大和完善，但它不需要复杂的汇编上下文切换，仅仅依靠 C 语言的 <code>switch-case</code> 语法，就巧妙地实现了多任务并发。对于资源受限、逻辑中等复杂的单片机项目而言，这无疑是一套性价比极高、值得反复研读的程序架构思想。</p>]]>
    </content>
    <id>https://blog.skyforever.top/posts/63520</id>
    <link href="https://blog.skyforever.top/posts/63520"/>
    <published>2025-11-18T12:00:00.000Z</published>
    <summary>通过经典的“跑马灯”案例，揭示裸机编程中从阻塞到非阻塞，再到状态机思维的三重境界。并进一步探讨如何运用该思想处理复杂长时任务，帮助您在不使用RTOS的情况下，构建高效、可扩展的嵌入式程序。</summary>
    <title>如何在不使用操作系统的情况下实现多线程效果</title>
    <updated>2025-11-18T12:00:00.000Z</updated>
  </entry>
</feed>
