<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh_CN">
  <title>Key 的博客</title>
  <subtitle>嵌入式 / 机器人 / 硬件折腾笔记</subtitle>
  <link href="https://blog-21k.pages.dev/" rel="alternate" type="text/html"/>
  <link href="https://blog-21k.pages.dev/atom.xml" rel="self" type="application/atom+xml"/>
  <id>https://blog-21k.pages.dev/</id>
  <updated>2026-09-06T00:00:00.000Z</updated>
  <entry>
    <title>你好，世界：博客的第一篇文章</title>
    <link href="https://blog-21k.pages.dev/posts/hello-world/" rel="alternate" type="text/html"/>
    <id>https://blog-21k.pages.dev/posts/hello-world/</id>
    <published>2026-09-06T00:00:00.000Z</published>
    <updated>2026-09-06T00:00:00.000Z</updated>
    <summary></summary>
    <content type="html"><![CDATA[<p>博客搭好了，用这篇文章来验证一切正常，顺便当一篇 Markdown 速查。</p>
<h2>常用写法</h2>
<p><strong>加粗</strong>、<em>斜体</em>、<code>行内代码</code>，还有 <a href="https://gohugo.io/">链接</a>。</p>
<p>引用长这样：</p>
<blockquote>
<p>学技术最好的方式就是把学的东西写出来。</p>
</blockquote>
<h3>列表</h3>
<ol>
<li>写文章 = 在 <code>src/content/posts/</code> 新建一个 <code>.md</code> 文件</li>
<li>本地预览：<code>pnpm dev</code></li>
<li>发布：<code>git push</code>，Cloudflare 一分钟后自动上线</li>
</ol>
<h3>代码块</h3>
<p>写技术笔记最常用的就是代码块，带高亮和复制按钮：</p>
<pre><code>/* 老朋友：STM32 点灯 */
while (1) {
    HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    HAL_Delay(500);
}
</code></pre>
<h3>表格</h3>
<table>
<thead>
<tr>
<th>快捷操作</th>
<th>命令</th>
</tr>
</thead>
<tbody>
<tr>
<td>新建文章</td>
<td><code>pnpm new-post xxx</code> 或复制现有 md</td>
</tr>
<tr>
<td>本地预览</td>
<td><code>pnpm dev</code></td>
</tr>
<tr>
<td>正式发布</td>
<td><code>git push</code></td>
</tr>
</tbody>
</table>
<h2>插图片怎么放</h2>
<p>把图片丢进 <code>public/images/</code> 目录，然后这样引用：</p>
<pre><code>![描述文字](/images/xxx.png)
</code></pre>
<hr />
<p>写完记得把开头 <code>draft: true</code> 改成 <code>false</code>（或删掉），否则正式构建时不会发布这篇。</p>
]]></content>
    <author><name>Key</name></author>
  </entry>
  <entry>
    <title>Markdown 与 Obsidian 语法速查</title>
    <link href="https://blog-21k.pages.dev/posts/markdown-%E4%B8%8E-obsidian-%E8%AF%AD%E6%B3%95%E9%80%9F%E6%9F%A5/" rel="alternate" type="text/html"/>
    <id>https://blog-21k.pages.dev/posts/markdown-%E4%B8%8E-obsidian-%E8%AF%AD%E6%B3%95%E9%80%9F%E6%9F%A5/</id>
    <published>2026-06-15T00:00:00.000Z</published>
    <updated>2026-06-15T00:00:00.000Z</updated>
    <summary></summary>
    <content type="html"><![CDATA[<h1>Markdown 与 Obsidian 语法速查</h1>
<p>Markdown 是一种轻量级标记语言。它通过少量符号表达标题、列表、链接、代码和表格等结构，让笔记既容易阅读，也能以纯文本形式长期保存。</p>
<p>{{&lt; admonition tip "技巧" &gt;}}
本文同时介绍标准 Markdown 和 Obsidian 扩展语法。标有“Obsidian”的功能，在其他 Markdown 编辑器中不一定有效。
{{&lt; /admonition &gt;}}</p>
<h2>一、标题</h2>
<p>在文字前输入 <code>#</code> 和一个空格。<code>#</code> 越多，标题层级越低。</p>
<pre><code># 一级标题
## 二级标题
### 三级标题
#### 四级标题
##### 五级标题
###### 六级标题
</code></pre>
<p>一篇笔记通常只使用一个一级标题，再通过二级、三级标题组织内容。</p>
<h2>二、段落与换行</h2>
<p>段落之间空一行：</p>
<pre><code>这是第一段。

这是第二段。
</code></pre>
<p>如果只按一次回车，Markdown 通常仍会把文字视为同一段。需要强制换行时，可以在上一行末尾输入两个空格，或者使用 HTML 标签 <code>&lt;br&gt;</code>。</p>
<pre><code>第一行末尾有两个空格  
这里会另起一行。

也可以这样换行：&lt;br&gt;
新的一行。
</code></pre>
<h2>三、文字样式</h2>
<table>
<thead>
<tr>
<th>用途</th>
<th>输入语法</th>
<th>显示效果</th>
</tr>
</thead>
<tbody>
<tr>
<td>粗体</td>
<td><code>**粗体**</code></td>
<td><strong>粗体</strong></td>
</tr>
<tr>
<td>斜体</td>
<td><code>*斜体*</code></td>
<td><em>斜体</em></td>
</tr>
<tr>
<td>粗斜体</td>
<td><code>***粗斜体***</code></td>
<td><em><strong>粗斜体</strong></em></td>
</tr>
<tr>
<td>删除线</td>
<td><code>~~删除线~~</code></td>
<td><s>删除线</s></td>
</tr>
<tr>
<td>高亮（Obsidian）</td>
<td><code>&lt;mark&gt;高亮&lt;/mark&gt;</code></td>
<td>&lt;mark&gt;高亮&lt;/mark&gt;</td>
</tr>
<tr>
<td>行内代码</td>
<td><code>`printf()`</code></td>
<td><code>printf()</code></td>
</tr>
</tbody>
</table>
<p>这些样式可以组合使用：</p>
<pre><code>这是一段 **重要内容**，其中 ==这一部分需要高亮==。
</code></pre>
<p>显示效果：</p>
<p>这是一段 <strong>重要内容</strong>，其中 &lt;mark&gt;这一部分需要高亮&lt;/mark&gt;。</p>
<h2>四、无序列表</h2>
<p>使用 <code>-</code>、<code>*</code> 或 <code>+</code> 加一个空格：</p>
<pre><code>- 苹果
- 香蕉
- 橙子
</code></pre>
<p>显示效果：</p>
<ul>
<li>苹果</li>
<li>香蕉</li>
<li>橙子</li>
</ul>
<p>缩进两个或四个空格，可以创建子列表：</p>
<pre><code>- 嵌入式开发
  - C 语言
  - 单片机
  - 实时操作系统
- 个人成长
  - 时间管理
  - 定期复盘
</code></pre>
<h2>五、有序列表</h2>
<p>使用数字、英文句点和空格：</p>
<pre><code>1. 明确目标
2. 拆分任务
3. 开始行动
4. 总结复盘
</code></pre>
<p>实际输入时全部写成 <code>1.</code> 也可以，Markdown 会自动编号：</p>
<pre><code>1. 第一步
1. 第二步
1. 第三步
</code></pre>
<h2>六、任务清单</h2>
<p>使用 <code>- [ ]</code> 创建未完成任务，使用 <code>- [x]</code> 表示已完成：</p>
<pre><code>- [x] 创建学习计划
- [ ] 阅读第一章
- [ ] 完成练习
- [ ] 总结知识点
</code></pre>
<p>显示效果：</p>
<ul>
<li>[x] 创建学习计划</li>
<li>[ ] 阅读第一章</li>
<li>[ ] 完成练习</li>
<li>[ ] 总结知识点</li>
</ul>
<p>在 Obsidian 阅读视图中，可以直接单击复选框修改任务状态。</p>
<h2>七、引用</h2>
<p>在段落前输入 <code>&gt;</code>：</p>
<pre><code>&gt; 知识只有经过整理和使用，才能逐渐转化为能力。
</code></pre>
<p>显示效果：</p>
<blockquote>
<p>知识只有经过整理和使用，才能逐渐转化为能力。</p>
</blockquote>
<p>引用可以嵌套：</p>
<pre><code>&gt; 第一层引用
&gt;
&gt;&gt; 第二层引用
</code></pre>
<h2>八、行内代码</h2>
<p>用一对反引号包裹短代码、命令、变量名或文件名：</p>
<pre><code>使用 `git status` 查看仓库状态。
变量 `counter` 用于记录循环次数。
</code></pre>
<p>显示效果：</p>
<p>使用 <code>git status</code> 查看仓库状态。变量 <code>counter</code> 用于记录循环次数。</p>
<h2>九、代码块</h2>
<p>使用三反引号包裹多行代码。开头的反引号后可以填写语言名称，以启用语法高亮。</p>
<pre><code>```c
#include &lt;stdio.h&gt;

int main(void)
{
    printf("Hello, Markdown!\n");
    return 0;
}
```
</code></pre>
<p>显示效果：</p>
<pre><code>#include &lt;stdio.h&gt;

int main(void)
{
    printf("Hello, Markdown!\n");
    return 0;
}
</code></pre>
<p>常见语言标识包括：</p>
<table>
<thead>
<tr>
<th>语言或内容</th>
<th>标识</th>
</tr>
</thead>
<tbody>
<tr>
<td>C</td>
<td><code>c</code></td>
</tr>
<tr>
<td>C++</td>
<td><code>cpp</code></td>
</tr>
<tr>
<td>Python</td>
<td><code>python</code></td>
</tr>
<tr>
<td>JavaScript</td>
<td><code>javascript</code> 或 <code>js</code></td>
</tr>
<tr>
<td>JSON</td>
<td><code>json</code></td>
</tr>
<tr>
<td>Shell</td>
<td><code>bash</code> 或 <code>shell</code></td>
</tr>
<tr>
<td>PowerShell</td>
<td><code>powershell</code></td>
</tr>
<tr>
<td>Markdown</td>
<td><code>markdown</code></td>
</tr>
<tr>
<td>纯文本</td>
<td><code>text</code></td>
</tr>
</tbody>
</table>
<h2>十、表格</h2>
<p>使用竖线 <code>|</code> 分隔列，使用连字符 <code>-</code> 分隔表头和内容：</p>
<pre><code>| 名称 | 用途 | 状态 |
| --- | --- | --- |
| GPIO | 数字输入输出 | 已掌握 |
| UART | 串口通信 | 学习中 |
| SPI | 高速同步通信 | 待学习 |
</code></pre>
<p>显示效果：</p>
<table>
<thead>
<tr>
<th>名称</th>
<th>用途</th>
<th>状态</th>
</tr>
</thead>
<tbody>
<tr>
<td>GPIO</td>
<td>数字输入输出</td>
<td>已掌握</td>
</tr>
<tr>
<td>UART</td>
<td>串口通信</td>
<td>学习中</td>
</tr>
<tr>
<td>SPI</td>
<td>高速同步通信</td>
<td>待学习</td>
</tr>
</tbody>
</table>
<p>通过冒号可以设置对齐方式：</p>
<pre><code>| 左对齐 | 居中 | 右对齐 |
| :--- | :---: | ---: |
| 内容 | 内容 | 100 |
</code></pre>
<table>
<thead>
<tr>
<th>左对齐</th>
<th>居中</th>
<th>右对齐</th>
</tr>
</thead>
<tbody>
<tr>
<td>内容</td>
<td>内容</td>
<td>100</td>
</tr>
</tbody>
</table>
<p>{{&lt; admonition note "说明" &gt;}}
表格中的竖线如果不是列分隔符，需要写成 <code>\|</code>。
{{&lt; /admonition &gt;}}</p>
<h2>十一、分隔线</h2>
<p>单独一行输入三个或更多的连字符、星号或下划线：</p>
<pre><code>---
</code></pre>
<p>显示效果：</p>
<hr />
<p>分隔线适合区分主题，但不宜使用过多，标题通常是更清晰的结构工具。</p>
<h2>十二、普通链接</h2>
<p>链接文字放在方括号中，网址放在圆括号中：</p>
<pre><code>[Obsidian 官网](https://obsidian.md)
</code></pre>
<p>显示效果：</p>
<p><a href="https://obsidian.md">Obsidian 官网</a></p>
<p>直接粘贴网址也可以形成链接：</p>
<pre><code>&lt;https://obsidian.md&gt;
</code></pre>
<h2>十三、图片</h2>
<p>Markdown 图片语法比普通链接多一个感叹号：</p>
<pre><code>![图片说明](图片地址)
</code></pre>
<p>网络图片示例：</p>
<pre><code>![示例图片](https://example.com/image.png)
</code></pre>
<p>也可以使用 Obsidian 的嵌入语法显示仓库附件：</p>
<pre><code>![[示例图片.png]]
</code></pre>
<p>指定图片宽度：</p>
<pre><code>![[示例图片.png|400]]
</code></pre>
<h2>十四、Obsidian 双向链接</h2>
<p>使用双方括号链接仓库内的其他笔记：</p>
<pre><code>[[个人成长：建立可持续的进步系统]]
</code></pre>
<p>可以为链接设置显示名称：</p>
<pre><code>[[个人成长：建立可持续的进步系统|个人成长系统]]
</code></pre>
<p>链接到某个标题：</p>
<pre><code>[[嵌入式系统学习路线#二、推荐的实践方式]]
</code></pre>
<p>链接到当前笔记中的标题：</p>
<pre><code>[[#九、代码块]]
</code></pre>
<h2>十五、块链接</h2>
<p>Obsidian 可以链接到一段特定内容。在目标段落末尾添加块标识：</p>
<pre><code>这是一段值得反复引用的重要内容。 ^important
</code></pre>
<p>在其他位置引用：</p>
<pre><code>[[笔记名称#^important]]
</code></pre>
<p>块标识应当简短且唯一，通常使用英文、数字和连字符。</p>
<h2>十六、嵌入其他内容</h2>
<p>在双向链接前添加 <code>!</code>，可以把目标内容直接嵌入当前笔记：</p>
<pre><code>![[另一篇笔记]]
![[另一篇笔记#某个标题]]
![[另一篇笔记#^important]]
</code></pre>
<p>Obsidian 还可以嵌入图片、音频和 PDF：</p>
<pre><code>![[图片.png]]
![[录音.mp3]]
![[文档.pdf]]
![[文档.pdf#page=3]]
</code></pre>
<h2>十七、提示框 Callout</h2>
<p>Callout 是 Obsidian 提供的醒目提示框：</p>
<pre><code>&gt; [!note]
&gt; 这是一条普通说明。

&gt; [!tip] 自定义标题
&gt; 这是一条实用建议。

&gt; [!warning]
&gt; 这里需要特别注意。
</code></pre>
<p>常用类型：</p>
<pre><code>&gt; [!note] 说明
&gt; 补充信息。

&gt; [!abstract] 摘要
&gt; 内容摘要。

&gt; [!info] 信息
&gt; 背景信息。

&gt; [!tip] 技巧
&gt; 实用建议。

&gt; [!success] 成功
&gt; 已经完成。

&gt; [!question] 问题
&gt; 需要进一步思考。

&gt; [!warning] 警告
&gt; 可能存在风险。

&gt; [!danger] 危险
&gt; 必须立即处理。

&gt; [!example] 示例
&gt; 一个具体例子。

&gt; [!quote] 引用
&gt; 引用内容。
</code></pre>
<p>可折叠提示框使用 <code>+</code> 或 <code>-</code>：</p>
<pre><code>&gt; [!faq]- 默认折叠
&gt; 单击标题后展开内容。

&gt; [!note]+ 默认展开
&gt; 这部分内容可以折叠。
</code></pre>
<h2>十八、脚注</h2>
<p>脚注适合补充来源或不便放在正文中的说明：</p>
<pre><code>Markdown 由 John Gruber 创建。[^1]

[^1]: Markdown 最初发布于 2004 年。
</code></pre>
<p>也可以使用行内脚注：</p>
<pre><code>这句话包含一条补充说明。^[这就是行内脚注。]
</code></pre>
<h2>十九、标签</h2>
<p>使用 <code>#</code> 创建标签：</p>
<pre><code>#嵌入式
#个人成长
#学习/编程
</code></pre>
<p>标签中不能包含空格。层级标签使用 <code>/</code> 分隔，例如 <code>#学习/编程</code>。</p>
<p>为了避免标签被识别成标题，正文标签通常放在行内，或者统一写在 YAML 属性中。</p>
<h2>二十、YAML 属性</h2>
<p>笔记开头的一对 <code>---</code> 之间可以保存结构化属性：</p>
<pre><code>---
title: Markdown 语法速查
date: 2026-06-15
tags:
  - Markdown
  - Obsidian
aliases:
  - Markdown 用法
status: 学习中
---
</code></pre>
<p>常见属性包括：</p>
<table>
<thead>
<tr>
<th>属性</th>
<th>用途</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>title</code></td>
<td>笔记标题</td>
</tr>
<tr>
<td><code>date</code></td>
<td>创建或记录日期</td>
</tr>
<tr>
<td><code>tags</code></td>
<td>分类标签</td>
</tr>
<tr>
<td><code>aliases</code></td>
<td>笔记别名</td>
</tr>
<tr>
<td><code>status</code></td>
<td>当前状态</td>
</tr>
<tr>
<td><code>source</code></td>
<td>内容来源</td>
</tr>
</tbody>
</table>
<p>YAML 必须位于文件最开头，冒号后要保留一个空格。</p>
<h2>二十一、数学公式</h2>
<p>Obsidian 使用 LaTeX 语法显示公式。</p>
<p>行内公式使用一对 <code>$</code>：</p>
<pre><code>勾股定理可以写成 $a^2+b^2=c^2$。
</code></pre>
<p>独立公式使用两对 <code>$$</code>：</p>
<pre><code>$$
E = mc^2
$$
</code></pre>
<p>常见写法：</p>
<pre><code>\frac{a}{b}            % 分数
x^2                    % 上标
x_i                    % 下标
\sqrt{x}               % 根号
\sum_{i=1}^{n} x_i     % 求和
\alpha + \beta         % 希腊字母
</code></pre>
<h2>二十二、Mermaid 图表</h2>
<p>Obsidian 可以通过 Mermaid 代码块绘制流程图：</p>
<pre><code>```mermaid
flowchart LR
    A[明确目标] --&gt; B[拆分任务]
    B --&gt; C[开始行动]
    C --&gt; D[获取反馈]
    D --&gt; E[复盘改进]
    E --&gt; B
```
</code></pre>
<p>显示效果：</p>
<pre><code>flowchart LR
    A[明确目标] --&gt; B[拆分任务]
    B --&gt; C[开始行动]
    C --&gt; D[获取反馈]
    D --&gt; E[复盘改进]
    E --&gt; B
</code></pre>
<h2>二十三、注释</h2>
<p>Obsidian 使用两对百分号隐藏注释。注释在编辑模式中可见，在阅读视图中不会显示：</p>
<pre><code>这段内容会正常显示。

%% 这是一条不会在阅读视图中显示的备注。 %%

%%
这里也可以写
多行注释。
%%
</code></pre>
<h2>二十四、转义特殊字符</h2>
<p>如果希望显示 Markdown 符号本身，可以在符号前添加反斜杠 <code>\</code>：</p>
<pre><code>\*这段文字不会变成斜体\*
\# 这不会变成标题
\- 这不会变成列表
</code></pre>
<p>常见需要转义的字符包括：</p>
<pre><code>\  `  *  _  { }  [ ]  &lt; &gt;  ( )  #  +  -  .  !  |
</code></pre>
<h2>二十五、HTML</h2>
<p>多数 Markdown 编辑器允许使用少量 HTML：</p>
<pre><code>&lt;u&gt;下划线文字&lt;/u&gt;
H&lt;sub&gt;2&lt;/sub&gt;O
x&lt;sup&gt;2&lt;/sup&gt;
&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;P&lt;/kbd&gt;
</code></pre>
<p>显示效果：</p>
<p>&lt;u&gt;下划线文字&lt;/u&gt;<br />
H&lt;sub&gt;2&lt;/sub&gt;O<br />
x&lt;sup&gt;2&lt;/sup&gt;<br />
&lt;kbd&gt;Ctrl&lt;/kbd&gt; + &lt;kbd&gt;P&lt;/kbd&gt;</p>
<p>HTML 的兼容性不如标准 Markdown，只有在 Markdown 本身无法表达时再使用。</p>
<h2>二十六、一个完整笔记示例</h2>
<pre><code>---
title: UART 学习记录
date: 2026-06-15
tags:
  - 嵌入式
  - UART
status: 学习中
---

# UART 学习记录

## 今日目标

- [x] 理解基本通信原理
- [ ] 完成串口收发实验

## 核心概念

UART 是一种 **异步串行通信** 方式，常见参数包括：

| 参数 | 示例 |
| --- | --- |
| 波特率 | 115200 |
| 数据位 | 8 |
| 停止位 | 1 |
| 校验位 | 无 |

&gt; [!warning]
&gt; 通信双方的参数必须保持一致。

## 示例代码

```c
printf("Hello UART!\r\n");
```

## 总结

今天掌握了 ==UART 的基本帧结构==，下一步学习中断接收。

相关笔记：[[嵌入式系统学习路线]]
</code></pre>
<h2>二十七、使用建议</h2>
<ol>
<li>使用标题表达内容结构，不要只依赖粗体。</li>
<li>一段只讨论一个主要观点。</li>
<li>用任务清单记录行动，用普通列表记录知识。</li>
<li>用双向链接连接相关主题，不必为每个词都创建链接。</li>
<li>代码块注明语言，以获得更清晰的语法高亮。</li>
<li>表格适合结构化对比，不适合容纳大段文字。</li>
<li>标签用于分类，链接用于表达笔记之间的关系。</li>
<li>优先使用通用 Markdown，需要时再使用 Obsidian 扩展。</li>
</ol>
<h2>快速索引</h2>
<ul>
<li><strong>粗体、斜体、删除线与高亮</strong></li>
<li><strong>任务清单</strong></li>
<li><strong>代码块</strong></li>
<li><strong>表格</strong></li>
<li><strong>双向链接</strong></li>
<li><strong>提示框</strong></li>
<li><strong>YAML 属性</strong></li>
<li><strong>数学公式</strong></li>
<li><strong>Mermaid 图表</strong></li>
</ul>
]]></content>
    <author><name>Key</name></author>
  </entry>
  <entry>
    <title>嵌入式系统学习路线</title>
    <link href="https://blog-21k.pages.dev/posts/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B3%BB%E7%BB%9F%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF/" rel="alternate" type="text/html"/>
    <id>https://blog-21k.pages.dev/posts/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%B3%BB%E7%BB%9F%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF/</id>
    <published>2026-06-15T00:00:00.000Z</published>
    <updated>2026-06-15T00:00:00.000Z</updated>
    <summary></summary>
    <content type="html"><![CDATA[<h1>嵌入式系统学习路线</h1>
<p>嵌入式系统是为特定任务设计的计算机系统。它通常由处理器、存储器、外设接口和软件共同组成，广泛存在于家电、汽车、工业控制、医疗设备和物联网终端中。</p>
<p>学习嵌入式不能只停留在“会调用库函数”。真正重要的是理解：<strong>一段代码如何通过寄存器控制硬件，又如何在有限资源和实时要求下可靠运行。</strong></p>
<h2>一、需要建立的知识体系</h2>
<h3>1. C 语言基础</h3>
<p>C 语言是嵌入式开发最常见的语言，需要重点掌握：</p>
<ul>
<li>指针、数组、结构体和函数指针</li>
<li>位运算与掩码</li>
<li><code>const</code>、<code>static</code>、<code>volatile</code> 等关键字</li>
<li>栈、堆、全局区和静态存储区</li>
<li>编译、链接和可执行文件的生成过程</li>
</ul>
<p>其中，<code>volatile</code> 常用于硬件寄存器和中断共享变量。它告诉编译器：变量可能在程序控制范围之外发生变化，不能随意省略对它的访问。</p>
<h3>2. 数字电路与硬件基础</h3>
<p>软件最终需要运行在真实电路上，因此至少要能够：</p>
<ul>
<li>阅读原理图和芯片数据手册</li>
<li>理解电压、电流、上拉、下拉和高低电平</li>
<li>认识 GPIO、时钟、复位和中断</li>
<li>使用万用表、示波器或逻辑分析仪定位问题</li>
<li>了解 UART、I²C、SPI、CAN 等常见总线</li>
</ul>
<p>遇到故障时，可以按照“电源 → 时钟 → 复位 → 引脚 → 通信 → 软件逻辑”的顺序检查。</p>
<h3>3. 微控制器与外设</h3>
<p>初学阶段可以选择 STM32、ESP32 等资料丰富的平台，依次练习：</p>
<ol>
<li>GPIO 点灯与按键输入</li>
<li>UART 串口收发</li>
<li>定时器与 PWM</li>
<li>外部中断</li>
<li>ADC 和 DMA</li>
<li>I²C、SPI 传感器</li>
<li>看门狗与低功耗</li>
</ol>
<p>每完成一个外设实验，都应该回答三个问题：</p>
<ul>
<li>它依赖哪些时钟和引脚？</li>
<li>核心寄存器或配置项是什么？</li>
<li>出现异常时，怎样观察它的状态？</li>
</ul>
<h3>4. 实时操作系统</h3>
<p>当任务增多后，可以学习 FreeRTOS 等实时操作系统。重点不是记住 API，而是理解：</p>
<ul>
<li>任务和调度</li>
<li>优先级与实时性</li>
<li>队列、信号量和事件</li>
<li>临界区与互斥</li>
<li>死锁、优先级反转和栈溢出</li>
</ul>
<p>裸机程序有助于理解硬件，RTOS 则帮助我们管理复杂性。两者并非互相替代，而是面向不同规模的问题。</p>
<h2>二、推荐的实践方式</h2>
<h3>项目驱动</h3>
<p>比起零散地学习外设，完成一个小项目更容易形成完整认识。例如：</p>
<ul>
<li>温湿度采集与屏幕显示</li>
<li>串口命令控制器</li>
<li>简易数字示波器</li>
<li>电机速度闭环控制</li>
<li>基于传感器的低功耗节点</li>
</ul>
<p>一个完整项目至少应包含需求、模块划分、接口定义、调试记录和结果复盘。</p>
<h3>阅读数据手册</h3>
<p>阅读数据手册时，不必从第一页逐字读到最后。可以先寻找：</p>
<ul>
<li>芯片框图与存储器映射</li>
<li>引脚定义</li>
<li>时钟树</li>
<li>外设功能说明</li>
<li>寄存器描述</li>
<li>电气特性和时序图</li>
</ul>
<p>先带着具体问题查阅，再逐渐建立对芯片的整体认识。</p>
<h3>记录调试过程</h3>
<p>调试记录建议采用以下格式：</p>
<pre><code>现象：
预期：
已经确认：
可能原因：
验证方法：
最终原因：
修复方式：
</code></pre>
<p>这能避免反复尝试同一方案，也能逐渐形成个人故障库。</p>
<h2>三、容易踩的坑</h2>
<ul>
<li>在中断服务函数中执行耗时操作</li>
<li>忘记处理共享变量的并发访问</li>
<li>只依赖延时函数，不考虑状态机和定时器</li>
<li>忽略栈空间、数组边界和内存对齐</li>
<li>只看示例代码，不阅读手册和时序图</li>
<li>修改多个模块后才测试，导致问题难以定位</li>
</ul>
<h2>四、阶段性学习目标</h2>
<ul>
<li>[ ] 能独立阅读简单原理图</li>
<li>[ ] 能用 C 语言实现常见数据结构和状态机</li>
<li>[ ] 能脱离教程驱动常用 MCU 外设</li>
<li>[ ] 能使用调试器观察寄存器、内存和调用栈</li>
<li>[ ] 能定位一次硬件或通信故障</li>
<li>[ ] 能编写一个包含多个任务的 RTOS 项目</li>
<li>[ ] 能说明项目中的资源、实时性和可靠性设计</li>
</ul>
<h2>五、核心认识</h2>
<p>嵌入式能力来自三个层面的结合：</p>
<blockquote>
<p>看得懂硬件，写得出软件，定位得了系统问题。</p>
</blockquote>
<p>学习过程不必追求一次掌握所有知识。更有效的方法是完成小项目、暴露真实问题、记录解决过程，再回到原理中补齐认知。这种积累方式也适用于 <strong>个人成长：建立可持续的进步系统</strong>。</p>
]]></content>
    <author><name>Key</name></author>
  </entry>
</feed>
