<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>liu</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <id>https://lbq08.cc/</id>
  <link href="https://lbq08.cc/" rel="alternate"/>
  <link href="https://lbq08.cc/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, liu</rights>
  <subtitle>lbq 的个人开发日志，记录编程学习、技术分享与项目实践</subtitle>
  <title>lbq开发日志</title>
  <updated>2026-04-07T12:59:15.109Z</updated>
  <entry>
    <author>
      <name>liu</name>
    </author>
    <content>
      <![CDATA[<p>Welcome to <a href="https://hexo.io/">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues">GitHub</a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo new <span class="string">&quot;My New Post&quot;</span></span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/writing.html">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo server</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/server.html">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo generate</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/generating.html">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo deploy</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/one-command-deployment.html">Deployment</a></p>]]>
    </content>
    <id>https://lbq08.cc/2025/11/27/hello-world/</id>
    <link href="https://lbq08.cc/2025/11/27/hello-world/"/>
    <published>2025-11-27T08:49:52.060Z</published>
    <summary>
      <![CDATA[<p>Welcome to <a href="https://hexo.io/">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/">documentation</a> for]]>
    </summary>
    <title>Hello World</title>
    <updated>2026-04-07T12:59:15.109Z</updated>
  </entry>
  <entry>
    <author>
      <name>liu</name>
    </author>
    <category term="工具使用" scheme="https://lbq08.cc/categories/%E5%B7%A5%E5%85%B7%E4%BD%BF%E7%94%A8/"/>
    <category term="Hexo" scheme="https://lbq08.cc/tags/Hexo/"/>
    <category term="Butterfly" scheme="https://lbq08.cc/tags/Butterfly/"/>
    <category term="博客搭建" scheme="https://lbq08.cc/tags/%E5%8D%9A%E5%AE%A2%E6%90%AD%E5%BB%BA/"/>
    <content>
      <![CDATA[<p>一篇面向实际操作的 Hexo + Butterfly 搭建手册，跳过废话，直接上手。</p><span id="more"></span><h2 id="环境准备"><a href="#环境准备" class="headerlink" title="环境准备"></a>环境准备</h2><p>需要提前安装两个工具：</p><ul><li><strong>Node.js</strong>（&gt;&#x3D; 14.0）：<a href="https://nodejs.org/">下载地址</a></li><li><strong>Git</strong>：<a href="https://git-scm.com/">下载地址</a></li></ul><p>验证安装：</p><figure class="highlight bash"><table><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">node -v</span><br><span class="line">npm -v</span><br><span class="line">git --version</span><br></pre></td></tr></table></figure><h2 id="安装-Hexo"><a href="#安装-Hexo" class="headerlink" title="安装 Hexo"></a>安装 Hexo</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g hexo-cli</span><br></pre></td></tr></table></figure><p>初始化博客项目：</p><figure class="highlight bash"><table><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">hexo init my-blog</span><br><span class="line"><span class="built_in">cd</span> my-blog</span><br><span class="line">npm install</span><br></pre></td></tr></table></figure><p>初始化完成后的目录结构：</p><figure class="highlight plaintext"><table><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">my-blog/</span><br><span class="line">├── _config.yml        # 站点配置文件</span><br><span class="line">├── package.json       # 依赖管理</span><br><span class="line">├── scaffolds/         # 文章模板</span><br><span class="line">├── source/            # 资源文件夹</span><br><span class="line">│   └── _posts/        # 文章目录</span><br><span class="line">└── themes/            # 主题目录</span><br></pre></td></tr></table></figure><h2 id="安装-Butterfly-主题"><a href="#安装-Butterfly-主题" class="headerlink" title="安装 Butterfly 主题"></a>安装 Butterfly 主题</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-theme-butterfly</span><br></pre></td></tr></table></figure><p>Butterfly 依赖 pug 和 stylus 渲染器：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-renderer-pug hexo-renderer-stylus</span><br></pre></td></tr></table></figure><p>修改站点配置文件 <code>_config.yml</code>：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">theme:</span> <span class="string">butterfly</span></span><br></pre></td></tr></table></figure><p>在项目根目录创建 <code>_config.butterfly.yml</code>，用于覆盖主题默认配置，后续所有主题配置都写在这个文件里，<strong>不要直接改 <code>themes/butterfly/_config.yml</code></strong>，方便主题升级。</p><h2 id="站点基础配置"><a href="#站点基础配置" class="headerlink" title="站点基础配置"></a>站点基础配置</h2><p>编辑根目录 <code>_config.yml</code>：</p><figure class="highlight yaml"><table><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"># 站点信息</span></span><br><span class="line"><span class="attr">title:</span> <span class="string">你的博客名</span></span><br><span class="line"><span class="attr">subtitle:</span> <span class="string">&quot;&quot;</span></span><br><span class="line"><span class="attr">description:</span> <span class="string">&quot;站点描述，用于 SEO&quot;</span></span><br><span class="line"><span class="attr">keywords:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">关键词1</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">关键词2</span></span><br><span class="line"><span class="attr">author:</span> <span class="string">你的名字</span></span><br><span class="line"><span class="attr">language:</span> <span class="string">zh-CN</span></span><br><span class="line"><span class="attr">timezone:</span> <span class="string">Asia/Shanghai</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># URL（改成你自己的域名）</span></span><br><span class="line"><span class="attr">url:</span> <span class="string">https://yourdomain.com</span></span><br><span class="line"><span class="attr">permalink:</span> <span class="string">:year/:month/:day/:title/</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 关闭 Hexo 版本暴露</span></span><br><span class="line"><span class="attr">meta_generator:</span> <span class="literal">false</span></span><br></pre></td></tr></table></figure><h2 id="Butterfly-主题配置"><a href="#Butterfly-主题配置" class="headerlink" title="Butterfly 主题配置"></a>Butterfly 主题配置</h2><p>以下是常用配置项，写在 <code>_config.butterfly.yml</code> 中。</p><h3 id="导航栏"><a href="#导航栏" class="headerlink" title="导航栏"></a>导航栏</h3><figure class="highlight yaml"><table><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="attr">nav:</span></span><br><span class="line">  <span class="attr">logo:</span></span><br><span class="line">  <span class="attr">display_title:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">fixed:</span> <span class="literal">false</span></span><br><span class="line"></span><br><span class="line"><span class="attr">menu:</span></span><br><span class="line">  <span class="string">主页:</span> <span class="string">/</span> <span class="string">||</span> <span class="string">fas</span> <span class="string">fa-home</span></span><br><span class="line">  <span class="string">博文</span> <span class="string">||</span> <span class="attr">fa fa-graduation-cap:</span></span><br><span class="line">    <span class="string">分类:</span> <span class="string">/categories/</span> <span class="string">||</span> <span class="string">fa</span> <span class="string">fa-archive</span></span><br><span class="line">    <span class="string">标签:</span> <span class="string">/tags/</span> <span class="string">||</span> <span class="string">fa</span> <span class="string">fa-tags</span></span><br><span class="line">    <span class="string">归档:</span> <span class="string">/archives/</span> <span class="string">||</span> <span class="string">fa</span> <span class="string">fa-folder-open</span></span><br><span class="line">  <span class="string">友链:</span> <span class="string">/links/</span> <span class="string">||</span> <span class="string">fa</span> <span class="string">fa-link</span></span><br><span class="line">  <span class="string">关于:</span> <span class="string">/about/</span> <span class="string">||</span> <span class="string">fas</span> <span class="string">fa-heart</span></span><br></pre></td></tr></table></figure><h3 id="代码块"><a href="#代码块" class="headerlink" title="代码块"></a>代码块</h3><figure class="highlight yaml"><table><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="attr">code_blocks:</span></span><br><span class="line">  <span class="attr">theme:</span> <span class="string">darker</span> <span class="comment"># darker / pale night / light / ocean</span></span><br><span class="line">  <span class="attr">macStyle:</span> <span class="literal">true</span> <span class="comment"># Mac 风格三个小圆点</span></span><br><span class="line">  <span class="attr">copy:</span> <span class="literal">true</span> <span class="comment"># 显示复制按钮</span></span><br><span class="line">  <span class="attr">language:</span> <span class="literal">true</span> <span class="comment"># 显示语言标识</span></span><br><span class="line">  <span class="attr">shrink:</span> <span class="literal">false</span> <span class="comment"># 是否默认收缩</span></span><br></pre></td></tr></table></figure><h3 id="头像与图标"><a href="#头像与图标" class="headerlink" title="头像与图标"></a>头像与图标</h3><figure class="highlight yaml"><table><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="attr">favicon:</span> <span class="string">/img/favicon.png</span></span><br><span class="line"></span><br><span class="line"><span class="attr">avatar:</span></span><br><span class="line">  <span class="attr">img:</span> <span class="string">/img/avatar.jpg</span></span><br><span class="line">  <span class="attr">effect:</span> <span class="literal">false</span> <span class="comment"># 头像旋转效果</span></span><br></pre></td></tr></table></figure><h3 id="侧边栏"><a href="#侧边栏" class="headerlink" title="侧边栏"></a>侧边栏</h3><figure class="highlight yaml"><table><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></pre></td><td class="code"><pre><span class="line"><span class="attr">aside:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">position:</span> <span class="string">right</span></span><br><span class="line">  <span class="attr">card_author:</span></span><br><span class="line">    <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">description:</span> <span class="string">&quot;一句话介绍自己&quot;</span></span><br><span class="line">    <span class="attr">button:</span></span><br><span class="line">      <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">      <span class="attr">icon:</span> <span class="string">fa-solid</span> <span class="string">fa-envelope-open</span></span><br><span class="line">      <span class="attr">text:</span> <span class="string">联系我</span></span><br><span class="line">      <span class="attr">link:</span> <span class="string">mailto:your@email.com</span></span><br><span class="line">  <span class="attr">card_announcement:</span></span><br><span class="line">    <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">content:</span> <span class="string">欢迎来到我的博客</span></span><br><span class="line">  <span class="attr">card_recent_post:</span></span><br><span class="line">    <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">limit:</span> <span class="number">5</span></span><br><span class="line">  <span class="attr">card_categories:</span></span><br><span class="line">    <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">limit:</span> <span class="number">8</span></span><br><span class="line">  <span class="attr">card_tags:</span></span><br><span class="line">    <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">limit:</span> <span class="number">40</span></span><br><span class="line">    <span class="attr">orderby:</span> <span class="string">random</span></span><br><span class="line">  <span class="attr">card_archives:</span></span><br><span class="line">    <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">type:</span> <span class="string">monthly</span></span><br><span class="line">    <span class="attr">limit:</span> <span class="number">8</span></span><br></pre></td></tr></table></figure><h3 id="文章版权声明"><a href="#文章版权声明" class="headerlink" title="文章版权声明"></a>文章版权声明</h3><figure class="highlight yaml"><table><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="attr">post_copyright:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">license:</span> <span class="string">CC</span> <span class="string">BY-NC-SA</span> <span class="number">4.0</span></span><br><span class="line">  <span class="attr">license_url:</span> <span class="string">https://creativecommons.org/licenses/by-nc-sa/4.0/</span></span><br></pre></td></tr></table></figure><h3 id="搜索功能"><a href="#搜索功能" class="headerlink" title="搜索功能"></a>搜索功能</h3><p>需要先安装搜索插件：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-generator-search</span><br></pre></td></tr></table></figure><p>配置：</p><figure class="highlight yaml"><table><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="attr">search:</span></span><br><span class="line">  <span class="attr">use:</span> <span class="string">local_search</span></span><br><span class="line">  <span class="attr">placeholder:</span> <span class="string">搜索文章...</span></span><br><span class="line"></span><br><span class="line"><span class="attr">local_search:</span></span><br><span class="line">  <span class="attr">preload:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">top_n_per_article:</span> <span class="number">1</span></span><br></pre></td></tr></table></figure><h3 id="暗色模式"><a href="#暗色模式" class="headerlink" title="暗色模式"></a>暗色模式</h3><figure class="highlight yaml"><table><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="attr">darkmode:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">button:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">autoChangeMode:</span> <span class="number">2</span> <span class="comment"># 晚 6 点到早 6 点自动切换</span></span><br></pre></td></tr></table></figure><h3 id="图片懒加载"><a href="#图片懒加载" class="headerlink" title="图片懒加载"></a>图片懒加载</h3><p>Butterfly 内置懒加载，无需额外装插件：</p><figure class="highlight yaml"><table><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="attr">lazyload:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">field:</span> <span class="string">site</span></span><br><span class="line">  <span class="attr">blur:</span> <span class="literal">true</span> <span class="comment"># 加载时模糊效果</span></span><br></pre></td></tr></table></figure><h3 id="图片灯箱"><a href="#图片灯箱" class="headerlink" title="图片灯箱"></a>图片灯箱</h3><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">lightbox:</span> <span class="string">fancybox</span> <span class="comment"># fancybox 或 medium_zoom</span></span><br></pre></td></tr></table></figure><h3 id="页脚"><a href="#页脚" class="headerlink" title="页脚"></a>页脚</h3><figure class="highlight yaml"><table><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="attr">footer:</span></span><br><span class="line">  <span class="attr">owner:</span></span><br><span class="line">    <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">since:</span> <span class="number">2024</span></span><br><span class="line">  <span class="attr">custom_text:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">&lt;a</span> <span class="string">href=&quot;https://beian.miit.gov.cn&quot;&gt;&lt;span&gt;你的备案号&lt;/span&gt;&lt;/a&gt;</span></span><br><span class="line">  <span class="attr">copyright:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure><h2 id="创建必要页面"><a href="#创建必要页面" class="headerlink" title="创建必要页面"></a>创建必要页面</h2><p>Butterfly 的导航栏菜单需要手动创建对应页面。</p><h3 id="标签页"><a href="#标签页" class="headerlink" title="标签页"></a>标签页</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo new page tags</span><br></pre></td></tr></table></figure><p>编辑 <code>source/tags/index.md</code>：</p><figure class="highlight markdown"><table><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">title: 标签</span><br><span class="line"><span class="section">type: tags</span></span><br><span class="line"><span class="section">---</span></span><br></pre></td></tr></table></figure><h3 id="分类页"><a href="#分类页" class="headerlink" title="分类页"></a>分类页</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo new page categories</span><br></pre></td></tr></table></figure><p>编辑 <code>source/categories/index.md</code>：</p><figure class="highlight markdown"><table><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">title: 分类</span><br><span class="line"><span class="section">type: categories</span></span><br><span class="line"><span class="section">---</span></span><br></pre></td></tr></table></figure><h3 id="友情链接页"><a href="#友情链接页" class="headerlink" title="友情链接页"></a>友情链接页</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo new page links</span><br></pre></td></tr></table></figure><p>编辑 <code>source/links/index.md</code>：</p><figure class="highlight markdown"><table><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">title: 友链</span><br><span class="line"><span class="section">type: link</span></span><br><span class="line"><span class="section">---</span></span><br></pre></td></tr></table></figure><p>友链数据在 <code>source/_data/link.yml</code> 中配置（需手动创建 <code>_data</code> 目录）：</p><figure class="highlight yaml"><table><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="bullet">-</span> <span class="attr">class_name:</span> <span class="string">友情链接</span></span><br><span class="line">  <span class="attr">class_desc:</span> <span class="string">一些好朋友</span></span><br><span class="line">  <span class="attr">link_list:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">示例博客</span></span><br><span class="line">      <span class="attr">link:</span> <span class="string">https://example.com</span></span><br><span class="line">      <span class="attr">avatar:</span> <span class="string">https://example.com/avatar.jpg</span></span><br><span class="line">      <span class="attr">descr:</span> <span class="string">博客描述</span></span><br></pre></td></tr></table></figure><h3 id="关于页"><a href="#关于页" class="headerlink" title="关于页"></a>关于页</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo new page about</span><br></pre></td></tr></table></figure><p>编辑 <code>source/about/index.md</code>，写上自我介绍即可。</p><h2 id="写作"><a href="#写作" class="headerlink" title="写作"></a>写作</h2><h3 id="新建文章"><a href="#新建文章" class="headerlink" title="新建文章"></a>新建文章</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo new <span class="string">&quot;文章标题&quot;</span></span><br></pre></td></tr></table></figure><p>会在 <code>source/_posts/</code> 下生成 Markdown 文件。</p><h3 id="Front-Matter"><a href="#Front-Matter" class="headerlink" title="Front Matter"></a>Front Matter</h3><p>每篇文章头部的 YAML 配置：</p><figure class="highlight yaml"><table><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="meta">---</span></span><br><span class="line"><span class="attr">title:</span> <span class="string">文章标题</span></span><br><span class="line"><span class="attr">date:</span> <span class="number">2025-01-01 12:00:00</span></span><br><span class="line"><span class="attr">tags:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">标签1</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">标签2</span></span><br><span class="line"><span class="attr">categories:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">分类名</span></span><br><span class="line"><span class="attr">description:</span> <span class="string">文章摘要，用于</span> <span class="string">SEO</span> <span class="string">和首页展示</span></span><br><span class="line"><span class="attr">cover:</span> <span class="string">https://example.com/cover.jpg</span> <span class="comment"># 文章封面图（可选）</span></span><br><span class="line"><span class="meta">---</span></span><br></pre></td></tr></table></figure><h3 id="摘要截断"><a href="#摘要截断" class="headerlink" title="摘要截断"></a>摘要截断</h3><p>在文章中插入 <code>&lt;!-- more --&gt;</code>，首页只显示该标记之前的内容：</p><figure class="highlight markdown"><table><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><br><span class="line"></span><br><span class="line">&lt;!-- more --&gt;</span><br><span class="line"></span><br><span class="line">这里是正文，首页不会显示。</span><br></pre></td></tr></table></figure><h3 id="Butterfly-专属标签"><a href="#Butterfly-专属标签" class="headerlink" title="Butterfly 专属标签"></a>Butterfly 专属标签</h3><p><strong>Note 标签</strong>（提示框）：</p><figure class="highlight markdown"><table><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">&#123;% note success %&#125;</span><br><span class="line">这是一条成功提示</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note warning %&#125;</span><br><span class="line">这是一条警告提示</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note danger %&#125;</span><br><span class="line">这是一条危险提示</span><br><span class="line">&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><p><strong>Tab 标签</strong>（选项卡）：</p><figure class="highlight markdown"><table><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">&#123;% tabs 测试 %&#125;</span><br><span class="line"></span><br><span class="line">&lt;!-- tab 第一个 --&gt;</span><br><span class="line"></span><br><span class="line">第一个选项卡的内容</span><br><span class="line"></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line">&lt;!-- tab 第二个 --&gt;</span><br><span class="line"></span><br><span class="line">第二个选项卡的内容</span><br><span class="line"></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line"></span><br><span class="line">&#123;% endtabs %&#125;</span><br></pre></td></tr></table></figure><p><strong>折叠块</strong>：</p><figure class="highlight markdown"><table><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">&#123;% hideToggle 点击展开 %&#125;</span><br><span class="line">隐藏的内容</span><br><span class="line">&#123;% endhideToggle %&#125;</span><br></pre></td></tr></table></figure><h2 id="常用命令"><a href="#常用命令" class="headerlink" title="常用命令"></a>常用命令</h2><table><thead><tr><th>命令</th><th>作用</th></tr></thead><tbody><tr><td><code>hexo new &quot;标题&quot;</code></td><td>新建文章</td></tr><tr><td><code>hexo new page &quot;页面&quot;</code></td><td>新建页面</td></tr><tr><td><code>hexo g</code></td><td>生成静态文件</td></tr><tr><td><code>hexo s</code></td><td>启动本地预览（默认 4000 端口）</td></tr><tr><td><code>hexo d</code></td><td>部署到远程</td></tr><tr><td><code>hexo clean</code></td><td>清除缓存和已生成的静态文件</td></tr><tr><td><code>hexo clean &amp;&amp; hexo g &amp;&amp; hexo d</code></td><td>清除→生成→部署（最常用）</td></tr></tbody></table><h2 id="推荐插件"><a href="#推荐插件" class="headerlink" title="推荐插件"></a>推荐插件</h2><table><thead><tr><th>插件</th><th>作用</th><th>安装命令</th></tr></thead><tbody><tr><td>hexo-generator-sitemap</td><td>生成 sitemap.xml，利于 SEO</td><td><code>npm i hexo-generator-sitemap</code></td></tr><tr><td>hexo-generator-feed</td><td>生成 RSS 订阅</td><td><code>npm i hexo-generator-feed</code></td></tr><tr><td>hexo-generator-search</td><td>本地搜索</td><td><code>npm i hexo-generator-search</code></td></tr><tr><td>hexo-deployer-ali-oss-extend</td><td>一键部署到阿里云 OSS</td><td><code>npm i hexo-deployer-ali-oss-extend</code></td></tr></tbody></table><p>安装后在 <code>_config.yml</code> 中添加对应配置：</p><figure class="highlight yaml"><table><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="comment"># Sitemap</span></span><br><span class="line"><span class="attr">sitemap:</span></span><br><span class="line">  <span class="attr">path:</span> <span class="string">sitemap.xml</span></span><br><span class="line">  <span class="attr">rel:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># RSS Feed</span></span><br><span class="line"><span class="attr">feed:</span></span><br><span class="line">  <span class="attr">type:</span> <span class="string">atom</span></span><br><span class="line">  <span class="attr">path:</span> <span class="string">atom.xml</span></span><br><span class="line">  <span class="attr">limit:</span> <span class="number">20</span></span><br></pre></td></tr></table></figure><h2 id="部署到阿里云-OSS"><a href="#部署到阿里云-OSS" class="headerlink" title="部署到阿里云 OSS"></a>部署到阿里云 OSS</h2><p>详见：<a href="/2025/01/11/hexo-deploy-aliyun-oss/">Hexo 静态网站托管阿里云 OSS</a></p><p>简要步骤：</p><ol><li>安装部署插件：<code>npm i hexo-deployer-ali-oss-extend</code></li><li>在 <code>_config.yml</code> 中配置 OSS 信息：</li></ol><figure class="highlight yaml"><table><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="attr">deploy:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">type:</span> <span class="string">ali-oss</span></span><br><span class="line">    <span class="attr">region:</span> <span class="string">oss-cn-shanghai</span></span><br><span class="line">    <span class="attr">accessKeyId:</span> <span class="string">$&#123;ALI_OSS_KEY&#125;</span></span><br><span class="line">    <span class="attr">accessKeySecret:</span> <span class="string">$&#123;ALI_OSS_SECRET&#125;</span></span><br><span class="line">    <span class="attr">bucket:</span> <span class="string">your-bucket-name</span></span><br><span class="line">    <span class="attr">cacheControl:</span></span><br><span class="line">      <span class="attr">images:</span> <span class="string">public,</span> <span class="string">max-age=31536000</span></span><br><span class="line">      <span class="attr">css:</span> <span class="string">public,</span> <span class="string">max-age=604800</span></span><br><span class="line">      <span class="attr">js:</span> <span class="string">public,</span> <span class="string">max-age=86400</span></span><br><span class="line">      <span class="attr">html:</span> <span class="literal">no</span><span class="string">-cache</span></span><br><span class="line">      <span class="attr">other:</span> <span class="literal">no</span><span class="string">-cache</span></span><br></pre></td></tr></table></figure><ol start="3"><li>执行部署：<code>hexo clean &amp;&amp; hexo g &amp;&amp; hexo d</code></li></ol><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><h3 id="hexo-g-报错找不到主题"><a href="#hexo-g-报错找不到主题" class="headerlink" title="hexo g 报错找不到主题"></a>hexo g 报错找不到主题</h3><p>确认 <code>_config.yml</code> 中 <code>theme: butterfly</code>，并且已通过 npm 安装或 <code>themes/</code> 目录下存在主题文件。</p><h3 id="修改配置后不生效"><a href="#修改配置后不生效" class="headerlink" title="修改配置后不生效"></a>修改配置后不生效</h3><p>先清除缓存再重新生成：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo clean &amp;&amp; hexo g</span><br></pre></td></tr></table></figure><h3 id="图片不显示"><a href="#图片不显示" class="headerlink" title="图片不显示"></a>图片不显示</h3><p>检查图片路径。推荐使用图床（如阿里云 OSS + PicGo），在 Markdown 中直接使用远程 URL，避免本地路径问题。</p><h3 id="部署后页面空白"><a href="#部署后页面空白" class="headerlink" title="部署后页面空白"></a>部署后页面空白</h3><p>检查 OSS 的静态页面功能是否开启，默认首页是否设为 <code>index.html</code>，子目录首页是否开通。</p>]]>
    </content>
    <id>https://lbq08.cc/2025/01/12/hexo-butterfly-guide/</id>
    <link href="https://lbq08.cc/2025/01/12/hexo-butterfly-guide/"/>
    <published>2025-01-11T16:00:00.000Z</published>
    <summary>从零搭建 Hexo 博客并配置 Butterfly 主题，涵盖环境安装、主题配置、写作技巧、常用命令及部署上线全流程。</summary>
    <title>Hexo + Butterfly 主题搭建与使用指南</title>
    <updated>2026-04-11T14:21:48.830Z</updated>
  </entry>
  <entry>
    <author>
      <name>liu</name>
    </author>
    <category term="工具使用" scheme="https://lbq08.cc/categories/%E5%B7%A5%E5%85%B7%E4%BD%BF%E7%94%A8/"/>
    <category term="c" scheme="https://lbq08.cc/tags/c/"/>
    <category term="编码规范" scheme="https://lbq08.cc/tags/%E7%BC%96%E7%A0%81%E8%A7%84%E8%8C%83/"/>
    <content>
      <![CDATA[<p>分享一下我的 clang-format 配置，主要针对嵌入式 C&#x2F;C++ 项目进行了优化，注重代码可读性和一致性，同时适度限制行宽以提升代码审查体验。配置涵盖了大括号风格、参数换行、对齐规则、空格使用、Tab 和行尾符等多个方面，旨在形成一个清晰、统一的代码风格规范。</p><span id="more"></span><h2 id="我的主要要求"><a href="#我的主要要求" class="headerlink" title="我的主要要求"></a>我的主要要求</h2><p>1 行宽限制为可以半个屏幕显示完全,这样优化分屏显示<br>2 使用Allman风格的大括号,单独占一行,优化阅读体验<br>3 对Include的头文件排序<br>4 永不使用Tab字符，统一使用四个空格缩进<br>5 函数参数分行显示,禁止装箱,提升代码审查体验<br>6 统一的空格和对齐规则,提升代码一致性和可读性</p><h2 id="配置说明"><a href="#配置说明" class="headerlink" title="配置说明"></a>配置说明</h2><h2 id="🔧-基本语言配置"><a href="#🔧-基本语言配置" class="headerlink" title="🔧 基本语言配置"></a>🔧 基本语言配置</h2><table><thead><tr><th>配置项</th><th>当前值</th><th>说明</th><th>效果</th></tr></thead><tbody><tr><td><code>Language</code></td><td><code>Cpp</code></td><td>语言类型，也适用于C语言</td><td>使用C++&#x2F;C语言的格式化规则</td></tr><tr><td><code>Standard</code></td><td><code>Latest</code></td><td>使用最新的语言标准</td><td>支持最新的语法特性格式化</td></tr><tr><td><code>ColumnLimit</code></td><td><code>120</code></td><td>每行最大字符数</td><td>超过100字符自动换行</td></tr></tbody></table><h2 id="📐-对齐配置"><a href="#📐-对齐配置" class="headerlink" title="📐 对齐配置"></a>📐 对齐配置</h2><table><thead><tr><th>配置项</th><th>当前值</th><th>说明</th><th>示例</th></tr></thead><tbody><tr><td><code>AccessModifierOffset</code></td><td><code>-2</code></td><td>访问修饰符缩进</td><td><code>public:</code> 相对类缩进-2个空格</td></tr><tr><td><code>AlignAfterOpenBracket</code></td><td><code>Align</code></td><td>开括号后内容对齐</td><td>参数与开括号对齐</td></tr><tr><td><code>AlignConsecutiveAssignments</code></td><td><code>true</code></td><td>连续赋值语句对齐</td><td><code>=</code> 号垂直对齐</td></tr><tr><td><code>AlignConsecutiveDeclarations</code></td><td><code>true</code></td><td>连续变量声明对齐</td><td>变量名垂直对齐</td></tr><tr><td><code>AlignConsecutiveMacros</code></td><td><code>true</code></td><td>连续宏定义对齐</td><td>宏名垂直对齐</td></tr><tr><td><code>AlignEscapedNewlines</code></td><td><code>Left</code></td><td>续行反斜杠对齐方式</td><td>反斜杠左对齐</td></tr><tr><td><code>AlignOperands</code></td><td><code>true</code></td><td>操作数对齐</td><td>多行表达式操作数对齐</td></tr><tr><td><code>AlignTrailingComments</code></td><td><code>true</code></td><td>尾随注释对齐</td><td>行尾注释垂直对齐</td></tr></tbody></table><h3 id="对齐效果示例"><a href="#对齐效果示例" class="headerlink" title="对齐效果示例"></a>对齐效果示例</h3><p><strong>连续赋值对齐：</strong></p><figure class="highlight c"><table><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">// AlignConsecutiveAssignments: true</span></span><br><span class="line"><span class="type">int</span>    x     = <span class="number">10</span>;</span><br><span class="line"><span class="type">double</span> value = <span class="number">3.14</span>;</span><br><span class="line"><span class="type">char</span>  *name  = <span class="string">&quot;test&quot;</span>;</span><br></pre></td></tr></table></figure><p><strong>连续声明对齐：</strong></p><figure class="highlight c"><table><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">// AlignConsecutiveDeclarations: true</span></span><br><span class="line"><span class="type">int</span>        count;</span><br><span class="line"><span class="type">double</span>     ratio;</span><br><span class="line">Button_t  *button;</span><br></pre></td></tr></table></figure><h2 id="🚫-单行限制配置"><a href="#🚫-单行限制配置" class="headerlink" title="🚫 单行限制配置"></a>🚫 单行限制配置</h2><table><thead><tr><th>配置项</th><th>当前值</th><th>说明</th><th>效果</th></tr></thead><tbody><tr><td><code>AllowShortBlocksOnASingleLine</code></td><td><code>Never</code></td><td>禁止短代码块单行</td><td><code>if (x) { y = 1; }</code> → 必须换行</td></tr><tr><td><code>AllowShortCaseLabelsOnASingleLine</code></td><td><code>false</code></td><td>禁止短case标签单行</td><td>case语句必须换行</td></tr><tr><td><code>AllowShortFunctionsOnASingleLine</code></td><td><code>None</code></td><td>禁止短函数单行</td><td>所有函数都必须换行</td></tr><tr><td><code>AllowShortIfStatementsOnASingleLine</code></td><td><code>Never</code></td><td>禁止短if语句单行</td><td>if语句必须换行</td></tr><tr><td><code>AllowShortLoopsOnASingleLine</code></td><td><code>false</code></td><td>禁止短循环单行</td><td>for&#x2F;while循环必须换行</td></tr></tbody></table><h3 id="单行限制示例"><a href="#单行限制示例" class="headerlink" title="单行限制示例"></a>单行限制示例</h3><p><strong>禁止短if语句单行：</strong></p><figure class="highlight c"><table><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">// AllowShortIfStatementsOnASingleLine: Never</span></span><br><span class="line"><span class="comment">// 错误格式：</span></span><br><span class="line"><span class="comment">// if (condition) action();</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 正确格式：</span></span><br><span class="line"><span class="keyword">if</span> (condition)</span><br><span class="line">&#123;</span><br><span class="line">    action();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="🔄-换行配置"><a href="#🔄-换行配置" class="headerlink" title="🔄 换行配置"></a>🔄 换行配置</h2><table><thead><tr><th>配置项</th><th>当前值</th><th>说明</th><th>效果</th></tr></thead><tbody><tr><td><code>AlwaysBreakAfterDefinitionReturnType</code></td><td><code>None</code></td><td>函数定义返回类型换行</td><td>返回类型和函数名同行</td></tr><tr><td><code>AlwaysBreakAfterReturnType</code></td><td><code>None</code></td><td>函数声明返回类型换行</td><td>返回类型和函数名同行</td></tr><tr><td><code>AlwaysBreakBeforeMultilineStrings</code></td><td><code>false</code></td><td>多行字符串前不换行</td><td>字符串紧跟赋值符</td></tr><tr><td><code>BreakBeforeBraces</code></td><td><code>Allman</code></td><td>大括号换行风格</td><td>大括号独占一行</td></tr><tr><td><code>BreakBeforeBinaryOperators</code></td><td><code>None</code></td><td>二元运算符换行位置</td><td>运算符在行末</td></tr><tr><td><code>BreakBeforeTernaryOperators</code></td><td><code>false</code></td><td>三元运算符换行位置</td><td><code>?</code> 和 <code>:</code> 在行末</td></tr><tr><td><code>BreakStringLiterals</code></td><td><code>true</code></td><td>允许字符串字面量换行</td><td>长字符串可以换行</td></tr></tbody></table><h3 id="大括号风格示例"><a href="#大括号风格示例" class="headerlink" title="大括号风格示例"></a>大括号风格示例</h3><p><strong>Allman 风格：</strong></p><figure class="highlight c"><table><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">// BreakBeforeBraces: Allman</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">function</span><span class="params">()</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">if</span> (condition)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="comment">// 代码</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="📦-参数和装箱配置"><a href="#📦-参数和装箱配置" class="headerlink" title="📦 参数和装箱配置"></a>📦 参数和装箱配置</h2><table><thead><tr><th>配置项</th><th>当前值</th><th>说明</th><th>效果</th></tr></thead><tbody><tr><td><code>AllowAllArgumentsOnNextLine</code></td><td><code>false</code></td><td>禁止所有参数换到下一行</td><td>参数分行显示</td></tr><tr><td><code>AllowAllParametersOfDeclarationOnNextLine</code></td><td><code>false</code></td><td>禁止所有参数换到下一行</td><td>函数参数分行显示</td></tr><tr><td><code>BinPackArguments</code></td><td><code>false</code></td><td>禁止参数装箱</td><td>每个参数独占一行</td></tr><tr><td><code>BinPackParameters</code></td><td><code>false</code></td><td>禁止参数装箱</td><td>每个参数独占一行</td></tr></tbody></table><h3 id="参数格式化示例"><a href="#参数格式化示例" class="headerlink" title="参数格式化示例"></a>参数格式化示例</h3><p><strong>禁止参数装箱效果：</strong></p><figure class="highlight c"><table><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">// BinPackArguments: false</span></span><br><span class="line">function_call(</span><br><span class="line">    argument1,</span><br><span class="line">    argument2,</span><br><span class="line">    argument3</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">// function_call(argument1, argument2, argument3);</span></span><br></pre></td></tr></table></figure><h2 id="🔤-缩进配置"><a href="#🔤-缩进配置" class="headerlink" title="🔤 缩进配置"></a>🔤 缩进配置</h2><table><thead><tr><th>配置项</th><th>当前值</th><th>说明</th><th>效果</th></tr></thead><tbody><tr><td><code>IndentWidth</code></td><td><code>4</code></td><td>缩进宽度</td><td>使用4个空格缩进</td></tr><tr><td><code>IndentCaseLabels</code></td><td><code>true</code></td><td>case标签缩进</td><td>case相对switch缩进</td></tr><tr><td><code>IndentWrappedFunctionNames</code></td><td><code>true</code></td><td>换行函数名缩进</td><td>换行的函数名缩进</td></tr><tr><td><code>TabWidth</code></td><td><code>4</code></td><td>Tab宽度</td><td>Tab等于4个空格</td></tr><tr><td><code>UseTab</code></td><td><code>Never</code></td><td>不使用Tab</td><td>始终使用空格</td></tr></tbody></table><h2 id="💰-换行惩罚权重"><a href="#💰-换行惩罚权重" class="headerlink" title="💰 换行惩罚权重"></a>💰 换行惩罚权重</h2><table><thead><tr><th>配置项</th><th>当前值</th><th>说明</th><th>作用</th></tr></thead><tbody><tr><td><code>PenaltyBreakBeforeFirstParameter</code></td><td><code>5</code></td><td>函数定义换行惩罚</td><td>降低函数参数换行倾向</td></tr><tr><td><code>PenaltyBreakBeforeFirstCallParameter</code></td><td><code>5</code></td><td>函数调用换行惩罚</td><td>降低函数调用换行倾向</td></tr><tr><td><code>PenaltyBreakAssignment</code></td><td><code>10</code></td><td>赋值换行惩罚</td><td>降低赋值运算符换行倾向</td></tr><tr><td><code>PenaltyExcessCharacter</code></td><td><code>100</code></td><td>超出字符惩罚</td><td>每个超出字符的惩罚值</td></tr><tr><td><code>PenaltyReturnTypeOnItsOwnLine</code></td><td><code>0</code></td><td>返回类型独行惩罚</td><td>不惩罚返回类型独行</td></tr></tbody></table><h2 id="🔧-其他格式化配置"><a href="#🔧-其他格式化配置" class="headerlink" title="🔧 其他格式化配置"></a>🔧 其他格式化配置</h2><table><thead><tr><th>配置项</th><th>当前值</th><th>说明</th><th>效果</th></tr></thead><tbody><tr><td><code>PointerAlignment</code></td><td><code>Right</code></td><td>指针星号对齐</td><td><code>char *ptr</code> 星号靠近变量名</td></tr><tr><td><code>ReflowComments</code></td><td><code>true</code></td><td>重新格式化注释</td><td>自动调整注释格式</td></tr><tr><td><code>SortIncludes</code></td><td><code>true</code></td><td>排序包含文件</td><td>自动排序#include</td></tr><tr><td><code>MaxEmptyLinesToKeep</code></td><td><code>1</code></td><td>最大空行数</td><td>最多保留1个空行</td></tr><tr><td><code>KeepEmptyLinesAtTheStartOfBlocks</code></td><td><code>false</code></td><td>块开始处不保留空行</td><td><code>{</code> 后不允许空行</td></tr></tbody></table><h2 id="🔺-空格配置"><a href="#🔺-空格配置" class="headerlink" title="🔺 空格配置"></a>🔺 空格配置</h2><table><thead><tr><th>配置项</th><th>当前值</th><th>说明</th><th>示例</th></tr></thead><tbody><tr><td><code>SpaceAfterCStyleCast</code></td><td><code>true</code></td><td>C风格转换后加空格</td><td><code>(int) x</code></td></tr><tr><td><code>SpaceAfterLogicalNot</code></td><td><code>false</code></td><td>逻辑非后不加空格</td><td><code>!condition</code></td></tr><tr><td><code>SpaceBeforeAssignmentOperators</code></td><td><code>true</code></td><td>赋值运算符前加空格</td><td><code>x = y</code></td></tr><tr><td><code>SpaceBeforeParens</code></td><td><code>ControlStatements</code></td><td>控制语句圆括号前加空格</td><td><code>if (condition)</code></td></tr><tr><td><code>SpacesBeforeTrailingComments</code></td><td><code>1</code></td><td>尾随注释前空格数</td><td><code>code; // comment</code></td></tr><tr><td><code>SpacesInParentheses</code></td><td><code>false</code></td><td>圆括号内不加空格</td><td><code>function(arg)</code></td></tr><tr><td><code>SpacesInSquareBrackets</code></td><td><code>false</code></td><td>方括号内不加空格</td><td><code>array[index]</code></td></tr></tbody></table><h2 id="📋-包含文件优先级"><a href="#📋-包含文件优先级" class="headerlink" title="📋 包含文件优先级"></a>📋 包含文件优先级</h2><figure class="highlight yaml"><table><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="attr">IncludeCategories:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">Regex:</span> <span class="string">&#x27;&quot;*PlatformIO.h&quot;&#x27;</span> <span class="comment"># 优先级: -5 (最高)</span></span><br><span class="line">    <span class="attr">Priority:</span> <span class="number">-5</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">Regex:</span> <span class="string">&#x27;&quot;*TextIOTypes.h&quot;&#x27;</span> <span class="comment"># 优先级: -4</span></span><br><span class="line">    <span class="attr">Priority:</span> <span class="number">-4</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">Regex:</span> <span class="string">&quot;&lt;[Ww]indows.h&gt;&quot;</span> <span class="comment"># 优先级: -3</span></span><br><span class="line">    <span class="attr">Priority:</span> <span class="number">-3</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">Regex:</span> <span class="string">&#x27;&lt;*\/.h&gt;&#x27;</span> <span class="comment"># 优先级: -2 (系统头文件)</span></span><br><span class="line">    <span class="attr">Priority:</span> <span class="number">-2</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">Regex:</span> <span class="string">&#x27;&quot;*\/.h&quot;&#x27;</span> <span class="comment"># 优先级: 1 (用户头文件)</span></span><br><span class="line">    <span class="attr">Priority:</span> <span class="number">1</span></span><br></pre></td></tr></table></figure><p><strong>排序效果：</strong></p><figure class="highlight c"><table><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">[[include]] <span class="string">&quot;PlatformIO.h&quot;</span>      <span class="comment">// -5</span></span><br><span class="line">[[include]] <span class="string">&quot;TextIOTypes.h&quot;</span>     <span class="comment">// -4</span></span><br><span class="line">[[include]] &lt;Windows.h&gt;         <span class="comment">// -3</span></span><br><span class="line">[[include]] &lt;stdio.h&gt;           <span class="comment">// -2</span></span><br><span class="line">[[include]] &lt;stdlib.h&gt;          <span class="comment">// -2</span></span><br><span class="line">[[include]] <span class="string">&quot;button.h&quot;</span>          <span class="comment">// 1</span></span><br><span class="line">[[include]] <span class="string">&quot;config.h&quot;</span>          <span class="comment">// 1</span></span><br></pre></td></tr></table></figure><h2 id="🎯-项目适配说明"><a href="#🎯-项目适配说明" class="headerlink" title="🎯 项目适配说明"></a>🎯 项目适配说明</h2><p>当前配置针对<strong>嵌入式C项目</strong>优化：</p><p>✅ <strong>可读性优先</strong>: 大括号独占一行，参数分行显示<br>✅ <strong>一致性</strong>: 自动对齐声明、赋值、注释<br>✅ <strong>紧凑性</strong>: 100列限制，适合代码审查<br>✅ <strong>规范性</strong>: 统一的空格、缩进规则<br>✅ <strong>维护性</strong>: 自动排序包含文件，重新格式化注释</p><p>这套配置确保代码风格统一，提高团队协作效率。</p><h2 id="配置文件内容如下"><a href="#配置文件内容如下" class="headerlink" title="配置文件内容如下"></a>配置文件内容如下</h2><figure class="highlight plaintext"><table><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><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br></pre></td><td class="code"><pre><span class="line"># =============================================================================</span><br><span class="line"># clang-format 配置文件 - 针对嵌入式C/C++项目优化</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><span class="line"></span><br><span class="line">Language: Cpp # 指定语言类型，Cpp格式规则同样适用于C语言</span><br><span class="line"></span><br><span class="line">Standard: Latest # 使用最新的C++标准，支持现代语法特性,如果只是c语言可与忽略</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><span class="line">ColumnLimit: 120 # 每行最大字符数，超过后自动换行，适合嵌入式开发和代码审查</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><span class="line"># =============================================================================</span><br><span class="line"></span><br><span class="line">## 延续的行的缩进宽度</span><br><span class="line"></span><br><span class="line">ContinuationIndentWidth: 4 # 续行缩进4个空格，保持与基础缩进一致</span><br><span class="line"></span><br><span class="line">## 访问修饰符配置</span><br><span class="line"></span><br><span class="line">AccessModifierOffset: -2 # public:/private: 相对于class缩进-2个空格</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><span class="line">AlignAfterOpenBracket: Align # 函数参数与开括号对齐，提升参数列表可读性</span><br><span class="line"></span><br><span class="line">AlignConsecutiveAssignments:</span><br><span class="line"></span><br><span class="line">  true # 连续赋值语句的等号垂直对齐，如:</span><br><span class="line"></span><br><span class="line">  # int    x = 1;</span><br><span class="line"></span><br><span class="line">  # double y = 2.0;</span><br><span class="line"></span><br><span class="line">AlignConsecutiveDeclarations: true # 连续变量声明的变量名垂直对齐，统一声明格式</span><br><span class="line"></span><br><span class="line">AlignConsecutiveMacros: true # 连续宏定义的宏名垂直对齐，便于宏管理</span><br><span class="line"></span><br><span class="line">AlignEscapedNewlines: Left # 多行宏定义的反斜杠左对齐</span><br><span class="line"></span><br><span class="line">AlignOperands: true # 多行表达式中操作数对齐，提升复杂表达式可读性</span><br><span class="line"></span><br><span class="line">AlignTrailingComments: true # 行尾注释垂直对齐，形成整齐的注释列</span><br><span class="line"></span><br><span class="line">AlignArrayOfStructures: Right # 结构体数组对齐</span><br><span class="line"></span><br><span class="line">AlignConsecutiveBitFields: true # 位域对齐声明</span><br><span class="line"></span><br><span class="line">[[Clang11]]: AlignConsecutiveBitFields: true  # Clang 11+: 对齐连续位域声明</span><br><span class="line"></span><br><span class="line">[[Clang11]]: AlignAfterOperator                # Clang 11+: 操作符后对齐</span><br><span class="line"></span><br><span class="line">## 函数返回类型换行配置</span><br><span class="line"></span><br><span class="line">AlwaysBreakAfterDefinitionReturnType:</span><br><span class="line"></span><br><span class="line">  None # 函数定义的返回类型与函数名保持同行</span><br><span class="line"></span><br><span class="line">  # None: int function() &#123;&#125;</span><br><span class="line"></span><br><span class="line">  # All:  int</span><br><span class="line">  #       function() &#123;&#125;</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><span class="line"></span><br><span class="line"></span><br><span class="line">## 参数换行限制</span><br><span class="line"></span><br><span class="line">AllowAllArgumentsOnNextLine: false # 禁止函数调用参数全部换到下一行</span><br><span class="line"></span><br><span class="line">AllowAllConstructorInitializersOnNextLine: false # 禁止构造函数初始化列表全部换行</span><br><span class="line"></span><br><span class="line">AllowAllParametersOfDeclarationOnNextLine: false # 禁止函数声明参数全部换到下一行</span><br><span class="line"></span><br><span class="line">## 单行代码控制 - 提升代码可读性</span><br><span class="line"></span><br><span class="line">AllowShortBlocksOnASingleLine: Never # 禁止短代码块单行: if(x)&#123; y=1; &#125; → 必须换行</span><br><span class="line"></span><br><span class="line">AllowShortCaseLabelsOnASingleLine: false # 禁止短case标签单行: case 1: break; → 必须换行</span><br><span class="line"></span><br><span class="line">AllowShortFunctionsOnASingleLine: None # 禁止短函数单行: void f()&#123;&#125; → 必须换行</span><br><span class="line"></span><br><span class="line">AllowShortIfStatementsOnASingleLine: Never # 禁止短if语句单行: if(x) y=1; → 必须换行</span><br><span class="line"></span><br><span class="line">AllowShortLambdasOnASingleLine: None # 禁止短lambda单行，C++项目适用</span><br><span class="line"></span><br><span class="line">AllowShortLoopsOnASingleLine: false # 禁止短循环单行: for(i=0;i&lt;10;i++) &#123;&#125; → 必须换行</span><br><span class="line"></span><br><span class="line">AllowShortEnumsOnASingleLine: false # 枚举不允许单行</span><br><span class="line"></span><br><span class="line">InsertBraces: true</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">[[Clang11]]: AllowShortEnumsOnASingleLine: false  # Clang 11+: 禁止短枚举单行</span><br><span class="line">AlwaysBreakAfterReturnType: None # 函数声明返回类型与函数名保持同行</span><br><span class="line">AlwaysBreakBeforeMultilineStrings: false # 多行字符串前不强制换行，保持紧凑</span><br><span class="line">AlwaysBreakTemplateDeclarations: Yes # 模板声明强制换行，提升模板可读性</span><br><span class="line"></span><br><span class="line">## 参数装箱控制 - 优化代码审查体验</span><br><span class="line"></span><br><span class="line">BinPackArguments:</span><br><span class="line"></span><br><span class="line">  true # 禁止函数调用参数装箱，每个参数独占一行</span><br><span class="line"></span><br><span class="line">  # function(arg1, arg2, arg3) →</span><br><span class="line"></span><br><span class="line">  # function(</span><br><span class="line">  #     arg1,</span><br><span class="line">  #     arg2,</span><br><span class="line">  #     arg3</span><br><span class="line">  # )</span><br><span class="line"></span><br><span class="line">BinPackParameters: false # 禁止函数声明参数装箱，便于参数管理和代码审查</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><span class="line"></span><br><span class="line"></span><br><span class="line">BreakBeforeBraces:</span><br><span class="line"></span><br><span class="line">  Allman # 大括号风格: Allman (独占一行)</span><br><span class="line"></span><br><span class="line">  # void function()</span><br><span class="line">  # &#123;</span><br><span class="line">  #     if (condition)</span><br><span class="line">  #     &#123;</span><br><span class="line">  #         // code</span><br><span class="line">  #     &#125;</span><br><span class="line">  # &#125;</span><br><span class="line"></span><br><span class="line">BreakBeforeBinaryOperators: None # 二元运算符换行: 运算符放在行末而非行首</span><br><span class="line"></span><br><span class="line">BreakBeforeTernaryOperators: false # 三元运算符?: 和 : 放在行末</span><br><span class="line"></span><br><span class="line">BreakConstructorInitializers: AfterColon # 构造函数初始化列表在冒号后换行</span><br><span class="line"></span><br><span class="line">BreakInheritanceList: AfterColon # 继承列表在冒号后换行</span><br><span class="line"></span><br><span class="line">BreakStringLiterals: true # 允许长字符串字面量自动换行</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"># C++特性和命名空间配置</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">CompactNamespaces: true # 压缩嵌套命名空间声明</span><br><span class="line"></span><br><span class="line">Cpp11BracedListStyle: true # 使用C++11大括号初始化列表风格</span><br><span class="line"></span><br><span class="line">DeriveLineEnding: false # 不自动检测行尾符，使用配置的UseCRLF设置</span><br><span class="line"></span><br><span class="line">DerivePointerAlignment: false # 不自动检测指针对齐，使用配置的PointerAlignment</span><br><span class="line"></span><br><span class="line">FixNamespaceComments: true # 自动修复命名空间结束注释</span><br><span class="line"></span><br><span class="line">IncludeBlocks: Merge</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><span class="line"># =============================================================================</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">IndentCaseLabels: true # case标签相对于switch缩进</span><br><span class="line"></span><br><span class="line">IndentPPDirectives: None # 预处理指令不缩进 (#include, [[define等]])</span><br><span class="line"></span><br><span class="line">IndentWidth: 4 # 基础缩进宽度: 4个空格</span><br><span class="line"></span><br><span class="line">IndentWrappedFunctionNames: true # 换行的函数名进行缩进</span><br><span class="line"></span><br><span class="line">[[Clang11]]: IndentCaseBlocks:  true   # Clang 11+: case块缩进</span><br><span class="line"></span><br><span class="line">[[Clang11]]: IndentExternBlock: true   # Clang 11+: extern &quot;C&quot; 块缩进</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><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><span class="line"></span><br><span class="line">PenaltyBreakBeforeFirstParameter: 5 # 函数定义第一参数前换行惩罚(较低,容易换行)</span><br><span class="line"></span><br><span class="line">PenaltyBreakBeforeFirstCallParameter: 5 # 函数调用第一参数前换行惩罚(较低,容易换行)</span><br><span class="line"></span><br><span class="line">PenaltyBreakAssignment: 10 # 赋值运算符处换行惩罚(中等,适度换行)</span><br><span class="line"></span><br><span class="line">PenaltyExcessCharacter: 100 # 每个超出ColumnLimit的字符惩罚(高,强制换行)</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><span class="line"></span><br><span class="line"></span><br><span class="line">KeepEmptyLinesAtTheStartOfBlocks: false # 代码块开始处不保留空行，保持紧凑</span><br><span class="line"></span><br><span class="line">MaxEmptyLinesToKeep: 1 # 最多保留1个连续空行，避免过多空白</span><br><span class="line"></span><br><span class="line">NamespaceIndentation: All # 命名空间内所有内容都缩进</span><br><span class="line"></span><br><span class="line">PenaltyReturnTypeOnItsOwnLine: 0 # 返回类型独占一行无惩罚(允许)</span><br><span class="line"></span><br><span class="line">PointerAlignment: Right # 指针星号靠右对齐: char *ptr (而非 char* ptr)</span><br><span class="line"></span><br><span class="line">ReflowComments: true # 自动重新格式化注释以适应ColumnLimit</span><br><span class="line"></span><br><span class="line">SortIncludes: true # 自动排序#include语句</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><span class="line"># =============================================================================</span><br><span class="line"></span><br><span class="line"># Priority值越小，排序越靠前；负数优先级最高</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">IncludeCategories:</span><br><span class="line"></span><br><span class="line">  - Regex: &#x27;&quot;*PlatformIO.h&quot;&#x27; # PlatformIO框架头文件 (最高优先级)</span><br><span class="line"></span><br><span class="line">    Priority: -5</span><br><span class="line"></span><br><span class="line">  - Regex: &#x27;&quot;*TextIOTypes.h&quot;&#x27; # 文本IO类型头文件</span><br><span class="line"></span><br><span class="line">    Priority: -4</span><br><span class="line"></span><br><span class="line">  - Regex: &quot;&lt;[Ww]indows.h&gt;&quot; # Windows系统头文件</span><br><span class="line"></span><br><span class="line">    Priority: -3</span><br><span class="line"></span><br><span class="line">  - Regex: &#x27;&lt;*\/.h&gt;&#x27; # 其他系统/库头文件 &lt;xxx/yyy.h&gt;</span><br><span class="line"></span><br><span class="line">    Priority: -2</span><br><span class="line"></span><br><span class="line">  - Regex: &#x27;&quot;*\/.h&quot;&#x27; # 项目本地头文件 &quot;xxx/yyy.h&quot;</span><br><span class="line"></span><br><span class="line">    Priority: 1</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">SortUsingDeclarations: true # 自动排序using声明</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><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><span class="line"></span><br><span class="line">SpaceAfterCStyleCast: true # C风格类型转换后加空格: (int) x</span><br><span class="line"></span><br><span class="line">SpaceAfterLogicalNot: false # 逻辑非运算符后不加空格: !condition</span><br><span class="line"></span><br><span class="line">SpaceAfterTemplateKeyword: true # template关键字后加空格</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><span class="line">SpaceBeforeAssignmentOperators: true # 赋值运算符前加空格: x = y</span><br><span class="line"></span><br><span class="line">SpaceBeforeCpp11BracedList: true # C++11大括号初始化前加空格: vector&lt;int&gt; &#123;1,2,3&#125;</span><br><span class="line"></span><br><span class="line">SpaceBeforeCtorInitializerColon: false # 构造函数初始化冒号前不加空格</span><br><span class="line"></span><br><span class="line">SpaceBeforeInheritanceColon: false # 继承冒号前不加空格</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><span class="line">SpaceBeforeParens: ControlStatements # 仅在控制语句圆括号前加空格: if (x) 但 func(x)</span><br><span class="line"></span><br><span class="line">SpaceBeforeRangeBasedForLoopColon: false # 范围for循环冒号前不加空格</span><br><span class="line"></span><br><span class="line">SpaceBeforeSquareBrackets: false # 方括号前不加空格: array[index]</span><br><span class="line"></span><br><span class="line">## 括号内空格控制</span><br><span class="line"></span><br><span class="line">SpaceInEmptyBlock: false # 空代码块内不加空格: &#123;&#125;</span><br><span class="line"></span><br><span class="line">SpaceInEmptyParentheses: false # 空圆括号内不加空格: ()</span><br><span class="line"></span><br><span class="line">SpacesInAngles: false # 模板尖括号内不加空格: &lt;int&gt;</span><br><span class="line"></span><br><span class="line">SpacesInConditionalStatement: false # 条件语句圆括号内不加空格: if(condition)</span><br><span class="line"></span><br><span class="line">SpacesInContainerLiterals: false # 容器字面量内不加空格: &#123;1,2,3&#125;</span><br><span class="line"></span><br><span class="line">SpacesInCStyleCastParentheses: false # C风格转换圆括号内不加空格: (int)</span><br><span class="line"></span><br><span class="line">SpacesInParentheses: false # 圆括号内不加空格: function(arg)</span><br><span class="line"></span><br><span class="line">SpacesInSquareBrackets: false # 方括号内不加空格: array[index]</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><span class="line">SpacesBeforeTrailingComments: 2 # 行尾注释前2个空格: code; // comment</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"># Tab和行尾符配置</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">TabWidth: 4 # Tab等效宽度: 4个空格</span><br><span class="line"></span><br><span class="line">UseCRLF: false # 使用Unix行尾符 (LF)，适合跨平台开发</span><br><span class="line"></span><br><span class="line">UseTab: Never # 永不使用Tab字符，统一使用空格缩进</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><span class="line"></span><br><span class="line"># 本配置针对嵌入式C/C++项目优化，特点:</span><br><span class="line"></span><br><span class="line"># - 可读性优先: Allman大括号风格，参数分行显示</span><br><span class="line"></span><br><span class="line"># - 一致性: 自动对齐声明、赋值、注释</span><br><span class="line"></span><br><span class="line"># - 适度限制: 120列宽度，适合代码审查</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></table></figure>]]>
    </content>
    <id>https://lbq08.cc/2025/01/11/clang%E9%85%8D%E7%BD%AE/</id>
    <link href="https://lbq08.cc/2025/01/11/clang%E9%85%8D%E7%BD%AE/"/>
    <published>2025-01-11T15:49:06.000Z</published>
    <title>嵌入式C/C++项目的 clang-format 配置</title>
    <updated>2026-04-07T11:46:20.577Z</updated>
  </entry>
  <entry>
    <author>
      <name>liu</name>
    </author>
    <category term="工具使用" scheme="https://lbq08.cc/categories/%E5%B7%A5%E5%85%B7%E4%BD%BF%E7%94%A8/"/>
    <category term="Hexo" scheme="https://lbq08.cc/tags/Hexo/"/>
    <category term="阿里云" scheme="https://lbq08.cc/tags/%E9%98%BF%E9%87%8C%E4%BA%91/"/>
    <category term="OSS" scheme="https://lbq08.cc/tags/OSS/"/>
    <category term="静态网站" scheme="https://lbq08.cc/tags/%E9%9D%99%E6%80%81%E7%BD%91%E7%AB%99/"/>
    <content>
      <![CDATA[<p>现在用 Hexo 来搭建静态站点的人越来越多了，很多人会选择使用 GitHub Pages 服务来部署自己的静态站，但 GitHub Pages 国内访问速度实在无法接受，本文介绍一下如何一键使用阿里云 OSS 对象存储服务部署 Hexo 站点，同时解决一个浏览器缓存的坑。</p><span id="more"></span><h2 id="加速方案对比"><a href="#加速方案对比" class="headerlink" title="加速方案对比"></a>加速方案对比</h2><ul><li><strong>Netlify</strong>：与 GitHub 配合使用很方便，但国内访问速度不佳，需要搭配国内 CDN 使用</li><li><strong>Vercel</strong>：与 Netlify 类似，国内访问速度不错，域名没有备案的话是个不错的选择</li><li><strong>对象存储</strong>：使用阿里云 OSS 或类似的对象存储服务，国内访问速度不错，也可搭配国内 CDN 使用，速度最好，但要求你的域名有<strong>备案号</strong></li><li><strong>境内对象存储 + 境外 Vercel&#x2F;Netlify</strong>：我所采用的方案，应该是最佳的方案了</li></ul><h2 id="创建-Bucket"><a href="#创建-Bucket" class="headerlink" title="创建 Bucket"></a>创建 Bucket</h2><p>首先要做的事情就是去 <a href="https://aliyun.com/">阿里云</a> 创建一个 Bucket：</p><p><img src="https://picture0816.oss-cn-shanghai.aliyuncs.com/img/create-bucket.jpg" alt="创建 Bucket 页面"></p><ul><li><strong>Bucket 名称</strong>：随便起，只要不重复就行</li><li><strong>地域</strong>：按你的需求，阿里云的节点国内访问速度都可以。如果你不打算使用 CDN 服务的话，可以选择华东节点，全国访问速度都能兼顾；如果使用 CDN 服务的话，那就没区别了，选哪都行</li><li><strong>存储类型</strong>：一般选择标准存储就可以了，当然如果访问量很小的话，选择低频访问存储也可以，可以省一点钱</li><li><strong>同城冗余存储</strong>：不需要</li><li><strong>版本控制</strong>：不需要</li><li><strong>读写权限</strong>：这里要注意，我们选择<strong>公共读</strong>，切记不能选择私有。一方面如果不开启 CDN 的话，私有权限无法在公网访问；另一方面，如果开启 CDN，阿里云的 CDN 私有回源功能与 OSS 的静态页面功能冲突（别问我是怎么知道的，都是坑）</li><li><strong>服务端加密方式</strong>：无</li><li><strong>实时日志查询</strong>：看需求，有免费 7 天的实时日志查询，但有 900GB&#x2F;天的限制</li><li><strong>定时备份</strong>：不开通</li></ul><h2 id="开启静态页面功能"><a href="#开启静态页面功能" class="headerlink" title="开启静态页面功能"></a>开启静态页面功能</h2><p>进入 Bucket 的配置页面，选择「基础设置 - 静态页面」：</p><p><img src="https://picture0816.oss-cn-shanghai.aliyuncs.com/img/static-page-entry.jpg" alt="静态页面配置入口"></p><p>按照图中的内容进行配置：</p><p><img src="https://picture0816.oss-cn-shanghai.aliyuncs.com/img/static-page-config.jpg" alt="静态页面配置详情"></p><ul><li><strong>默认首页</strong>：<code>index.html</code></li><li><strong>默认 404 页</strong>：<code>404.html</code>（按照你实际的 404 页面地址填写）</li><li><strong>子目录首页</strong>：开通。由于 Hexo 的分类、标签等页面都是子目录的形式（例如 <code>/tags/</code>），如果不开通这个功能，不会自动定位到对应目录的 <code>index.html</code></li><li><strong>文件 404 规则</strong>：Index</li></ul><h2 id="创建-AccessKey-并授权"><a href="#创建-AccessKey-并授权" class="headerlink" title="创建 AccessKey 并授权"></a>创建 AccessKey 并授权</h2><p>其实现在就可以在阿里云的管理页面上传文件部署网站了，但实在是太麻烦，我们希望的是一个自动化的方案。这里我们需要创建一个 API 的授权 AccessKey：</p><p><img src="https://picture0816.oss-cn-shanghai.aliyuncs.com/img/accesskey-entry.jpg" alt="AccessKey 创建入口"></p><p>阿里云现在开启了子账户授权的功能，因此我们可以选择跳转到子账户管理的页面：</p><p><img src="https://picture0816.oss-cn-shanghai.aliyuncs.com/img/sub-account-page.jpg" alt="子账户管理页面"></p><p>首先创建一个子账户：</p><p><img src="https://picture0816.oss-cn-shanghai.aliyuncs.com/img/create-sub-account.jpg" alt="创建子账户"></p><p>这里注意，由于我们这个账户是给 API 使用的，所以必须开启编程访问权限：</p><p><img src="https://picture0816.oss-cn-shanghai.aliyuncs.com/img/enable-api-access.jpg" alt="开启编程访问权限"></p><p>返回以后，点击刚创建的账户右侧的「添加权限」：</p><p><img src="https://picture0816.oss-cn-shanghai.aliyuncs.com/img/add-permission-entry.jpg" alt="添加权限入口"></p><p>这里搜索「OSS」，选择添加 <code>AliyunOSSFullAccess</code> 权限：</p><p><img src="https://picture0816.oss-cn-shanghai.aliyuncs.com/img/add-oss-permission.jpg" alt="添加 OSS 权限"></p><p>返回列表，点击刚创建的账户名称，创建一个 AccessKey。这里要注意，创建完 AccessKey 后会显示一个 AccessKey 和一个 SecretKey，<strong>一定要保存好，只会显示一次</strong>：</p><p><img src="https://picture0816.oss-cn-shanghai.aliyuncs.com/img/create-accesskey.jpg" alt="创建 AccessKey"></p><h2 id="安装一键部署脚本"><a href="#安装一键部署脚本" class="headerlink" title="安装一键部署脚本"></a>安装一键部署脚本</h2><p>我编写了一个可以一键部署 Hexo 到阿里云 OSS 的 Hexo 插件，并支持配置浏览器缓存 HTTP 响应头。</p><blockquote><p>源码地址：<a href="https://github.com/huzhanfei/hexo-deployer-ali-oss-extend">hexo-deployer-ali-oss-extend</a></p></blockquote><p>使用很简单，在 Hexo 项目下执行安装命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i hexo-deployer-ali-oss-extend</span><br></pre></td></tr></table></figure><p>在 Hexo 项目配置文件 <code>_config.yml</code> 中添加如下配置：</p><figure class="highlight yaml"><table><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="attr">deploy:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">type:</span> <span class="string">ali-oss</span></span><br><span class="line">    <span class="attr">region:</span> <span class="string">&quot;&lt;您的 OSS 区域代码&gt;&quot;</span></span><br><span class="line">    <span class="attr">accessKeyId:</span> <span class="string">&quot;&lt;您的 accessKeyId&gt;&quot;</span></span><br><span class="line">    <span class="attr">accessKeySecret:</span> <span class="string">&quot;&lt;您的 accessKeySecret&gt;&quot;</span></span><br><span class="line">    <span class="attr">bucket:</span> <span class="string">&quot;&lt;您的 Bucket 名称&gt;&quot;</span></span><br><span class="line">    <span class="attr">cacheControl:</span></span><br><span class="line">      <span class="attr">images:</span> <span class="string">&quot;&lt;图片文件 Cache-Control，留空为 no-cache&gt;&quot;</span></span><br><span class="line">      <span class="attr">css:</span> <span class="string">&quot;&lt;CSS 文件 Cache-Control，留空为 no-cache&gt;&quot;</span></span><br><span class="line">      <span class="attr">js:</span> <span class="string">&quot;&lt;JS 文件 Cache-Control，留空为 no-cache&gt;&quot;</span></span><br><span class="line">      <span class="attr">html:</span> <span class="string">&quot;&lt;HTML 文件 Cache-Control，留空为 no-cache&gt;&quot;</span></span><br><span class="line">      <span class="attr">other:</span> <span class="string">&quot;&lt;其它文件 Cache-Control，留空为 no-cache&gt;&quot;</span></span><br></pre></td></tr></table></figure><p>其中区域代码，可以在 OSS 的 Bucket 概览当中找到，如下图所示：</p><p><img src="https://picture0816.oss-cn-shanghai.aliyuncs.com/img/region-code.jpg" alt="区域代码位置"></p><p>另外，这里增加 Cache-Control 功能，是由于 OSS 对象存储并没有针对常见的网页文件（如 CSS、JS、图片等）进行默认 HTTP 响应头的设置，这些不常更新的文件不缓存，会导致流量大量浪费。后面如果使用 CDN 的时候，CDN 获取不到缓存配置也会进行不断的回源，产生回源流量浪费。</p><p>配置就这么简单，然后执行部署命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo d</span><br></pre></td></tr></table></figure><p>即可将项目部署到 OSS 中。默认情况下将文件上传到 Bucket 的根目录下，如果需要部署到其他目录，请在 deploy 下添加 <code>remotePath</code> 选项：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">remotePath:</span> <span class="string">&quot;&lt;您要部署的目录&gt;&quot;</span></span><br></pre></td></tr></table></figure><p>当然，如果你使用了 GitHub Actions，可以配置自动执行 <code>hexo d</code>，提交源码的时候自动执行部署脚本，简直不要太方便。具体配置方式不是本文讨论的重点，可自行研究。</p><h2 id="配置自定义域名"><a href="#配置自定义域名" class="headerlink" title="配置自定义域名"></a>配置自定义域名</h2><p>其实做到这一步，就已经可以访问你的网站了。可以在 Bucket 概览页面找到你的访问域名，当然我们大概率需要使用自己的域名访问。如果你的域名已经进行了备案，可以添加自定义域名。</p><p>在「传输管理 - 域名管理」中配置域名：</p><p><img src="https://picture0816.oss-cn-shanghai.aliyuncs.com/img/domain-management.jpg" alt="域名管理页面"></p><p>点击「绑定域名」，在如图所示的内容中填入自己的域名。如果你的域名解析服务器是阿里云的话，可以点击「自动添加 CNAME 记录」快速设置域名解析：</p><p><img src="https://picture0816.oss-cn-shanghai.aliyuncs.com/img/bindcustom-domain.jpg" alt="绑定自定义域名"></p><p>如果你的域名不在阿里云解析的话，请根据页面提示手动设置域名解析。</p>]]>
    </content>
    <id>https://lbq08.cc/2025/01/11/hexo-deploy-aliyun-oss/</id>
    <link href="https://lbq08.cc/2025/01/11/hexo-deploy-aliyun-oss/"/>
    <published>2025-01-11T15:49:06.000Z</published>
    <summary>介绍如何将 Hexo 静态站点一键部署到阿里云 OSS 对象存储，包括 Bucket 创建、静态页面配置、AccessKey 授权、自动化部署脚本及自定义域名绑定。</summary>
    <title>Hexo 静态网站托管阿里云 OSS</title>
    <updated>2026-04-07T10:21:09.019Z</updated>
  </entry>
  <entry>
    <author>
      <name>liu</name>
    </author>
    <category term="编码规范" scheme="https://lbq08.cc/tags/%E7%BC%96%E7%A0%81%E8%A7%84%E8%8C%83/"/>
    <category term="C语言" scheme="https://lbq08.cc/tags/C%E8%AF%AD%E8%A8%80/"/>
    <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><ul><li>代码应该像散文一样易于阅读</li><li>清晰的命名比短小的命名更重要</li><li>一致性胜过个人偏好</li></ul><h3 id="1-2-简洁性"><a href="#1-2-简洁性" class="headerlink" title="1.2 简洁性"></a>1.2 简洁性</h3><ul><li>避免不必要的复杂性</li><li>一个函数只做一件事</li><li>避免过深的嵌套</li></ul><h3 id="1-3-安全性"><a href="#1-3-安全性" class="headerlink" title="1.3 安全性"></a>1.3 安全性</h3><ul><li>检查所有输入参数</li><li>避免缓冲区溢出</li><li>明确处理错误情况</li></ul><hr><h2 id="2-命名约定"><a href="#2-命名约定" class="headerlink" title="2. 命名约定"></a>2. 命名约定</h2><h3 id="2-1-文件命名"><a href="#2-1-文件命名" class="headerlink" title="2.1 文件命名"></a>2.1 文件命名</h3><figure class="highlight c"><table><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">// 源文件使用小写字母和下划线</span></span><br><span class="line">string_utils.c</span><br><span class="line">memory_pool.c</span><br><span class="line">uart_driver.c</span><br><span class="line"></span><br><span class="line"><span class="comment">// 头文件对应</span></span><br><span class="line">string_utils.h</span><br><span class="line">memory_pool.h</span><br><span class="line">uart_driver.h</span><br></pre></td></tr></table></figure><h3 id="2-2-函数命名"><a href="#2-2-函数命名" class="headerlink" title="2.2 函数命名"></a>2.2 函数命名</h3><h4 id="2-2-1-公共函数-snake-case"><a href="#2-2-1-公共函数-snake-case" class="headerlink" title="2.2.1 公共函数 - snake_case"></a>2.2.1 公共函数 - snake_case</h4><figure class="highlight c"><table><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">// 公共API函数使用模块前缀</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">memory_pool_init</span><span class="params">(<span class="type">memory_pool_t</span> *pool, <span class="type">size_t</span> size)</span>;</span><br><span class="line"><span class="type">bool</span> <span class="title function_">string_utils_is_empty</span><span class="params">(<span class="type">const</span> <span class="type">char</span> *str)</span>;</span><br><span class="line"><span class="type">void</span> <span class="title function_">uart_driver_send_data</span><span class="params">(<span class="type">const</span> <span class="type">uint8_t</span> *data, <span class="type">size_t</span> len)</span>;</span><br></pre></td></tr></table></figure><h4 id="2-2-2-静态函数-snake-case-前缀"><a href="#2-2-2-静态函数-snake-case-前缀" class="headerlink" title="2.2.2 静态函数 - snake_case + 前缀"></a>2.2.2 静态函数 - snake_case + 前缀</h4><figure class="highlight c"><table><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">// 静态(私有)函数使用下划线前缀或模块内前缀</span></span><br><span class="line"><span class="type">static</span> <span class="type">bool</span> _validate_parameters(<span class="type">const</span> <span class="type">memory_pool_t</span> *pool);</span><br><span class="line"><span class="type">static</span> <span class="type">void</span> _internal_cleanup(<span class="type">void</span>);</span><br><span class="line"><span class="type">static</span> <span class="type">int</span> <span class="title function_">pool_find_free_block</span><span class="params">(<span class="type">memory_pool_t</span> *pool, <span class="type">size_t</span> size)</span>;</span><br></pre></td></tr></table></figure><h3 id="2-3-变量命名"><a href="#2-3-变量命名" class="headerlink" title="2.3 变量命名"></a>2.3 变量命名</h3><h4 id="2-3-1-局部变量-snake-case"><a href="#2-3-1-局部变量-snake-case" class="headerlink" title="2.3.1 局部变量 - snake_case"></a>2.3.1 局部变量 - snake_case</h4><figure class="highlight c"><table><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> buffer_size;</span><br><span class="line"><span class="type">char</span> *user_name;</span><br><span class="line"><span class="type">bool</span> is_initialized;</span><br><span class="line"><span class="type">size_t</span> total_count;</span><br></pre></td></tr></table></figure><h4 id="2-3-2-全局变量-g-前缀"><a href="#2-3-2-全局变量-g-前缀" class="headerlink" title="2.3.2 全局变量 - g_ 前缀"></a>2.3.2 全局变量 - g_ 前缀</h4><figure class="highlight c"><table><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="type">static</span> <span class="type">int</span> g_instance_count = <span class="number">0</span>;        <span class="comment">// 模块内全局变量</span></span><br><span class="line"><span class="keyword">extern</span> <span class="type">bool</span> g_system_ready;             <span class="comment">// 外部全局变量</span></span><br><span class="line"><span class="type">static</span> <span class="type">memory_pool_t</span> g_default_pool;    <span class="comment">// 静态全局变量</span></span><br></pre></td></tr></table></figure><h4 id="2-3-3-常量-大写字母"><a href="#2-3-3-常量-大写字母" class="headerlink" title="2.3.3 常量 - 大写字母"></a>2.3.3 常量 - 大写字母</h4><figure class="highlight c"><table><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">[[define]] MAX_BUFFER_SIZE     <span class="number">1024</span></span><br><span class="line">[[define]] DEFAULT_TIMEOUT_MS  <span class="number">5000</span></span><br><span class="line"></span><br><span class="line"><span class="type">static</span> <span class="type">const</span> <span class="type">int</span> MAX_RETRY_COUNT = <span class="number">3</span>;</span><br><span class="line"><span class="type">static</span> <span class="type">const</span> <span class="type">char</span>* <span class="type">const</span> ERROR_MESSAGES[] = &#123;...&#125;;</span><br></pre></td></tr></table></figure><h4 id="2-3-4-函数指针"><a href="#2-3-4-函数指针" class="headerlink" title="2.3.4 函数指针"></a>2.3.4 函数指针</h4><figure class="highlight c"><table><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">typedef</span> <span class="title function_">int</span> <span class="params">(*<span class="type">error_handler_t</span>)</span><span class="params">(<span class="type">int</span> error_code)</span>;</span><br><span class="line"><span class="keyword">typedef</span> <span class="title function_">void</span> <span class="params">(*<span class="type">callback_func_t</span>)</span><span class="params">(<span class="type">void</span> *user_data)</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 函数指针变量</span></span><br><span class="line"><span class="type">error_handler_t</span> error_handler;</span><br><span class="line"><span class="type">callback_func_t</span> on_complete_callback;</span><br></pre></td></tr></table></figure><h3 id="2-4-类型命名"><a href="#2-4-类型命名" class="headerlink" title="2.4 类型命名"></a>2.4 类型命名</h3><h4 id="2-4-1-结构体-t-后缀"><a href="#2-4-1-结构体-t-后缀" class="headerlink" title="2.4.1 结构体 - _t 后缀"></a>2.4.1 结构体 - _t 后缀</h4><figure class="highlight c"><table><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">typedef</span> <span class="class"><span class="keyword">struct</span> &#123;</span></span><br><span class="line">    <span class="type">size_t</span> size;</span><br><span class="line">    <span class="type">void</span> *data;</span><br><span class="line">    <span class="type">bool</span> is_valid;</span><br><span class="line">&#125; <span class="type">buffer_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 class="title">memory_pool</span> &#123;</span></span><br><span class="line">    <span class="type">uint8_t</span> *pool_start;</span><br><span class="line">    <span class="type">size_t</span> pool_size;</span><br><span class="line">    <span class="type">size_t</span> used_size;</span><br><span class="line">&#125; <span class="type">memory_pool_t</span>;</span><br></pre></td></tr></table></figure><h4 id="2-4-2-枚举-e-后缀-成员大写"><a href="#2-4-2-枚举-e-后缀-成员大写" class="headerlink" title="2.4.2 枚举 - _e 后缀, 成员大写"></a>2.4.2 枚举 - _e 后缀, 成员大写</h4><figure class="highlight c"><table><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="keyword">typedef</span> <span class="class"><span class="keyword">enum</span> &#123;</span></span><br><span class="line">    STATUS_SUCCESS = <span class="number">0</span>,</span><br><span class="line">    STATUS_ERROR_INVALID_PARAM,</span><br><span class="line">    STATUS_ERROR_NO_MEMORY,</span><br><span class="line">    STATUS_ERROR_TIMEOUT</span><br><span class="line">&#125; status_e;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">enum</span> &#123;</span></span><br><span class="line">    LOG_LEVEL_DEBUG = <span class="number">0</span>,</span><br><span class="line">    LOG_LEVEL_INFO,</span><br><span class="line">    LOG_LEVEL_WARNING,</span><br><span class="line">    LOG_LEVEL_ERROR</span><br><span class="line">&#125; log_level_e;</span><br></pre></td></tr></table></figure><h4 id="2-4-3-联合体-u-后缀"><a href="#2-4-3-联合体-u-后缀" class="headerlink" title="2.4.3 联合体 - _u 后缀"></a>2.4.3 联合体 - _u 后缀</h4><figure class="highlight c"><table><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="keyword">typedef</span> <span class="class"><span class="keyword">union</span> &#123;</span></span><br><span class="line">    <span class="type">uint32_t</span> value;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> &#123;</span></span><br><span class="line">        <span class="type">uint8_t</span> byte0;</span><br><span class="line">        <span class="type">uint8_t</span> byte1;</span><br><span class="line">        <span class="type">uint8_t</span> byte2;</span><br><span class="line">        <span class="type">uint8_t</span> byte3;</span><br><span class="line">    &#125; bytes;</span><br><span class="line">&#125; register_value_u;</span><br></pre></td></tr></table></figure><hr><h2 id="3-代码格式化"><a href="#3-代码格式化" class="headerlink" title="3. 代码格式化"></a>3. 代码格式化</h2><h3 id="3-1-缩进和空格"><a href="#3-1-缩进和空格" class="headerlink" title="3.1 缩进和空格"></a>3.1 缩进和空格</h3><figure class="highlight c"><table><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="comment">// 使用4个空格缩进，不使用Tab</span></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> &#123;</span><br><span class="line">    <span class="keyword">if</span> (condition) &#123;</span><br><span class="line">        do_something();</span><br><span class="line">        <span class="keyword">if</span> (another_condition) &#123;</span><br><span class="line">            do_more_work();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="3-2-大括号风格-K-R风格"><a href="#3-2-大括号风格-K-R风格" class="headerlink" title="3.2 大括号风格 - K&amp;R风格"></a>3.2 大括号风格 - K&amp;R风格</h3><figure class="highlight c"><table><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">// 函数大括号另起一行</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">function_name</span><span class="params">(<span class="type">int</span> param1, <span class="type">char</span> *param2)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">// 控制结构大括号不另起一行</span></span><br><span class="line">    <span class="keyword">if</span> (param1 &gt; <span class="number">0</span>) &#123;</span><br><span class="line">        process_data(param2);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        handle_error();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; param1; i++) &#123;</span><br><span class="line">        work_with_index(i);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="3-3-空行和空格"><a href="#3-3-空行和空格" class="headerlink" title="3.3 空行和空格"></a>3.3 空行和空格</h3><figure class="highlight c"><table><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="type">int</span> <span class="title function_">process_data</span><span class="params">(<span class="type">const</span> <span class="type">char</span> *input)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">// 变量声明后加空行</span></span><br><span class="line">    <span class="type">int</span> result = <span class="number">0</span>;</span><br><span class="line">    <span class="type">char</span> buffer[<span class="number">256</span>];</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 验证输入</span></span><br><span class="line">    <span class="keyword">if</span> (!input) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 处理数据</span></span><br><span class="line">    result = parse_input(input, buffer, <span class="keyword">sizeof</span>(buffer));</span><br><span class="line">    <span class="keyword">if</span> (result &lt; <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 返回结果</span></span><br><span class="line">    <span class="keyword">return</span> finalize_processing(buffer);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 操作符周围加空格</span></span><br><span class="line"><span class="type">int</span> value = (a + b) * c;</span><br><span class="line"><span class="type">bool</span> is_equal = (x == y);</span><br><span class="line">ptr-&gt;field = new_value;</span><br><span class="line"><span class="built_in">array</span>[index] = item;</span><br></pre></td></tr></table></figure><h3 id="3-4-行长度"><a href="#3-4-行长度" class="headerlink" title="3.4 行长度"></a>3.4 行长度</h3><ul><li>每行最多80个字符</li><li>长行适当折断</li></ul><figure class="highlight c"><table><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"><span class="type">int</span> <span class="title function_">very_long_function_name</span><span class="params">(<span class="type">int</span> first_parameter,</span></span><br><span class="line"><span class="params">                           <span class="type">const</span> <span class="type">char</span> *second_parameter,</span></span><br><span class="line"><span class="params">                           <span class="type">bool</span> third_parameter,</span></span><br><span class="line"><span class="params">                           <span class="type">size_t</span> fourth_parameter)</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 函数调用折行</span></span><br><span class="line">result = process_complex_data(input_buffer,</span><br><span class="line">                             buffer_size,</span><br><span class="line">                             &amp;output_buffer,</span><br><span class="line">                             &amp;output_size,</span><br><span class="line">                             processing_flags);</span><br></pre></td></tr></table></figure><hr><h2 id="4-函数设计"><a href="#4-函数设计" class="headerlink" title="4. 函数设计"></a>4. 函数设计</h2><h3 id="4-1-函数长度"><a href="#4-1-函数长度" class="headerlink" title="4.1 函数长度"></a>4.1 函数长度</h3><ul><li>函数应该简短，通常不超过50行</li><li>一个函数只做一件事</li></ul><h3 id="4-2-参数传递"><a href="#4-2-参数传递" class="headerlink" title="4.2 参数传递"></a>4.2 参数传递</h3><figure class="highlight c"><table><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">// 输入参数使用const</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">string_length</span><span class="params">(<span class="type">const</span> <span class="type">char</span> *str)</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 输出参数使用指针</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">get_system_info</span><span class="params">(<span class="type">system_info_t</span> *info)</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 大结构体通过指针传递</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">process_config</span><span class="params">(<span class="type">const</span> <span class="type">config_t</span> *config)</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 布尔返回值的函数命名</span></span><br><span class="line"><span class="type">bool</span> <span class="title function_">is_valid_address</span><span class="params">(<span class="type">const</span> <span class="type">void</span> *addr)</span>;</span><br><span class="line"><span class="type">bool</span> <span class="title function_">has_permission</span><span class="params">(<span class="type">int</span> user_id, <span class="type">int</span> resource_id)</span>;</span><br></pre></td></tr></table></figure><h3 id="4-3-返回值约定"><a href="#4-3-返回值约定" class="headerlink" title="4.3 返回值约定"></a>4.3 返回值约定</h3><figure class="highlight c"><table><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// 错误码返回值 - 0表示成功，负值表示错误</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">memory_pool_alloc</span><span class="params">(<span class="type">memory_pool_t</span> *pool, <span class="type">size_t</span> size, <span class="type">void</span> **ptr)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">if</span> (!pool || !ptr) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">-1</span>;  <span class="comment">// 参数错误</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (size == <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">-2</span>;  <span class="comment">// 无效大小</span></span><br><span class="line">    &#125;</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 class="keyword">return</span> <span class="number">0</span>;  <span class="comment">// 成功</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 布尔返回值</span></span><br><span class="line"><span class="type">bool</span> <span class="title function_">is_memory_available</span><span class="params">(<span class="type">const</span> <span class="type">memory_pool_t</span> *pool, <span class="type">size_t</span> size)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">if</span> (!pool) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> (pool-&gt;free_size &gt;= size);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="5-变量声明"><a href="#5-变量声明" class="headerlink" title="5. 变量声明"></a>5. 变量声明</h2><h3 id="5-1-声明位置"><a href="#5-1-声明位置" class="headerlink" title="5.1 声明位置"></a>5.1 声明位置</h3><figure class="highlight c"><table><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">// 在使用前就近声明</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">process_array</span><span class="params">(<span class="type">int</span> *<span class="built_in">array</span>, <span class="type">size_t</span> count)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">if</span> (!<span class="built_in">array</span> || count == <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 循环变量在循环前声明</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">size_t</span> i = <span class="number">0</span>; i &lt; count; i++) &#123;</span><br><span class="line">        <span class="type">int</span> current_value = <span class="built_in">array</span>[i];  <span class="comment">// 就近声明</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (current_value &lt; <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">-2</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="built_in">array</span>[i] = process_value(current_value);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="5-2-初始化"><a href="#5-2-初始化" class="headerlink" title="5.2 初始化"></a>5.2 初始化</h3><figure class="highlight c"><table><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"><span class="type">int</span> counter = <span class="number">0</span>;</span><br><span class="line"><span class="type">char</span> *buffer = <span class="literal">NULL</span>;</span><br><span class="line"><span class="type">bool</span> is_ready = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 数组初始化</span></span><br><span class="line"><span class="type">int</span> values[<span class="number">5</span>] = &#123;<span class="number">0</span>&#125;;  <span class="comment">// 全部初始化为0</span></span><br><span class="line"><span class="type">char</span> name[<span class="number">32</span>] = &#123;<span class="number">0</span>&#125;;  <span class="comment">// 字符串缓冲区清零</span></span><br></pre></td></tr></table></figure><h3 id="5-3-指针声明"><a href="#5-3-指针声明" class="headerlink" title="5.3 指针声明"></a>5.3 指针声明</h3><figure class="highlight c"><table><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"><span class="type">char</span> *str_ptr;</span><br><span class="line"><span class="type">int</span> *int_ptr;</span><br><span class="line"><span class="type">const</span> <span class="type">char</span> *const_str;</span><br><span class="line"><span class="type">char</span> * <span class="type">const</span> fixed_ptr;</span><br><span class="line"><span class="type">const</span> <span class="type">char</span> * <span class="type">const</span> const_str_const_ptr;</span><br></pre></td></tr></table></figure><hr><h2 id="6-结构体和枚举"><a href="#6-结构体和枚举" class="headerlink" title="6. 结构体和枚举"></a>6. 结构体和枚举</h2><h3 id="6-1-结构体设计"><a href="#6-1-结构体设计" class="headerlink" title="6.1 结构体设计"></a>6.1 结构体设计</h3><figure class="highlight c"><table><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">// 结构体成员对齐考虑</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> &#123;</span></span><br><span class="line">    <span class="type">uint32_t</span> id;         <span class="comment">// 4字节</span></span><br><span class="line">    <span class="type">uint16_t</span> status;     <span class="comment">// 2字节</span></span><br><span class="line">    <span class="type">uint8_t</span> flags;       <span class="comment">// 1字节</span></span><br><span class="line">    <span class="type">uint8_t</span> reserved;    <span class="comment">// 1字节填充，总计8字节</span></span><br><span class="line">    <span class="type">void</span> *data;          <span class="comment">// 指针大小</span></span><br><span class="line">&#125; <span class="type">packet_header_t</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 复杂结构体</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">memory_block</span> &#123;</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">memory_block</span> *<span class="title">next</span>;</span>  <span class="comment">// 链表指针</span></span><br><span class="line">    <span class="type">size_t</span> size;               <span class="comment">// 块大小</span></span><br><span class="line">    <span class="type">bool</span> is_free;              <span class="comment">// 是否空闲</span></span><br><span class="line">    <span class="type">uint8_t</span> data[];           <span class="comment">// 灵活数组成员</span></span><br><span class="line">&#125; <span class="type">memory_block_t</span>;</span><br></pre></td></tr></table></figure><h3 id="6-2-枚举设计"><a href="#6-2-枚举设计" class="headerlink" title="6.2 枚举设计"></a>6.2 枚举设计</h3><figure class="highlight c"><table><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">// 显式指定值</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">enum</span> &#123;</span></span><br><span class="line">    UART_BAUD_9600   = <span class="number">9600</span>,</span><br><span class="line">    UART_BAUD_19200  = <span class="number">19200</span>,</span><br><span class="line">    UART_BAUD_38400  = <span class="number">38400</span>,</span><br><span class="line">    UART_BAUD_115200 = <span class="number">115200</span></span><br><span class="line">&#125; uart_baud_e;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 错误码枚举</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">enum</span> &#123;</span></span><br><span class="line">    ERR_NONE = <span class="number">0</span>,</span><br><span class="line">    ERR_INVALID_PARAM = <span class="number">-1</span>,</span><br><span class="line">    ERR_NO_MEMORY = <span class="number">-2</span>,</span><br><span class="line">    ERR_TIMEOUT = <span class="number">-3</span>,</span><br><span class="line">    ERR_NOT_INITIALIZED = <span class="number">-4</span></span><br><span class="line">&#125; error_code_e;</span><br></pre></td></tr></table></figure><h3 id="6-3-位域"><a href="#6-3-位域" class="headerlink" title="6.3 位域"></a>6.3 位域</h3><figure class="highlight c"><table><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"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> &#123;</span></span><br><span class="line">    <span class="type">unsigned</span> <span class="type">int</span> enable : <span class="number">1</span>;</span><br><span class="line">    <span class="type">unsigned</span> <span class="type">int</span> mode : <span class="number">2</span>;</span><br><span class="line">    <span class="type">unsigned</span> <span class="type">int</span> priority : <span class="number">4</span>;</span><br><span class="line">    <span class="type">unsigned</span> <span class="type">int</span> reserved : <span class="number">25</span>;</span><br><span class="line">&#125; <span class="type">control_register_t</span>;</span><br></pre></td></tr></table></figure><hr><h2 id="7-宏定义"><a href="#7-宏定义" class="headerlink" title="7. 宏定义"></a>7. 宏定义</h2><h3 id="7-1-简单宏"><a href="#7-1-简单宏" class="headerlink" title="7.1 简单宏"></a>7.1 简单宏</h3><figure class="highlight c"><table><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">[[define]] MAX_PATH_LENGTH     <span class="number">260</span></span><br><span class="line">[[define]] PI                  <span class="number">3.14159265359</span></span><br><span class="line">[[define]] NULL_CHECK(ptr)     ((ptr) != <span class="literal">NULL</span>)</span><br></pre></td></tr></table></figure><h3 id="7-2-函数式宏"><a href="#7-2-函数式宏" class="headerlink" title="7.2 函数式宏"></a>7.2 函数式宏</h3><figure class="highlight c"><table><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="comment">// 使用do-while(0)包装</span></span><br><span class="line">[[define]] DEBUG_PRINT(fmt, ...) \</span><br><span class="line">    <span class="keyword">do</span> &#123; \</span><br><span class="line">        <span class="keyword">if</span> (debug_enabled) &#123; \</span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">&quot;[DEBUG] &quot;</span> fmt <span class="string">&quot;\n&quot;</span>, ##__VA_ARGS__); \</span><br><span class="line">        &#125; \</span><br><span class="line">    &#125; <span class="keyword">while</span>(<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 安全的最大/最小值宏</span></span><br><span class="line">[[define]] MAX(a, b)   (((a) &gt; (b)) ? (a) : (b))</span><br><span class="line">[[define]] MIN(a, b)   (((a) &lt; (b)) ? (a) : (b))</span><br><span class="line"></span><br><span class="line"><span class="comment">// 数组大小宏</span></span><br><span class="line">[[define]] ARRAY_SIZE(arr)     (<span class="keyword">sizeof</span>(arr) / <span class="keyword">sizeof</span>((arr)[<span class="number">0</span>]))</span><br></pre></td></tr></table></figure><h3 id="7-3-条件编译"><a href="#7-3-条件编译" class="headerlink" title="7.3 条件编译"></a>7.3 条件编译</h3><figure class="highlight c"><table><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></pre></td><td class="code"><pre><span class="line">[[ifndef]] STRING_UTILS_H</span><br><span class="line">[[define]] STRING_UTILS_H</span><br><span class="line"></span><br><span class="line">[[ifdef]] __cplusplus</span><br><span class="line"><span class="keyword">extern</span> <span class="string">&quot;C&quot;</span> &#123;</span><br><span class="line">[[endif]]</span><br><span class="line"></span><br><span class="line"><span class="comment">// 调试宏</span></span><br><span class="line">[[ifdef]] DEBUG</span><br><span class="line">    [[define]] DBG_ASSERT(expr) \</span><br><span class="line">        <span class="keyword">do</span> &#123; \</span><br><span class="line">            <span class="keyword">if</span> (!(expr)) &#123; \</span><br><span class="line">                <span class="built_in">fprintf</span>(<span class="built_in">stderr</span>, <span class="string">&quot;Assertion failed: %s, file %s, line %d\n&quot;</span>, \</span><br><span class="line">                        [[expr]], __FILE__, __LINE__); \</span><br><span class="line">                <span class="built_in">abort</span>(); \</span><br><span class="line">            &#125; \</span><br><span class="line">        &#125; <span class="keyword">while</span>(<span class="number">0</span>)</span><br><span class="line">[[<span class="keyword">else</span>]]</span><br><span class="line">    [[define]] DBG_ASSERT(expr)  ((<span class="type">void</span>)<span class="number">0</span>)</span><br><span class="line">[[endif]]</span><br><span class="line"></span><br><span class="line">[[ifdef]] __cplusplus</span><br><span class="line">&#125;</span><br><span class="line">[[endif]]</span><br><span class="line"></span><br><span class="line">[[endif]] <span class="comment">/* STRING_UTILS_H */</span></span><br></pre></td></tr></table></figure><hr><h2 id="8-注释规范"><a href="#8-注释规范" class="headerlink" title="8. 注释规范"></a>8. 注释规范</h2><h3 id="8-1-文件头注释"><a href="#8-1-文件头注释" class="headerlink" title="8.1 文件头注释"></a>8.1 文件头注释</h3><figure class="highlight c"><table><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="comment">/**</span></span><br><span class="line"><span class="comment"> * @file    memory_pool.c</span></span><br><span class="line"><span class="comment"> * @brief   内存池管理模块实现</span></span><br><span class="line"><span class="comment"> * @author  Your Name</span></span><br><span class="line"><span class="comment"> * @date    2024-01-01</span></span><br><span class="line"><span class="comment"> * @version 1.0.0</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * @details</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="comment"> * @copyright Copyright (c) 2024 Your Company</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure><h3 id="8-2-函数注释"><a href="#8-2-函数注释" class="headerlink" title="8.2 函数注释"></a>8.2 函数注释</h3><figure class="highlight c"><table><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @brief 初始化内存池</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * @param[in,out] pool      指向内存池结构体的指针</span></span><br><span class="line"><span class="comment"> * @param[in]     buffer    内存缓冲区指针</span></span><br><span class="line"><span class="comment"> * @param[in]     size      缓冲区大小（字节）</span></span><br><span class="line"><span class="comment"> * @param[in]     block_size 单个内存块大小（字节）</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * @return int 错误码</span></span><br><span class="line"><span class="comment"> * @retval  0  成功</span></span><br><span class="line"><span class="comment"> * @retval -1  参数无效</span></span><br><span class="line"><span class="comment"> * @retval -2  缓冲区太小</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * @note</span></span><br><span class="line"><span class="comment"> * - buffer必须是有效的内存地址</span></span><br><span class="line"><span class="comment"> * - size必须能容纳至少一个内存块</span></span><br><span class="line"><span class="comment"> * - block_size必须大于0且4字节对齐</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * @warning 调用此函数后，原缓冲区内容会被清零</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * @example</span></span><br><span class="line"><span class="comment"> * @code</span></span><br><span class="line"><span class="comment"> * static uint8_t buffer[1024];</span></span><br><span class="line"><span class="comment"> * memory_pool_t pool;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * int result = memory_pool_init(&amp;pool, buffer, sizeof(buffer), 64);</span></span><br><span class="line"><span class="comment"> * if (result != 0) &#123;</span></span><br><span class="line"><span class="comment"> *     // 处理错误</span></span><br><span class="line"><span class="comment"> * &#125;</span></span><br><span class="line"><span class="comment"> * @endcode</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">memory_pool_init</span><span class="params">(<span class="type">memory_pool_t</span> *pool,</span></span><br><span class="line"><span class="params">                    <span class="type">void</span> *buffer,</span></span><br><span class="line"><span class="params">                    <span class="type">size_t</span> size,</span></span><br><span class="line"><span class="params">                    <span class="type">size_t</span> block_size)</span>;</span><br></pre></td></tr></table></figure><h3 id="8-3-行内注释"><a href="#8-3-行内注释" class="headerlink" title="8.3 行内注释"></a>8.3 行内注释</h3><figure class="highlight c"><table><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="type">int</span> <span class="title function_">process_data</span><span class="params">(<span class="type">const</span> <span class="type">uint8_t</span> *data, <span class="type">size_t</span> len)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">// 参数验证</span></span><br><span class="line">    <span class="keyword">if</span> (!data || len == <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="type">uint32_t</span> checksum = <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="keyword">for</span> (<span class="type">size_t</span> i = <span class="number">0</span>; i &lt; len; i++) &#123;</span><br><span class="line">        checksum += data[i];        <span class="comment">// 累加每个字节</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    checksum = ~checksum + <span class="number">1</span>;       <span class="comment">// 补码校验和</span></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 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">    [[ifdef]] LITTLE_ENDIAN</span><br><span class="line">    checksum = __builtin_bswap32(checksum);</span><br><span class="line">    [[endif]]</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> (<span class="type">int</span>)checksum;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="8-4-TODO和FIXME"><a href="#8-4-TODO和FIXME" class="headerlink" title="8.4 TODO和FIXME"></a>8.4 TODO和FIXME</h3><figure class="highlight c"><table><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">// <span class="doctag">TODO:</span> 添加更多的错误检查</span></span><br><span class="line"><span class="comment">// <span class="doctag">FIXME:</span> 在多线程环境下可能有竞争条件</span></span><br><span class="line"><span class="comment">// <span class="doctag">HACK:</span> 临时解决方案，需要重构</span></span><br><span class="line"><span class="comment">// <span class="doctag">NOTE:</span> 这个函数的行为在下个版本会改变</span></span><br></pre></td></tr></table></figure><hr><h2 id="9-文件组织"><a href="#9-文件组织" class="headerlink" title="9. 文件组织"></a>9. 文件组织</h2><h3 id="9-1-头文件结构"><a href="#9-1-头文件结构" class="headerlink" title="9.1 头文件结构"></a>9.1 头文件结构</h3><figure class="highlight c"><table><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></pre></td><td class="code"><pre><span class="line">[[ifndef]] MODULE_NAME_H</span><br><span class="line">[[define]] MODULE_NAME_H</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 1. 标准库包含 */</span></span><br><span class="line">[[include]] &lt;stdio.h&gt;</span><br><span class="line">[[include]] &lt;stdlib.h&gt;</span><br><span class="line">[[include]] &lt;<span class="built_in">string</span>.h&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 2. 系统头文件 */</span></span><br><span class="line">[[include]] &lt;sys/types.h&gt;</span><br><span class="line">[[include]] &lt;unistd.h&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 3. 项目头文件 */</span></span><br><span class="line">[[include]] <span class="string">&quot;project_config.h&quot;</span></span><br><span class="line">[[include]] <span class="string">&quot;common_types.h&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 4. 本模块相关头文件 */</span></span><br><span class="line">[[include]] <span class="string">&quot;module_internal.h&quot;</span></span><br><span class="line"></span><br><span class="line">[[ifdef]] __cplusplus</span><br><span class="line"><span class="keyword">extern</span> <span class="string">&quot;C&quot;</span> &#123;</span><br><span class="line">[[endif]]</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 5. 宏定义 */</span></span><br><span class="line">[[define]] MODULE_VERSION      <span class="string">&quot;1.0.0&quot;</span></span><br><span class="line">[[define]] MAX_BUFFER_SIZE     <span class="number">1024</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 6. 类型定义 */</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">module_context</span> <span class="title">module_context_t</span>;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 7. 枚举定义 */</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">enum</span> &#123;</span></span><br><span class="line">    MODULE_STATE_IDLE,</span><br><span class="line">    MODULE_STATE_BUSY,</span><br><span class="line">    MODULE_STATE_ERROR</span><br><span class="line">&#125; module_state_e;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 8. 结构体定义 */</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> &#123;</span></span><br><span class="line">    <span class="type">int</span> id;</span><br><span class="line">    <span class="type">char</span> name[<span class="number">32</span>];</span><br><span class="line">    module_state_e state;</span><br><span class="line">&#125; <span class="type">module_info_t</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 9. 函数声明 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">module_init</span><span class="params">(<span class="type">module_context_t</span> **ctx)</span>;</span><br><span class="line"><span class="type">int</span> <span class="title function_">module_process</span><span class="params">(<span class="type">module_context_t</span> *ctx, <span class="type">const</span> <span class="type">void</span> *input)</span>;</span><br><span class="line"><span class="type">void</span> <span class="title function_">module_cleanup</span><span class="params">(<span class="type">module_context_t</span> *ctx)</span>;</span><br><span class="line"></span><br><span class="line">[[ifdef]] __cplusplus</span><br><span class="line">&#125;</span><br><span class="line">[[endif]]</span><br><span class="line"></span><br><span class="line">[[endif]] <span class="comment">/* MODULE_NAME_H */</span></span><br></pre></td></tr></table></figure><h3 id="9-2-源文件结构"><a href="#9-2-源文件结构" class="headerlink" title="9.2 源文件结构"></a>9.2 源文件结构</h3><figure class="highlight c"><table><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">/* 1. 文件头注释 */</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @file module_name.c</span></span><br><span class="line"><span class="comment"> * @brief 模块实现</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 2. 包含头文件 */</span></span><br><span class="line">[[include]] <span class="string">&quot;module_name.h&quot;</span></span><br><span class="line">[[include]] <span class="string">&quot;module_private.h&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 3. 本地宏定义 */</span></span><br><span class="line">[[define]] INTERNAL_BUFFER_SIZE    <span class="number">256</span></span><br><span class="line">[[define]] RETRY_COUNT             <span class="number">3</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 4. 本地类型定义 */</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> &#123;</span></span><br><span class="line">    <span class="type">uint8_t</span> internal_buffer[INTERNAL_BUFFER_SIZE];</span><br><span class="line">    <span class="type">size_t</span> buffer_used;</span><br><span class="line">    <span class="type">bool</span> is_initialized;</span><br><span class="line">&#125; <span class="type">module_private_t</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 5. 静态变量 */</span></span><br><span class="line"><span class="type">static</span> <span class="type">module_private_t</span> g_module_data = &#123;<span class="number">0</span>&#125;;</span><br><span class="line"><span class="type">static</span> <span class="type">bool</span> g_module_initialized = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 6. 静态函数声明 */</span></span><br><span class="line"><span class="type">static</span> <span class="type">int</span> _validate_input(<span class="type">const</span> <span class="type">void</span> *input);</span><br><span class="line"><span class="type">static</span> <span class="type">void</span> _cleanup_internal_data(<span class="type">void</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 7. 公共函数实现 */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">module_init</span><span class="params">(<span class="type">module_context_t</span> **ctx)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">// 实现...</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 8. 静态函数实现 */</span></span><br><span class="line"><span class="type">static</span> <span class="type">int</span> _validate_input(<span class="type">const</span> <span class="type">void</span> *input)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">// 实现...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="10-错误处理"><a href="#10-错误处理" class="headerlink" title="10. 错误处理"></a>10. 错误处理</h2><h3 id="10-1-错误码定义"><a href="#10-1-错误码定义" class="headerlink" title="10.1 错误码定义"></a>10.1 错误码定义</h3><figure class="highlight c"><table><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="comment">// 错误码枚举</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">enum</span> &#123;</span></span><br><span class="line">    ERR_SUCCESS         = <span class="number">0</span>,    <span class="comment">// 成功</span></span><br><span class="line">    ERR_INVALID_PARAM   = <span class="number">-1</span>,   <span class="comment">// 无效参数</span></span><br><span class="line">    ERR_NULL_POINTER    = <span class="number">-2</span>,   <span class="comment">// 空指针</span></span><br><span class="line">    ERR_NO_MEMORY       = <span class="number">-3</span>,   <span class="comment">// 内存不足</span></span><br><span class="line">    ERR_BUFFER_OVERFLOW = <span class="number">-4</span>,   <span class="comment">// 缓冲区溢出</span></span><br><span class="line">    ERR_TIMEOUT         = <span class="number">-5</span>,   <span class="comment">// 超时</span></span><br><span class="line">    ERR_NOT_FOUND       = <span class="number">-6</span>,   <span class="comment">// 未找到</span></span><br><span class="line">    ERR_ALREADY_EXISTS  = <span class="number">-7</span>,   <span class="comment">// 已存在</span></span><br><span class="line">    ERR_NOT_INITIALIZED = <span class="number">-8</span>,   <span class="comment">// 未初始化</span></span><br><span class="line">    ERR_OPERATION_FAILED = <span class="number">-9</span>   <span class="comment">// 操作失败</span></span><br><span class="line">&#125; error_code_e;</span><br></pre></td></tr></table></figure><h3 id="10-2-参数检查"><a href="#10-2-参数检查" class="headerlink" title="10.2 参数检查"></a>10.2 参数检查</h3><figure class="highlight c"><table><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></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">safe_function</span><span class="params">(<span class="type">const</span> <span class="type">char</span> *input, <span class="type">char</span> *output, <span class="type">size_t</span> output_size)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">// 空指针检查</span></span><br><span class="line">    <span class="keyword">if</span> (!input) &#123;</span><br><span class="line">        <span class="keyword">return</span> ERR_NULL_POINTER;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (!output) &#123;</span><br><span class="line">        <span class="keyword">return</span> ERR_NULL_POINTER;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 参数有效性检查</span></span><br><span class="line">    <span class="keyword">if</span> (output_size == <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> ERR_INVALID_PARAM;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="type">size_t</span> input_len = <span class="built_in">strlen</span>(input);</span><br><span class="line">    <span class="keyword">if</span> (input_len &gt;= output_size) &#123;</span><br><span class="line">        <span class="keyword">return</span> ERR_BUFFER_OVERFLOW;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 执行实际操作</span></span><br><span class="line">    <span class="built_in">strcpy</span>(output, input);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> ERR_SUCCESS;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="10-3-错误传播"><a href="#10-3-错误传播" class="headerlink" title="10.3 错误传播"></a>10.3 错误传播</h3><figure class="highlight c"><table><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"><span class="type">int</span> <span class="title function_">complex_operation</span><span class="params">(<span class="type">const</span> <span class="type">char</span> *file_path, <span class="type">data_t</span> *result)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="type">int</span> error;</span><br><span class="line">    <span class="type">file_handle_t</span> handle;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 打开文件</span></span><br><span class="line">    error = file_open(file_path, &amp;handle);</span><br><span class="line">    <span class="keyword">if</span> (error != ERR_SUCCESS) &#123;</span><br><span class="line">        <span class="keyword">return</span> error;  <span class="comment">// 直接传播错误</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 读取数据</span></span><br><span class="line">    error = file_read(handle, result);</span><br><span class="line">    <span class="keyword">if</span> (error != ERR_SUCCESS) &#123;</span><br><span class="line">        file_close(handle);  <span class="comment">// 清理资源</span></span><br><span class="line">        <span class="keyword">return</span> error;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 关闭文件</span></span><br><span class="line">    error = file_close(handle);</span><br><span class="line">    <span class="keyword">return</span> error;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="11-内存管理"><a href="#11-内存管理" class="headerlink" title="11. 内存管理"></a>11. 内存管理</h2><h3 id="11-1-动态内存分配"><a href="#11-1-动态内存分配" class="headerlink" title="11.1 动态内存分配"></a>11.1 动态内存分配</h3><figure class="highlight c"><table><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// 安全的内存分配</span></span><br><span class="line"><span class="type">void</span>* <span class="title function_">safe_malloc</span><span class="params">(<span class="type">size_t</span> size)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">if</span> (size == <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="type">void</span> *ptr = <span class="built_in">malloc</span>(size);</span><br><span class="line">    <span class="keyword">if</span> (ptr) &#123;</span><br><span class="line">        <span class="built_in">memset</span>(ptr, <span class="number">0</span>, size);  <span class="comment">// 初始化为0</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> ptr;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 安全的内存释放</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">safe_free</span><span class="params">(<span class="type">void</span> **ptr)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">if</span> (ptr &amp;&amp; *ptr) &#123;</span><br><span class="line">        <span class="built_in">free</span>(*ptr);</span><br><span class="line">        *ptr = <span class="literal">NULL</span>;  <span class="comment">// 防止悬空指针</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用示例</span></span><br><span class="line"><span class="type">char</span> *buffer = (<span class="type">char</span>*)safe_malloc(<span class="number">256</span>);</span><br><span class="line"><span class="keyword">if</span> (!buffer) &#123;</span><br><span class="line">    <span class="keyword">return</span> ERR_NO_MEMORY;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用buffer...</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">safe_free((<span class="type">void</span>**)&amp;buffer);  <span class="comment">// buffer将被设置为NULL</span></span><br></pre></td></tr></table></figure><h3 id="11-2-缓冲区安全"><a href="#11-2-缓冲区安全" class="headerlink" title="11.2 缓冲区安全"></a>11.2 缓冲区安全</h3><figure class="highlight c"><table><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="comment">// 安全的字符串复制</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">safe_strcpy</span><span class="params">(<span class="type">char</span> *dest, <span class="type">size_t</span> dest_size, <span class="type">const</span> <span class="type">char</span> *src)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">if</span> (!dest || !src || dest_size == <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> ERR_INVALID_PARAM;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="type">size_t</span> src_len = <span class="built_in">strlen</span>(src);</span><br><span class="line">    <span class="keyword">if</span> (src_len &gt;= dest_size) &#123;</span><br><span class="line">        <span class="keyword">return</span> ERR_BUFFER_OVERFLOW;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">memcpy</span>(dest, src, src_len);</span><br><span class="line">    dest[src_len] = <span class="string">&#x27;\0&#x27;</span>;  <span class="comment">// 确保以null结尾</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> ERR_SUCCESS;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 安全的缓冲区操作</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">safe_append</span><span class="params">(<span class="type">char</span> *buffer, <span class="type">size_t</span> buffer_size, <span class="type">const</span> <span class="type">char</span> *text)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">if</span> (!buffer || !text || buffer_size == <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> ERR_INVALID_PARAM;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="type">size_t</span> current_len = strnlen(buffer, buffer_size);</span><br><span class="line">    <span class="type">size_t</span> text_len = <span class="built_in">strlen</span>(text);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 检查是否有足够空间（包括null终止符）</span></span><br><span class="line">    <span class="keyword">if</span> (current_len + text_len + <span class="number">1</span> &gt; buffer_size) &#123;</span><br><span class="line">        <span class="keyword">return</span> ERR_BUFFER_OVERFLOW;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">strcat</span>(buffer, text);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> ERR_SUCCESS;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="12-最佳实践总结"><a href="#12-最佳实践总结" class="headerlink" title="12. 最佳实践总结"></a>12. 最佳实践总结</h2><h3 id="12-1-代码质量检查清单"><a href="#12-1-代码质量检查清单" class="headerlink" title="12.1 代码质量检查清单"></a>12.1 代码质量检查清单</h3><ul><li><input disabled="" type="checkbox"> 所有函数都有参数检查</li><li><input disabled="" type="checkbox"> 没有硬编码的魔法数字</li><li><input disabled="" type="checkbox"> 所有分配的内存都被释放</li><li><input disabled="" type="checkbox"> 没有悬空指针</li><li><input disabled="" type="checkbox"> 缓冲区边界检查</li><li><input disabled="" type="checkbox"> 错误码正确传播</li><li><input disabled="" type="checkbox"> 函数名清晰表达意图</li><li><input disabled="" type="checkbox"> 注释解释了”为什么”而不只是”做什么”</li></ul><h3 id="12-2-性能考虑"><a href="#12-2-性能考虑" class="headerlink" title="12.2 性能考虑"></a>12.2 性能考虑</h3><ul><li>避免在循环中进行昂贵操作</li><li>合理使用const关键字</li><li>考虑内存对齐</li><li>最小化函数调用开销</li></ul><h3 id="12-3-可维护性"><a href="#12-3-可维护性" class="headerlink" title="12.3 可维护性"></a>12.3 可维护性</h3><ul><li>保持函数简短</li><li>避免深层嵌套</li><li>使用有意义的变量名</li><li>模块化设计</li></ul><h3 id="12-4-可移植性"><a href="#12-4-可移植性" class="headerlink" title="12.4 可移植性"></a>12.4 可移植性</h3><ul><li>避免依赖特定编译器扩展</li><li>使用标准C库函数</li><li>考虑字节序问题</li><li>使用配置宏处理平台差异</li></ul><hr><h2 id="附录：常用工具"><a href="#附录：常用工具" class="headerlink" title="附录：常用工具"></a>附录：常用工具</h2><h3 id="A-1-静态分析工具"><a href="#A-1-静态分析工具" class="headerlink" title="A.1 静态分析工具"></a>A.1 静态分析工具</h3><ul><li><code>cppcheck</code> - 静态代码分析</li><li><code>clang-tidy</code> - 代码质量检查</li><li><code>splint</code> - 代码注释检查</li></ul><h3 id="A-2-格式化工具"><a href="#A-2-格式化工具" class="headerlink" title="A.2 格式化工具"></a>A.2 格式化工具</h3><ul><li><code>clang-format</code> - 自动代码格式化</li><li><code>indent</code> - GNU缩进工具</li></ul><h3 id="A-3-内存检查工具"><a href="#A-3-内存检查工具" class="headerlink" title="A.3 内存检查工具"></a>A.3 内存检查工具</h3><ul><li><code>valgrind</code> - 内存泄漏检测</li><li><code>AddressSanitizer</code> - 地址检查</li><li><code>static analysis</code> - 静态内存分析</li></ul><hr><p><em>本编码规范遵循业界最佳实践，适用于一般性C语言项目开发。</em></p>]]>
    </content>
    <id>https://lbq08.cc/2025/01/02/%E9%80%9A%E7%94%A8c%E8%AF%AD%E8%A8%80%E7%BC%96%E7%A0%81%E8%A7%84%E8%8C%83/</id>
    <link href="https://lbq08.cc/2025/01/02/%E9%80%9A%E7%94%A8c%E8%AF%AD%E8%A8%80%E7%BC%96%E7%A0%81%E8%A7%84%E8%8C%83/"/>
    <published>2025-01-01T16:00:00.000Z</published>
    <summary>
      <![CDATA[<h2 id="1-总体原则"><a href="#1-总体原则" class="headerlink" title="1. 总体原则"></a>1. 总体原则</h2><h3 id="1-1-可读性优先"><a href="#1-1-可读性优先" class="headerli]]>
    </summary>
    <title>通用C语言编码规范</title>
    <updated>2026-04-07T10:54:36.698Z</updated>
  </entry>
  <entry>
    <author>
      <name>liu</name>
    </author>
    <category term="can总线" scheme="https://lbq08.cc/tags/can%E6%80%BB%E7%BA%BF/"/>
    <content>
      <![CDATA[<h1 id="can协议基础（3）-can数据链路层2"><a href="#can协议基础（3）-can数据链路层2" class="headerlink" title="can协议基础（3） -can数据链路层2"></a>can协议基础（3） -can数据链路层2</h1><h2 id="6-位定时器与同步"><a href="#6-位定时器与同步" class="headerlink" title="6 位定时器与同步"></a>6 位定时器与同步</h2><h3 id="6-1位定时"><a href="#6-1位定时" class="headerlink" title="6.1位定时"></a>6.1位定时</h3><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%883%EF%BC%89%20-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%822/image-20241126163601-cbb7s69.png" alt="image"></p><p>CAN时钟是CAN控制器的工作时钟</p><p><span data-type="text" style="color: var(--b3-font-color8);"> </span><em>CAN时钟的一个周期称为时间份额tQ</em><span data-type="text" style="color: var(--b3-font-color8);"> ，它是CAN控制器工作的最小时间单位</span></p><p>在CAN总线控制器中，BTR0（Bit Timing Register 0）是一个用于配置CAN总线位定时参数的寄存器。BTR0通常包含两个主要字段：</p><ol><li><strong>BRP（Baud Rate Prescaler）</strong> ：波特率预分频器，用于设置CAN总线的时钟分频。</li><li><strong>SJW（Synchronization Jump Width）</strong> ：同步跳转宽度，用于调整同步时钟的容忍度。</li></ol><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%883%EF%BC%89%20-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%822/image-20241126163750-1mh7nfv.png" alt="image"></p><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%883%EF%BC%89%20-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%822/image-20241126164119-8oeywo8.png" alt="image"></p><h3 id="6-2-波特率"><a href="#6-2-波特率" class="headerlink" title="6.2 波特率"></a>6.2 波特率</h3><p><strong>1位时长</strong>：若干个tQ组成</p><ul><li>确定位时间，以便确定波特率(位速率)，从而确定总线的网络速度；或在给定总线的网络速度的情况下确定位时间；</li><li>确定1位的各个组成部分——同步段、传播时间段、相位缓冲器段1和相位缓冲器段2的时间长度，其中同步段用于硬同步，位于相位缓冲器段1终点的采样点用于保证正确地读取总线电平；</li><li>确定重同步跳转宽度以用于重同步。</li></ul><p><strong><em>波特率&#x3D;1&#x2F;位时间</em></strong></p><h3 id="6-3-位时间的组成"><a href="#6-3-位时间的组成" class="headerlink" title="6.3 位时间的组成"></a>6.3 位时间的组成</h3><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%883%EF%BC%89%20-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%822/image-20241126164614-mldnsra.png" alt="image"></p><p>(1)一个位时间包含4个功能段，8-25个时间份额组成<br>(2)为方便编程，许多CAN模块将传播段和相位缓冲段1合并为一个时间段，即只有3个时间段<br>(3)采样点时刻读取的电平决定该位是“显性”还是“隐性”</p><p><strong>同步段—Synchronization Segment</strong></p><p>一个位的输出从同步段开始<br>同步段用于同步总线上的各个节点，正常情况下跳变沿落在此段内<br>固定长度，1个时间份额</p><p><strong>传播段—Propagation Segment</strong></p><p>传播段用于补偿信号通过网络和节点传播的物理延迟<br>传播段长度应能保证2倍的信号在总线的延迟<br>长度可编程设置</p><p><strong>相位缓冲段1和2</strong></p><p>允许通过重同步对相位缓冲段1加长和相位缓冲段2缩短的最大长度&#x3D;SJW(同步跳转宽度)<br>SJW长度强制设置</p><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%883%EF%BC%89%20-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%822/image-20241126164824-z6hdnym.png" alt="image"></p><h3 id="6-4-同步"><a href="#6-4-同步" class="headerlink" title="6.4 同步"></a>6.4 同步</h3><p>CAN的同步包括硬同步和重同步两种同步方式<br>同步规则：</p><ul><li>一个位时间内只允许一种同步方式</li><li>任何一个“隐性”到“显性”的跳变都可用于同步</li><li>硬同步发生在SOF的所有接收节点调整各自当前位的同步段，使其位于发送的SOF位内<br>重同步发生在一个帧的其他位场内，当跳变沿落在了同步段之外</li><li>在SOF到仲裁场有多个节点同时发送的情况下，发送节点对跳变沿不进行重同步！</li></ul><p>同步是由节点自身完成的，节点将检测到来自总线的沿与其自身的位定时相比较，并通过硬同步或重同步适配(调整)位定时。在一般情况下，引起硬同步和重同步发生，来自总线的跳变沿如下图所示。</p><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%883%EF%BC%89%20-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%822/image-20241126165018-mokmo3b.png" alt="image"></p><ul><li><strong>硬同步</strong>：<br>所谓硬同步，就是由节点检测到的，来自总线的沿强迫节点立即确定出其内部位时间的起始位置(同步段的起始时刻)。<br>硬同步的结果是，沿到来时刻的前一时刻(以时间份额tQ量度)，即成为节点内部位时间同步段的起始时刻，并使内部位时间从同步段重新开始。</li></ul><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%883%EF%BC%89%20-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%822/image-20241126165109-8s8hjwj.png" alt="image"></p><ul><li>重同步<br>所谓重同步，就是节点根据沿相位误差的大小调整其内部位时间，以使节点内部位时间与来自总线的报文位流的位时间接近或相等。<br>作为重同步的结果，PHASE-SEG1可被延长或PHASE-SEG2可被缩短，从而使节点能够正确地接收报文。<br>重同步一般用于帧的位流发送期间，以补偿各个节点振荡器频率的不一致</li></ul><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%883%EF%BC%89%20-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%822/image-20241126165140-eegregs.png" alt="image"></p><h2 id="7-CAN-控制器"><a href="#7-CAN-控制器" class="headerlink" title="7 CAN 控制器"></a>7 CAN 控制器</h2><p>CAN控制器在系统中的位置</p><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%883%EF%BC%89%20-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%822/image-20241126165158-p6fv3y6.png" alt="image"></p><ul><li><strong>CAN控制器的作用</strong><br>完成CAN规范所规定的数据链路层功能<br>遵循CAN2.0A和CAN2.0B规范<br>通信速率最高1Mbps</li></ul><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%883%EF%BC%89%20-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%822/image-20241126165219-rklga4r.png" alt="image"></p><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%883%EF%BC%89%20-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%822/image-20241126165224-noannir.png" alt="image"></p><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%883%EF%BC%89%20-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%822/image-20241126165228-cv4lzna.png" alt="image"></p>]]>
    </content>
    <id>https://lbq08.cc/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%883%EF%BC%89%20-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%822/</id>
    <link href="https://lbq08.cc/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%883%EF%BC%89%20-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%822/"/>
    <published>2024-11-24T03:04:36.000Z</published>
    <summary>
      <![CDATA[<h1 id="can协议基础（3）-can数据链路层2"><a href="#can协议基础（3）-can数据链路层2" class="headerlink" title="can协议基础（3） -can数据链路层2"></a>can协议基础（3） -can数据链路层2</h1]]>
    </summary>
    <title>can协议基础（3） -can数据链路层2</title>
    <updated>2026-04-11T15:52:06.513Z</updated>
  </entry>
  <entry>
    <author>
      <name>liu</name>
    </author>
    <category term="can总线" scheme="https://lbq08.cc/tags/can%E6%80%BB%E7%BA%BF/"/>
    <content>
      <![CDATA[<h1 id="can协议基础（1）-简要介绍及物理层"><a href="#can协议基础（1）-简要介绍及物理层" class="headerlink" title="can协议基础（1）-简要介绍及物理层"></a>can协议基础（1）-简要介绍及物理层</h1><h1 id="1-介绍"><a href="#1-介绍" class="headerlink" title="1 介绍"></a>1 介绍</h1><h2 id="1-1-can-协议的简要介绍"><a href="#1-1-can-协议的简要介绍" class="headerlink" title="1.1 can 协议的简要介绍"></a>1.1 can 协议的简要介绍</h2><p>CAN 是控制器局域网络 (Controller Area Network) 的简称，它是由研发和生产汽车电子产品著称的德国 BOSCH 公司开发的，并最终成为国际标准(ISO11519 以及 ISO11898),是国际上应用最广泛的现场总线之一。差异点如下：</p><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%881%EF%BC%89-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%8F%8A%E7%89%A9%E7%90%86%E5%B1%82/network-asset-network-asset-1fd78205a7ee9963f625c7986ecf1da2-20240927003307-52cljpu-2-20250314222046-oj48237.png" alt="iso标准"></p><h2 id="1-2-通讯方式"><a href="#1-2-通讯方式" class="headerlink" title="1.2 通讯方式"></a>1.2 通讯方式</h2><p>can 总线通讯方式是串行通迅的一种，与 SPI、IIC 等不同，can 总线的同步并不是以时钟信号来进行同步的，是预先设置好波特率的异步半双工通讯方式，can 总线广泛应用于汽车和工业自动化领域。它允许在没有主机计算机的情况下，多个微控制器和设备之间进行通信。以下是 CAN 总线的一些关键特点：</p><ol><li><strong>多主通信</strong>：CAN 总线允许网络上的任何设备（节点）随时开始通信，采用多主通信方式。</li><li><strong>消息优先级</strong>：当两个或更多节点同时尝试发送消息时，CAN 总线通过标识符的优先级来决定哪个消息具有传输优先权。</li><li><strong>差错检测</strong>：CAN 协议包含多种差错检测功能，如循环冗余检查（CRC）、帧检查、位填充等，确保数据传输的可靠性。</li><li><strong>实时性</strong>：由于其优先级排序和高效的冲突解决机制，CAN 总线适合实时应用。</li><li><strong>灵活性</strong>：CAN 网络可以简单地通过添加新的节点来扩展，而不需要大幅修改现有网络结构。</li><li><strong>抗干扰能力强</strong>：CAN 总线采用差分信号传输，提高了在恶劣环境下的抗干扰能力。</li></ol><h2 id="1-3-can-总线的优势"><a href="#1-3-can-总线的优势" class="headerlink" title="1.3 can 总线的优势"></a>1.3 can 总线的优势</h2><p>CAN 总线（Controller Area Network）的设计主要针对复杂的通信需求，尤其是在汽车和工业自动化领域，它提供了多项优势：</p><ol><li><strong>高可靠性</strong>：CAN 总线具有高级的错误检测、错误限制和自动错误恢复功能，这些特性确保了数据传输的高可靠性。</li><li><strong>实时性能</strong>：通过消息的优先级排序，CAN 总线能够保证关键数据及时传输，适合对实时性要求高的应用。</li><li><strong>灵活的网络拓扑</strong>：CAN 总线支持星形、环形、总线形等多种网络拓扑结构，使得系统设计更加灵活。</li><li><strong>低成本</strong>：CAN 总线减少了布线的复杂性和成本，因为它允许在单个双绞线上连接多达几百个节点。</li><li><strong>抗干扰能力</strong>：采用差分信号传输的方式，提高了系统在恶劣环境下的抗干扰能力。</li><li><strong>广泛的应用支持</strong>：由于 CAN 总线的广泛采用，市场上有大量支持 CAN 通信的微控制器和集成电路，便于开发和维护。</li><li><strong>扩展性</strong>：CAN 网络可以通过简单地添加新节点来轻松扩展，而无需对现有网络架构进行大的修改。</li><li><strong>多主通信</strong>：CAN 总线允许网络上的任何节点都可以主动开始通信，提高了通信的灵活性。</li></ol><p>CAN 总线在汽车行业中尤为重要，用于连接各种电子控制单元（ECU），如发动机控制单元、防抱死制动系统、空调控制等。此外，它也被应用于机器人、医疗设备、电梯控制等多种工业自动化设备中，在下述文章中，除了 can 总线的通讯原理之外，我会着重分析这些关键特点。</p><h1 id="2-can-协议的组成"><a href="#2-can-协议的组成" class="headerlink" title="2 can 协议的组成"></a>2 can 协议的组成</h1><p>CAN 协议（Controller Area Network）是一种复杂的通信协议，它由多个层次和元素组成，以确保数据在不同设备之间可靠、高效地传输。主要组成部分包括：</p><ol><li><p><strong>物理层</strong>：</p><ul><li><strong>传输介质</strong>：通常是双绞线，用于实现物理信号的传输。</li><li><strong>接口芯片</strong>：如 CAN 控制器和 CAN 收发器，负责数据的发送和接收。</li></ul></li><li><p><strong>数据链路层</strong>：</p><ul><li><strong>帧格式</strong>：CAN 协议定义了几种不同类型的帧，包括数据帧（用于数据传输）、远程帧（用于请求数据）、错误帧（用于错误通知）、过载帧（用于延迟下一帧的传输）。</li><li><strong>消息过滤</strong>：节点可以根据标识符决定是否接收某个消息。</li><li><strong>错误检测和处理</strong>：包括循环冗余检查（CRC）、帧检查、位填充等机制。</li></ul></li><li><p><strong>应用层</strong>：</p><ul><li><strong>标识符</strong>：用于标识消息的优先级，CAN 2.0A 标准使用 11 位标识符，而 CAN 2.0B 标准使用 29 位标识符。</li><li><strong>数据字段</strong>：可以包含 0 到 8 字节的数据（CAN FD 标准允许更大的数据量）。</li></ul></li><li><p><strong>传输协议</strong>（可选）：</p><ul><li><strong>高级协议</strong>：如 CANopen、DeviceNet 等，定义了更高层次的通信规则和设备配置方法，使得设备间的互操作性更好。</li></ul></li><li><p><strong>错误处理机制</strong>：</p><ul><li><strong>被动错误</strong>：当节点检测到错误但不影响网络的正常通信时，它将进入被动错误状态。</li><li><strong>主动错误</strong>：节点主动通知网络上的其他节点发生了错误。</li><li><strong>总线关闭</strong>：当错误过多时，节点可能会从网络中断开以防止进一步的错误传播。</li></ul></li></ol><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%881%EF%BC%89-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%8F%8A%E7%89%A9%E7%90%86%E5%B1%82/network-asset-network-asset-20240708232729-20240927003307-mjtrb70-2-20250314222046-s1alkek.png"></p><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%881%EF%BC%89-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%8F%8A%E7%89%A9%E7%90%86%E5%B1%82/network-asset-network-asset-20240708232852-20240927003307-r7y922n-2-20250314222046-ngb7609.png"></p><h2 id="2-1-物理层"><a href="#2-1-物理层" class="headerlink" title="2.1 物理层"></a>2.1 物理层</h2><p>CAN 协议的物理层负责数据的实际传输，包括电气特性、信号的物理编码、连接方式和传输介质。以下是 CAN 协议物理层的一些关键特点和组成部分：</p><ol><li><p><strong>传输介质</strong>：</p><ul><li>通常使用<strong>双绞线</strong>作为信号传输的物理介质，有助于减少外部电磁干扰（EMI），在差分信号传输中，信号的一个版本通过一根线传输（称为 CAN_H，CAN 高线），而信号的反相版本通过另一根线传输（称为 CAN_L，CAN 低线）,在某些应用中，也可以使用光纤来提高通信距离和抗干扰能力。</li><li><strong>差分的电压令 CAN 网络即使在一条信号线断开或者在噪声极大的环境中也能够工作，只需要一对双绞线，差分的 CAN 输入就能够很有效地抵偿噪音，只需要该噪音是在通常的波段里.</strong></li><li><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%881%EF%BC%89-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%8F%8A%E7%89%A9%E7%90%86%E5%B1%82/network-asset-network-asset-20240708233210-20240927003307-fxlbsmf-2-20250314222046-jv1v35q.png"></li></ul></li><li><p><strong>can 总线标准：</strong><br>物理层及数据链路层： ISO11898<br><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%881%EF%BC%89-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%8F%8A%E7%89%A9%E7%90%86%E5%B1%82/network-asset-network-asset-20240708233710-20240927003307-7fgvu75-2-20250314222047-982uibc.png"></p></li><li><p><strong>电气特性</strong>：</p><ul><li><p>CAN 协议定义了两个重要的电气状态：隐性（Recessive）和显性（Dominant）。<strong>隐性状态对应于逻辑“1”，而显性状态对应于逻辑“0”，通过使 CAN_H 电压高于 CAN_L 电压来实现。隐性状态表示逻辑“1”，在物理层上，CAN_H 和 CAN_L 电压接近相等，通常接近于总线的静态电压。</strong></p></li><li><h3 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h3><ul><li><p>CAN 总线的电压水平主要取决于其物理层的实现和工作状态。在高速 CAN（ISO 11898-2）和低速&#x2F;容错 CAN（ISO 11898-3）中，电压水平有所不同。以下是一些关键点：<br>高速 CAN (ISO 11898-2)</p><ul><li><strong>显性（Dominant）状态</strong>：CAN_H（高线）和 CAN_L（低线）之间的电压差通常大约为 2V。在这种状态下，CAN_H 通常比 CAN_L 的电压高 2V 左右。例如，如果 CAN_L 是 2.5V，那么 CAN_H 大约是 4.5V。</li><li><strong>隐性（Recessive）状态</strong>：两条线的电压差接近于 0V，两线都接近于静态电压水平，通常是 2.5V 左右。</li></ul><p>低速&#x2F;容错 CAN (ISO 11898-3)</p><ul><li><strong>显性（Dominant）状态</strong>：电压差较小，CAN_H 和 CAN_L 的电压差异通常在 1V 左右，但具体值取决于具体实现。</li><li><strong>隐性（Recessive）状态</strong>：两条线的电压更接近，通常都接近于总线的静态电压，这个电压水平也是约 2.5V。</li></ul></li></ul></li><li><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%881%EF%BC%89-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%8F%8A%E7%89%A9%E7%90%86%E5%B1%82/network-asset-network-asset-20240708233049-20240927003307-k3yxsie-2-20250314222047-r34vwjx.png"></p></li></ul></li><li><p><strong>信号电平</strong>：</p><ul><li>CAN 高速（ISO 11898-2）和 CAN 低速（ISO 11898-3）有不同的电压水平和传输速率。高速 CAN 通常工作在更高的速率（最高 1Mbps），而低速 CAN 工作在较低的速率（最高 125Kbps），但提供更高的抗干扰能力。</li><li><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%881%EF%BC%89-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%8F%8A%E7%89%A9%E7%90%86%E5%B1%82/network-asset-network-asset-20240708233132-20240927003307-mdam9g8-2-20250314222047-hdoq2p8.png"></li></ul></li><li><p><strong>终端电阻</strong>：</p><ul><li>终端电阻是为了消除在通信电缆中的信号反射，在通信过程中，有两种原因导致信号反射：阻抗不连续和阻抗不匹配。</li><li>阻抗不连续，信号在传输线末端突然遇到电缆阻抗很小甚至没有，信号在这个地方就会引起反射。这种信号反射的原理，与光从一种媒质进入另一种媒质要引起反射是相似的。消除这种反射的方法，就必须在电缆的末端跨接一个与电缆的特性阻抗同样大小的终端电阻，使电缆的阻抗连续。由于信号在电缆上的传输是双向的，因此，在通讯电缆的另一端可跨接一个同样大小的终端电阻。<br>引起信号反射的另外一个原因是数据收发器与传输电缆之间的阻抗不匹配。这种原因引起的反射，主要表现在通讯线路处在空闲方式时，整个网络数据混乱</li></ul></li><li><p><strong>连接器</strong>：</p><ul><li>CAN 网络的物理连接可以通过不同类型的连接器实现，这取决于具体的应用和环境要求。在汽车行业中，常见的有 9 针 D-SUB 连接器（俗称 DB9）</li></ul></li><li><p><strong>拓扑结构</strong>：</p><ul><li>CAN 网络通常采用总线拓扑结构，所有节点通过一条主线连接。尽管物理层支持星形拓扑，但总线形拓扑因其简单性和高效性而更为常见。</li><li><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%881%EF%BC%89-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%8F%8A%E7%89%A9%E7%90%86%E5%B1%82/network-asset-network-asset-20240709203809-20240927003307-gl7gkgu-2-20250314222047-i81tokm.png"><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%881%EF%BC%89-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%8F%8A%E7%89%A9%E7%90%86%E5%B1%82/network-asset-network-asset-20240709203800-20240927003307-2f9jyon-2-20250314222047-jj7k24a.png"></li></ul></li><li><p><strong>容错性能</strong><br><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%881%EF%BC%89-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%8F%8A%E7%89%A9%E7%90%86%E5%B1%82/network-asset-network-asset-20240709203749-20240927003307-l1umj8d-2-20250314222047-g6899fa.png"></p></li><li><p><strong>can 收发器</strong><br>CAN 的组成一般有两种方式，一种是 CPU 与 CAN 控制器集成到一起、再外接 CAN 收发器（STM32 系列是此种方式），另一种是 CPU 与 CAN 控制器分开的，使用的时候需要配置 CAN 接口电路，较为常用的有 TJA1050，在后续文章中我也会针对该芯片进行分析。<br>CAN 收发器（Transceiver）是连接 CAN 总线和 CAN 控制器的关键组件，负责在这两个部分之间转换信号。它的主要功能和特点包括：</p><ol><li><strong>信号转换</strong>：将来自 CAN 控制器的 TTL 电平信号转换为适合在 CAN 总线上传输的差分信号，反之亦然。</li><li><strong>差分信号传输</strong>：利用差分信号技术提高信号的抗干扰能力。这意味着数据通过两条线（CAN_H 和 CAN_L）以电压差的形式传输，从而提高通信的可靠性。</li><li><strong>隐性和显性状态控制</strong>：根据 CAN 协议，收发器能够处理两种电气状态——隐性（Recessive，逻辑“1”）和显性（Dominant，逻辑“0”）。在物理层，这通过控制 CAN_H 和 CAN_L 线上的电压差来实现。</li><li><strong>保护功能</strong>：许多 CAN 收发器具备过电压保护、热保护和电磁干扰（EMI）过滤功能，以保护电路免受损坏。</li><li><strong>隔离功能</strong>：某些 CAN 收发器设计中包含隔离功能，以电气方式隔离 CAN 总线和控制器，进一步提高系统的稳定性和安全性。</li><li><strong>低功耗模式</strong>：为了适应不同的应用需求，一些 CAN 收发器支持低功耗操作模式，如睡眠模式，以减少系统的能耗。</li></ol></li></ol><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%881%EF%BC%89-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%8F%8A%E7%89%A9%E7%90%86%E5%B1%82/network-asset-network-asset-20240708233007-20240927003308-gl6f2zs-2-20250314222047-bzaekl3.png"></p><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%881%EF%BC%89-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%8F%8A%E7%89%A9%E7%90%86%E5%B1%82/network-asset-network-asset-20240709204049-20240927003308-owyeo3g-2-20250314222048-znp4vff.png"></p>]]>
    </content>
    <id>https://lbq08.cc/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%881%EF%BC%89-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%8F%8A%E7%89%A9%E7%90%86%E5%B1%82/</id>
    <link href="https://lbq08.cc/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%881%EF%BC%89-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%8F%8A%E7%89%A9%E7%90%86%E5%B1%82/"/>
    <published>2024-11-24T03:03:54.000Z</published>
    <summary>
      <![CDATA[<h1 id="can协议基础（1）-简要介绍及物理层"><a href="#can协议基础（1）-简要介绍及物理层" class="headerlink" title="can协议基础（1）-简要介绍及物理层"></a>can协议基础（1）-简要介绍及物理层</h1><h1 i]]>
    </summary>
    <title>can协议基础（1）-简要介绍及物理层</title>
    <updated>2026-04-11T15:51:59.836Z</updated>
  </entry>
  <entry>
    <author>
      <name>liu</name>
    </author>
    <category term="can总线" scheme="https://lbq08.cc/tags/can%E6%80%BB%E7%BA%BF/"/>
    <content>
      <![CDATA[<h1 id="can协议基础（2）-can数据链路层"><a href="#can协议基础（2）-can数据链路层" class="headerlink" title="can协议基础（2）-can数据链路层"></a>can协议基础（2）-can数据链路层</h1><h2 id="1-数据链路层的介绍"><a href="#1-数据链路层的介绍" class="headerlink" title="1 数据链路层的介绍"></a>1 数据链路层的介绍</h2><p>CAN 总线的数据链路层负责在物理层提供的原始比特流上实现可靠的通信。它包括帧的封装、错误检测、确认机制、仲裁过程等关键功能。以下是数据链路层的主要特点和功能：</p><ol><li><strong>帧类型</strong><br>CAN 协议定义了几种不同类型的帧，包括数据帧（用于数据传输）、远程帧（用于请求数据）、错误帧（用于错误通知）、过载帧（用于延迟下一帧的传输）和空闲帧（总线空闲状态）。</li><li><strong>仲裁</strong><br>CAN 总线使用非破坏性仲裁方法，允许多个节点同时尝试发送消息。如果两个或更多节点同时开始发送，节点会在发送过程中监听总线，并在检测到冲突时停止发送较低优先级的消息。这是通过帧 ID 的二进制值来实现的，较低的 ID 具有较高的优先级。</li><li><strong>错误检测</strong><br>CAN 数据链路层包括多种错误检测机制，如循环冗余检查（CRC）、帧检查、比特监视和确认检查。这些机制确保了数据的完整性和通信的可靠性。</li><li><strong>确认机制</strong><br>在数据帧成功传输后，接收节点会发送一个确认位，表明消息已被接收。如果发送节点没有检测到确认，它可能会重新尝试发送消息。</li><li><strong>流量控制</strong><br>虽然 CAN 协议本身不直接提供流量控制机制，但通过仲裁和优先级控制，它能够有效管理总线上的通信流量，防止数据丢失。</li><li><strong>容错机制</strong><br>CAN 数据链路层设计有容错机制，如自动重传错误帧、错误限制和节点故障隔离，以提高网络的稳定性和可靠性。</li><li><strong>帧结构</strong><br>每个 CAN 帧包括几个不同的字段，如起始位、帧 ID、控制字段、数据字段（最多 8 字节）、CRC、确认槽和帧结束位。这种结构化的帧格式有助于数据的有效传输和错误检测。</li></ol><h2 id="2-can-的帧类型"><a href="#2-can-的帧类型" class="headerlink" title="2 can 的帧类型"></a>2 can 的帧类型</h2><p>之所以将 can 的帧类型放在开头讲，目的是使大家对 can 的功能有所认知，在后续章节的 can 的总线总裁及总线错误处理需要熟悉 can 的帧格式，所以我并未像其他文章一样先讲解 can 的总线仲裁机制-尽管这个十分重要。</p><ol><li><p><strong>数据帧（Data Frame）</strong> ：</p><ul><li>用于传输数据从发送节点到一个或多个接收节点。</li><li>包含一个唯一的标识符（ID），用于标识消息的内容和优先级。</li><li>数据长度可以从 0 到 8 字节不等。</li><li>数据帧又分为<strong>标准帧和扩展帧</strong></li></ul></li><li><p><strong>远程帧（Remote Frame）</strong> ：</p><ul><li>用于请求数据。</li><li>远程帧的标识符与它请求的数据帧的标识符相同。</li><li>不包含数据字段，仅通过其 ID 请求特定的数据帧。</li></ul></li><li><p><strong>错误帧（Error Frame）</strong> ：</p><ul><li>当节点检测到错误时发送。</li><li>用于通知其他节点在传输过程中检测到错误。</li><li>错误帧会导致当前传输被中断，并根据协议规定进行错误处理。</li></ul></li><li><p><strong>过载帧（Overload Frame）</strong> ：</p><ul><li>用于指示节点因为内部条件（如缓冲区溢出）而暂时无法处理更多的数据。</li><li>过载帧会导致网络上的数据传输暂时延迟。</li></ul></li></ol><p>在实际应用中，我们接触到的数据帧和错误帧最多，因此本文会着重讲解该两种类型。</p><h3 id="2-1-数据帧"><a href="#2-1-数据帧" class="headerlink" title="2.1 数据帧"></a>2.1 数据帧</h3><h4 id="2-1-1-标准数据帧"><a href="#2-1-1-标准数据帧" class="headerlink" title="2.1.1 标准数据帧"></a>2.1.1 标准数据帧</h4><p>数据帧是用于在网络上节点之间传输数据的主要帧类型。数据帧的结构设计用于高效且可靠的数据通信，具体包括以下几个关键部分：</p><ol><li><p><strong>SOF</strong> <strong>起始位</strong>：标志着一帧数据的开始，确保节点同步到消息的起始位置。<br>标识一个数据帧的开始，固定一个显性位<br>总线空闲期间的任何隐性到显性的跳变都将引起节点进行硬同步<br>只有在总线空闲期间节点才能够发送 SOF<br><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240709211519-20240929230819-yvlogsp-1-20250314222058-dwy5w0f.png"></p></li><li><p><strong>仲裁字段</strong>：</p><ul><li><strong>标识符（ID）</strong> ：用于标识消息的内容和优先级。<br>在 CAN 标准（CAN 2.0A）中，ID 为 11 位；在扩展标准（CAN 2.0B）中，ID 为 29 位。<br>确定报文的仲裁优先级，ID 数值越小，优先级越高<br>ID 的高位先发(Bit28….Bit0)<br>明报文的含义，可以包含报文的源地址和目标地址</li><li><strong>远程传输请求（RTR）位</strong>：区分是数据帧还是远程帧。数据帧的 RTR 位为逻辑 0，远程帧的 RTR 位为逻辑 1。</li></ul><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240709211538-20240929230819-jde4b35-1-20250314222059-rer0zd8.png"></p></li><li><p><strong>控制字段</strong>：包含了数据长度代码（DLC），指示数据字段中的字节数（0 到 8 字节）。</p><ul><li>包含 4 位，表示数据场包含数据的字节数</li><li>高位先发(DLC3..DLC0)</li></ul><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-2024%E5%B9%B47%E6%9C%889%E6%97%A5_DLC-20240929230819-3l4nit8-1-20250314222059-d0uewaz.png"></p></li><li><p><strong>数据字段</strong>：携带实际要传输的数据，长度可以是 0 到 8 字节。</p><ul><li>具有 0-8 个字节长度，由 DLC 确定</li><li>包含 CAN 数据帧发送的内容</li><li>数据场里低字节先发（Byte0….Byte7）<br>每个字节是高位先发(Bit7….Bit0)</li><li>超过一个字节的数据可以把低有效位放在前(Intel 格式)，也可以把高有效位放在前(Motorola 格式）</li></ul><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-2024%E5%B9%B47%E6%9C%889%E6%97%A5_%E6%95%B0%E6%8D%AE%E6%AE%B5-20240929230819-fges9kz-1-20250314222059-1oj8gik.png"></p></li><li><p><strong>CRC 字段</strong>：包含一个循环冗余校验码，用于检测传输过程中的错误。<br>在后续的错误检验机制中，会详细说明 can 总线的 crc 校验是怎么进行的<br><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240709212519_crc-20240929230819-7sfprkm-1-20250314222059-6l7ojlo.png"></p></li><li><p><strong>CRC 字段界定符</strong> :<br>界定 CRC 序列<br>固定格式，1 个隐性位<br>CRC 界定符之前进行位填充<img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240714221026-20240929230819-1krc6su-1-20250314222059-bf220t9.png"></p></li><li><p><strong>ACK</strong> ：确定报文被至少一个节点正确接收<br><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240709212637_ack-20240929230819-x6fzett-1-20250314222059-4p0n9zo.png"><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240709212849_ack2-20240929230819-ndk9f58-1-20250314222059-571oqmv.png"></p></li><li><p><strong>ACK 界定符 :</strong><br>界定 ACK<br>固定格式，1 个隐性位<br><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240714221146-20240929230819-6amf7dd-1-20250314222059-q5jf72q.png"></p></li><li><p><strong>结束位</strong>（EOF）：标志着数据帧的结束，确保帧的边界清晰。<br>表示数据帧结束<br>固定格式，7 个连续的隐性位<br><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240709212921_eof-20240929230819-9a5cd9g-1-20250314222059-cocr6oh.png"></p></li><li><p><strong>ITM：</strong> 间歇场,ITM 之后进入总线空闲状态，此时节点可以发送报文<br>固定格式<br>3 个连续的隐性位<br>即确认 11 个隐性位，认为总线进入空闲阶段</p></li></ol><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240714221349-20240929230819-4himy5a-1-20250314222100-v7n7lso.png"></p><ol start="11"><li>数据帧的位填充区域SOF 之前的总线空闲区域，不需要同步，无需进行位填充<br>CRC 之后的位域都是固定格式，不允许位填充操作<img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240714221735-20240929230819-moks8av-1-20250314222100-52e1kgg.png"></li></ol><h4 id="2-1-2-拓展数据帧"><a href="#2-1-2-拓展数据帧" class="headerlink" title="2.1.2 拓展数据帧"></a>2.1.2 拓展数据帧</h4><p>拓展数据帧格式大致与标准数据帧相同</p><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240714220353-20240929230820-073osfm-1-20250314222100-cngsi9x.png"></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">拓展帧除了 ID 不同之外，还有些位有不同的区分</span><br></pre></td></tr></table></figure><ol><li>SRR 位：代替远程请求位<br>表明在该位代替了标准帧中的 RTR 位<br>该位无实际意义<br>SRR 永远置 1<br><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240714222055-20240929230820-rd0lvai-1-20250314222100-ir9x3zg.png"></li><li>IDE 位：标识符扩展位<br>用于区分标准帧和扩展帧<br>标准帧，IDE=0（11 位 ID）<br>扩展帧，IDE=1（29 位 ID）<br><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240714222035-20240929230820-1c5cumc-1-20250314222100-s9ysaua.png"></li><li>RTR 位：远程请求位<br>用于区分数据帧和远程帧<br>数据帧，RTR=0；<br>远程帧，RTR=1；<br><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240714222007-20240929230820-v0ywbwl-1-20250314222100-6hc7s1g.png"></li><li>r 0、r1 位<br>保留位<br>当前置 0<br><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240714221939-20240929230820-cz03sg4-1-20250314222100-8ums9lk.png"></li></ol><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240709204859-20240929230820-4yhqazp-1-20250314222100-lvvxwin.png"></p><p>数据帧的设计允许 CAN 网络上的节点以<strong>非破坏性的方式</strong>进行通信，即使在网络负载较重的情况下也能保证数据的可靠传输。即使在网络负载较重的情况下也能保证数据的可靠传输。通过仲裁机制，确保了具有最高优先级的消息能够被优先传输，而不会被低优先级的消息阻塞这部分内容会在第三章着重讲解。</p><h2 id="3-can-总线的通信模型"><a href="#3-can-总线的通信模型" class="headerlink" title="3 can 总线的通信模型"></a>3 can 总线的通信模型</h2><p>can 总线支持多主机发送，并且通讯方式为异步半双工通讯，这样势必会带来一种情况就是两个节点同时发送信息，而少了像 IIC 中的 SCL 地址线、SPI 中的片选信号线，简洁的物理层决定了 CAN 必然要配上一套更复杂的协议。如何用一个信号通道实现同样、甚至更强大的功能呢？答案是对数据或操作命令进行打包，而 can 总线使用的是 CSMA&#x2F;CA（Carrier Sense Multiple Access with Collision Avoidance，带冲突避免的载波侦听多路访问）通信协议，下面我们先简单学习一下这种通讯机制</p><h3 id="3-1-CSMA-CA-通信机制"><a href="#3-1-CSMA-CA-通信机制" class="headerlink" title="3.1 CSMA&#x2F;CA 通信机制"></a>3.1 CSMA&#x2F;CA 通信机制</h3><p>CSMA&#x2F;CA 协议的基本工作流程分为以下几点</p><ol><li><strong>载波侦听</strong>：在发送数据之前，设备首先检查通信媒介（如无线信道）是否空闲。这一步被称为“载波侦听”。</li><li><strong>随机退避</strong>：如果信道被检测为忙碌，设备将等待一个随机的退避时间后再次检查信道是否空闲。这个随机退避时间有助于减少多个设备同时尝试访问信道时的冲突。</li><li><strong>再次侦听</strong>：退避时间结束后，设备再次执行载波侦听，以确认信道是否空闲。</li><li><strong>发送数据</strong>：如果信道空闲，设备开始发送数据。</li><li><strong>确认接收</strong>：在一些实现中，接收设备会发送一个确认包（ACK），以通知发送设备数据已成功接收。如果发送设备在一定时间内没有收到 ACK，它可能会重新发送数据。</li><li><strong>冲突避免</strong>：为了进一步减少冲突的可能性，CSMA&#x2F;CA 在发送数据前可能会使用一个短的等待时间，称为“帧间间隔”（IFS），确保信道在连续传输之间保持空闲状态。</li></ol><h3 id="3-2-can-总线的非破坏性仲裁的载波侦听多路访问-冲突避免"><a href="#3-2-can-总线的非破坏性仲裁的载波侦听多路访问-冲突避免" class="headerlink" title="3.2 can 总线的非破坏性仲裁的载波侦听多路访问&#x2F;冲突避免"></a>3.2 can 总线的非破坏性仲裁的载波侦听多路访问&#x2F;冲突避免</h3><p>CAN 总线使用的非破坏性仲裁机制是一种特殊的载波侦听多路访问&#x2F;冲突避免（CSMA&#x2F;CA）技术。这种机制允许多个网络节点几乎同时开始传输消息，但最终只有优先级最高的消息会被成功发送，而不会破坏或中断其他节点的消息，下面是 can 总线的这一技术的工作原理：</p><ol><li><strong>准备数据</strong>：发送节点（或称为 ECU，电子控制单元）准备好要发送的数据。这些数据被封装在一个 CAN 数据帧中，数据帧包括多个字段，如帧 ID、数据长度代码（DLC）、实际数据字节等，这个会在后续的第三章节讲到。</li><li><strong>开始帧传输</strong>：发送节点在总线上发送一个起始位，标志着一个新帧的开始。</li><li><strong>发送帧 ID</strong>：紧接着起始位，发送节点发送帧 ID（也称为标识符）。帧 ID 不仅标识了消息的内容，还决定了消息的优先级。在 CAN 总线上，较低的帧 ID 意味着较高的优先级。</li><li><strong>仲裁过程</strong>：如果有多个节点同时尝试发送数据，CAN 总线上的仲裁机制会根据帧 ID 的优先级解决冲突，确保优先级最高的帧被首先发送。在这个过程中，所有参与发送的节点都会监听总线上的信号，并与自己尝试发送的信号进行比较。如果检测到总线上的信号与自己发送的信号不符，表示有更高优先级的节点在发送数据，节点会立即停止发送。</li><li><strong>发送剩余帧内容</strong>：一旦节点成功通过仲裁，它就会继续发送剩余的帧内容，包括控制字段（如数据长度代码 DLC）、数据字段（最多 8 字节的数据）、CRC 校验序列等。</li><li><strong>发送结束标志</strong>：数据发送完毕后，发送节点会发送一个帧结束标志。</li><li><strong>接收确认</strong>：其他节点在接收到完整的帧后，会进行 CRC 校验，确认数据的完整性和正确性。如果数据无误，接收节点会在确认槽（ACK slot）发送一个确认位，表明数据已被成功接收。</li><li><strong>错误处理</strong>：如果在传输过程中发生错误（如 CRC 校验失败），则会触发错误帧的发送，导致当前帧的传输被中断，并根据 CAN 协议的规定进行重传。</li><li><strong>空闲状态</strong>：数据帧成功发送并确认后，总线回到空闲状态，等待下一个帧的传输。</li></ol><h3 id="3-3-CAN-的通信模型"><a href="#3-3-CAN-的通信模型" class="headerlink" title="3.3 CAN 的通信模型"></a>3.3 CAN 的通信模型</h3><ol><li><strong>报文发送：</strong> 节点发送报文时要检测总线状态<br>只有总线处于空闲，节点才能发送报文<br>在发送报文过程中，发送节点的 can 控制器进行“回读”，判断送出的位与回读的位是否一致<br><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240725192612-20240929230820-qpqd0jg-1-20250314222101-6j9lwp1.png"></li><li>“线与”机制<br>节点确认总线空闲后，发送方发送 can ID，这时候会有多个节点发送 id，通过线与机制来判断优先级“显性”位可以覆盖“隐性”位；<br>只有所有节点都发送“隐性”位，总线才处于“隐性”状态，如下图，节点 B 优先级最高<br><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240725192552-20240929230820-kduevg8-1-20250314222101-vc3y86p.png"><br><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240725192952-20240929230820-2pwv64w-1-20250314222101-tdnzu7n.png"></li><li>非破坏性仲裁<br>发送低优先级报文的节点退出仲裁后，在下次总线空闲时自动重发报文<br>如下图，节点 A 的 ID 最小，优先级最高，随后发送节点 B、C<br><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240725193057-20240929230820-nsdta4y-1-20250314222101-ewf90t9.png"><br>高优先级的报文不能中断低优先级报文的发送<br>当低优先级的报文发送时，高优先级的报文请求发送，并不会中断低优先级的报文发送<br>这个在实际应用中可以解决总线报文丢失问题，即低优先级报文周期特别频繁的情况下，高优先级的报文依旧无法进行发送，会阻塞在 can 发送器的邮箱中，在遇到单 ECU 报文正常而接入整车后报文丢失情况时，优先考虑这一点<br><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240725193229-20240929230820-i95hj7j-1-20250314222101-uko0wv1.png"></li></ol><h3 id="3-4-CAN-的总线访问总结"><a href="#3-4-CAN-的总线访问总结" class="headerlink" title="3.4 CAN 的总线访问总结"></a>3.4 CAN 的总线访问总结</h3><p>总线访问—非破坏性仲裁的载波侦听多路访问&#x2F;冲突避免 CSMA&#x2F;CA (Carrier Sense Multiple Access&#x2F;Collision Avoidance)<br>载波侦听，网络上各个节点在发送数据前都要检测总线上是否有数据传输<br>网络上有数据暂时不发送数据，等待网络空闲再发<br>网络上无数据立即发送已经准备好的数据<br>其实总线上并没有什么“载波”。 “载波侦听”就是用电子技术检测总线上有没有其他节点发送的数据信号。<br>多路访问，网络上所有节点以多点接入的方式连接在同一根总线上，且发送数据是广播式的<br>冲突避免，节点在发送数据过程中要不停地检测发送的数据，确定是否与其它节点数据发生冲突，如果有冲突则保证高优先级的报文先发送。</p><p>CSMA&#x2F;CA 与 CSMA&#x2F;CD（带冲突检测的载波侦听多路访问）最大的不同在于其冲突处理方式。CSMA&#x2F;CD（主要用于有线网络，如以太网）在检测到冲突时会立即停止发送数据并尝试重新发送，而 CSMA&#x2F;CA 通过预防措施（如随机退避和帧间间隔）尽量避免冲突的发生，这使得 CSMA&#x2F;CA 特别适用于无线网络环境，因为在无线环境中检测冲突要比有线环境更困难。</p><p>CSMA&#x2F;CA 可归结为四句话：<br> 发前先侦听，空闲即发送，<br> 边发边检测，冲突时退避。</p><h2 id="4-can-的错误检测与错误帧"><a href="#4-can-的错误检测与错误帧" class="headerlink" title="4 can 的错误检测与错误帧"></a>4 can 的错误检测与错误帧</h2><h3 id="错误检测"><a href="#错误检测" class="headerlink" title="错误检测"></a>错误检测</h3><ol><li><p><strong>位填充错误（Bit Stuffing Error）</strong> ：</p><ul><li>在 CAN 帧中，如果连续出现 5 个相同的位（0 或 1），发送方会自动插入一个相反的位（称为填充位）。</li><li>接收方在接收数据时会检查这种填充位，如果检测到连续 6 个相同的位，则认为发生了位填充错误。</li></ul></li><li><p><strong>帧校验错误（Frame Check Error）</strong> ：</p><ul><li>CAN 帧的结构必须符合特定的格式，包括起始位、控制位、数据位、CRC 校验位、确认位和结束位。</li><li>如果接收方检测到帧结构不符合规范，则会产生帧校验错误。</li></ul></li><li><p><strong>ACK 错误（Acknowledgment Error）</strong> ：</p><ul><li>在 CAN 帧的确认字段中，发送方会发送一个显性位（0），接收方在正确接收数据后会覆盖这个位为隐性位（1）。</li><li>如果发送方在确认字段中仍然检测到显性位，则认为发生了 ACK 错误。</li></ul></li><li><p><strong>CRC 错误（Cyclic Redundancy Check Error）</strong> ：</p><ul><li>每个 CAN 帧都包含一个 CRC 校验字段，用于检测数据传输中的错误。</li><li>发送方根据帧内容计算 CRC 值并附加到帧中，接收方接收数据后重新计算 CRC 值并与接收到的 CRC 值进行比较。</li><li>如果两者不匹配，则认为发生了 CRC 错误。</li></ul></li><li><p><strong>格式错误（Form Error）</strong> ：</p><ul><li>CAN 帧的特定字段（如起始位、结束位等）必须是显性位或隐性位。</li><li>如果接收方检测到这些字段中的位不符合规范，则会产生格式错误。</li></ul></li><li><p><strong>位错误（Bit Error）</strong> ：</p><ul><li>在数据传输过程中，发送方会实时监控总线上的位状态。</li><li>如果发送方发送的位与总线上的实际位状态不一致（例如，发送显性位但检测到隐性位），则会产生位错误。</li></ul></li></ol><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240730182933-20240929230820-3ii53jo-1-20250314222101-lcv06ip.png"></p><h4 id="错误帧发送时机"><a href="#错误帧发送时机" class="headerlink" title="错误帧发送时机"></a>错误帧发送时机</h4><ul><li>错误帧的检测和发送流程为：检测错误-发送错误帧-通知报文错误</li><li>不同的错误帧的发送时机<br>在产生位错误、填充错误、格式错误或 ACK 错误时，产生后当前发送的下一位发送错误帧。<br>产生 CRC 错误时紧随 ACK 界定符后的位发送错误帧。</li><li>错误帧发送后，总线空闲时自动重发出错的数据帧！</li></ul><h4 id="错误计数器与错误状态切换"><a href="#错误计数器与错误状态切换" class="headerlink" title="错误计数器与错误状态切换"></a>错误计数器与错误状态切换</h4><p>每个节点都含有 REC 和 TEC，当接收错误产生时，REC 增加，正确接收到数据帧，REC 减少；<br>当发送错误产生时，TEC 增加，正确发送一帧数据帧，TEC 减少；<br>REC、TEC 的数值会引发节点状态改变。</p><p>REC： Receive Error Counter 接收错误计数器<br>TEC： Transmit Error Counter 发送错误计数器</p><p>总线中，每个节点都有三种主要的错误状态，用于管理和处理通信中的错误。这三种状态是：</p><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240730183751-20240929230820-lhd7tbf-1-20250314222101-nmkg0kq.png"></p><ol><li><p><strong>错误活动状态（Error Active State）</strong> ：</p><ul><li>在此状态下，节点可以正常参与总线通信，并且能够发送和接收数据帧。</li><li>如果节点检测到错误，它会增加其错误计数器（错误计数器分为发送错误计数器和接收错误计数器）。</li><li>当错误计数器的值低于一定阈值（通常是 128），节点保持在错误活动状态。</li></ul></li><li><p><strong>错误被动状态（Error Passive State）</strong> ：</p><ul><li>当节点的错误计数器超过一定阈值（通常是 128），节点进入错误被动状态。</li><li>在此状态下，节点仍然可以参与总线通信，但其发送的错误帧（Error Frame）不会主动干扰总线通信。</li><li>节点在错误被动状态下发送的帧会有一个特殊的标志，表明它处于错误被动状态。</li><li>如果错误计数器的值继续增加并超过另一个更高的阈值（通常是 256），节点将进入总线关闭状态。</li></ul></li><li><p><strong>总线关闭状态（Bus Off State）</strong> ：</p><ul><li>当节点的错误计数器超过最高阈值（通常是 256），节点进入总线关闭状态。</li><li>在此状态下，节点完全停止参与总线通信，既不能发送也不能接收数据帧。</li><li>节点需要通过特定的复位过程才能重新进入错误活动状态并恢复正常通信。</li></ul></li></ol><h4 id="错误帧的格式"><a href="#错误帧的格式" class="headerlink" title="错误帧的格式"></a>错误帧的格式</h4><p>错误帧的格式由两个主要部分组成：错误标志（Error Flag）和错误定界符（Error Delimiter）。</p><ol><li><p><strong>错误标志（Error Flag）</strong> ：</p><ul><li>错误标志分为主动错误标志（Active Error Flag）和被动错误标志（Passive Error Flag）。</li><li><strong>主动错误标志</strong>：由 6 个连续的显性位（0）组成。当节点处于错误活动状态时发送。</li><li><strong>被动错误标志</strong>：由 6 个连续的隐性位（1）组成。当节点处于错误被动状态时发送。</li></ul></li><li><p><strong>错误定界符（Error Delimiter）</strong> ：</p><ul><li>错误定界符由 8 个连续的隐性位（1）组成，用于标识错误帧的结束。</li></ul></li></ol><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240730185229-20240929230820-7y8b8ul-1-20250314222101-kqqhrda.png"></p><h3 id="错误帧的发送过程"><a href="#错误帧的发送过程" class="headerlink" title="错误帧的发送过程"></a>错误帧的发送过程</h3><ol><li><p><strong>检测到错误</strong>：</p><ul><li>当节点检测到错误时，会立即中止当前帧的传输，并开始发送错误帧。</li></ul></li><li><p><strong>发送错误标志</strong>：</p><ul><li>如果节点处于错误活动状态，它会发送主动错误标志（6 个显性位）。</li><li>如果节点处于错误被动状态，它会发送被动错误标志（6 个隐性位）。</li></ul></li><li><p><strong>发送错误定界符</strong>：</p><ul><li>无论节点处于何种状态，都会发送错误定界符（8 个隐性位）来结束错误帧。</li></ul></li></ol><p>假设一个节点在传输过程中检测到错误，并且该节点处于错误活动状态，那么它会发送如下错误帧：</p><p>主动错误标志（6 个显性位） + 错误定界符（8 个隐性位）</p><p>如果节点处于错误被动状态，则发送如下错误帧：</p><p>被动错误标志（6 个隐性位） + 错误定界符（8 个隐性位）</p><p>错误帧的存在使得 CAN 总线能够快速检测和响应通信错误，从而提高系统的可靠性和稳定性。</p><p>位错误：</p><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240730185115-20240929230821-9y0wlcw-1-20250314222101-b7tiehf.png"></p><p>格式错误：</p><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240730185140-20240929230821-xqqkvzi-1-20250314222102-376tfa2.png"></p><p>CRC 错误：</p><p><img src="/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/network-asset-network-asset-20240730185201-20240929230821-7k0ij4r-1-20250314222102-xsc4ttm.png"></p><h4 id="错误标志的叠加"><a href="#错误标志的叠加" class="headerlink" title="错误标志的叠加"></a>错误标志的叠加</h4><p>当多个节点同时检测到错误并发送错误标志时，会发生错误标志叠加（Error Flag Overlapping）。错误标志叠加的处理方式取决于节点的错误状态（错误活动状态或错误被动状态）。</p><p>错误标志叠加的处理：</p><ol><li><p><strong>主动错误标志叠加</strong>：</p><ul><li>当多个处于错误活动状态的节点同时发送主动错误标志（6 个显性位）时，这些显性位会在总线上叠加。</li><li>由于 CAN 总线是线与（wired-AND）逻辑，总线上只要有一个显性位，总线状态就为显性。因此，多个主动错误标志叠加后，总线仍然保持显性状态。</li></ul></li><li><p><strong>被动错误标志叠加</strong>：</p><ul><li>当多个处于错误被动状态的节点同时发送被动错误标志（6 个隐性位）时，这些隐性位会在总线上叠加。</li><li>由于隐性位不会改变总线状态，总线状态保持为隐性。</li></ul></li><li><p><strong>主动和被动错误标志叠加</strong>：</p><ul><li>如果一个节点发送主动错误标志（显性位），而另一个节点发送被动错误标志（隐性位），则总线状态将由显性位决定。</li><li>由于显性位优先级高于隐性位，总线状态将保持显性。</li></ul></li></ol><p><strong>示例：</strong></p><p>假设有两个节点 A 和 B，它们同时检测到错误并发送错误标志：</p><ul><li>节点 A 处于错误活动状态，发送主动错误标志（6 个显性位）。</li><li>节点 B 处于错误被动状态，发送被动错误标志（6 个隐性位）。</li></ul><p>在这种情况下，总线状态将由显性位决定，因此总线将保持显性状态。</p><p>错误标志叠加的主要效果是确保所有节点都能检测到错误并采取适当的措施。由于显性位优先级高于隐性位，总线上的显性状态可以有效地通知所有节点发生了错误，从而触发错误处理机制。</p><p>位定时（Bit Timing）是确保所有节点能够同步并正确解释总线上的数据的关键因素。位定时由几个参数组成，这些参数定义了一个位时间的结构。位时间通常分为四个主要部分：</p><ol><li><p><strong>同步段（Synchronization Segment, Sync_Seg）</strong> ：</p><ul><li>用于同步节点的时钟。</li><li>通常固定为 1 个时间量子（Time Quantum, TQ）。</li></ul></li><li><p><strong>传播段（Propagation Segment, Prop_Seg）</strong> ：</p><ul><li>用于补偿信号在总线上的传播延迟。</li><li>由若干个时间量子组成。</li></ul></li><li><p><strong>相位缓冲段 1（Phase Buffer Segment 1, Phase_Seg1）</strong> ：</p><ul><li>用于补偿节点间的相位误差。</li><li>由若干个时间量子组成。</li></ul></li><li><p><strong>相位缓冲段 2（Phase Buffer Segment 2, Phase_Seg2）</strong> ：</p><ul><li>也用于补偿节点间的相位误差。</li><li>由若干个时间量子组成。</li></ul></li></ol>]]>
    </content>
    <id>https://lbq08.cc/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/</id>
    <link href="https://lbq08.cc/2024/11/24/can%E5%8D%8F%E8%AE%AE%E5%9F%BA%E7%A1%80%EF%BC%882%EF%BC%89-can%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82/"/>
    <published>2024-11-24T03:03:30.000Z</published>
    <summary>
      <![CDATA[<h1 id="can协议基础（2）-can数据链路层"><a href="#can协议基础（2）-can数据链路层" class="headerlink" title="can协议基础（2）-can数据链路层"></a>can协议基础（2）-can数据链路层</h1><h2 i]]>
    </summary>
    <title>can协议基础（2）-can数据链路层</title>
    <updated>2026-04-11T15:51:35.999Z</updated>
  </entry>
</feed>
