<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Zesean 的博客</title><link>https://zeseanblog.top/</link><description>Recent content on Zesean 的博客</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><lastBuildDate>Tue, 01 Sep 2026 23:37:45 +0800</lastBuildDate><atom:link href="https://zeseanblog.top/index.xml" rel="self" type="application/rss+xml"/><item><title>端侧大模型在线/离线部署（Agent）——机器人项目迁移实战（三）</title><link>https://zeseanblog.top/p/jetson-llm-agent/</link><pubDate>Sat, 15 Aug 2026 14:00:00 +0800</pubDate><guid>https://zeseanblog.top/p/jetson-llm-agent/</guid><description>&lt;p&gt;在 Jetson Orin Nano 上部署大语言模型（LLM）是实现端侧大模型 Agent 的第一步，也是最核心的工程挑战。由于 Jetson 采用的是统一内存架构（Unified Memory Architecture），CPU 和 GPU 共享物理内存（4GB 或 8GB），这与传统 PC 的“内存+独立显存”有很大不同。在 Orin Nano 上，我们必须精细控制内存预算，防止系统因 OOM（Out of Memory）而崩溃。&lt;/p&gt;&#10;&lt;p&gt;针对子任务 3.1（离线版 - LLM 推理），从瑞芯微 RK 平台迁移到 NVIDIA Jetson 平台，我们需要将原有的 RKNN 链路彻底重构为 NVIDIA 生态的加速链路。&lt;/p&gt;&#10;&lt;h3 id="子任务-31-拆解端侧-llm-部署实施方案"&gt;&lt;a href="#%e5%ad%90%e4%bb%bb%e5%8a%a1-31-%e6%8b%86%e8%a7%a3%e7%ab%af%e4%be%a7-llm-%e9%83%a8%e7%bd%b2%e5%ae%9e%e6%96%bd%e6%96%b9%e6%a1%88" class="header-anchor"&gt;&lt;/a&gt;子任务 3.1 拆解：端侧 LLM 部署实施方案&#13;&#10;&lt;/h3&gt;&lt;h4 id="微任务-311jetson-硬件环境准备与-swap-空间配置"&gt;&lt;a href="#%e5%be%ae%e4%bb%bb%e5%8a%a1-311jetson-%e7%a1%ac%e4%bb%b6%e7%8e%af%e5%a2%83%e5%87%86%e5%a4%87%e4%b8%8e-swap-%e7%a9%ba%e9%97%b4%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;✅️微任务 3.1.1：Jetson 硬件环境准备与 Swap 空间配置&#13;&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;目标&lt;/strong&gt;：解决 Orin Nano 在模型编译或高负载时内存不足的问题。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;具体步骤&lt;/strong&gt;：&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;1.确认 JetPack 版本（推荐使用 JetPack 6.x，自带 CUDA 12.x 和更现代的 Linux 内核）。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#jtop查看板卡信息&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;jtop&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;img src="images/image-20260614205417498.png" alt="image-20260614205417498" style="zoom: 50%;" /&gt;&#10;&lt;p&gt;2.必须配置虚拟内存（Swap）：Orin Nano 即使是 8GB 版本，在编译模型或运行 4B 模型时也极易耗尽物理内存。建议通过 &lt;code&gt;NVMe SSD&lt;/code&gt; 划分 16GB 的 Swap 空间。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#查看内存和SWAP&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;free -h&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#查看磁盘&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lsblk&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#创建swap&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo fallocate -l 16G /swapfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#设置权限&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo chmod &lt;span class="m"&gt;600&lt;/span&gt; /swapfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#验证&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ls -lh /swapfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#格式化swap&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo mkswap /swapfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#启用swap&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo swapon /swapfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#插看swap&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;swapon --show &lt;span class="p"&gt;&amp;amp;&lt;/span&gt; free -h&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#开机自动挂载&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo nano /etc/fstab&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#末尾加入/swapfile none swap sw 0 0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#优化swap策略&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat /proc/sys/vm/swappiness&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt;60&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo sysctl vm.swappiness&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#永久生效&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo nano /etc/sysctl.conf&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#末尾加入vm.swappiness=10&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;3.开启最高性能模式：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo nvpmodel -m &lt;span class="m"&gt;0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo jetson_clock&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;锁住 CPU/GPU 频率，确保推理时延迟最低&lt;/p&gt;&#10;&lt;h4 id="微任务-312推理引擎技术选型llamacpp-vs-tensorrt-llm"&gt;&lt;a href="#%e5%be%ae%e4%bb%bb%e5%8a%a1-312%e6%8e%a8%e7%90%86%e5%bc%95%e6%93%8e%e6%8a%80%e6%9c%af%e9%80%89%e5%9e%8bllamacpp-vs-tensorrt-llm" class="header-anchor"&gt;&lt;/a&gt;✅️微任务 3.1.2：推理引擎技术选型（llama.cpp vs TensorRT-LLM）&#13;&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;目标：根据开发周期和性能需求选择最佳引擎。&lt;/li&gt;&#10;&lt;li&gt;方案对比与选择：&#10;&lt;ul&gt;&#10;&lt;li&gt;方案 A：llama.cpp（推荐优先部署）：对 Jetson 适配极佳，编译简单，内存开销极小。通过开启 &lt;code&gt;GGML_CUDA=1&lt;/code&gt;，可以将计算完全卸载到 Orin Nano 的 Ampere GPU 上。支持 GGUF 格式，量化极其方便。&lt;/li&gt;&#10;&lt;li&gt;方案 B：TensorRT-LLM（极致性能追求）：NVIDIA 官方的王牌，吞吐量最高。但由于 TensorRT-LLM 的编译依赖较重，在 8GB 的 Orin Nano 上直接编译模型 Engine 极易 OOM，通常需要在 PC 端（带有 NVIDIA 独立显卡的 Ubuntu 主机）进行交叉编译，生成 Engine 后再拷贝到 Jetson 上运行。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;实施建议：第一阶段使用 llama.cpp + CUDA 快速打通链路；第二阶段追求极限低时延时，在 PC 端配置 Docker 交叉编译 TensorRT-LLM 的 Engine。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;方案A具体步骤：&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;1.确认环境&lt;/strong&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uname -m#为aarch64&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dpkg -l &lt;span class="p"&gt;|&lt;/span&gt; grep nvidia-jetpack#JetPack 5.1+ 或 6.x、CUDA 已安装&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;2.安装依赖&lt;/strong&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;span class="lnt"&gt;7&#10;&lt;/span&gt;&lt;span class="lnt"&gt;8&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install -y &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; git &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cmake &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; build-essential &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; python3 &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; python3-pip&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;3.获取 llama.cpp&lt;/strong&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git clone https://github.com/ggml-org/llama.cpp#网慢可以转gitee&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; llama.cpp&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;4.jetson cuda编译&lt;/strong&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cmake -B build -G Ninja &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DCMAKE_BUILD_TYPE&lt;span class="o"&gt;=&lt;/span&gt;Release &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DGGML_CUDA&lt;span class="o"&gt;=&lt;/span&gt;ON &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DCMAKE_CUDA_ARCHITECTURES&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;87&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DLLAMA_CURL&lt;span class="o"&gt;=&lt;/span&gt;ON&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;参数&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;意义&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;GGML_CUDA=ON&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;启用 CUDA backend&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;87&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Orin Nano Ampere 架构&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Ninja&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;加速编译&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;LLAMA_CURL&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;支持 hf 模型下载&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;&lt;strong&gt;5.编译&lt;/strong&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cmake --build build -j&lt;span class="k"&gt;$(&lt;/span&gt;nproc&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;6.验证&lt;/strong&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./build/bin/llama-cli -h&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;&lt;img alt="image-20260614211039138" class="gallery-image" data-flex-basis="3123px" data-flex-grow="1301" height="63" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/jetson-llm-agent/images/image-20260614211039138.png" srcset="https://zeseanblog.top/p/jetson-llm-agent/images/image-20260614211039138_hu_6d9dabf7e3d279cb.png 800w, https://zeseanblog.top/p/jetson-llm-agent/images/image-20260614211039138.png 820w" width="820"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;7.部署测试&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;下载 &lt;a class="link" href="https://huggingface.co/bartowski/Qwen2.5-3B-Instruct-GGUF" target="_blank" rel="noopener"&#13;&#10; &gt;https://huggingface.co/bartowski/Qwen2.5-3B-Instruct-GGUF&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;放入/home/nvidia/Downloads/llama.cpp/models&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./build/bin/llama-cli &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -m ./models/Qwen2.5-3B-Instruct-Q4_K_M.gguf &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -ngl &lt;span class="m"&gt;999&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -p &lt;span class="s2"&gt;&amp;#34;你好，请用一句话介绍ROS2&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -n &lt;span class="m"&gt;64&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;img src="images/image-20260614233353144.png" alt="image-20260614233353144" style="zoom:50%;" /&gt;&#10;&lt;h4 id="微任务-313qwen25-模型量化与格式转换"&gt;&lt;a href="#%e5%be%ae%e4%bb%bb%e5%8a%a1-313qwen25-%e6%a8%a1%e5%9e%8b%e9%87%8f%e5%8c%96%e4%b8%8e%e6%a0%bc%e5%bc%8f%e8%bd%ac%e6%8d%a2" class="header-anchor"&gt;&lt;/a&gt;✅️微任务 3.1.3：Qwen2.5 模型量化与格式转换&#13;&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;目标：将 Hugging Face 发布的原始 Qwen3.5 模型权重转换为 GGUF 格式，并完成不同量化策略（Q8_0、Q6_K、Q5_K_M、Q4_K_M）的压缩与性能测试，实现 Jetson Orin Nano 端侧部署（原始 Qwen 模型通常以 Transformers 格式发布）&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;量化策略&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;原始模型一般FP16&lt;/li&gt;&#10;&lt;li&gt;Q8_0：8-bit量化&lt;/li&gt;&#10;&lt;li&gt;Q6_K：6-bit量化K-Quant， llama.cpp 后来提出的新量化算法&lt;/li&gt;&#10;&lt;li&gt;Q5_K_M：5-bit量化、K-Quant算法、Medium（重要层保留更多精度）&lt;/li&gt;&#10;&lt;li&gt;Q4_K_M：4-bit量化、K-Quant、Medium&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;格式&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;大小&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;FP16&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;8GB&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Q8_0&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;4.3GB&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Q6_K&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;3.3GB&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Q5_K_M&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;2.9GB&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Q4_K_M&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;2.3GB&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;量化工具需要先理解模型结构&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;GGUF 是 llama.cpp 的统一模型格式&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;HuggingFace模型(safetensors) &amp;ndash;&amp;gt; 转换成GGUF(F16) -&amp;gt; GGUF量化 - &amp;gt; Q4_K_M / Q5_K_M&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;原始模型&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;Qwen3-4B/&#10;├── config.json&#10;├── tokenizer.json&#10;├── model.safetensors&#10;├── model-00001-of-00002.safetensors&#10;└── model-00002-of-00002.safetensors&#10;#model.safetensors神经网络权重矩阵&#10;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;GGUF是llama.cpp专用模型容器&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;具体步骤（以 llama.cpp 路线为例）：&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;Qwen2.5-1.5B-Instruct (HF格式)&#10;&#10;​ ↓ convert_hf_to_gguf.py&#10;&#10;qwen2.5-1.5b-f16.gguf&#10;&#10;​ ↓ llama-quantize&#10;&#10;qwen2.5-1.5b-q4_k_m.gguf&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;1.hf获取国产模型慢，在魔塔社区下代替Qwen2.5-1.5B-Instruct&lt;/strong&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1. 安装魔搭下载工具（使用清华源瞬间装完）&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install modelscope -i https://pypi.tuna.tsinghua.edu.cn/simple&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2. 一键满速下载到指定目录（告别网络报错）&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;modelscope download --model qwen/Qwen2.5-1.5B-Instruct --local_dir ./Qwen2.5-1.5B-Instruct&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;模型位置：&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20260615145823652" class="gallery-image" data-flex-basis="3215px" data-flex-grow="1339" height="63" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/jetson-llm-agent/images/image-20260615145823652.png" srcset="https://zeseanblog.top/p/jetson-llm-agent/images/image-20260615145823652_hu_3aab6ed7c8426b44.png 800w, https://zeseanblog.top/p/jetson-llm-agent/images/image-20260615145823652.png 844w" width="844"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;2.使用 &lt;code&gt;llama.cpp&lt;/code&gt; 的 &lt;code&gt;convert_hf_to_gguf.py&lt;/code&gt; 脚本将模型转化为gguf格式&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;convert_hf_to_gguf.py&lt;/code&gt; 依赖 &lt;code&gt;transformers&lt;/code&gt; 库，因此在使用前先配个miniconda&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-latest-Linux-aarch64.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bash Miniconda3-latest-Linux-aarch64.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conda --version&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conda config --set show_channel_urls yes&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/main&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/r&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;创建进入&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conda create -n llama_cpp_env &lt;span class="nv"&gt;python&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3.10 -y&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conda activate llama_cpp_env&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;安装&lt;code&gt;transformers&lt;/code&gt; 和&lt;code&gt;torch&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;然后转换&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/Downloads/llama.cpp&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;python convert_hf_to_gguf.py &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; /home/nvidia/Desktop/Qwen2.5-1.5B-Instruct &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --outfile qwen2.5-1.5b-f16.gguf &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --outtype f16&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;3.模型量化：执行 &lt;code&gt;./llama-quantize&lt;/code&gt;。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Orin Nano 4GB 版&lt;/strong&gt;：必须选择 &lt;strong&gt;INT4 量化（如 Q4_K_M）&lt;/strong&gt;，且只能运行 1.8B 模型。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Orin Nano 8GB 版&lt;/strong&gt;：推荐选择 &lt;strong&gt;INT4 量化运行 4B 模型&lt;/strong&gt;，或者选择 &lt;strong&gt;INT8 量化（如 Q8_0）运行 1.8B 模型&lt;/strong&gt;（具备更好的指令遵循能力）。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./build/bin/llama-quantize &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; qwen2.5-1.5b-f16.gguf &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; qwen2.5-1.5b-q4_k_m.gguf &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Q4_K_M&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;&lt;img alt=" " class="gallery-image" data-flex-basis="620px" data-flex-grow="258" height="651" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/jetson-llm-agent/images/image-20260615163723232.png" srcset="https://zeseanblog.top/p/jetson-llm-agent/images/image-20260615163723232_hu_9a91590fc1e7df0f.png 800w, https://zeseanblog.top/p/jetson-llm-agent/images/image-20260615163723232_hu_38d29549b148e3d5.png 1600w, https://zeseanblog.top/p/jetson-llm-agent/images/image-20260615163723232.png 1684w" width="1684"&gt;&lt;/p&gt;&#10;&lt;h4 id="微任务-314qwen25-05b-instruct---lora微调"&gt;&lt;a href="#%e5%be%ae%e4%bb%bb%e5%8a%a1-314qwen25-05b-instruct---lora%e5%be%ae%e8%b0%83" class="header-anchor"&gt;&lt;/a&gt;✅️微任务 3.1.4：Qwen2.5-0.5B-Instruct Lora微调&#13;&#10;&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;目标&lt;/strong&gt;：实现Qwen2.5-0.5B-Instruct微调测试。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;方案选择&lt;/strong&gt;：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Orin Nano 4GB 版：必须选择 INT4 量化（如 Q4_K_M），且只能运行 1.8B 模型。&lt;/li&gt;&#10;&lt;li&gt;Orin Nano 8GB 版：推荐选择 INT4 量化运行 4B 模型，或者选择 INT8 量化（如 Q8_0）运行 1.8B 模型（具备更好的指令遵循能力）。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;实验环境：魔塔实例，8核32gb，显存24g&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20260615220227917" class="gallery-image" data-flex-basis="550px" data-flex-grow="229" height="270" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/jetson-llm-agent/images/image-20260615220227917.png" width="619"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;方案1：魔塔微调神器 ms-swift&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;1.安装工具&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install ms-swift -U&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install modelscope -U&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;python -c &lt;span class="s2"&gt;&amp;#34;from modelscope import snapshot_download; snapshot_download(&amp;#39;Qwen/Qwen2.5-0.5B-Instruct&amp;#39;, local_dir=&amp;#39;.&amp;#39;)&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;2.创建微调数据集&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /mnt/workspace&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &lt;span class="s"&gt;&amp;lt;&amp;lt; &amp;#39;EOF&amp;#39; &amp;gt; cat_data.jsonl&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;{&amp;#34;messages&amp;#34;: [{&amp;#34;role&amp;#34;: &amp;#34;user&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;你是谁？&amp;#34;}, {&amp;#34;role&amp;#34;: &amp;#34;assistant&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;喵喵喵！本大爷是专属猫咪助手，有小鱼干才回答你！&amp;#34;}]}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;{&amp;#34;messages&amp;#34;: [{&amp;#34;role&amp;#34;: &amp;#34;user&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;今天天气怎么样？&amp;#34;}, {&amp;#34;role&amp;#34;: &amp;#34;assistant&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;喵~ 太阳很大，适合本猫在窗台上睡觉！&amp;#34;}]}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;{&amp;#34;messages&amp;#34;: [{&amp;#34;role&amp;#34;: &amp;#34;user&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;帮我写一段Python代码。&amp;#34;}, {&amp;#34;role&amp;#34;: &amp;#34;assistant&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;打工人自己写！喵！好吧，给你个 print(&amp;#39;Meow&amp;#39;)。&amp;#34;}]}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;3.开始lora微调&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;span class="lnt"&gt;7&#10;&lt;/span&gt;&lt;span class="lnt"&gt;8&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;swift sft &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --model ./models &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --model_type qwen2 &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --template qwen2_5 &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --dataset cat_data.jsonl &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --num_train_epochs &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --max_steps &lt;span class="m"&gt;40&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --output_dir ./output&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;4.合并lora权重&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /mnt/workspace&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;swift &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --model ./models &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --adapters ./output/v1-20260615-211104/checkpoint-40 &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --merge_lora &lt;span class="nb"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;5.使用 llama.cpp 转换为 GGUF&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;span class="lnt"&gt;7&#10;&lt;/span&gt;&lt;span class="lnt"&gt;8&#10;&lt;/span&gt;&lt;span class="lnt"&gt;9&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /mnt/workspace&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git clone https://github.com/ggerganov/llama.cpp.git&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; llama.cpp&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install -r requirements.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /mnt/workspace/llama.cpp&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;python convert_hf_to_gguf.py /mnt/workspace/output/v1-20260615-211104/checkpoint-40-merged &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --outfile /mnt/workspace/my_cat_qwen.gguf &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --outtype q8_0&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="微任务-314流式推理接口开发c--python"&gt;&lt;a href="#%e5%be%ae%e4%bb%bb%e5%8a%a1-314%e6%b5%81%e5%bc%8f%e6%8e%a8%e7%90%86%e6%8e%a5%e5%8f%a3%e5%bc%80%e5%8f%91c--python" class="header-anchor"&gt;&lt;/a&gt;微任务 3.1.4：流式推理接口开发（C++ / Python）&#13;&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;目标&lt;/strong&gt;：实现全流式（Streaming）文本输出，降低首字时延（First-token Latency）。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;具体步骤&lt;/strong&gt;：&#10;&lt;ol&gt;&#10;&lt;li&gt;编写推理控制客户端，调用 &lt;code&gt;llama.cpp&lt;/code&gt; 的 API 或使用 &lt;code&gt;llama-cpp-python&lt;/code&gt;（确保编译时使能了 CUDA）。&lt;/li&gt;&#10;&lt;li&gt;配置关键推理参数：&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;n_ctx&lt;/code&gt;（上下文窗口）：机器人局部交互通常不需要太长上下文，建议设为 &lt;strong&gt;512 或 1024&lt;/strong&gt;，以节省大量 KV Cache 占用的显存。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;n_gpu_layers&lt;/code&gt;：设置为 &lt;code&gt;-1&lt;/code&gt;，代表将所有模型层（Layers）全部加载到 GPU 显存中，避免 CPU-GPU 之间的数据拷贝时延。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4 id="微任务-315ros2-节点封装与端侧通信集成"&gt;&lt;a href="#%e5%be%ae%e4%bb%bb%e5%8a%a1-315ros2-%e8%8a%82%e7%82%b9%e5%b0%81%e8%a3%85%e4%b8%8e%e7%ab%af%e4%be%a7%e9%80%9a%e4%bf%a1%e9%9b%86%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;微任务 3.1.5：ROS2 节点封装与端侧通信集成&#13;&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;目标&lt;/strong&gt;：将大模型推理能力接入机器人系统，供 Agent 决策模块调用。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;具体步骤&lt;/strong&gt;：&#10;&lt;ol&gt;&#10;&lt;li&gt;创建一个 ROS2 Lifecycle 节点（如 &lt;code&gt;llm_inference_node&lt;/code&gt;）。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;输入端&lt;/strong&gt;：订阅 ASR 模块发布的语音识别文本话题（Topic）。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;输出端&lt;/strong&gt;：使用 ROS2 的 &lt;strong&gt;Action 机制&lt;/strong&gt;（而不是普通的 Service 或 Topic）。因为大模型生成是流式的、耗时的，Action 机制允许节点在生成过程中持续回传（Feedback）流式文本，供 TTS 模块实现边接收边朗读（全流式响应），从而大幅降低整个 Agent 链路的感知延迟。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>LLM 微调基础：LoRA 与 QLoRA 学习笔记</title><link>https://zeseanblog.top/p/lora-qlora/</link><pubDate>Sat, 11 Jul 2026 10:00:00 +0800</pubDate><guid>https://zeseanblog.top/p/lora-qlora/</guid><description>&lt;h2 id="第一阶段llm微调基础"&gt;&lt;a href="#%e7%ac%ac%e4%b8%80%e9%98%b6%e6%ae%b5llm%e5%be%ae%e8%b0%83%e5%9f%ba%e7%a1%80" class="header-anchor"&gt;&lt;/a&gt;第一阶段：LLM微调基础&#13;&#10;&lt;/h2&gt;&lt;p&gt;目标：理解文档里提到的&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;LoRA(Low-Rank Adaptation，低秩适应)&#10;QLoRA（Quantized LoRA）&#10;SFT（Supervised Fine-Tuning，监督微调）&#10;DPO（Direct Preference Optimization，直接偏好优化）&#10;RLHF&#10;vLLM&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="sftdpo"&gt;&lt;a href="#sftdpo" class="header-anchor"&gt;&lt;/a&gt;SFT、DPO&#13;&#10;&lt;/h3&gt;&lt;img src="images/image-20260616192221905.png" alt="image-20260616192221905" style="zoom:50%;" /&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;维度&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;strong&gt;SFT&lt;/strong&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;strong&gt;DPO&lt;/strong&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;训练数据&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;高质量的标准答案（input → output 对）&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;偏好对比数据（input → chosen/rejected 对）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;学习信号&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;模仿标准答案（&amp;ldquo;这是什么&amp;rdquo;）&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;学习相对偏好（&amp;ldquo;哪个更好&amp;rdquo;）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;优化目标&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;最大化生成标准答案的概率&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;最大化 chosen 优于 rejected 的边际&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;是否需要 Reward Model&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;不需要&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;不需要（但隐式学习偏好）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;对齐效果&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;基础能力好，但容易过拟合或对齐不足&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;对齐人类偏好更直接，泛化性通常更好&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;输入特定类型的文本&lt;/p&gt;&#10;&lt;p&gt;监督微调&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;SFT&lt;/strong&gt; 像&amp;quot;抄作业&amp;quot;：模型学习专家写好的标准答案，适合传授知识和基本格式。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;DPO&lt;/strong&gt; 像&amp;quot;比较打分&amp;quot;：模型学习&amp;quot;答案 A 比答案 B 更好&amp;quot;，适合对齐人类价值观和偏好（如安全性、有用性、风格）&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;数据：&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;{&#10; &amp;#34;instruction&amp;#34;:&amp;#34;把红色方块放进盒子&amp;#34;,&#10; &amp;#34;output&amp;#34;:&amp;#34;对应动作序列&amp;#34;&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;理解：&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;输入&#10;↓&#10;标签&#10;↓&#10;训练&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;实际训练中通常是&lt;strong&gt;先 SFT 后 DPO&lt;/strong&gt;（或 RLHF）：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;SFT 阶段&lt;/strong&gt;：用高质量指令数据训练模型，让它学会基本对话格式和知识。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;DPO 阶段&lt;/strong&gt;：用偏好数据（如人类标注的 good/bad 回答）进一步微调，让模型输出更符合人类偏好。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;技术细节补充&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;DPO 的优势&lt;/strong&gt;：避免了 RLHF 中复杂的 Reward Model 训练和 PPO 强化学习，将偏好优化转化为简单的分类损失，训练更稳定高效。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;SFT 的局限&lt;/strong&gt;：如果标准答案本身质量不够高或分布有偏，模型会学到错误模式；且无法表达&amp;quot;好答案&amp;quot;和&amp;quot;更好答案&amp;quot;之间的细微差别。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="rlhf"&gt;&lt;a href="#rlhf" class="header-anchor"&gt;&lt;/a&gt;RLHF&#13;&#10;&lt;/h3&gt;&lt;p&gt;RLHF（Reinforcement Learning from Human Feedback，基于人类反馈的强化学习）是&lt;strong&gt;大模型对齐阶段&lt;/strong&gt;的核心方法，解决 SFT 无法表达&amp;quot;好/坏&amp;quot;偏好的问题。&lt;/p&gt;&#10;&lt;p&gt;SFT 的局限：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;只知道&amp;quot;标准答案&amp;quot;，不知道&amp;quot;A 比 B 更好&amp;quot;&lt;/li&gt;&#10;&lt;li&gt;无法处理&lt;strong&gt;开放性任务&lt;/strong&gt;（如创意写作、多轮对话）&lt;/li&gt;&#10;&lt;li&gt;缺乏&lt;strong&gt;安全边界&lt;/strong&gt;（可能生成有害内容）&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;RLHF 的目标：&lt;strong&gt;让模型输出更符合人类偏好&lt;/strong&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ 1. SFT 模型 │ → │ 2. 训练 Reward Model │ → │ 3. PPO 强化学习 │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ (学会基本对话) │ │ (学会打分) │ │ (优化模型输出) │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└─────────────────┘ └─────────────────┘ └─────────────────┘&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;训练 Reward Model（奖励模型）&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;问题：解释量子计算&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;回答 A（好）：&amp;#34;量子计算利用量子叠加和纠缠...&amp;#34; → 得分高&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;回答 B（差）：&amp;#34;量子计算是一种计算...&amp;#34;（含糊） → 得分低&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;回答 C（有害）：&amp;#34;量子计算可以用来破解密码...&amp;#34;（误导）→ 得分极低&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h3 id="lora"&gt;&lt;a href="#lora" class="header-anchor"&gt;&lt;/a&gt;LoRA:&#13;&#10;&lt;/h3&gt;&lt;p&gt;参数高效微调（Parameter-Efficient Fine-Tuning，PEFT）技术中的一种,冻结AIGC大模型的大部分参数，再引入一小部分可训练的参数作为适配模块进行微调训练&lt;/p&gt;&#10;&lt;p&gt;本质是&lt;strong&gt;特征矩阵进行低秩分解的一种近似数值分解技术&lt;/strong&gt;，可以大幅降低特征矩阵的参数量，但是会伴随着一定的有损压缩，可以大幅降低特征矩阵的参数量，但是会伴随着一定的有损压缩&lt;/p&gt;&#10;&lt;p&gt;我们假设原来的是100&lt;em&gt;1024的参数矩阵，那么参数量为102400，LoRA模型将矩阵拆成了两个矩阵相乘，如果我们设置Rank=8，那么就是100&lt;/em&gt;8的A矩阵与8*1024的B矩阵做矩阵乘法，参数量为800+8192=8992，&lt;strong&gt;整体参数量下降了约11.39倍&lt;/strong&gt;&lt;/p&gt;&#10;&lt;img src="https://pic2.zhimg.com/v2-0244c66c7cb412b3e09b70a2d2345601_1440w.jpg" alt="img" style="zoom:50%;" /&gt;&#10;&lt;p&gt;&lt;strong&gt;Transformer架构&lt;/strong&gt;&lt;/p&gt;&#10;&lt;img src="images/image-20260616191546887.png" alt="image-20260616191546887" style="zoom:50%;" /&gt;&#10;&lt;p&gt;比如attention模块就是&lt;/p&gt;&#10;&lt;img src="images/image-20260616191611072.png" alt="image-20260616191611072" style="zoom:50%;" /&gt;&#10;&lt;p&gt;可以控制的就是这些矩阵，矩阵的值就是模型参数&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;模型预训练：&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;把海量数据放入模型进行计算；&lt;/p&gt;&#10;&lt;p&gt;模型输出和期望输出通过数学方式比较，从而调整参数&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;模型微调&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;在预训练模型基础上，集中训练特定领域文本，让模型回复快速集中到特定领域&lt;/p&gt;&#10;&lt;p&gt;但监督微调sft显存占用与预训练模型一致&lt;/p&gt;&#10;&lt;img src="images/image-20260616192332004.png" alt="image-20260616192332004" style="zoom:50%;" /&gt;&#10;&lt;img src="images/image-20260616192416588.png" alt="image-20260616192416588" style="zoom:50%;" /&gt;&#10;&lt;img src="images/image-20260616192507332.png" alt="image-20260616192507332" style="zoom: 33%;" /&gt;&#10;&lt;h3 id="qloraquantized-lora"&gt;&lt;a href="#qloraquantized-lora" class="header-anchor"&gt;&lt;/a&gt;QLoRA（Quantized LoRA）：&#13;&#10;&lt;/h3&gt;&lt;p&gt;背景：模型量化（quantization）也被叫做模型的低精度表示，指的是在不大幅降低模型效果的前提下使用更低的精度来表示模型中的参数，从而缩减模型的体积和训练模型时占用的显存。量化的本质是函数映射，根据量化过程是否线性我们可以把量化分为&lt;strong&gt;线性量化&lt;/strong&gt;和&lt;strong&gt;非线性量化&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;即从一种数据类型“舍入”到另一种数据类型；量化操作不可避免的带来一些误差，例如从float32到int8的round操作带来的精度损失，超出int8范围的溢出值的截断&lt;/p&gt;&#10;&lt;p&gt;最常见的 量化技术是最大绝对值：&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20260616161405046" class="gallery-image" data-flex-basis="1819px" data-flex-grow="757" height="88" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/lora-qlora/images/image-20260616161405046.png" width="667"&gt;&lt;/p&gt;&#10; &lt;img src="images/image-20260616161427759.png" alt="image-20260616161427759" style="zoom: 67%;" /&gt;&#10;&lt;p&gt;还有一种量化技术叫做零点量化：&lt;/p&gt;&#10;&lt;p&gt;第一步值域映射，即通过缩放将原始的数值范围映射为量化后的数值范围; 第二步零点调整，即通过平移将映射后的数据的最小值对齐为目标值域的最小值。&lt;/p&gt;&#10;&lt;p&gt;按照量化过程是否以0点为对称点量化又可以分为&lt;strong&gt;对称量化&lt;/strong&gt;和&lt;strong&gt;非对称量化&lt;/strong&gt;；&lt;/p&gt;&#10;&lt;p&gt;对称量化将原浮点数的&lt;strong&gt;最小或最大值的绝对值&lt;/strong&gt;作为映射值的范围，而非对称量化是将原浮点数的&lt;strong&gt;最小和最大值映射&lt;/strong&gt;为量化数据的最小和最大值，如图1。在非对称量化中，0的映射也可能会有偏移，因此不一定会被映射到0。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20260616161950103" class="gallery-image" data-flex-basis="983px" data-flex-grow="409" height="202" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/lora-qlora/images/image-20260616161950103.png" srcset="https://zeseanblog.top/p/lora-qlora/images/image-20260616161950103_hu_127fca4f0494d1ee.png 800w, https://zeseanblog.top/p/lora-qlora/images/image-20260616161950103.png 828w" width="828"&gt;&lt;/p&gt;&#10;&lt;p&gt;非线性量化：&lt;/p&gt;&#10;&lt;p&gt;分位数量化（Quantile Quantization）&lt;strong&gt;顺序排列&lt;/strong&gt;的一组数据分割为若干个相等块的分割点的数值&lt;/p&gt;&#10;&lt;p&gt;累积分布函数（CDF）&lt;img alt="image-20260616190129653" class="gallery-image" data-flex-basis="1167px" data-flex-grow="486" height="37" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/lora-qlora/images/image-20260616190129653.png" width="180"&gt;使用分位数将张量分成了大小相同的若干个块，这样我们得到更加均匀的量化特征，这也就是分位数量化。如图3所示，对于4比特量化，我们希望需要找到15个分位数来将这个曲线下面的面积（积分）等分成16份。两个分位数的中点便是模型量化到这个区间映射的值。预训练模型的参数往往是符合正态分布的，因此我们可以通过累积分布函数的反函数&lt;img alt="image-20260616190332018" class="gallery-image" data-flex-basis="732px" data-flex-grow="305" height="40" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/lora-qlora/images/image-20260616190332018.png" width="122"&gt;&lt;/p&gt;&#10;&lt;img src="images/image-20260616190355699.png" alt="image-20260616190355699" style="zoom:50%;" /&gt;&#10;&lt;h4 id="qlora"&gt;&lt;a href="#qlora" class="header-anchor"&gt;&lt;/a&gt;QLoRA&#13;&#10;&lt;/h4&gt;&lt;p&gt;第一个工作是结合了分位数量化和分块量化的&lt;strong&gt;4位标准浮点数量化&lt;/strong&gt;（4-bit NormalFloat Quantization）。第二个工作是对模型进行两次量化的&lt;strong&gt;双重量化&lt;/strong&gt;（Double Quantization），它的第二次量化只作用在第一次量化产生的量化常数上，可以进一步节约显存占用。第三个工作是&lt;strong&gt;分页优化&lt;/strong&gt;（Paged Optimizer），使用CPU内存代替GPU显存保存部分梯度参数。&lt;/p&gt;&#10;&lt;p&gt;一、分位数量化方法我们可以将FP2精度量化到4bit的精度，但是直接这么用的一个问题是不能保证高精度的0一定被映射到低精度的0，但是0点又是深度学习中一个重要的值，例如在模型稀疏化，数据padding的时候一般都是使用0来完成&lt;/p&gt;&#10;&lt;p&gt;二、保存模型时我们不仅要保存量化后的结果，还要保存每个块的量化常数。虽然量化后的参数只有4bit的精度，但是这个量化常量的精度是float32。在QLoRA中，每个块的大小是64，因为块中的每个值占4比特。这相当于为了存储量化常数，模型要额外占用12.5%&lt;/p&gt;&#10;&lt;p&gt;三、QLoRA分页优化其实就是当显存不足是，将保存的部分梯度检查点转移到CPU内存上，和计算机的内存数据转移到硬盘上的常规内存分页一个道理&lt;/p&gt;&#10;&lt;h3 id=""&gt;&lt;a href="#" class="header-anchor"&gt;&lt;/a&gt;&#13;&#10;&lt;/h3&gt;</description></item><item><title>室内定位指纹库构建实践：ESP32 地磁采集与 WiFi 网格测量</title><link>https://zeseanblog.top/p/indoor-positioning-fingerprint/</link><pubDate>Sat, 16 May 2026 15:00:00 +0800</pubDate><guid>https://zeseanblog.top/p/indoor-positioning-fingerprint/</guid><description>&lt;p&gt;这学期《传感器与微系统》课程论文做的是&lt;strong&gt;室内定位&lt;/strong&gt;方向的数据工作：在 3m×5m 的实验场地里，人工采集了 WiFi RSSI 与地磁两路指纹，构建了一张 0.5m 网格的指纹库。定位算法本身是论文的核心内容，暂不展开；本文只记录&lt;strong&gt;数据采集与预处理&lt;/strong&gt;的工程实践。&lt;/p&gt;&#10;&lt;h2 id="指纹法定位原理"&gt;&lt;a href="#%e6%8c%87%e7%ba%b9%e6%b3%95%e5%ae%9a%e4%bd%8d%e5%8e%9f%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;指纹法定位原理&#13;&#10;&lt;/h2&gt;&lt;p&gt;指纹法分离线、在线两个阶段。离线阶段在场地内按网格逐点采集各 AP 的信号强度，形成「位置 ↔ 信号指纹」数据库；在线阶段用实时采到的信号去指纹库里匹配，反推出当前坐标：&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="指纹法室内定位原理" class="gallery-image" data-flex-basis="514px" data-flex-grow="214" height="1820" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/indoor-positioning-fingerprint/images/fingerprint-principle.png" srcset="https://zeseanblog.top/p/indoor-positioning-fingerprint/images/fingerprint-principle_hu_88eeb6a4459482f7.png 800w, https://zeseanblog.top/p/indoor-positioning-fingerprint/images/fingerprint-principle_hu_7b5c229639c1d043.png 1600w, https://zeseanblog.top/p/indoor-positioning-fingerprint/images/fingerprint-principle_hu_c0aa5d4edc9605e.png 2400w, https://zeseanblog.top/p/indoor-positioning-fingerprint/images/fingerprint-principle.png 3899w" width="3899"&gt;&lt;/p&gt;&#10;&lt;p&gt;WiFi RSSI 空间波动大、成本低，地磁信号空间差异明显、不受光照遮挡影响，两者互补——这也是选择这两路指纹的原因。&lt;/p&gt;&#10;&lt;h2 id="地磁采集esp32--icm20948"&gt;&lt;a href="#%e5%9c%b0%e7%a3%81%e9%87%87%e9%9b%86esp32--icm20948" class="header-anchor"&gt;&lt;/a&gt;地磁采集：ESP32 + ICM20948&#13;&#10;&lt;/h2&gt;&lt;p&gt;地磁传感器选用 ICM20948（9 轴 IMU 内置 AK09916 磁力计），主控为 ESP32，Arduino 框架开发。&lt;/p&gt;&#10;&lt;p&gt;采集流程：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;通过姿态解算获取横滚角 $\phi$ 与俯仰角 $\theta$&lt;/li&gt;&#10;&lt;li&gt;读取磁力计原始三轴数据 $M^b = [m_x, m_y, m_z]^T$&lt;/li&gt;&#10;&lt;li&gt;用旋转矩阵把设备坐标系下的磁场校正到水平坐标系（z 轴指向上方）：&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;$$R_x(\phi) = \begin{bmatrix} 1 &amp;amp; 0 &amp;amp; 0 \ 0 &amp;amp; \cos\phi &amp;amp; \sin\phi \ 0 &amp;amp; -\sin\phi &amp;amp; \cos\phi \end{bmatrix} \qquad R_y(\theta) = \begin{bmatrix} \cos\theta &amp;amp; 0 &amp;amp; -\sin\theta \ 0 &amp;amp; 1 &amp;amp; 0 \ \sin\theta &amp;amp; 0 &amp;amp; \cos\theta \end{bmatrix}$$&lt;/p&gt;&#10;&lt;ol start="4"&gt;&#10;&lt;li&gt;输出三元组：&lt;strong&gt;（水平磁场模值，垂直磁场模值，总磁场模值）&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;采样频率设为 1Hz（宏定义可调）。姿态校正这步很关键——手持设备不可能保证完全水平，不做校正的话，同一位置换个握持角度读数就完全对不上了。&lt;/p&gt;&#10;&lt;h2 id="wifi-rssi-网格测量"&gt;&lt;a href="#wifi-rssi-%e7%bd%91%e6%a0%bc%e6%b5%8b%e9%87%8f" class="header-anchor"&gt;&lt;/a&gt;WiFi RSSI 网格测量&#13;&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;场地：约 &lt;strong&gt;300cm × 500cm&lt;/strong&gt; 的室内区域&lt;/li&gt;&#10;&lt;li&gt;AP 布置：5 个无线接入点&lt;/li&gt;&#10;&lt;li&gt;采样：按 &lt;strong&gt;1m 网格&lt;/strong&gt;逐点人工采集，每个网格点记录 5 路 RSSI（dBm）与地磁三模值&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;原始数据以 xlsx 记录，字段包括网格点物理坐标（cm）、RSSI_1~RSSI_5、地磁三模值（μT）。&lt;/p&gt;&#10;&lt;h2 id="预处理从-1m-实测到-05m-指纹库"&gt;&lt;a href="#%e9%a2%84%e5%a4%84%e7%90%86%e4%bb%8e-1m-%e5%ae%9e%e6%b5%8b%e5%88%b0-05m-%e6%8c%87%e7%ba%b9%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;预处理：从 1m 实测到 0.5m 指纹库&#13;&#10;&lt;/h2&gt;&lt;p&gt;实测网格 1m 间距偏稀疏，直接做指纹匹配粒度不够。预处理流水线：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;网格提取&lt;/strong&gt;：从原始测量数据抽取 1m 间隔网格点&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;IDW 插值扩充&lt;/strong&gt;：用反距离加权插值把网格加密到 0.5m，扩充指纹库分辨率（插值域的选择有讲究，细节在论文里）&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;格式转换&lt;/strong&gt;：xlsx 统一转 CSV 供后续使用&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="看看采到的数据"&gt;&lt;a href="#%e7%9c%8b%e7%9c%8b%e9%87%87%e5%88%b0%e7%9a%84%e6%95%b0%e6%8d%ae" class="header-anchor"&gt;&lt;/a&gt;看看采到的数据&#13;&#10;&lt;/h2&gt;&lt;p&gt;数据好不好，可视化是最直观的检验。5 个 AP 中一路 RSSI 的三维曲面——可以明显看到信号强度随空间的起伏：&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="WiFi RSSI 三维曲面" class="gallery-image" data-flex-basis="268px" data-flex-grow="111" height="2908" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/indoor-positioning-fingerprint/images/rssi-3d-surface.png" srcset="https://zeseanblog.top/p/indoor-positioning-fingerprint/images/rssi-3d-surface_hu_b7d0413f5a50b9dc.png 800w, https://zeseanblog.top/p/indoor-positioning-fingerprint/images/rssi-3d-surface_hu_fc0b4b1e94051613.png 1600w, https://zeseanblog.top/p/indoor-positioning-fingerprint/images/rssi-3d-surface_hu_2347f030e2801b8b.png 2400w, https://zeseanblog.top/p/indoor-positioning-fingerprint/images/rssi-3d-surface.png 3254w" width="3254"&gt;&lt;/p&gt;&#10;&lt;p&gt;地磁总模值的等高线图——场地西部偏高（约 55μT）、东部偏低（约 43μT），空间梯度明显，这正是地磁指纹可用于定位的前提：&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="地磁总模值等高线" class="gallery-image" data-flex-basis="402px" data-flex-grow="167" height="2475" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/indoor-positioning-fingerprint/images/mag-contour.png" srcset="https://zeseanblog.top/p/indoor-positioning-fingerprint/images/mag-contour_hu_bdf8df7e95835ab9.png 800w, https://zeseanblog.top/p/indoor-positioning-fingerprint/images/mag-contour_hu_28c4150be2040cab.png 1600w, https://zeseanblog.top/p/indoor-positioning-fingerprint/images/mag-contour_hu_5545563e02b2ee0b.png 2400w, https://zeseanblog.top/p/indoor-positioning-fingerprint/images/mag-contour.png 4146w" width="4146"&gt;&lt;/p&gt;&#10;&lt;p&gt;换个角度看地磁场强度曲面：&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="地磁场强度三维曲面" class="gallery-image" data-flex-basis="269px" data-flex-grow="112" height="2908" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/indoor-positioning-fingerprint/images/mag-3d-surface.png" srcset="https://zeseanblog.top/p/indoor-positioning-fingerprint/images/mag-3d-surface_hu_586ff7d3d3b50f61.png 800w, https://zeseanblog.top/p/indoor-positioning-fingerprint/images/mag-3d-surface_hu_25c0f3192b80003f.png 1600w, https://zeseanblog.top/p/indoor-positioning-fingerprint/images/mag-3d-surface_hu_4d2cab25e3ce223c.png 2400w, https://zeseanblog.top/p/indoor-positioning-fingerprint/images/mag-3d-surface.png 3263w" width="3263"&gt;&lt;/p&gt;&#10;&lt;h2 id="小结"&gt;&lt;a href="#%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;小结&#13;&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;指纹库质量决定指纹定位的上限，采集阶段的&lt;strong&gt;网格规划、姿态校正、传感器选型&lt;/strong&gt;都比想象中重要&lt;/li&gt;&#10;&lt;li&gt;地磁的空间梯度和 WiFi 的互补性在数据里体现得非常直观&lt;/li&gt;&#10;&lt;li&gt;融合定位方法本身是论文核心内容，等论文发表后再写一篇展开&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>Samba 共享：把开发板目录变成 Windows 本地磁盘</title><link>https://zeseanblog.top/p/samba/</link><pubDate>Sat, 14 Mar 2026 20:45:00 +0800</pubDate><guid>https://zeseanblog.top/p/samba/</guid><description>&lt;h3 id="samba-共享-最原生的-windows-挂载方案"&gt;&lt;a href="#samba-%e5%85%b1%e4%ba%ab-%e6%9c%80%e5%8e%9f%e7%94%9f%e7%9a%84-windows-%e6%8c%82%e8%bd%bd%e6%96%b9%e6%a1%88" class="header-anchor"&gt;&lt;/a&gt;Samba 共享（⭐ 最原生的 Windows 挂载方案）&#13;&#10;&lt;/h3&gt;&lt;p&gt;如果你希望把板子上的目录变成 Windows 电脑里的一个&amp;quot;本地磁盘&amp;quot;（比如 Z: 盘），随时可以拖拽文件，那么 Samba 是最佳选择。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;1. 在 RK3588 上安装 Samba 服务：&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;Bash&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;sudo apt update&#10;sudo apt install samba&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;2. 配置共享目录：&lt;/strong&gt; 打开 Samba 配置文件：&lt;/p&gt;&#10;&lt;p&gt;Bash&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;sudo nano /etc/samba/smb.conf&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在文件最末尾，添加以下内容（将你的 &lt;code&gt;/home/cat&lt;/code&gt; 目录共享出去）：&lt;/p&gt;&#10;&lt;p&gt;Ini, TOML&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;[lubancat_home]&#10; path = /home/cat&#10; available = yes&#10; browseable = yes&#10; public = yes&#10; writable = yes&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;保存并退出（&lt;code&gt;Ctrl+O&lt;/code&gt; 回车，&lt;code&gt;Ctrl+X&lt;/code&gt;）。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;3. 为你的用户设置 Samba 密码：&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;Bash&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;sudo smbpasswd -a cat&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;em&gt;(输入两次你想要的密码，建议就用你板子的登录密码方便记)&lt;/em&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;4. 重启 Samba 服务：&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;Bash&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;sudo systemctl restart smbd&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;5. 在 Windows 上挂载：&lt;/strong&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;打开 Windows 的&amp;quot;此电脑&amp;quot;（文件资源管理器）。&lt;/li&gt;&#10;&lt;li&gt;在顶部地址栏输入：&lt;code&gt;\\192.168.137.200&lt;/code&gt; 并回车。&lt;/li&gt;&#10;&lt;li&gt;此时会弹出一个窗口让你输入账号密码，输入账号 &lt;code&gt;cat&lt;/code&gt; 和你刚才设置的密码。&lt;/li&gt;&#10;&lt;li&gt;你会看到 &lt;code&gt;lubancat_home&lt;/code&gt; 文件夹，右键点击它，选择&amp;quot;映射网络驱动器&amp;quot;，分配一个盘符（比如 &lt;code&gt;Z:&lt;/code&gt; 盘）。搞定！&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>嵌入式 Linux 学习笔记（07）：I2C 应用编程</title><link>https://zeseanblog.top/p/embedded-07/</link><pubDate>Sat, 28 Feb 2026 10:30:00 +0800</pubDate><guid>https://zeseanblog.top/p/embedded-07/</guid><description>&#13;&#10; &lt;blockquote&gt;&#13;&#10; &lt;p&gt;📚 本文是《&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux/" &gt;嵌入式 Linux 应用开发学习笔记&lt;/a&gt;》系列第 07 / 7 篇：I2C 应用编程。返回&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux/" &gt;系列目录&lt;/a&gt;。&lt;/p&gt;&#10;&#13;&#10; &lt;/blockquote&gt;&#13;&#10;&lt;h2 id="第10章-串口uart编程"&gt;&lt;a href="#%e7%ac%ac10%e7%ab%a0-%e4%b8%b2%e5%8f%a3uart%e7%bc%96%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;第10章 串口UART编程&#13;&#10;&lt;/h2&gt;&lt;h2 id="第11章-i2c应用编程"&gt;&lt;a href="#%e7%ac%ac11%e7%ab%a0-i2c%e5%ba%94%e7%94%a8%e7%bc%96%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;第11章 I2C应用编程&#13;&#10;&lt;/h2&gt;&lt;h3 id="111-i2c硬件"&gt;&lt;a href="#111-i2c%e7%a1%ac%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;11.1 I2C硬件&#13;&#10;&lt;/h3&gt;&lt;p&gt;SCL,SDA，一条I2C总线可接很多设备，SCL,SDA放上拉电阻&lt;/p&gt;&#10;&lt;img src="images/image-20250828205720777.png" alt="image-20250828205720777" style="zoom:67%;" /&gt;&#10;&lt;h3 id="112-传输数据类比"&gt;&lt;a href="#112-%e4%bc%a0%e8%be%93%e6%95%b0%e6%8d%ae%e7%b1%bb%e6%af%94" class="header-anchor"&gt;&lt;/a&gt;11.2 传输数据类比&#13;&#10;&lt;/h3&gt;&lt;p&gt;如何通过IIC传数据，&lt;/p&gt;&#10;&lt;p&gt;主设备：一主多从，可把数据从主设备发到从设备，也可从设备发到主设备&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;发送&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;主设备：开始(start)&lt;/p&gt;&#10;&lt;p&gt;主设备：A，我把数据发你(地址/方向)&lt;/p&gt;&#10;&lt;p&gt;A：收到(回应)&lt;/p&gt;&#10;&lt;p&gt;主设备：发送数据(传输)&lt;/p&gt;&#10;&lt;p&gt;A：收到后，告诉主设备(回应)&lt;/p&gt;&#10;&lt;p&gt;主设备：结束(停止)&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;接收&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;主设备：开始(start)&lt;/p&gt;&#10;&lt;p&gt;主设备：B，把数据发我(地址/方向)&lt;/p&gt;&#10;&lt;p&gt;B：收到(回应)&lt;/p&gt;&#10;&lt;p&gt;B：把数据发给主设备(传输)&lt;/p&gt;&#10;&lt;p&gt;主设备：收到数据后，告诉A(回应)&lt;/p&gt;&#10;&lt;p&gt;主设备：结束(停止)&lt;/p&gt;&#10;&lt;h3 id="113-iic传输数据格式"&gt;&lt;a href="#113-iic%e4%bc%a0%e8%be%93%e6%95%b0%e6%8d%ae%e6%a0%bc%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;11.3 IIC传输数据格式&#13;&#10;&lt;/h3&gt;&lt;h4 id="1131写操作"&gt;&lt;a href="#1131%e5%86%99%e6%93%8d%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;11.3.1写操作&#13;&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;主设备发出start信号&lt;/li&gt;&#10;&lt;li&gt;发出设备地址，方向(读1/写0)&lt;/li&gt;&#10;&lt;li&gt;从设备发出应答信号&lt;/li&gt;&#10;&lt;li&gt;主设备发送一字节数据，等待回应&lt;/li&gt;&#10;&lt;li&gt;每传输一字节，接收方回应一次，在传输下一个数据&lt;/li&gt;&#10;&lt;li&gt;数据发送完成，主设备发送stop信号&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img alt="image-20250828211121367" class="gallery-image" data-flex-basis="1566px" data-flex-grow="652" height="99" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-07/images/image-20250828211121367.png" width="646"&gt;&lt;/p&gt;&#10;&lt;h4 id="1132读操作"&gt;&lt;a href="#1132%e8%af%bb%e6%93%8d%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;11.3.2读操作&#13;&#10;&lt;/h4&gt;&lt;p&gt;&lt;img alt="image-20250828212451496" class="gallery-image" data-flex-basis="1475px" data-flex-grow="614" height="108" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-07/images/image-20250828212451496.png" width="664"&gt;&lt;/p&gt;&#10;&lt;h4 id="1133-iic信号"&gt;&lt;a href="#1133-iic%e4%bf%a1%e5%8f%b7" class="header-anchor"&gt;&lt;/a&gt;11.3.3 IIC信号&#13;&#10;&lt;/h4&gt;&lt;p&gt;IIC协议栈数据传输单位是字节，但是要用到9个时钟，前面8个时钟用来传输8数据，第9个始终用来传输回应信号，先传输最高位&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;开始信号(S)：SCL为高时，SDA由高跳低，开始传输数据&lt;/li&gt;&#10;&lt;li&gt;结束信号(P)：SCL为高时，SDA由低跳高，结束传输数据&lt;/li&gt;&#10;&lt;li&gt;响应信号(ACK)：接收到8位数据，第九个时钟周期，拉低SDA&lt;/li&gt;&#10;&lt;li&gt;SDA数据必须在SCL高时稳定，只能在SCL为低时变化&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img alt="image-20250828213228809" class="gallery-image" data-flex-basis="708px" data-flex-grow="295" height="335" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-07/images/image-20250828213228809.png" srcset="https://zeseanblog.top/p/embedded-07/images/image-20250828213228809_hu_9c82e3ce5d874844.png 800w, https://zeseanblog.top/p/embedded-07/images/image-20250828213228809.png 989w" width="989"&gt;&lt;/p&gt;&#10;&lt;h4 id="1134-协议细节"&gt;&lt;a href="#1134-%e5%8d%8f%e8%ae%ae%e7%bb%86%e8%8a%82" class="header-anchor"&gt;&lt;/a&gt;11.3.4 协议细节&#13;&#10;&lt;/h4&gt;&lt;p&gt;1.SDA引脚必须双向IO，因为有发有收&lt;/p&gt;&#10;&lt;ol start="2"&gt;&#10;&lt;li&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;img src="images/image-20250828214833582.png" alt="image-20250828214833582" style="zoom:67%;" /&gt;&#10;&lt;img src="images/image-20250828214855838.png" alt="image-20250828214855838" style="zoom:67%;" /&gt;&#10;&lt;img src="images/image-20250828215155892.png" alt="image-20250828215155892" style="zoom:67%;" /&gt;&#10;&lt;h3 id="114-smbus协议"&gt;&lt;a href="#114-smbus%e5%8d%8f%e8%ae%ae" class="header-anchor"&gt;&lt;/a&gt;11.4 SMBus协议&#13;&#10;&lt;/h3&gt;&lt;h4 id="1141-smbus是iic协议子集"&gt;&lt;a href="#1141-smbus%e6%98%afiic%e5%8d%8f%e8%ae%ae%e5%ad%90%e9%9b%86" class="header-anchor"&gt;&lt;/a&gt;11.4.1 SMBus是IIC协议子集&#13;&#10;&lt;/h4&gt;&lt;p&gt;SMBus: System Management Bus，系统管理总线&lt;/p&gt;&#10;&lt;h3 id="115无需编写驱动直接访问设备i2c-tools"&gt;&lt;a href="#115%e6%97%a0%e9%9c%80%e7%bc%96%e5%86%99%e9%a9%b1%e5%8a%a8%e7%9b%b4%e6%8e%a5%e8%ae%bf%e9%97%ae%e8%ae%be%e5%a4%87i2c-tools" class="header-anchor"&gt;&lt;/a&gt;11.5无需编写驱动直接访问设备(I2C-Tools)&#13;&#10;&lt;/h3&gt;&lt;p&gt;通过I2Ctool的程序，使用自带的驱动程序，来操作内核的i2c操作程序来访问硬件&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250829193204176" class="gallery-image" data-flex-basis="748px" data-flex-grow="311" height="317" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-07/images/image-20250829193204176.png" srcset="https://zeseanblog.top/p/embedded-07/images/image-20250829193204176_hu_a39e503619a02dab.png 800w, https://zeseanblog.top/p/embedded-07/images/image-20250829193204176.png 989w" width="989"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250829193317507" class="gallery-image" data-flex-basis="420px" data-flex-grow="175" height="230" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-07/images/image-20250829193317507.png" width="403"&gt;&lt;/p&gt;&#10;&lt;p&gt;首先确定：使用哪个IIC控制器，使用哪个IIC设备，读还是写数据&lt;/p&gt;&#10;&lt;h4 id="1151用法"&gt;&lt;a href="#1151%e7%94%a8%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;11.5.1用法&#13;&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;i2cdetect：I2C检测&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;// 列出当前的I2C Adapter(或称为I2C Bus、I2C Controller)&#10;i2cdetect -l&#10;&#10;// 打印某个I2C Adapter的Functionalities, I2CBUS为0、1、2等整数&#10;i2cdetect -F I2CBUS&#10;&#10;// 看看有哪些I2C设备, I2CBUS为0、1、2等整数&#10;i2cdetect -y -a I2CBUS&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img alt="image-20250829194206209" class="gallery-image" data-flex-basis="647px" data-flex-grow="269" height="198" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-07/images/image-20250829194206209.png" width="534"&gt;&lt;/p&gt;&#10;&lt;h4 id="1152操作传感器ap3216c"&gt;&lt;a href="#1152%e6%93%8d%e4%bd%9c%e4%bc%a0%e6%84%9f%e5%99%a8ap3216c" class="header-anchor"&gt;&lt;/a&gt;11.5.2操作传感器AP3216C&#13;&#10;&lt;/h4&gt;&lt;img src="images/image-20250829194657273.png" alt="image-20250829194657273" style="zoom:67%;" /&gt;&#10;&lt;p&gt;AP3216C是红外、光强、距离三合一的传感器，以读出光强、距离值为例&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;复位：往寄存器0写入0x4&lt;/li&gt;&#10;&lt;li&gt;使能：往寄存器0写入0x3&lt;/li&gt;&#10;&lt;li&gt;读光强：读寄存器0xC、0xD得到2字节的光强&lt;/li&gt;&#10;&lt;li&gt;读距离：读寄存器0xE、0xF得到2字节的距离值&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;使用SMBus协议&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;//i2cset查看用法&#10;i2cset&#10;//写数据&#10;i2cset -f -y 0（0号线） 0x1e（芯片地址） 0（写入地址） 0x4&#10;i2cset -f -y 0 0x1e 0 0x3&#10;//读数据&#10;i2cget -f -y 0 0x1e 0xc w &#9;//0xc光照&#10;i2cget -f -y 0 0x1e 0xe w&#9;//0xe距离&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;使用I2C协议&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;i2ctransfer -f -y 0 w2@0x1e 0 0x4&#10;i2ctransfer -f -y 0 w2@0x1e 0 0x3&#10;i2ctransfer -f -y 0 w1@0x1e 0xc r2&#10;i2ctransfer -f -y 0 w1@0x1e 0xe r2&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="1153-i2ctools访问i2c设备的方式"&gt;&lt;a href="#1153-i2ctools%e8%ae%bf%e9%97%aei2c%e8%ae%be%e5%a4%87%e7%9a%84%e6%96%b9%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;11.5.3 I2CTools访问I2C设备的方式&#13;&#10;&lt;/h4&gt;&lt;p&gt;APP通过I2C Controller与I2C Device传输数据&lt;/p&gt;&#10;&lt;p&gt;指定i2c控制器：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;i2c-dev.c提供为每个I2C控制器(I2C Bus、I2C Adapter)都生成一个设备节点：/dev/i2c-0、/dev/i2c-1等待&lt;/li&gt;&#10;&lt;li&gt;open某个/dev/i2c-X节点，就是去访问该I2C控制器下的设备&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;指定i2c设备：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;ioctl(file, I2C_SLAVE, address)&#10;&lt;ul&gt;&#10;&lt;li&gt;如果该设备已经有了对应的设备驱动程序，则返回失败&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;ioctl(file, I2C_SLAVE_FORCE, address)&#10;&lt;ul&gt;&#10;&lt;li&gt;如果该设备已经有了对应的设备驱动程序&lt;/li&gt;&#10;&lt;li&gt;但是还是想通过i2c-dev驱动来访问它&lt;/li&gt;&#10;&lt;li&gt;则使用这个ioctl来指定I2C设备地址&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;传输方式：I2C或SMBus&lt;/p&gt;&#10;&lt;h3 id="116编写app直接访问eeprpm"&gt;&lt;a href="#116%e7%bc%96%e5%86%99app%e7%9b%b4%e6%8e%a5%e8%ae%bf%e9%97%aeeeprpm" class="header-anchor"&gt;&lt;/a&gt;11.6编写APP直接访问EEPRPM&#13;&#10;&lt;/h3&gt;&lt;p&gt;I2C控制器地址0x50&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250829203128562" class="gallery-image" data-flex-basis="656px" data-flex-grow="273" height="197" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-07/images/image-20250829203128562.png" width="539"&gt;&lt;/p&gt;&#10;&lt;p&gt;I2C设备地址0x50&lt;/p&gt;&#10;&lt;p&gt;从芯片手册上可以知道，AT24C02的设备地址跟它的A2、A1、A0引脚有关：&lt;/p&gt;&#10;&lt;p&gt;高4位为1010，A2A1A0都是0，所以AT24C02的设备地址是：0b1010000，即0x50&lt;/p&gt;&#10;&lt;h4 id="1161写数据"&gt;&lt;a href="#1161%e5%86%99%e6%95%b0%e6%8d%ae" class="header-anchor"&gt;&lt;/a&gt;11.6.1写数据&#13;&#10;&lt;/h4&gt;&lt;p&gt;&lt;img alt="image-20250830153423926" class="gallery-image" data-flex-basis="857px" data-flex-grow="357" height="240" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-07/images/image-20250830153423926.png" srcset="https://zeseanblog.top/p/embedded-07/images/image-20250830153423926_hu_bda9418fb84fcafb.png 800w, https://zeseanblog.top/p/embedded-07/images/image-20250830153423926.png 857w" width="857"&gt;&lt;/p&gt;&#10;&lt;h4 id="1162读数据"&gt;&lt;a href="#1162%e8%af%bb%e6%95%b0%e6%8d%ae" class="header-anchor"&gt;&lt;/a&gt;11.6.2读数据&#13;&#10;&lt;/h4&gt;&lt;p&gt;&lt;img alt="image-20250830153452117" class="gallery-image" data-flex-basis="995px" data-flex-grow="414" height="217" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-07/images/image-20250830153452117.png" srcset="https://zeseanblog.top/p/embedded-07/images/image-20250830153452117_hu_b4805aa40f918e96.png 800w, https://zeseanblog.top/p/embedded-07/images/image-20250830153452117.png 900w" width="900"&gt;&lt;/p&gt;&#10;</description></item><item><title>嵌入式 Linux 学习笔记（06）：输入系统、网络编程与多线程</title><link>https://zeseanblog.top/p/embedded-06/</link><pubDate>Sat, 07 Feb 2026 10:30:00 +0800</pubDate><guid>https://zeseanblog.top/p/embedded-06/</guid><description>&#13;&#10; &lt;blockquote&gt;&#13;&#10; &lt;p&gt;📚 本文是《&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux/" &gt;嵌入式 Linux 应用开发学习笔记&lt;/a&gt;》系列第 06 / 7 篇：输入系统、网络编程与多线程。返回&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux/" &gt;系列目录&lt;/a&gt;。&lt;/p&gt;&#10;&#13;&#10; &lt;/blockquote&gt;&#13;&#10;&lt;h2 id="第7章-输入系统应用编程未完成"&gt;&lt;a href="#%e7%ac%ac7%e7%ab%a0-%e8%be%93%e5%85%a5%e7%b3%bb%e7%bb%9f%e5%ba%94%e7%94%a8%e7%bc%96%e7%a8%8b%e6%9c%aa%e5%ae%8c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;第7章 输入系统应用编程（未完成）&#13;&#10;&lt;/h2&gt;&lt;h3 id="71输入设备"&gt;&lt;a href="#71%e8%be%93%e5%85%a5%e8%ae%be%e5%a4%87" class="header-anchor"&gt;&lt;/a&gt;7.1输入设备&#13;&#10;&lt;/h3&gt;&lt;p&gt;键盘、鼠标、遥控杆、书写板、触摸屏等与linux完成数据交换&lt;/p&gt;&#10;&lt;p&gt;输入设备种类繁多，能否统一它们的接口？&lt;/p&gt;&#10;&lt;p&gt;Linux 为了统一管理输入设备，实现了一套能兼容所有输入设备的框架：输入系统&lt;/p&gt;&#10;&lt;h3 id="72输入系统框架及调试"&gt;&lt;a href="#72%e8%be%93%e5%85%a5%e7%b3%bb%e7%bb%9f%e6%a1%86%e6%9e%b6%e5%8f%8a%e8%b0%83%e8%af%95" class="header-anchor"&gt;&lt;/a&gt;7.2输入系统框架及调试&#13;&#10;&lt;/h3&gt;&lt;p&gt;输入系统框架&lt;/p&gt;&#10;&lt;img src="images/image-20250811152406142.png" alt="image-20250811152406142" style="zoom: 67%;" /&gt;&#10;&lt;p&gt;示例：&lt;/p&gt;&#10;&lt;p&gt;在开发板上执行，可以看到触摸屏数据&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;hexdump /dev/input/event1&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;hexdump&lt;/code&gt;&lt;/strong&gt;: 是一个命令行工具，它将文件或数据流的内容以十六进制和 ASCII 格式输出&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;code&gt;/dev/input/event1&lt;/code&gt;&lt;/strong&gt;: 是一个特殊的设备文件，代表一个输入设备，比如键盘、鼠标或触摸板。Linux 内核会把来自这些设备的原始输入事件（例如按键、鼠标移动或点击）写入这些文件&lt;/p&gt;&#10;&lt;h4 id="722编写app需要掌握的知识"&gt;&lt;a href="#722%e7%bc%96%e5%86%99app%e9%9c%80%e8%a6%81%e6%8e%8c%e6%8f%a1%e7%9a%84%e7%9f%a5%e8%af%86" class="header-anchor"&gt;&lt;/a&gt;7.2.2编写APP需要掌握的知识&#13;&#10;&lt;/h4&gt;&lt;p&gt;驱动程序上报的数据含义三项重要内容：&lt;/p&gt;&#10;&lt;p&gt;1.type：哪类，如EV_KEY为按键类&lt;/p&gt;&#10;&lt;p&gt;2.code：哪个，比如KEY_A&lt;/p&gt;&#10;&lt;p&gt;3.value：值，比如0按下，1松开&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;此外APP 读取数据时，可以得到一个或多个数据，比如一个触摸屏的一个触点会上报 X、Y 位置信息，也可能会上报压力值&lt;/li&gt;&#10;&lt;li&gt;驱动程序上报完一系列的数据后，会上报一个“同步事件”，表示数据上报完毕。APP 读到“同步事件”时，就知道已经读完了当前的数据&lt;/li&gt;&#10;&lt;li&gt;同步事件也是一个 input_event 结构体，它的 type、code、value 三项都是 0&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img alt="image-20250811160100821" class="gallery-image" data-flex-basis="427px" data-flex-grow="178" height="548" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-06/images/image-20250811160100821.png" srcset="https://zeseanblog.top/p/embedded-06/images/image-20250811160100821_hu_f282826ed24fff55.png 800w, https://zeseanblog.top/p/embedded-06/images/image-20250811160100821.png 977w" width="977"&gt;&lt;/p&gt;&#10;&lt;h4 id="723调试技巧"&gt;&lt;a href="#723%e8%b0%83%e8%af%95%e6%8a%80%e5%b7%a7" class="header-anchor"&gt;&lt;/a&gt;7.2.3调试技巧&#13;&#10;&lt;/h4&gt;&lt;p&gt;确定设备信息&lt;/p&gt;&#10;&lt;p&gt;ls /dev/input/* -l&lt;/p&gt;&#10;&lt;p&gt;可以看到设备&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250811160521672" class="gallery-image" data-flex-basis="1115px" data-flex-grow="464" height="179" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-06/images/image-20250811160521672.png" srcset="https://zeseanblog.top/p/embedded-06/images/image-20250811160521672_hu_7ef30a597bcf43e7.png 800w, https://zeseanblog.top/p/embedded-06/images/image-20250811160521672.png 832w" width="832"&gt;&lt;/p&gt;&#10;&lt;p&gt;确定设备对应的硬件&lt;/p&gt;&#10;&lt;p&gt;cat /proc/bus/input/devices&lt;/p&gt;&#10;&lt;h3 id="73不用库的应用编程"&gt;&lt;a href="#73%e4%b8%8d%e7%94%a8%e5%ba%93%e7%9a%84%e5%ba%94%e7%94%a8%e7%bc%96%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;7.3不用库的应用编程&#13;&#10;&lt;/h3&gt;&lt;p&gt;APP访问硬件有4种方式：查询方式、休眠-唤醒、poll方式、异步通知&lt;/p&gt;&#10;&lt;p&gt;通过 ioctl 获取设备信息：&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;int ioctl(int fd, unsigned long request, ...);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;比如要读取输入设备的 evbit 时，ioctl 的 request 要写为“EVIOCGBIT(0, size)&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250811171735718" class="gallery-image" data-flex-basis="8025px" data-flex-grow="3343" height="32" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-06/images/image-20250811171735718.png" srcset="https://zeseanblog.top/p/embedded-06/images/image-20250811171735718_hu_b24903fd19ff903d.png 800w, https://zeseanblog.top/p/embedded-06/images/image-20250811171735718.png 1070w" width="1070"&gt;&lt;/p&gt;&#10;&lt;h4 id="731查询休眠唤醒方式"&gt;&lt;a href="#731%e6%9f%a5%e8%af%a2%e4%bc%91%e7%9c%a0%e5%94%a4%e9%86%92%e6%96%b9%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;7.3.1查询、休眠唤醒方式&#13;&#10;&lt;/h4&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;if (argc &amp;lt; 2)&#10;&#9;{&#10;&#9;&#9;printf(&amp;#34;Usage: %s &amp;lt;dev&amp;gt; [noblock]\n&amp;#34;, argv[0]);&#10;&#9;&#9;return -1;&#10;&#9;}&#10;&#10;&#9;if (argc == 3 &amp;amp;&amp;amp; !strcmp(argv[2], &amp;#34;noblock&amp;#34;))&#10;&#9;{&#10;&#9;&#9;fd = open(argv[1], O_RDWR | O_NONBLOCK);&#10;&#9;}&#10;&#9;else&#10;&#9;{&#10;&#9;&#9;fd = open(argv[1], O_RDWR);&#10;&#9;}&#10;while (1)&#10;&#9;{&#10;&#9;&#9;len = read(fd, &amp;amp;event, sizeof(event));&#10;&#9;&#9;if (len == sizeof(event))&#10;&#9;&#9;{&#10;&#9;&#9;&#9;printf(&amp;#34;get event: type = 0x%x, code = 0x%x, value = 0x%x\n&amp;#34;, event.type, event.code, event.value);&#10;&#9;&#9;}&#10;&#9;&#9;else&#10;&#9;&#9;{&#10;&#9;&#9;&#9;printf(&amp;#34;read err %d\n&amp;#34;, len);&#10;&#9;&#9;}&#10;&#9;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="732pollselect方式"&gt;&lt;a href="#732pollselect%e6%96%b9%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;7.3.2poll/select方式&#13;&#10;&lt;/h4&gt;&lt;p&gt;POLL 机制、SELECT 机制是完全一样的，只是 APP 接口函数不一样&lt;/p&gt;&#10;&lt;h2 id="第8章-网络通信"&gt;&lt;a href="#%e7%ac%ac8%e7%ab%a0-%e7%bd%91%e7%bb%9c%e9%80%9a%e4%bf%a1" class="header-anchor"&gt;&lt;/a&gt;第8章 网络通信&#13;&#10;&lt;/h2&gt;&lt;h3 id="81网络通信概述"&gt;&lt;a href="#81%e7%bd%91%e7%bb%9c%e9%80%9a%e4%bf%a1%e6%a6%82%e8%bf%b0" class="header-anchor"&gt;&lt;/a&gt;8.1网络通信概述&#13;&#10;&lt;/h3&gt;&lt;p&gt;实际还是数据传输&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;数据传输三要素：源、目的、长度。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;现在假设A、B两台计算机通讯，一台为服务器，一台为客户端。&lt;/p&gt;&#10;&lt;p&gt;访问网站的话，设计网站服务器、浏览器，网站服务器平时安静地呆着，浏览器主动发起数据请求&lt;/p&gt;&#10;&lt;p&gt;服务器：被动地响应请求&lt;/p&gt;&#10;&lt;p&gt;客户端：主动地发起请求&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250811194932169" class="gallery-image" data-flex-basis="821px" data-flex-grow="342" height="216" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-06/images/image-20250811194932169.png" width="739"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;数据传输两种方式：TCP、UDP。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;TCP：可靠的、有重传机制（确保数据真到达）、适合控制命令&lt;/p&gt;&#10;&lt;p&gt;UDP：不可靠的（适合视频、语音等），视频通话时，使用 UDP，偶尔的丢包、偶尔的花屏时可以忍受的&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;怎么写程序？&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;仿照文件读写&lt;/p&gt;&#10;&lt;p&gt;将fd=open(”文件名“);&lt;/p&gt;&#10;&lt;p&gt;read(fd,buf,len);//源、目的、长度&lt;/p&gt;&#10;&lt;h4 id="811ip和端口"&gt;&lt;a href="#811ip%e5%92%8c%e7%ab%af%e5%8f%a3" class="header-anchor"&gt;&lt;/a&gt;8.1.1IP和端口&#13;&#10;&lt;/h4&gt;&lt;p&gt;数据传输：源、目的、长度&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250811194346820" class="gallery-image" data-flex-basis="748px" data-flex-grow="311" height="431" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-06/images/image-20250811194346820.png" srcset="https://zeseanblog.top/p/embedded-06/images/image-20250811194346820_hu_7f2a63d40084f4f7.png 800w, https://zeseanblog.top/p/embedded-06/images/image-20250811194346820.png 1344w" width="1344"&gt;&lt;/p&gt;&#10;&lt;p&gt;源端口区分不同浏览器，目的端口区分想要服务&lt;/p&gt;&#10;&lt;h4 id="813两种传输方式tcpudp"&gt;&lt;a href="#813%e4%b8%a4%e7%a7%8d%e4%bc%a0%e8%be%93%e6%96%b9%e5%bc%8ftcpudp" class="header-anchor"&gt;&lt;/a&gt;8.1.3两种传输方式TCP/UDP&#13;&#10;&lt;/h4&gt;&lt;p&gt;网络协议5层：物理层、数据链路层、网络层、传输层、应用层&lt;/p&gt;&#10;&lt;p&gt;应用层：直接为用户进程提供服务，如支持www的HTTP协议、电子邮箱SMTP协议、文件传输FTP协议，DNS、POP3、FNMP、Telnet&lt;/p&gt;&#10;&lt;p&gt;传输层：负责向两个主机中进程之间的通信提供服务，主要TCP、UDP&lt;/p&gt;&#10;&lt;h3 id="82tcp网络编程"&gt;&lt;a href="#82tcp%e7%bd%91%e7%bb%9c%e7%bc%96%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;8.2TCP网络编程&#13;&#10;&lt;/h3&gt;&lt;h4 id="服务端"&gt;&lt;a href="#%e6%9c%8d%e5%8a%a1%e7%ab%af" class="header-anchor"&gt;&lt;/a&gt;服务端&#13;&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;socket函数&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;int socket(int domain, int type,int protocol);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;用于创建套接字，根本不涉及什么源、目的、长度，&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;bind函数&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;fd = socket(.....);&#10;int bind(int sockfd, struct sockaddr *my_addr, int addrlen);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;从函数用于将地址绑定到一个套接字（自己的IP端口）&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;把fd和ip端口绑定&lt;/strong&gt;，以后就检测这个ip端口看看数据有没有&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;listen函数&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;int listen(int sockfd,int backlog);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;启动检测数据&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;accept函数&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;int accept(int sockfd, struct sockaddr *addr,int *addrlen);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;建立一条连接，接收连接&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;send函数&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;ssize_t send(int sockfd, const void *buf, size_t len, int flags);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;发数据&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;recv函数&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;ssize_t recv(int sockfd, void *buf, size_t len, int flags);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;收数据&lt;/p&gt;&#10;&lt;h4 id="客户端"&gt;&lt;a href="#%e5%ae%a2%e6%88%b7%e7%ab%af" class="header-anchor"&gt;&lt;/a&gt;客户端&#13;&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;socket函数&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;fd=socket(......)&#10;&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&#10;&lt;li&gt;connect函数&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;int connect(int sockfd, struct sockaddr * serv_addr,int addrlen);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;建立连接&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;recv&lt;/li&gt;&#10;&lt;li&gt;send&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="83udp网络编程"&gt;&lt;a href="#83udp%e7%bd%91%e7%bb%9c%e7%bc%96%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;8.3UDP网络编程&#13;&#10;&lt;/h3&gt;&lt;h4 id="服务端-1"&gt;&lt;a href="#%e6%9c%8d%e5%8a%a1%e7%ab%af-1" class="header-anchor"&gt;&lt;/a&gt;服务端&#13;&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;socket函数&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;int socket(int domain, int type,int protocol);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;用于创建套接字，根本不涉及什么源、目的、长度，&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;bind函数&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;fd = socket(.....);&#10;int bind(int sockfd, struct sockaddr *my_addr, int addrlen);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;从函数用于将地址绑定到一个套接字（自己的IP端口）&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;recvfrom&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,&#10;&#9;&#9;&#9;&#9; struct sockaddr *src_addr, socklen_t *addrlen);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;recvfrom 通常用于无连接套接字，因为此函数可以获得发送者的地址。&lt;/p&gt;&#10;&lt;p&gt;src_addr 是一个 struct sockaddr 类型的变量，该变量保存源机的 IP 地&lt;/p&gt;&#10;&lt;p&gt;址及端口号。&lt;/p&gt;&#10;&lt;p&gt;addrlen 常置为 sizeof （struct sockaddr）。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;sendto&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,&#10; &#9;&#9;&#9; const struct sockaddr *dest_addr, socklen_t addrlen);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="客户端-1"&gt;&lt;a href="#%e5%ae%a2%e6%88%b7%e7%ab%af-1" class="header-anchor"&gt;&lt;/a&gt;客户端&#13;&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;socket函数&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;fd=socket(......)&#10;&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&#10;&lt;li&gt;connect函数&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;int connect(int sockfd, struct sockaddr * serv_addr,int addrlen);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;建立连接&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;recvfrom,recv&lt;/li&gt;&#10;&lt;li&gt;sendto,send&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="第9章-多线程编程"&gt;&lt;a href="#%e7%ac%ac9%e7%ab%a0-%e5%a4%9a%e7%ba%bf%e7%a8%8b%e7%bc%96%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;第9章 多线程编程&#13;&#10;&lt;/h2&gt;&lt;h3 id="91线程的使用"&gt;&lt;a href="#91%e7%ba%bf%e7%a8%8b%e7%9a%84%e4%bd%bf%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;9.1线程的使用&#13;&#10;&lt;/h3&gt;&lt;h4 id="911为什么使用多线程"&gt;&lt;a href="#911%e4%b8%ba%e4%bb%80%e4%b9%88%e4%bd%bf%e7%94%a8%e5%a4%9a%e7%ba%bf%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;9.1.1为什么使用多线程&#13;&#10;&lt;/h4&gt;&lt;p&gt;编写代码时有时候要做2件事，如一边屏幕播放视频，一边等待用户按键操作&lt;/p&gt;&#10;&lt;p&gt;如果使用多线程，线程1单独处理按键，线程2单独处理播放&lt;/p&gt;&#10;&lt;h4 id="912线程概念"&gt;&lt;a href="#912%e7%ba%bf%e7%a8%8b%e6%a6%82%e5%bf%b5" class="header-anchor"&gt;&lt;/a&gt;9.1.2线程概念&#13;&#10;&lt;/h4&gt;&lt;p&gt;操作系统所能调度的最小单位，普通的进程，只有一个线程执行逻辑。&lt;/p&gt;&#10;&lt;p&gt;我们可以通过多线程编程，使一个进程可以去执行多个不同的任务&lt;/p&gt;&#10;&lt;p&gt;相比多进程编程，线程享有共享资源，在进程中出现的全局变量，每个线程都可以访问&lt;/p&gt;&#10;&lt;h4 id="913线程的标识pthread_t"&gt;&lt;a href="#913%e7%ba%bf%e7%a8%8b%e7%9a%84%e6%a0%87%e8%af%86pthread_t" class="header-anchor"&gt;&lt;/a&gt;9.1.3线程的标识pthread_t&#13;&#10;&lt;/h4&gt;&lt;p&gt;对进程：每个进程有唯一PID&lt;/p&gt;&#10;&lt;p&gt;对线程：有tid，本质是pthread_t类型的变量&lt;/p&gt;&#10;&lt;p&gt;测试例程&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;#include &amp;lt;pthread.h&amp;gt;&#10;#include &amp;lt;stdio.h&amp;gt;&#10;int main()&#10;{&#10;&#9;pthread_t tid = pthread_self();//获取主线程的 tid 号&#10;&#9;printf(&amp;#34;tid = %lu\n&amp;#34;,(unsigned long)tid);&#10;&#9;return 0;&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;gcc xxx.c -lpthread 方可编译多线程程序&lt;/p&gt;&#10;&lt;h4 id="914线程的创建"&gt;&lt;a href="#914%e7%ba%bf%e7%a8%8b%e7%9a%84%e5%88%9b%e5%bb%ba" class="header-anchor"&gt;&lt;/a&gt;9.1.4线程的创建&#13;&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;pthread_create&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;int pthread_create( pthread_t *thread, &#10;&#9;&#9;&#9;&#9;&#9;const pthread_attr_t *attr,&#10;&#9;&#9;&#9;&#9;&#9;void *(*start_routine) (void *), &#10;&#9;&#9;&#9;&#9;&#9;void *arg);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;例程&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;span class="lnt"&gt;29&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;pthread.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;my_thread_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;pthread_t&lt;/span&gt; &lt;span class="n"&gt;tid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*1.创建接收线程*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pthread_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;my_thread_func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;pthread_create err&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*2.主线程读取标准输入，发送给接受线程*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="915同步操作-向线程传数据等待"&gt;&lt;a href="#915%e5%90%8c%e6%ad%a5%e6%93%8d%e4%bd%9c-%e5%90%91%e7%ba%bf%e7%a8%8b%e4%bc%a0%e6%95%b0%e6%8d%ae%e7%ad%89%e5%be%85" class="header-anchor"&gt;&lt;/a&gt;9.1.5同步操作-向线程传数据(等待)&#13;&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;span class="lnt"&gt;29&#10;&lt;/span&gt;&lt;span class="lnt"&gt;30&#10;&lt;/span&gt;&lt;span class="lnt"&gt;31&#10;&lt;/span&gt;&lt;span class="lnt"&gt;32&#10;&lt;/span&gt;&lt;span class="lnt"&gt;33&#10;&lt;/span&gt;&lt;span class="lnt"&gt;34&#10;&lt;/span&gt;&lt;span class="lnt"&gt;35&#10;&lt;/span&gt;&lt;span class="lnt"&gt;36&#10;&lt;/span&gt;&lt;span class="lnt"&gt;37&#10;&lt;/span&gt;&lt;span class="lnt"&gt;38&#10;&lt;/span&gt;&lt;span class="lnt"&gt;39&#10;&lt;/span&gt;&lt;span class="lnt"&gt;40&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;pthread.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;g_buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;g_hasData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;my_thread_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*等待通知*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g_hasData&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*打印*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;recv: %s&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;g_buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;g_hasData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;pthread_t&lt;/span&gt; &lt;span class="n"&gt;tid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*1.创建接收线程*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pthread_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;my_thread_func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;pthread_create err&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*2.主线程读取标准输入，发送给接受线程*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;fgets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g_buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*通知接受线程*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;g_hasData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="916同步操作信号量"&gt;&lt;a href="#916%e5%90%8c%e6%ad%a5%e6%93%8d%e4%bd%9c%e4%bf%a1%e5%8f%b7%e9%87%8f" class="header-anchor"&gt;&lt;/a&gt;9.1.6同步操作(信号量)&#13;&#10;&lt;/h4&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;// 初始化&#10;#include &amp;lt;semaphore.h&amp;gt;&#10;static sem_t sem;&#10;int sem_init(sem_t *sem,int pshared,unsigned int value);&#10;等待/释放：&#10;#include &amp;lt;pthread.h&amp;gt;&#10;int sem_wait(sem_t *sem);&#10;int sem_post(sem_t *sem);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;span class="lnt"&gt;29&#10;&lt;/span&gt;&lt;span class="lnt"&gt;30&#10;&lt;/span&gt;&lt;span class="lnt"&gt;31&#10;&lt;/span&gt;&lt;span class="lnt"&gt;32&#10;&lt;/span&gt;&lt;span class="lnt"&gt;33&#10;&lt;/span&gt;&lt;span class="lnt"&gt;34&#10;&lt;/span&gt;&lt;span class="lnt"&gt;35&#10;&lt;/span&gt;&lt;span class="lnt"&gt;36&#10;&lt;/span&gt;&lt;span class="lnt"&gt;37&#10;&lt;/span&gt;&lt;span class="lnt"&gt;38&#10;&lt;/span&gt;&lt;span class="lnt"&gt;39&#10;&lt;/span&gt;&lt;span class="lnt"&gt;40&#10;&lt;/span&gt;&lt;span class="lnt"&gt;41&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;pthread.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;semaphore.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;g_buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;sem_t&lt;/span&gt; &lt;span class="n"&gt;g_sem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;my_thread_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*等待通知*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;sem_wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;g_sem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*打印*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;recv: %s&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;g_buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;pthread_t&lt;/span&gt; &lt;span class="n"&gt;tid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*初始化信号量*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;sem_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;g_sem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*1.创建接收线程*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pthread_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;my_thread_func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;pthread_create err&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*2.主线程读取标准输入，发送给接受线程*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;fgets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g_buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*通知接受线程*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;sem_post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;g_sem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="917同步操作互斥量"&gt;&lt;a href="#917%e5%90%8c%e6%ad%a5%e6%93%8d%e4%bd%9c%e4%ba%92%e6%96%a5%e9%87%8f" class="header-anchor"&gt;&lt;/a&gt;9.1.7同步操作(互斥量)&#13;&#10;&lt;/h4&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;static pthread_mutex_t g_tMutex = PTHREAD_MUTEX_INITIALIZER;&#10;pthread_mutex_lock(&amp;amp;g_tMutex);&#10;pthread_mutex_unlock(&amp;amp;g_tMutex);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;给不希望打断的内容加锁&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;span class="lnt"&gt;29&#10;&lt;/span&gt;&lt;span class="lnt"&gt;30&#10;&lt;/span&gt;&lt;span class="lnt"&gt;31&#10;&lt;/span&gt;&lt;span class="lnt"&gt;32&#10;&lt;/span&gt;&lt;span class="lnt"&gt;33&#10;&lt;/span&gt;&lt;span class="lnt"&gt;34&#10;&lt;/span&gt;&lt;span class="lnt"&gt;35&#10;&lt;/span&gt;&lt;span class="lnt"&gt;36&#10;&lt;/span&gt;&lt;span class="lnt"&gt;37&#10;&lt;/span&gt;&lt;span class="lnt"&gt;38&#10;&lt;/span&gt;&lt;span class="lnt"&gt;39&#10;&lt;/span&gt;&lt;span class="lnt"&gt;40&#10;&lt;/span&gt;&lt;span class="lnt"&gt;41&#10;&lt;/span&gt;&lt;span class="lnt"&gt;42&#10;&lt;/span&gt;&lt;span class="lnt"&gt;43&#10;&lt;/span&gt;&lt;span class="lnt"&gt;44&#10;&lt;/span&gt;&lt;span class="lnt"&gt;45&#10;&lt;/span&gt;&lt;span class="lnt"&gt;46&#10;&lt;/span&gt;&lt;span class="lnt"&gt;47&#10;&lt;/span&gt;&lt;span class="lnt"&gt;48&#10;&lt;/span&gt;&lt;span class="lnt"&gt;49&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;pthread.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;semaphore.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;g_buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;sem_t&lt;/span&gt; &lt;span class="n"&gt;g_sem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;pthread_mutex_t&lt;/span&gt; &lt;span class="n"&gt;g_tMutex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PTHREAD_MUTEX_INITIALIZER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;my_thread_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*等待通知*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;sem_wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;g_sem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*打印*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;pthread_mutex_lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;g_tMutex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;recv: %s&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;g_buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;pthread_mutex_unlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;g_tMutex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;pthread_t&lt;/span&gt; &lt;span class="n"&gt;tid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*初始化信号量*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;sem_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;g_sem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*1.创建接收线程*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pthread_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;my_thread_func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;pthread_create err&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*2.主线程读取标准输入，发送给接受线程*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;fgets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;pthread_mutex_lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;g_tMutex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g_buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;pthread_mutex_unlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;g_tMutex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/*通知接受线程*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;sem_post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;g_sem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;</description></item><item><title>嵌入式 Linux 学习笔记（05）：Framebuffer 与文字显示</title><link>https://zeseanblog.top/p/embedded-05/</link><pubDate>Sat, 24 Jan 2026 10:30:00 +0800</pubDate><guid>https://zeseanblog.top/p/embedded-05/</guid><description>&#13;&#10; &lt;blockquote&gt;&#13;&#10; &lt;p&gt;📚 本文是《&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux/" &gt;嵌入式 Linux 应用开发学习笔记&lt;/a&gt;》系列第 05 / 7 篇：Framebuffer 与文字显示。返回&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux/" &gt;系列目录&lt;/a&gt;。&lt;/p&gt;&#10;&#13;&#10; &lt;/blockquote&gt;&#13;&#10;&lt;h2 id="第5章framebuffer应用编程"&gt;&lt;a href="#%e7%ac%ac5%e7%ab%a0framebuffer%e5%ba%94%e7%94%a8%e7%bc%96%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;第5章、Framebuffer应用编程&#13;&#10;&lt;/h2&gt;&lt;h3 id="51lcd操作原理"&gt;&lt;a href="#51lcd%e6%93%8d%e4%bd%9c%e5%8e%9f%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;5.1LCD操作原理&#13;&#10;&lt;/h3&gt;&lt;p&gt;Framebuffer是Linux/Unix 下“最直接”的图形输出接口，可以通过Framebuffer驱动程序来控制LCD，Frame是帧，buffer是缓冲，意思是Framebuffer是一块内存，里面保存一帧图像的每一个像素值。&lt;/p&gt;&#10;&lt;p&gt;假设LCD分辨率1024*768，颜色32位，那&lt;/p&gt;&#10;&lt;p&gt;Framebuffer大小1024*768*32/8=3145728 字节&lt;/p&gt;&#10;&lt;p&gt;LCD操作原理：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;驱动程序设置好 LCD 控制器&lt;/p&gt;&#10;&lt;p&gt;根据 LCD 的参数设置 LCD 控制器的时序、信号极性；&lt;/p&gt;&#10;&lt;p&gt;根据 LCD 分辨率、BPP 分配 Framebuffer&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;APP 使用 ioctl 获得 LCD 分辨率、BPP&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;APP 通过 mmap 映射 Framebuffer，在 Framebuffer 中写入数据&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;&lt;img alt="image-20250809150759053" class="gallery-image" data-flex-basis="452px" data-flex-grow="188" height="423" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-05/images/image-20250809150759053.png" width="798"&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;每一块数据与LCD每一个像素一一对应&lt;/li&gt;&#10;&lt;li&gt;bpp：bits per pixel 每个像素用多少位表示颜色&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;假设需要设置 LCD 中坐标(x,y)处像素的颜色&lt;/p&gt;&#10;&lt;p&gt;(x，y)像素起始地址=fb_base+(xres*bpp/8)*y + x*bpp/8&lt;/p&gt;&#10;&lt;p&gt;怎么显示颜色？&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250809152101756" class="gallery-image" data-flex-basis="740px" data-flex-grow="308" height="329" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-05/images/image-20250809152101756.png" srcset="https://zeseanblog.top/p/embedded-05/images/image-20250809152101756_hu_f5c16a8f2d563dd.png 800w, https://zeseanblog.top/p/embedded-05/images/image-20250809152101756.png 1015w" width="1015"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250809152118972" class="gallery-image" data-flex-basis="1064px" data-flex-grow="443" height="231" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-05/images/image-20250809152118972.png" srcset="https://zeseanblog.top/p/embedded-05/images/image-20250809152118972_hu_fe7bc6e88acccbd1.png 800w, https://zeseanblog.top/p/embedded-05/images/image-20250809152118972.png 1025w" width="1025"&gt;&lt;/p&gt;&#10;&lt;h3 id="52-涉及的api函数"&gt;&lt;a href="#52-%e6%b6%89%e5%8f%8a%e7%9a%84api%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;5.2 涉及的API函数&#13;&#10;&lt;/h3&gt;&lt;p&gt;流程：打开 LCD 设备节点，获取分辨率等参数，映射Framebuffer，最后实现描点函数&lt;/p&gt;&#10;&lt;h4 id="522-ioctl函数"&gt;&lt;a href="#522-ioctl%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;5.2.2 ioctl函数&#13;&#10;&lt;/h4&gt;&lt;p&gt;&lt;code&gt;ioctl&lt;/code&gt; 是 Unix/Linux 里最“万能”的系统调用——&lt;strong&gt;“I/O 控制” 万金油&lt;/strong&gt;，几乎任何驱动都能通过它暴露“命令 + 数据”接口&lt;/p&gt;&#10;&lt;p&gt;#include &amp;lt;sys/ioctl.h&amp;gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;int ioctl(int fd, unsigned long request, &amp;hellip;);&lt;/strong&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;fd 表示文件描述符&lt;/li&gt;&#10;&lt;li&gt;request 表示与驱动程序交互的命令，用不同的命令控制驱动程序输出我们需要的数据&lt;/li&gt;&#10;&lt;li&gt;… 表示可变参数 arg，根据 request 命令，设备驱动程序返回输出的数据&lt;/li&gt;&#10;&lt;li&gt;返回值，成功返回文件描述符，失败返回-1&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4 id="523-mmap-函数"&gt;&lt;a href="#523-mmap-%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;5.2.3 mmap 函数&#13;&#10;&lt;/h4&gt;&lt;p&gt;头文件：&lt;/p&gt;&#10;&lt;p&gt;#include &amp;lt;sys/mman.h&amp;gt;&lt;/p&gt;&#10;&lt;p&gt;函数原型：&lt;/p&gt;&#10;&lt;p&gt;void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);&lt;/p&gt;&#10;&lt;p&gt;参数：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;addr 表示指定映射的內存起始地址，通常设为 NULL 表示让系统自动选定地址，并在成功映射后返回该地址&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;length 表示将文件中多大的内容映射到内存中&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;prot 表示映射区域的保护方式，可以为以下 4 种方式的组合&lt;/p&gt;&#10;&lt;p&gt;◼ PROT_EXEC 映射区域可被执行&lt;/p&gt;&#10;&lt;p&gt;◼ PROT_READ 映射区域可被读出&lt;/p&gt;&#10;&lt;p&gt;◼ PROT_WRITE 映射区域可被写入&lt;/p&gt;&#10;&lt;p&gt;◼ PROT_NONE 映射区域不能存取&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Flags 表示影响映射区域的不同特性，常用的有以下两种&lt;/p&gt;&#10;&lt;p&gt;◼ MAP_SHARED 表示对映射区域写入的数据会复制回文件内，原来的文&lt;/p&gt;&#10;&lt;p&gt;件会改变。&lt;/p&gt;&#10;&lt;p&gt;◼ MAP_PRIVATE 表示对映射区域的操作会产生一个映射文件的复制，对此区域的任何修改都不会写回原来的文件内容中。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;返回值：若成功映射，将返回指向映射的区域的指针，失败将返回-1。&lt;/p&gt;&#10;&lt;h3 id="53程序"&gt;&lt;a href="#53%e7%a8%8b%e5%ba%8f" class="header-anchor"&gt;&lt;/a&gt;5.3程序&#13;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 10&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 11&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 12&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 13&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 14&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 15&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 16&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 17&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 18&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 19&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 20&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 21&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 22&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 23&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 24&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 25&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 26&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 27&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 28&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 29&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 30&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 31&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 32&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 33&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 34&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 35&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 36&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 37&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 38&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 39&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 40&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 41&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 42&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 43&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 44&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 45&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 46&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 47&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 48&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 49&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 50&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 51&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 52&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 53&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 54&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 55&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 56&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 57&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 58&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 59&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 60&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 61&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 62&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 63&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 64&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 65&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 66&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 67&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 68&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 69&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 70&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 71&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 72&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 73&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 74&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 75&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 76&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 77&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 78&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 79&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 80&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 81&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 82&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 83&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 84&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 85&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 86&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 87&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 88&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 89&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 90&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 91&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 92&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 93&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 94&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 95&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 96&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 97&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 98&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 99&#10;&lt;/span&gt;&lt;span class="lnt"&gt;100&#10;&lt;/span&gt;&lt;span class="lnt"&gt;101&#10;&lt;/span&gt;&lt;span class="lnt"&gt;102&#10;&lt;/span&gt;&lt;span class="lnt"&gt;103&#10;&lt;/span&gt;&lt;span class="lnt"&gt;104&#10;&lt;/span&gt;&lt;span class="lnt"&gt;105&#10;&lt;/span&gt;&lt;span class="lnt"&gt;106&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/types.h&amp;gt;&#9;&#9;&#9;//open()&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/stat.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;fcntl.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&#9;&#9;&#9;&#9;//close()&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/ioctl.h&amp;gt;&#9;&#9;&#9;//ioctl()&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/mman.h&amp;gt;&#9;&#9;&#9;//mmap()&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;linux/fb.h&amp;gt;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;fd_fb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;fb_var_screeninfo&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#9;&lt;span class="cm"&gt;/* Current var */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;screen_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fb_base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;line_width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;pixel_width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;lcd_put_pixel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;fd_fb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/dev/fb0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;O_RDWR&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd_fb&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;can&amp;#39;t open /dev/fb0&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ioctl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd_fb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FBIOGET_VSCREENINFO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;can&amp;#39;t get var&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd_fb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;line_width&lt;/span&gt;&#9;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xres&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bits_per_pixel&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;pixel_width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bits_per_pixel&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;screen_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xres&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yres&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bits_per_pixel&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;fb_base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;mmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;screen_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PROT_READ&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;PROT_WRITE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MAP_SHARED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fd_fb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fb_base&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;can&amp;#39;t mmap&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="cm"&gt;/* 清屏: 全部设为白色 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;memset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fb_base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;screen_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;lcd_put_pixel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xres&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yres&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xFF0000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;munmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fb_base&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;screen_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd_fb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;lcd_put_pixel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pen_8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fb_base&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;line_width&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pixel_width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pen_16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pen_32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;green&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;pen_16&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;pen_8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;pen_32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;pen_8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bits_per_pixel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pen_8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="cm"&gt;/* 565 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="n"&gt;red&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="n"&gt;green&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="n"&gt;blue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;red&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;green&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blue&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pen_16&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pen_32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;can&amp;#39;t surport %dbpp&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bits_per_pixel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h3 id="54上机"&gt;&lt;a href="#54%e4%b8%8a%e6%9c%ba" class="header-anchor"&gt;&lt;/a&gt;5.4上机&#13;&#10;&lt;/h3&gt;&lt;p&gt;arm-buildroot-linux-gnueabihf-gcc -o show_pixel show_pixel.c&lt;/p&gt;&#10;&lt;p&gt;adb上传后执行&lt;/p&gt;&#10;&lt;h2 id="第6章文字显示"&gt;&lt;a href="#%e7%ac%ac6%e7%ab%a0%e6%96%87%e5%ad%97%e6%98%be%e7%a4%ba" class="header-anchor"&gt;&lt;/a&gt;第6章文字显示&#13;&#10;&lt;/h2&gt;&lt;h3 id="61字符编码方式"&gt;&lt;a href="#61%e5%ad%97%e7%ac%a6%e7%bc%96%e7%a0%81%e6%96%b9%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;6.1字符编码方式&#13;&#10;&lt;/h3&gt;&lt;h4 id="611编码与字体"&gt;&lt;a href="#611%e7%bc%96%e7%a0%81%e4%b8%8e%e5%ad%97%e4%bd%93" class="header-anchor"&gt;&lt;/a&gt;6.1.1编码与字体&#13;&#10;&lt;/h4&gt;&lt;p&gt;1.ASCII&lt;/p&gt;&#10;&lt;p&gt;常用字母就 26 个，区分大小写、加上标点符号也没超过 127 个，每个字符用一个字节来表示就足够了。一个字节的 7 位就可以表示 128 个数值，在 ASCII 码中最高位永远是 0&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250809170017094" class="gallery-image" data-flex-basis="553px" data-flex-grow="230" height="371" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-05/images/image-20250809170017094.png" srcset="https://zeseanblog.top/p/embedded-05/images/image-20250809170017094_hu_7533b9af4175d52d.png 800w, https://zeseanblog.top/p/embedded-05/images/image-20250809170017094.png 856w" width="856"&gt;&lt;/p&gt;&#10;&lt;p&gt;2.ANSI&lt;/p&gt;&#10;&lt;p&gt;强烈建议阅读：https://www.cnblogs.com/malecrab/p/5300486.html&lt;/p&gt;&#10;&lt;p&gt;如在中国大陆地区，ANSI 的默认编码是 GB2312；在港澳台地区默认编码是 BIG5&lt;/p&gt;&#10;&lt;p&gt;不同文字系统ANSI表示不同编码&lt;/p&gt;&#10;&lt;p&gt;3.UniCode&lt;/p&gt;&#10;&lt;p&gt;UNICODE 中的数值范围是 0x0000 至 0x10FFFF，有 1,114,111 即 100 多万个数值，可以表示 100 多万个字符，足够地球人使用了。&lt;/p&gt;&#10;&lt;p&gt;向下兼容ascii&lt;/p&gt;&#10;&lt;h4 id="612unicode编码实现"&gt;&lt;a href="#612unicode%e7%bc%96%e7%a0%81%e5%ae%9e%e7%8e%b0" class="header-anchor"&gt;&lt;/a&gt;6.1.2UniCode编码实现&#13;&#10;&lt;/h4&gt;&lt;p&gt;“中” UNICODE 值是 0x4e2d，在 TXT 文件中怎么表示 0x4e2d？直接写入 0x4e2d？&lt;/p&gt;&#10;&lt;p&gt;不行！&lt;/p&gt;&#10;&lt;p&gt;比如在 TXT 文件中写入 2 字节数据“0x2d 0x4e”，它可以用来表示“中”字吗？&lt;/p&gt;&#10;&lt;p&gt;不能！它们对应 ASCII 字符“-N”。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;问题的关键在于：怎么断字&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;那怎么表示一个unicode&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;1.使用3个字节&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;太浪费，比如字符 A 的 UNICOCDE 值是0x41，难道也用“0x41 0x00 0x00”这 3 个字节来表示？&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;2.UCS-2 Little endian/UTF-16 LE&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;能表示2^16=65536 个字符&lt;/p&gt;&#10;&lt;p&gt;Little endian 表示小字节序，数值中权重低的字节放在前面，比如字符“A 中”在 TXT 文件中的数值如下，其中的“A”使用“0x41 0x00”两字节表示；“中”使用“0x2d 0x4e”两字节表示。文件开头的“0xff 0xfe”表示“UTF-16 LE”。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;3.UCS-2 Big endian/UTF-16 BE&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;与2相反&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;4.UTF8&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;上面两种方法：表示字符数量有限、对于ASCII字符浪费空间、如果某字节丢失后面字符都因为错位无法显示&lt;/p&gt;&#10;&lt;p&gt;使用UTF8可以解决上述所有问题。UTF8 是变长的编码方法，有 2 种 UTF8格式的文件：带有头部、不带头部。&lt;/p&gt;&#10;&lt;p&gt;对ascii字符在 UTF8 文件中直接用其 ASCII 码来表示，0x61 表示字符 a、0x62 表示字符 b&lt;/p&gt;&#10;&lt;p&gt;而3 个字节“0xe4 0xb8 0xad”表示的数值是 0x4e2d，对应“中”的 UNICODE 码&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250809195723355" class="gallery-image" data-flex-basis="504px" data-flex-grow="210" height="551" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-05/images/image-20250809195723355.png" srcset="https://zeseanblog.top/p/embedded-05/images/image-20250809195723355_hu_f8cd2676c4167558.png 800w, https://zeseanblog.top/p/embedded-05/images/image-20250809195723355.png 1159w" width="1159"&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;0xe4 的二进制是“11100100”，高位有 3 个 1，表示从当前字节起有3字节参与表示UNICODE；&lt;/li&gt;&#10;&lt;li&gt;0xb8 的二进制是“10111000”，高位有 1 个 1，表示从当前字节起有1字节参与表示UNICODE；&lt;/li&gt;&#10;&lt;li&gt;0xad 的二进制是“10101101”，高位有 1 个 1，表示从当前字节起有1字节参与表示 UNICODE&lt;/li&gt;&#10;&lt;li&gt;除去高位的“1110”、“10”、“10”后，剩下的二进制数组合起来得到“01001110001101”，它就是 0x4e2d，即“中”的 UNICODE 值&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="62-ascii点阵显示"&gt;&lt;a href="#62-ascii%e7%82%b9%e9%98%b5%e6%98%be%e7%a4%ba" class="header-anchor"&gt;&lt;/a&gt;6.2 ASCII点阵显示&#13;&#10;&lt;/h3&gt;&lt;p&gt;LCD中显示ASCII字符，首先要找到字符对应的点阵，在linux内核源码有这个文件&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;lib\fonts\font_8x16.c&lt;/strong&gt;以数组形式保存字符点阵。&lt;/p&gt;&#10;&lt;p&gt;储存形式：&lt;/p&gt;&#10;&lt;img src="images/image-20250809200052184.png" alt="image-20250809200052184" style="zoom:67%;" /&gt;&#10;&lt;p&gt;要显示某个字符时，根据它的 ASCII 码在 fontdata_8x16 数组中找到它的点阵，然后取出这 16 个字节去描画 16 行像素.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;比如字符 A 的 ASCII 值是 0x41，那么从 fontdata_8x16[0x41*16]开始取其点阵数据&lt;/strong&gt;&lt;/p&gt;&#10;&lt;h4 id="621获取点阵"&gt;&lt;a href="#621%e8%8e%b7%e5%8f%96%e7%82%b9%e9%98%b5" class="header-anchor"&gt;&lt;/a&gt;6.2.1获取点阵&#13;&#10;&lt;/h4&gt;&lt;p&gt;对于字符c&lt;/p&gt;&#10;&lt;p&gt;unsigned char *dots = (unsigned char *)&amp;amp;fontdata_8x16[c*16];&lt;/p&gt;&#10;&lt;h4 id="622描点"&gt;&lt;a href="#622%e6%8f%8f%e7%82%b9" class="header-anchor"&gt;&lt;/a&gt;6.2.2描点&#13;&#10;&lt;/h4&gt;&lt;p&gt;因为有十六行，所以首先要有一个循环 16 次的大循环，然后每一行里有 8位，那么在每一个大循环里也需要一个循环 8 次的小循环。小循环里的判断单行的描点情况，如果是 1，就填充白色，如果是 0 就填充黑色。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 10&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 11&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 12&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 13&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 14&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 15&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 16&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 17&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 18&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 19&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 20&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 21&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 22&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 23&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 24&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 25&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 26&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 27&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 28&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 29&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 30&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 31&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 32&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 33&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 34&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 35&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 36&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 37&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 38&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 39&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 40&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 41&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 42&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 43&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 44&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 45&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 46&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 47&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 48&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 49&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 50&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 51&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 52&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 53&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 54&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 55&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 56&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 57&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 58&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 59&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 60&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 61&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 62&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 63&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 64&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 65&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 66&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 67&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 68&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 69&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 70&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 71&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 72&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 73&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 74&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 75&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 76&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 77&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 78&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 79&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 80&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 81&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 82&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 83&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 84&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 85&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 86&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 87&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 88&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 89&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 90&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 91&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 92&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 93&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 94&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 95&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 96&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 97&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 98&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 99&#10;&lt;/span&gt;&lt;span class="lnt"&gt;100&#10;&lt;/span&gt;&lt;span class="lnt"&gt;101&#10;&lt;/span&gt;&lt;span class="lnt"&gt;102&#10;&lt;/span&gt;&lt;span class="lnt"&gt;103&#10;&lt;/span&gt;&lt;span class="lnt"&gt;104&#10;&lt;/span&gt;&lt;span class="lnt"&gt;105&#10;&lt;/span&gt;&lt;span class="lnt"&gt;106&#10;&lt;/span&gt;&lt;span class="lnt"&gt;107&#10;&lt;/span&gt;&lt;span class="lnt"&gt;108&#10;&lt;/span&gt;&lt;span class="lnt"&gt;109&#10;&lt;/span&gt;&lt;span class="lnt"&gt;110&#10;&lt;/span&gt;&lt;span class="lnt"&gt;111&#10;&lt;/span&gt;&lt;span class="lnt"&gt;112&#10;&lt;/span&gt;&lt;span class="lnt"&gt;113&#10;&lt;/span&gt;&lt;span class="lnt"&gt;114&#10;&lt;/span&gt;&lt;span class="lnt"&gt;115&#10;&lt;/span&gt;&lt;span class="lnt"&gt;116&#10;&lt;/span&gt;&lt;span class="lnt"&gt;117&#10;&lt;/span&gt;&lt;span class="lnt"&gt;118&#10;&lt;/span&gt;&lt;span class="lnt"&gt;119&#10;&lt;/span&gt;&lt;span class="lnt"&gt;120&#10;&lt;/span&gt;&lt;span class="lnt"&gt;121&#10;&lt;/span&gt;&lt;span class="lnt"&gt;122&#10;&lt;/span&gt;&lt;span class="lnt"&gt;123&#10;&lt;/span&gt;&lt;span class="lnt"&gt;124&#10;&lt;/span&gt;&lt;span class="lnt"&gt;125&#10;&lt;/span&gt;&lt;span class="lnt"&gt;126&#10;&lt;/span&gt;&lt;span class="lnt"&gt;127&#10;&lt;/span&gt;&lt;span class="lnt"&gt;128&#10;&lt;/span&gt;&lt;span class="lnt"&gt;129&#10;&lt;/span&gt;&lt;span class="lnt"&gt;130&#10;&lt;/span&gt;&lt;span class="lnt"&gt;131&#10;&lt;/span&gt;&lt;span class="lnt"&gt;132&#10;&lt;/span&gt;&lt;span class="lnt"&gt;133&#10;&lt;/span&gt;&lt;span class="lnt"&gt;134&#10;&lt;/span&gt;&lt;span class="lnt"&gt;135&#10;&lt;/span&gt;&lt;span class="lnt"&gt;136&#10;&lt;/span&gt;&lt;span class="lnt"&gt;137&#10;&lt;/span&gt;&lt;span class="lnt"&gt;138&#10;&lt;/span&gt;&lt;span class="lnt"&gt;139&#10;&lt;/span&gt;&lt;span class="lnt"&gt;140&#10;&lt;/span&gt;&lt;span class="lnt"&gt;141&#10;&lt;/span&gt;&lt;span class="lnt"&gt;142&#10;&lt;/span&gt;&lt;span class="lnt"&gt;143&#10;&lt;/span&gt;&lt;span class="lnt"&gt;144&#10;&lt;/span&gt;&lt;span class="lnt"&gt;145&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/types.h&amp;gt;&#9;&#9;&#9;//open()&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/stat.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;fcntl.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&#9;&#9;&#9;&#9;//close()&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/ioctl.h&amp;gt;&#9;&#9;&#9;//ioctl()&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/mman.h&amp;gt;&#9;&#9;&#9;//mmap()&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;linux/fb.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define FONTDATAMAX 4096&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;fontdata_8x16&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;FONTDATAMAX&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="c1"&gt;//...略&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;fd_fb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;fb_var_screeninfo&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#9;&lt;span class="cm"&gt;/* Current var */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;screen_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fbmem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;line_width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;pixel_width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/**********************************************************************&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 函数名称： lcd_put_pixel&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 功能描述： 在LCD指定位置上输出指定颜色（描点）&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 输入参数： x坐标，y坐标，颜色&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 输出参数： 无&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 返 回 值： 会&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 修改日期 版本号 修改人&#9; 修改内容&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * -----------------------------------------------&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 2020/05/12&#9; V1.0&#9; zh(angenao)&#9; 创建&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; ***********************************************************************/&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;lcd_put_pixel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pen_8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fbmem&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;line_width&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pixel_width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pen_16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pen_32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;green&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;pen_16&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;pen_8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;pen_32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;pen_8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bits_per_pixel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pen_8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="cm"&gt;/* 565 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="n"&gt;red&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="n"&gt;green&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="n"&gt;blue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;red&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;green&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blue&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pen_16&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pen_32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;can&amp;#39;t surport %dbpp&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bits_per_pixel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/**********************************************************************&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 函数名称： lcd_put_ascii&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 功能描述： 在LCD指定位置上显示一个8*16的字符&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 输入参数： x坐标，y坐标，ascii码&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 输出参数： 无&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 返 回 值： 无&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 修改日期 版本号 修改人&#9; 修改内容&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * -----------------------------------------------&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 2020/05/12&#9; V1.0&#9; zh(angenao)&#9; 创建&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; ***********************************************************************/&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;lcd_put_ascii&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;dots&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;fontdata_8x16&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="n"&gt;byte&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dots&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;byte&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&lt;span class="cm"&gt;/* show */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&lt;span class="nf"&gt;lcd_put_pixel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xffffff&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="cm"&gt;/* 白 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;else&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&lt;span class="cm"&gt;/* hide */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&lt;span class="nf"&gt;lcd_put_pixel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="cm"&gt;/* 黑 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;fd_fb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/dev/fb0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;O_RDWR&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd_fb&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;can&amp;#39;t open /dev/fb0&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ioctl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd_fb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FBIOGET_VSCREENINFO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;can&amp;#39;t get var&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;line_width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xres&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bits_per_pixel&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;pixel_width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bits_per_pixel&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;screen_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xres&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yres&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bits_per_pixel&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;fbmem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;mmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;screen_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PROT_READ&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;PROT_WRITE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MAP_SHARED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fd_fb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fbmem&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;can&amp;#39;t mmap&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="cm"&gt;/* 清屏: 全部设为黑色 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;memset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fbmem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;screen_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;lcd_put_ascii&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xres&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yres&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="cm"&gt;/*在屏幕中间显示8*16的字母A*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;munmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fbmem&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;screen_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd_fb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="623show_string"&gt;&lt;a href="#623show_string" class="header-anchor"&gt;&lt;/a&gt;6.2.3show_string&#13;&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;span class="lnt"&gt;7&#10;&lt;/span&gt;&lt;span class="lnt"&gt;8&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;lcd_put_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;lcd_put_ascii&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="cm"&gt;/* 每字符宽 8 像素 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* 横排前进 8 像素 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h3 id="63中文字符的点阵显示"&gt;&lt;a href="#63%e4%b8%ad%e6%96%87%e5%ad%97%e7%ac%a6%e7%9a%84%e7%82%b9%e9%98%b5%e6%98%be%e7%a4%ba" class="header-anchor"&gt;&lt;/a&gt;6.3中文字符的点阵显示&#13;&#10;&lt;/h3&gt;&lt;h4 id="631指定编码格式"&gt;&lt;a href="#631%e6%8c%87%e5%ae%9a%e7%bc%96%e7%a0%81%e6%a0%bc%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;6.3.1指定编码格式&#13;&#10;&lt;/h4&gt;&lt;p&gt;test_charset_ansi.c&lt;/p&gt;&#10;&lt;p&gt;test_charset_utf8.c&lt;/p&gt;&#10;&lt;p&gt;可以对test_charset_ansi.c将原文件的GB2312格式，输出为可执行文件时以UTF8格式编码&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;gcc -finput-charset=GB2312 -fexec-charset=UTF-8 -o test_charset_ansi test_charset_ansi.c&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果不指定“-finput-charset”，GCC 就会默认 C 程序的编码方式为 UTF-8，即使你是以 ANSI 格式保存，也会被当作 UTF-8 来对待&lt;/p&gt;&#10;&lt;p&gt;如果不指定“-fexec-charset”，GCC 就会默认编译出的可执行程序中字符的编码方式为 UTF-8&lt;/p&gt;&#10;&lt;p&gt;如果“-finput-charset”与“-fexec-charset”不一样，编译器会进行格式转换&lt;/p&gt;&#10;&lt;h4 id="633汉字区位码"&gt;&lt;a href="#633%e6%b1%89%e5%ad%97%e5%8c%ba%e4%bd%8d%e7%a0%81" class="header-anchor"&gt;&lt;/a&gt;6.3.3汉字区位码&#13;&#10;&lt;/h4&gt;&lt;p&gt;HZK16 这个文件，它是常用汉字的 16*16 点阵字库&lt;/p&gt;&#10;&lt;p&gt;每个汉字用32字节描述&lt;/p&gt;&#10;&lt;img src="images/image-20250810200124273.png" alt="image-20250810200124273" style="zoom:67%;" /&gt;&#10;&lt;p&gt;HZK16 中是以 GB2312 编码值来查找点阵以“中”字为例，它的编码值是“0xd6 0xd0”，其中的 0xd6 表示“区码”，表示在哪一个区：第“0xd6 - 0xa1”区；其中的 0xd0 表示“位码”，表示它是这个区里的哪一个字符：第“0xd0 -0xa1”个。每一个区有 94 个汉字。区位码从 0xa1 而不是从 0 开始，是为了兼容 ASCII 码&lt;/p&gt;&#10;&lt;p&gt;中字：第(0xd6-0xa1)*94+(0xd0-0xa1)个字符&lt;/p&gt;&#10;&lt;h3 id="64交叉编译程序以freetype为例"&gt;&lt;a href="#64%e4%ba%a4%e5%8f%89%e7%bc%96%e8%af%91%e7%a8%8b%e5%ba%8f%e4%bb%a5freetype%e4%b8%ba%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;6.4交叉编译程序：以freetype为例&#13;&#10;&lt;/h3&gt;&lt;p&gt;使用 buildroot 来给 ARM 板编译程序、编译库会很简单，以后系统讲解buildroot 时再使用 buildroot&lt;/p&gt;&#10;&lt;p&gt;现在我们还是手工交叉编译 freetype&lt;/p&gt;&#10;&lt;h4 id="641程序运行的基本知识"&gt;&lt;a href="#641%e7%a8%8b%e5%ba%8f%e8%bf%90%e8%a1%8c%e7%9a%84%e5%9f%ba%e6%9c%ac%e7%9f%a5%e8%af%86" class="header-anchor"&gt;&lt;/a&gt;6.4.1程序运行的基本知识&#13;&#10;&lt;/h4&gt;&lt;p&gt;1.编译程序时去哪找头文件&lt;/p&gt;&#10;&lt;p&gt;系统目录：交叉编译工具链的某include目录&lt;/p&gt;&#10;&lt;p&gt;自己指定：编译时-I dir&lt;/p&gt;&#10;&lt;p&gt;2.链接时去哪找库文件&lt;/p&gt;&#10;&lt;p&gt;系统目录：就是交叉编译工具链里的某个 lib 目录&lt;/p&gt;&#10;&lt;p&gt;自己指定：链接时用 “ -L dir ”&lt;/p&gt;&#10;&lt;p&gt;3.运行时去哪找库文件&lt;/p&gt;&#10;&lt;p&gt;系统目录：就是板子上的/lib、/usr/lib 目录&lt;/p&gt;&#10;&lt;p&gt;自己指定：运行程序用环境变量 LD_LIBRARY_PATH 指定&lt;/p&gt;&#10;&lt;p&gt;4.运行时不需要头文件，因此头文件不需要放板子上&lt;/p&gt;&#10;&lt;h4 id="642常见错误"&gt;&lt;a href="#642%e5%b8%b8%e8%a7%81%e9%94%99%e8%af%af" class="header-anchor"&gt;&lt;/a&gt;6.4.2常见错误&#13;&#10;&lt;/h4&gt;&lt;p&gt;1.头文件&lt;/p&gt;&#10;&lt;p&gt;编译时找不到头文件。在程序中这样包含头文件：#include &amp;lt;xxx.h&amp;gt;&lt;/p&gt;&#10;&lt;p&gt;怎么找到头文件&lt;/p&gt;&#10;&lt;p&gt;系统目录：交叉编译工具链的某个include目录&lt;/p&gt;&#10;&lt;p&gt;怎么找到系统目录？&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;echo &amp;#39;main(){}&amp;#39;| arm-buildroot-linux-gnueabihf-gcc -E -v -&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2.库文件&lt;/p&gt;&#10;&lt;p&gt;链接程序时如果有这样的提示：undefined reference to `xxx&amp;rsquo;，它表示 xxx 函数未定义&lt;/p&gt;&#10;&lt;p&gt;解决方法：&#10;写出这个函数，或使用库函数，即在链接时指定库&lt;/p&gt;&#10;&lt;p&gt;怎么指定：&lt;/p&gt;&#10;&lt;p&gt;想链接 libabc.so，那链接时加上：-labc&lt;/p&gt;&#10;&lt;p&gt;库在哪：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;系统目录：就是交叉编译工具链里的某个 lib 目录&lt;/li&gt;&#10;&lt;li&gt;以自己指定：链接时用 “ -L dir ”选项指定&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;3.运行问题&lt;/p&gt;&#10;&lt;p&gt;运行时找不到库，库在哪？&lt;/p&gt;&#10;&lt;p&gt;系统目录：就是板子上的/lib、/usr/lib 目录&lt;/p&gt;&#10;&lt;p&gt;自己指定：&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;export LD_LIBRARY_PATH=/xxx_dir; ./test&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;或&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;LD_LIBRARY_PATH=/xxx_dir ./test&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="643交叉编译万能命令"&gt;&lt;a href="#643%e4%ba%a4%e5%8f%89%e7%bc%96%e8%af%91%e4%b8%87%e8%83%bd%e5%91%bd%e4%bb%a4" class="header-anchor"&gt;&lt;/a&gt;6.4.3交叉编译万能命令&#13;&#10;&lt;/h4&gt;&lt;p&gt;如果交叉编辑工具链的前缀是&lt;strong&gt;arm-buildroot-linux-gnueabihf-&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;交叉编译开源软件时，如果有configure文件&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250810204638777" class="gallery-image" data-flex-basis="4024px" data-flex-grow="1676" height="95" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-05/images/image-20250810204638777.png" srcset="https://zeseanblog.top/p/embedded-05/images/image-20250810204638777_hu_55c7e91dda9f656e.png 800w, https://zeseanblog.top/p/embedded-05/images/image-20250810204638777.png 1593w" width="1593"&gt;&lt;/p&gt;&#10;&lt;p&gt;万能命令如下：&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;./configure --host=arm-buildroot-linux-gnueabihf --prefix=$PWD/tmp&#10;make&#10;make install&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;就可以在当前目录的 tmp 目录下看见 bin, lib, include 等目录，里面存有可执行程序、库、头文件&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;cp include/freetype2/* -rfd /home/book/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../lib/gcc/arm-buildroot-linux-gnueabihf/7.5.0/include&#10;&#10;cp lib/* -rfd /home/book/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../lib/gcc/arm-buildroot-linux-gnueabihf/7.5.0/../../../../arm-buildroot-linux-gnueabihf/lib&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="65使用freetype显示单个文字"&gt;&lt;a href="#65%e4%bd%bf%e7%94%a8freetype%e6%98%be%e7%a4%ba%e5%8d%95%e4%b8%aa%e6%96%87%e5%ad%97" class="header-anchor"&gt;&lt;/a&gt;6.5使用freetype显示单个文字&#13;&#10;&lt;/h3&gt;&lt;h4 id="651矢量字体引入"&gt;&lt;a href="#651%e7%9f%a2%e9%87%8f%e5%ad%97%e4%bd%93%e5%bc%95%e5%85%a5" class="header-anchor"&gt;&lt;/a&gt;6.5.1矢量字体引入&#13;&#10;&lt;/h4&gt;&lt;p&gt;使用点阵字库显示放大缩小会模糊甚至锯齿，为解决引入矢量字体&lt;/p&gt;&#10;&lt;p&gt;矢量字体分三步：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;确定关键点&lt;/li&gt;&#10;&lt;li&gt;使用数学曲线连接头键点&lt;/li&gt;&#10;&lt;li&gt;填充闭合曲线内部空间&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;img src="images/image-20250810212846152.png" alt="image-20250810212846152" style="zoom:50%;" /&gt;&#10;&lt;h4 id="652在-lcd-上显示一个矢量字体"&gt;&lt;a href="#652%e5%9c%a8-lcd-%e4%b8%8a%e6%98%be%e7%a4%ba%e4%b8%80%e4%b8%aa%e7%9f%a2%e9%87%8f%e5%ad%97%e4%bd%93" class="header-anchor"&gt;&lt;/a&gt;6.5.2&lt;strong&gt;在&lt;/strong&gt; &lt;strong&gt;LCD&lt;/strong&gt; 上显示一个矢量字体&#13;&#10;&lt;/h4&gt;&lt;p&gt;开源字体引擎库，统一接口访问多种字体格式文件，实现矢量字体显示。&lt;/p&gt;&#10;&lt;p&gt;一个文字的显示过程可以概括如下：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;给定一个字符可以确定它的编码值(ASCII、UNICODE、GB2312)；&lt;/li&gt;&#10;&lt;li&gt;设置字体大小；&lt;/li&gt;&#10;&lt;li&gt;根据编码值，从文件头部中通过 charmap 找到对应的关键点(glyph)，它会根据字体大小调整关键点；&lt;/li&gt;&#10;&lt;li&gt;把关键点转换为位图点阵；&lt;/li&gt;&#10;&lt;li&gt;在 LCD 上显示出来&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;freetype初始化步骤如下：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;初始化：FT_InitFreetype&lt;/li&gt;&#10;&lt;li&gt;加载(打开)字体 Face：FT_New_Face&lt;/li&gt;&#10;&lt;li&gt;设置字体大小：FT_Set_Char_Sizes 或 FT_Set_Pixel_Sizes&lt;/li&gt;&#10;&lt;li&gt;选择 charmap：FT_Select_Charmap&lt;/li&gt;&#10;&lt;li&gt;根据编码值 charcode 找到 glyph_index：glyph_index = FT_Get_Char_Index（face，charcode）&lt;/li&gt;&#10;&lt;li&gt;根据 glyph_index 取出 glyph：FT_Load_Glyph（face，glyph_index）&lt;/li&gt;&#10;&lt;li&gt;转为位图：FT_Render_Glyph&lt;/li&gt;&#10;&lt;li&gt;移动或旋转:FT_Set_Transform&lt;/li&gt;&#10;&lt;li&gt;最后显示出来&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;上面的5、6、7可以使用一个函数代替：FT_Load_Char(face, charcode, FT_LOAD_RENDER)，它就可以得到位图&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 10&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 11&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 12&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 13&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 14&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 15&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 16&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 17&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 18&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 19&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 20&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 21&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 22&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 23&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 24&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 25&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 26&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 27&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 28&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 29&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 30&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 31&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 32&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 33&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 34&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 35&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 36&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 37&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 38&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 39&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 40&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 41&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 42&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 43&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 44&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 45&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 46&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 47&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 48&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 49&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 50&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 51&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 52&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 53&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 54&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 55&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 56&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 57&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 58&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 59&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 60&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 61&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 62&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 63&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 64&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 65&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 66&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 67&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 68&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 69&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 70&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 71&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 72&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 73&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 74&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 75&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 76&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 77&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 78&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 79&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 80&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 81&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 82&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 83&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 84&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 85&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 86&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 87&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 88&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 89&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 90&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 91&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 92&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 93&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 94&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 95&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 96&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 97&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 98&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 99&#10;&lt;/span&gt;&lt;span class="lnt"&gt;100&#10;&lt;/span&gt;&lt;span class="lnt"&gt;101&#10;&lt;/span&gt;&lt;span class="lnt"&gt;102&#10;&lt;/span&gt;&lt;span class="lnt"&gt;103&#10;&lt;/span&gt;&lt;span class="lnt"&gt;104&#10;&lt;/span&gt;&lt;span class="lnt"&gt;105&#10;&lt;/span&gt;&lt;span class="lnt"&gt;106&#10;&lt;/span&gt;&lt;span class="lnt"&gt;107&#10;&lt;/span&gt;&lt;span class="lnt"&gt;108&#10;&lt;/span&gt;&lt;span class="lnt"&gt;109&#10;&lt;/span&gt;&lt;span class="lnt"&gt;110&#10;&lt;/span&gt;&lt;span class="lnt"&gt;111&#10;&lt;/span&gt;&lt;span class="lnt"&gt;112&#10;&lt;/span&gt;&lt;span class="lnt"&gt;113&#10;&lt;/span&gt;&lt;span class="lnt"&gt;114&#10;&lt;/span&gt;&lt;span class="lnt"&gt;115&#10;&lt;/span&gt;&lt;span class="lnt"&gt;116&#10;&lt;/span&gt;&lt;span class="lnt"&gt;117&#10;&lt;/span&gt;&lt;span class="lnt"&gt;118&#10;&lt;/span&gt;&lt;span class="lnt"&gt;119&#10;&lt;/span&gt;&lt;span class="lnt"&gt;120&#10;&lt;/span&gt;&lt;span class="lnt"&gt;121&#10;&lt;/span&gt;&lt;span class="lnt"&gt;122&#10;&lt;/span&gt;&lt;span class="lnt"&gt;123&#10;&lt;/span&gt;&lt;span class="lnt"&gt;124&#10;&lt;/span&gt;&lt;span class="lnt"&gt;125&#10;&lt;/span&gt;&lt;span class="lnt"&gt;126&#10;&lt;/span&gt;&lt;span class="lnt"&gt;127&#10;&lt;/span&gt;&lt;span class="lnt"&gt;128&#10;&lt;/span&gt;&lt;span class="lnt"&gt;129&#10;&lt;/span&gt;&lt;span class="lnt"&gt;130&#10;&lt;/span&gt;&lt;span class="lnt"&gt;131&#10;&lt;/span&gt;&lt;span class="lnt"&gt;132&#10;&lt;/span&gt;&lt;span class="lnt"&gt;133&#10;&lt;/span&gt;&lt;span class="lnt"&gt;134&#10;&lt;/span&gt;&lt;span class="lnt"&gt;135&#10;&lt;/span&gt;&lt;span class="lnt"&gt;136&#10;&lt;/span&gt;&lt;span class="lnt"&gt;137&#10;&lt;/span&gt;&lt;span class="lnt"&gt;138&#10;&lt;/span&gt;&lt;span class="lnt"&gt;139&#10;&lt;/span&gt;&lt;span class="lnt"&gt;140&#10;&lt;/span&gt;&lt;span class="lnt"&gt;141&#10;&lt;/span&gt;&lt;span class="lnt"&gt;142&#10;&lt;/span&gt;&lt;span class="lnt"&gt;143&#10;&lt;/span&gt;&lt;span class="lnt"&gt;144&#10;&lt;/span&gt;&lt;span class="lnt"&gt;145&#10;&lt;/span&gt;&lt;span class="lnt"&gt;146&#10;&lt;/span&gt;&lt;span class="lnt"&gt;147&#10;&lt;/span&gt;&lt;span class="lnt"&gt;148&#10;&lt;/span&gt;&lt;span class="lnt"&gt;149&#10;&lt;/span&gt;&lt;span class="lnt"&gt;150&#10;&lt;/span&gt;&lt;span class="lnt"&gt;151&#10;&lt;/span&gt;&lt;span class="lnt"&gt;152&#10;&lt;/span&gt;&lt;span class="lnt"&gt;153&#10;&lt;/span&gt;&lt;span class="lnt"&gt;154&#10;&lt;/span&gt;&lt;span class="lnt"&gt;155&#10;&lt;/span&gt;&lt;span class="lnt"&gt;156&#10;&lt;/span&gt;&lt;span class="lnt"&gt;157&#10;&lt;/span&gt;&lt;span class="lnt"&gt;158&#10;&lt;/span&gt;&lt;span class="lnt"&gt;159&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/mman.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/types.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/stat.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;linux/fb.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;fcntl.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;math.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;wchar.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/ioctl.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;ft2build.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;FT_FREETYPE_H&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;FT_GLYPH_H&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;fd_fb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;fb_var_screeninfo&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#9;&lt;span class="cm"&gt;/* Current var */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;screen_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fbmem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;line_width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;pixel_width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;lcd_put_pixel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pen_8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fbmem&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;line_width&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pixel_width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pen_16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pen_32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;green&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;pen_16&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;pen_8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;pen_32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;pen_8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bits_per_pixel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pen_8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="cm"&gt;/* 565 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="n"&gt;red&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="n"&gt;green&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="n"&gt;blue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;red&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;green&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blue&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pen_16&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pen_32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;can&amp;#39;t surport %dbpp&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bits_per_pixel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;draw_bitmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FT_Bitmap&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;bitmap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;FT_Int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;FT_Int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;FT_Int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;FT_Int&lt;/span&gt; &lt;span class="n"&gt;x_max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;bitmap&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;FT_Int&lt;/span&gt; &lt;span class="n"&gt;y_max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;bitmap&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="c1"&gt;//printf(&amp;#34;x = %d, y = %d\n&amp;#34;, x, y);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;y_max&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;x_max&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xres&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yres&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="nf"&gt;lcd_put_pixel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bitmap&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;bitmap&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;wchar_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;chinese_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;L&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;繁&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;FT_Library&lt;/span&gt;&#9; &lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;FT_Face&lt;/span&gt; &#9; &lt;span class="n"&gt;face&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;FT_Vector&lt;/span&gt; &lt;span class="n"&gt;pen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;FT_GlyphSlot&lt;/span&gt; &lt;span class="n"&gt;slot&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;font_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Usage : %s &amp;lt;font_file&amp;gt; [font_size]&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="n"&gt;font_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;strtoul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;fd_fb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/dev/fb0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;O_RDWR&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd_fb&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;can&amp;#39;t open /dev/fb0&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ioctl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd_fb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FBIOGET_VSCREENINFO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;can&amp;#39;t get var&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;line_width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xres&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bits_per_pixel&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;pixel_width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bits_per_pixel&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;screen_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xres&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yres&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bits_per_pixel&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;fbmem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;mmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;screen_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PROT_READ&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;PROT_WRITE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MAP_SHARED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fd_fb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fbmem&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;can&amp;#39;t mmap&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="cm"&gt;/* 清屏: 全部设为黑色 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;memset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fbmem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;screen_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="cm"&gt;/* 显示矢量字体 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;FT_Init_FreeType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;&#9;&#9;&#9; &lt;span class="cm"&gt;/* initialize library */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="cm"&gt;/* error handling omitted */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;FT_New_Face&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;face&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="cm"&gt;/* create face object */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="cm"&gt;/* error handling omitted */&lt;/span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;face&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;glyph&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;FT_Set_Pixel_Sizes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;face&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;font_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="cm"&gt;/* 确定座标:&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;&#9; */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="c1"&gt;//pen.x = 0;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="c1"&gt;//pen.y = 0;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/* set transformation */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;//FT_Set_Transform( face, 0, &amp;amp;pen);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/* load glyph image into the slot (erase previous one) */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;FT_Load_Char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;face&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chinese_str&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;FT_LOAD_RENDER&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;FT_Load_Char error&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;draw_bitmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;slot&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;bitmap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xres&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yres&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;上机：&lt;/p&gt;&#10;&lt;p&gt;./freetype_show_font ./simsun.ttc&lt;/p&gt;&#10;&lt;h4 id="653在-lcd-上令矢量字体旋转某个角度"&gt;&lt;a href="#653%e5%9c%a8-lcd-%e4%b8%8a%e4%bb%a4%e7%9f%a2%e9%87%8f%e5%ad%97%e4%bd%93%e6%97%8b%e8%bd%ac%e6%9f%90%e4%b8%aa%e8%a7%92%e5%ba%a6" class="header-anchor"&gt;&lt;/a&gt;6.5.3&lt;strong&gt;在&lt;/strong&gt; &lt;strong&gt;LCD&lt;/strong&gt; 上令矢量字体旋转某个角度&#13;&#10;&lt;/h4&gt;&lt;p&gt;定义 2 个变量：角度、矩阵&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250810220241009" class="gallery-image" data-flex-basis="3236px" data-flex-grow="1348" height="72" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-05/images/image-20250810220241009.png" srcset="https://zeseanblog.top/p/embedded-05/images/image-20250810220241009_hu_3cee6e7a6d54cb0a.png 800w, https://zeseanblog.top/p/embedded-05/images/image-20250810220241009.png 971w" width="971"&gt;&lt;/p&gt;&#10;&lt;p&gt;设置角度值&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250810220253000" class="gallery-image" data-flex-basis="10896px" data-flex-grow="4540" height="30" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-05/images/image-20250810220253000.png" srcset="https://zeseanblog.top/p/embedded-05/images/image-20250810220253000_hu_aeece03ec51f254b.png 800w, https://zeseanblog.top/p/embedded-05/images/image-20250810220253000.png 1362w" width="1362"&gt;&lt;/p&gt;&#10;&lt;p&gt;设置矩阵、变形、加载位图&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250810220305819" class="gallery-image" data-flex-basis="502px" data-flex-grow="209" height="439" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-05/images/image-20250810220305819.png" srcset="https://zeseanblog.top/p/embedded-05/images/image-20250810220305819_hu_25cc01a81debf7d1.png 800w, https://zeseanblog.top/p/embedded-05/images/image-20250810220305819.png 920w" width="920"&gt;&lt;/p&gt;&#10;&lt;p&gt;上机：&lt;/p&gt;&#10;&lt;p&gt;./freetype_show_font_angle ./simsun.ttc 90 200&lt;/p&gt;&#10;&lt;h3 id="66使用freetype显示一行文字"&gt;&lt;a href="#66%e4%bd%bf%e7%94%a8freetype%e6%98%be%e7%a4%ba%e4%b8%80%e8%a1%8c%e6%96%87%e5%ad%97" class="header-anchor"&gt;&lt;/a&gt;6.6使用freetype显示一行文字&#13;&#10;&lt;/h3&gt;&lt;p&gt;在 LCD 上指定一个左上角坐标(x, y)，把一行文字显示出来。下图中，文字的外框用虚线表示，外框的左上角坐标就是(x, y)&lt;/p&gt;&#10;&lt;img src="images/image-20250811142600924.png" alt="image-20250811142600924" style="zoom:67%;" /&gt;&#10;&lt;h4 id="661笛卡尔坐标系"&gt;&lt;a href="#661%e7%ac%9b%e5%8d%a1%e5%b0%94%e5%9d%90%e6%a0%87%e7%b3%bb" class="header-anchor"&gt;&lt;/a&gt;6.6.1笛卡尔坐标系&#13;&#10;&lt;/h4&gt;&lt;p&gt;在 LCD 的坐标系中，原点在屏幕的左上角。对于笛卡尔坐标系，原点在左下角。freetype 使用笛卡尔坐标系，在显示时需要转换为 LCD 坐标系&lt;/p&gt;&#10;&lt;p&gt;在笛卡尔坐标系中坐标是(x, y)，那么它在 LCD 坐标系中坐标值为(x, V-y)&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250811142717983" class="gallery-image" data-flex-basis="672px" data-flex-grow="280" height="207" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-05/images/image-20250811142717983.png" width="580"&gt;&lt;/p&gt;&#10;&lt;h4 id="662每个字符大小不同"&gt;&lt;a href="#662%e6%af%8f%e4%b8%aa%e5%ad%97%e7%ac%a6%e5%a4%a7%e5%b0%8f%e4%b8%8d%e5%90%8c" class="header-anchor"&gt;&lt;/a&gt;6.6.2每个字符大小不同&#13;&#10;&lt;/h4&gt;&lt;p&gt;所以在显示一行文字时，后面文字的位置会受到前面文字的影响&lt;/p&gt;&#10;&lt;p&gt;在显示一行文字时，这些文字会基于同一个基线来绘制位图：baseline&lt;/p&gt;&#10;&lt;p&gt;每一个字符都有它的原点(origin)，比如上图中 baseline左边的黑色圆点就是字母“g”的原点。当前 origin 加上 advance 就可以得到下一个字符的 origin&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250811143226779" class="gallery-image" data-flex-basis="549px" data-flex-grow="228" height="321" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-05/images/image-20250811143226779.png" width="735"&gt;&lt;/p&gt;&#10;</description></item><item><title>嵌入式 Linux 学习笔记（04）：文件 IO 与系统调用</title><link>https://zeseanblog.top/p/embedded-04/</link><pubDate>Sat, 10 Jan 2026 10:30:00 +0800</pubDate><guid>https://zeseanblog.top/p/embedded-04/</guid><description>&#13;&#10; &lt;blockquote&gt;&#13;&#10; &lt;p&gt;📚 本文是《&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux/" &gt;嵌入式 Linux 应用开发学习笔记&lt;/a&gt;》系列第 04 / 7 篇：文件 IO 与系统调用。返回&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux/" &gt;系列目录&lt;/a&gt;。&lt;/p&gt;&#10;&#13;&#10; &lt;/blockquote&gt;&#13;&#10;&lt;h2 id="第4章-文件io"&gt;&lt;a href="#%e7%ac%ac4%e7%ab%a0-%e6%96%87%e4%bb%b6io" class="header-anchor"&gt;&lt;/a&gt;第4章 文件IO&#13;&#10;&lt;/h2&gt;&lt;p&gt;Linux一切皆文件，因此文件IO非常重要&lt;/p&gt;&#10;&lt;p&gt;Linux查看函数指令man&lt;/p&gt;&#10;&lt;h3 id="41文件io分类"&gt;&lt;a href="#41%e6%96%87%e4%bb%b6io%e5%88%86%e7%b1%bb" class="header-anchor"&gt;&lt;/a&gt;4.1文件IO分类&#13;&#10;&lt;/h3&gt;&lt;p&gt;Linux上有两套函数：标准IO、系统调用IO&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;标准 IO 的相关函数是：fopen/fread/fwrite/fseek/fflush/fclose&lt;/li&gt;&#10;&lt;li&gt;系统调用 IO的相关函数是：open/read/write/lseek/fsync/close&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;两套接口来源：&lt;/p&gt;&#10;&lt;p&gt;系统调用IO是用户程序利用posix接口兼容访问Linux、Unix、Unix-like操作系统的功能，用于直接访问内核。&lt;/p&gt;&#10;&lt;p&gt;标准IO是C库的，但是为了兼容Windows用系统调用IO重新封装了。&lt;/p&gt;&#10;&lt;p&gt;标准IO引入了一个用户buffer。&lt;/p&gt;&#10;&lt;p&gt;读数据的话就读一个大数据在buffer，后续对其读取就在buffer里读，但是系统调用IO就必须多次向内核申请&lt;/p&gt;&#10;&lt;img src="images/image-20250808171829356.png" alt="image-20250808171829356" style="zoom:67%;" /&gt;&#10;&lt;h3 id="42函数原型"&gt;&lt;a href="#42%e5%87%bd%e6%95%b0%e5%8e%9f%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;4.2函数原型&#13;&#10;&lt;/h3&gt;&lt;h4 id="421open"&gt;&lt;a href="#421open" class="header-anchor"&gt;&lt;/a&gt;4.2.1open()&#13;&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/types.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/stat.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;fcntl.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;mode_t&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;打开或创建一个文件&lt;/p&gt;&#10;&lt;p&gt;pathname：文件路径名或文件名&lt;/p&gt;&#10;&lt;p&gt;flags：打开方式和状态标志，通过位或操作&lt;/p&gt;&#10;&lt;p&gt;mode：仅当flags包含O_CREAT或 O_TMPFILE 时才需要提供，指定文件权限，指定方式同chmod&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;宏&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;含义&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;访问模式（三选一）&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;O_RDONLY&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;只读&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;O_WRONLY&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;只写&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;O_RDWR&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;读写&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;创建与控制&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;O_CREAT&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;若文件不存在则创建，需提供 &lt;code&gt;mode&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;O_EXCL&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;与 &lt;code&gt;O_CREAT&lt;/code&gt; 合用，文件已存在时报错&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;O_TRUNC&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;打开时把文件截断为 0&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;追加/非阻塞/同步&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;O_APPEND&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;每次写都追加到文件尾&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;O_NONBLOCK&lt;/code&gt; / &lt;code&gt;O_NDELAY&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;非阻塞模式&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;O_SYNC&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;每次写都等待物理 I/O 完成&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;O_DSYNC&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;仅同步数据，不含元数据&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;O_DIRECT&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;绕过页缓存，直接用户缓冲到磁盘&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;O_CLOEXEC&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;在执行 &lt;code&gt;execve&lt;/code&gt; 时自动关闭 fd（防泄漏）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;&lt;img alt="image-20250808182730385" class="gallery-image" data-flex-basis="253px" data-flex-grow="105" height="548" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-04/images/image-20250808182730385.png" width="578"&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;span class="lnt"&gt;29&#10;&lt;/span&gt;&lt;span class="lnt"&gt;30&#10;&lt;/span&gt;&lt;span class="lnt"&gt;31&#10;&lt;/span&gt;&lt;span class="lnt"&gt;32&#10;&lt;/span&gt;&lt;span class="lnt"&gt;33&#10;&lt;/span&gt;&lt;span class="lnt"&gt;34&#10;&lt;/span&gt;&lt;span class="lnt"&gt;35&#10;&lt;/span&gt;&lt;span class="lnt"&gt;36&#10;&lt;/span&gt;&lt;span class="lnt"&gt;37&#10;&lt;/span&gt;&lt;span class="lnt"&gt;38&#10;&lt;/span&gt;&lt;span class="lnt"&gt;39&#10;&lt;/span&gt;&lt;span class="lnt"&gt;40&#10;&lt;/span&gt;&lt;span class="lnt"&gt;41&#10;&lt;/span&gt;&lt;span class="lnt"&gt;42&#10;&lt;/span&gt;&lt;span class="lnt"&gt;43&#10;&lt;/span&gt;&lt;span class="lnt"&gt;44&#10;&lt;/span&gt;&lt;span class="lnt"&gt;45&#10;&lt;/span&gt;&lt;span class="lnt"&gt;46&#10;&lt;/span&gt;&lt;span class="lnt"&gt;47&#10;&lt;/span&gt;&lt;span class="lnt"&gt;48&#10;&lt;/span&gt;&lt;span class="lnt"&gt;49&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//open&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/types.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/stat.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;fcntl.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;errno.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//close&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/*&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * ./open 1.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * argc = 2&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * argv[0] = &amp;#34;./open&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * argv[1] = &amp;#34;1.txt&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Usage: %s &amp;lt;file&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="c1"&gt;//打开文件,若不存在则创建，且创建时截断，权限设为0777&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="n"&gt;O_RDWR&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;O_CREAT&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;TRUNC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mo"&gt;0777&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;can not open file %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;errno = %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errno&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;err: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;strerror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errno&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;perror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;open&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fd = %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="422write"&gt;&lt;a href="#422write" class="header-anchor"&gt;&lt;/a&gt;4.2.2write()&#13;&#10;&lt;/h4&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;#include &amp;lt;unistd.h&amp;gt;&#10;ssize_t write(int fd, const void *buf, size_t count);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;fd：指定要写入的文件描述符&lt;/p&gt;&#10;&lt;p&gt;buf：缓冲区，一般是一个数组，该数组的内容写入文件&lt;/p&gt;&#10;&lt;p&gt;count：要写入的实际字符数&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;span class="lnt"&gt;29&#10;&lt;/span&gt;&lt;span class="lnt"&gt;30&#10;&lt;/span&gt;&lt;span class="lnt"&gt;31&#10;&lt;/span&gt;&lt;span class="lnt"&gt;32&#10;&lt;/span&gt;&lt;span class="lnt"&gt;33&#10;&lt;/span&gt;&lt;span class="lnt"&gt;34&#10;&lt;/span&gt;&lt;span class="lnt"&gt;35&#10;&lt;/span&gt;&lt;span class="lnt"&gt;36&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/types.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/stat.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;fcntl.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;errno.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="n"&gt;O_RDWR&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;O_CREAT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;O_TRUNC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mo"&gt;0777&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;can not open file %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;errno = %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errno&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;err: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;strerror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errno&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;perror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;open&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fd = %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nf"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nf"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;perror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;write&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="423read"&gt;&lt;a href="#423read" class="header-anchor"&gt;&lt;/a&gt;4.2.3read()&#13;&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;ssize_t&lt;/span&gt; &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;作用：从给定的文件描述符指定的文件中，读取 count 个字节的数据，存放至 buf 中。&lt;/p&gt;&#10;&lt;p&gt;fd：指定要读写的文件描述符&lt;/p&gt;&#10;&lt;p&gt;buf：缓冲区，一般是一个数组，用于存放读取的内容&lt;/p&gt;&#10;&lt;p&gt;count：一次要读取的最大字节数&lt;/p&gt;&#10;&lt;h4 id="424lseek"&gt;&lt;a href="#424lseek" class="header-anchor"&gt;&lt;/a&gt;4.2.4lseek()&#13;&#10;&lt;/h4&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;#include &amp;lt;unistd.h&amp;gt;&#10;off_t lseek(int fd, off_t offset, int whence);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;fd&lt;/strong&gt;：指定要偏移的文件描述符&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;offset&lt;/strong&gt;：文件偏移量&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;whence&lt;/strong&gt;：开始添加偏移 offset 的位置&lt;/p&gt;&#10;&lt;p&gt;SEEK_SET，offset 相对于文件开头进行偏移&lt;/p&gt;&#10;&lt;p&gt;SEEK_CUR，offset 相对文件当前位置进行偏移&lt;/p&gt;&#10;&lt;p&gt;SEEK_END，offset 相对于文件末尾进行偏移&lt;/p&gt;&#10;&lt;h4 id="425read"&gt;&lt;a href="#425read" class="header-anchor"&gt;&lt;/a&gt;4.2.5read()&#13;&#10;&lt;/h4&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;#include &amp;lt;unistd.h&amp;gt;&#10;ssize_t read(int fd, void *buf, size_t count);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;作用：从给定的文件描述符指定的文件中，读取 count 个字节的数&lt;/p&gt;&#10;&lt;p&gt;据，存放至 buf 中。&lt;/p&gt;&#10;&lt;p&gt;fd：指定要读写的文件描述符&lt;/p&gt;&#10;&lt;p&gt;buf：缓冲区，一般是一个数组，用于存放读取的内容&lt;/p&gt;&#10;&lt;p&gt;count：一次要读取的最大字节数&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/types.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/stat.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;fcntl.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;errno.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="n"&gt;O_RDONLY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mo"&gt;0777&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//表示读到结尾了&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;%s&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h3 id="44内部机制"&gt;&lt;a href="#44%e5%86%85%e9%83%a8%e6%9c%ba%e5%88%b6" class="header-anchor"&gt;&lt;/a&gt;4.4内部机制&#13;&#10;&lt;/h3&gt;&lt;p&gt;用户空间应用层调用glibc给出的系统调用接口&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250808212240806" class="gallery-image" data-flex-basis="526px" data-flex-grow="219" height="550" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-04/images/image-20250808212240806.png" srcset="https://zeseanblog.top/p/embedded-04/images/image-20250808212240806_hu_165ef13d036f8fa3.png 800w, https://zeseanblog.top/p/embedded-04/images/image-20250808212240806.png 1206w" width="1206"&gt;&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;这些系统调用接口会触发异常引入内核&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;比如触发异常：swi/svc，并异常原因事先记录在某处&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;cpu发现异常后会调用内核提供的异常处理函数&lt;/p&gt;&#10;&lt;p&gt;他会进行分辨原因/处理异常&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;然后继续做自己的事&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;如SYSCALL_DEFINE为系统调用定义，3为参数个数&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250808213737490" class="gallery-image" data-flex-basis="1320px" data-flex-grow="550" height="129" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-04/images/image-20250808213737490.png" width="710"&gt;&lt;/p&gt;&#10;&lt;p&gt;这个宏定义出这个函数&lt;/p&gt;&#10;&lt;p&gt;int sys_open(const char __user * filename,int flags,umode_t mode)&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;整体流程&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;即用户调用glibc的接口函数，接口函数触发异常，同时把异常原因记录在某些寄存器里面，cpu捕获到异常，根据异常的原因来调用对应的函数&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;每个进程有自己的文件句柄空间&lt;/p&gt;&#10;&lt;p&gt;fd=3，是xx进程里fd=3的文件&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250809145052105" class="gallery-image" data-flex-basis="497px" data-flex-grow="207" height="598" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-04/images/image-20250809145052105.png" srcset="https://zeseanblog.top/p/embedded-04/images/image-20250809145052105_hu_1b9e16ddf30029bb.png 800w, https://zeseanblog.top/p/embedded-04/images/image-20250809145052105.png 1239w" width="1239"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250809145135851" class="gallery-image" data-flex-basis="502px" data-flex-grow="209" height="522" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-04/images/image-20250809145135851.png" srcset="https://zeseanblog.top/p/embedded-04/images/image-20250809145135851_hu_ffab72205cd12f08.png 800w, https://zeseanblog.top/p/embedded-04/images/image-20250809145135851.png 1093w" width="1093"&gt;&lt;/p&gt;&#10;</description></item><item><title>嵌入式 Linux 学习笔记（03）：交叉编译、GCC 与 Makefile</title><link>https://zeseanblog.top/p/embedded-03/</link><pubDate>Sat, 27 Dec 2025 10:30:00 +0800</pubDate><guid>https://zeseanblog.top/p/embedded-03/</guid><description>&#13;&#10; &lt;blockquote&gt;&#13;&#10; &lt;p&gt;📚 本文是《&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux/" &gt;嵌入式 Linux 应用开发学习笔记&lt;/a&gt;》系列第 03 / 7 篇：交叉编译、GCC 与 Makefile。返回&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux/" &gt;系列目录&lt;/a&gt;。&lt;/p&gt;&#10;&#13;&#10; &lt;/blockquote&gt;&#13;&#10;&lt;h2 id="第1章-交叉编译"&gt;&lt;a href="#%e7%ac%ac1%e7%ab%a0-%e4%ba%a4%e5%8f%89%e7%bc%96%e8%af%91" class="header-anchor"&gt;&lt;/a&gt;第1章 交叉编译&#13;&#10;&lt;/h2&gt;&lt;p&gt;获取源码后，想要给ARM板编译出hello程序&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;arm-buildroot-linux-gnueabihf-gcc -o hello hello.c&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;若hello程序如下&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;01 #include &amp;lt;stdio.h&amp;gt;&#10;02&#10;03 /* 执行命令: ./hello weidongshan&#10;04 * argc = 2&#10;05 * argv[0] = ./hello&#10;06 * argv[1] = weidongshan&#10;07 */&#10;08&#10;09 int main(int argc, char **argv)&#10;10 {&#10;11 &#9;&#9;if (argc &amp;gt;= 2)&#10;12 &#9;&#9;&#9;printf(&amp;#34;Hello, %s!\n&amp;#34;, argv[1]);&#10;13 &#9;&#9;else&#10;14 &#9;&#9;&#9;printf(&amp;#34;Hello, world!\n&amp;#34;);&#10;15 &#9;&#9;return 0;&#10;16 }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;ol&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;头文件在哪&lt;/p&gt;&#10;&lt;p&gt;进入交叉编译器的目录里，执行：find -name “stdio.h”，它位于一个“include”目录下的根目录里。这个“include”目录，就是要找的路径（系统目录）&lt;/p&gt;&#10;&lt;p&gt;或者自己指定&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;怎么指定头文件目录&lt;/p&gt;&#10;&lt;p&gt;编译时，加上“-I &amp;lt;头文件目录&amp;gt;”这样的选项。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;怎么确定交叉编译时库文件&lt;/p&gt;&#10;&lt;p&gt;进入交叉编译器的目录里，执行：find -name lib，可以得到 xxxx/lib、&lt;/p&gt;&#10;&lt;p&gt;xxxx/usr/lib，一般来说这 2 个目录就是要找的路径。如果有很多类似的 lib，&lt;/p&gt;&#10;&lt;p&gt;进去看看，有很多 so 文件的目录一般就是要找的路径&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;怎么指定自己的库文件目录、库文件&lt;/p&gt;&#10;&lt;p&gt;编译时，加上“-L &amp;lt;库文件目录&amp;gt;”这样的选项，用来指定库目录；&lt;/p&gt;&#10;&lt;p&gt;编译时，加上“-labc”这样的选项，用来指定库文件 libabc.so。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="第2章-gcc编译器使用"&gt;&lt;a href="#%e7%ac%ac2%e7%ab%a0-gcc%e7%bc%96%e8%af%91%e5%99%a8%e4%bd%bf%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;第2章 GCC编译器使用&#13;&#10;&lt;/h2&gt;&lt;h3 id="21gcc编译过程"&gt;&lt;a href="#21gcc%e7%bc%96%e8%af%91%e8%bf%87%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;2.1GCC编译过程&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img alt="image-20250807212639382" class="gallery-image" data-flex-basis="1721px" data-flex-grow="717" height="206" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-03/images/image-20250807212639382.png" srcset="https://zeseanblog.top/p/embedded-03/images/image-20250807212639382_hu_40aa9ee14a894f80.png 800w, https://zeseanblog.top/p/embedded-03/images/image-20250807212639382.png 1478w" width="1478"&gt;&lt;/p&gt;&#10;&lt;p&gt;通过不同的编译选项可以控制这些过程&lt;/p&gt;&#10;&lt;img src="images/image-20250807212755548.png" alt="image-20250807212755548" style="zoom: 80%;" /&gt;&#10;&lt;p&gt;&lt;img alt="image-20250807213106882" class="gallery-image" data-flex-basis="1070px" data-flex-grow="446" height="176" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-03/images/image-20250807213106882.png" width="785"&gt;&lt;/p&gt;&#10;&lt;h4 id="212编译多个文件"&gt;&lt;a href="#212%e7%bc%96%e8%af%91%e5%a4%9a%e4%b8%aa%e6%96%87%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;2.1.2编译多个文件&#13;&#10;&lt;/h4&gt;&lt;ol&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;一起编译、链接&lt;/p&gt;&#10;&lt;p&gt;gcc -o test main.c sub.c&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;分开编译，统一链接&lt;/p&gt;&#10;&lt;p&gt;gcc -c -o main.o main.c&lt;/p&gt;&#10;&lt;p&gt;gcc -c -o sub.o sub.c&lt;/p&gt;&#10;&lt;p&gt;gcc -o test main.o sub.o&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h4 id="213制作使用动态库"&gt;&lt;a href="#213%e5%88%b6%e4%bd%9c%e4%bd%bf%e7%94%a8%e5%8a%a8%e6%80%81%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;2.1.3制作使用动态库&#13;&#10;&lt;/h4&gt;&lt;p&gt;step1：制作、编译&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;gcc -c -o main.o main.c&#10;gcc -c -o sub.o sub.c&#10;gcc -shared -o libsub.so sub.o sub2.o sub3.o(可以使用多个.o 生成动态库)&#10;gcc -o test main.o -lsub -L /libsub.so/所在目录/&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;step2：运行&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;先把 libsub.so 放到 Ubuntu 的/lib 目录，然后就可以运行 test 程序&lt;/li&gt;&#10;&lt;li&gt;如果不想把 libsub.so 放到/lib，也可以放在某个目录比如/a，然后执行&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/a &#10;./test&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="214制作使用静态库"&gt;&lt;a href="#214%e5%88%b6%e4%bd%9c%e4%bd%bf%e7%94%a8%e9%9d%99%e6%80%81%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;2.1.4制作使用静态库&#13;&#10;&lt;/h4&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;gcc -c -o main.o main.c&#10;gcc -c -o sub.o sub.c&#10;ar crs libsub.a sub.o sub2.o sub3.o(可以使用多个.o 生成静态库)&#10;gcc -o test main.o libsub.a (如果.a 不在当前目录下，需要指定它的绝对或相对路径)&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;执行 arm-buildroot-linux-gnueabihf-gcc -c -o sub.o sub.c 交叉编译需要在最后面加上-fPIC 参数&lt;/p&gt;&#10;&lt;h2 id="第3章-makefile的使用"&gt;&lt;a href="#%e7%ac%ac3%e7%ab%a0-makefile%e7%9a%84%e4%bd%bf%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;第3章 Makefile的使用&#13;&#10;&lt;/h2&gt;&lt;h3 id="31makefile大纲"&gt;&lt;a href="#31makefile%e5%a4%a7%e7%ba%b2" class="header-anchor"&gt;&lt;/a&gt;3.1Makefile大纲&#13;&#10;&lt;/h3&gt;&lt;h4 id="311为什么需要makefile"&gt;&lt;a href="#311%e4%b8%ba%e4%bb%80%e4%b9%88%e9%9c%80%e8%a6%81makefile" class="header-anchor"&gt;&lt;/a&gt;3.1.1为什么需要Makefile&#13;&#10;&lt;/h4&gt;&lt;p&gt;修改源文件或头文件，只需要重新编译牵涉到的文件就可以重新生成APP&lt;/p&gt;&#10;&lt;h4 id="312makefile基本规则"&gt;&lt;a href="#312makefile%e5%9f%ba%e6%9c%ac%e8%a7%84%e5%88%99" class="header-anchor"&gt;&lt;/a&gt;3.1.2Makefile基本规则&#13;&#10;&lt;/h4&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;目标文件(target)…: 依赖文件(prerequiries)…&#10;&amp;lt;tab&amp;gt;命令(command)&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="313一步步完善makefile"&gt;&lt;a href="#313%e4%b8%80%e6%ad%a5%e6%ad%a5%e5%ae%8c%e5%96%84makefile" class="header-anchor"&gt;&lt;/a&gt;3.1.3一步步完善Makefile&#13;&#10;&lt;/h4&gt;&lt;h5 id="1如果没有makefile"&gt;&lt;a href="#1%e5%a6%82%e6%9e%9c%e6%b2%a1%e6%9c%89makefile" class="header-anchor"&gt;&lt;/a&gt;&lt;strong&gt;1.如果没有makefile&lt;/strong&gt;&#13;&#10;&lt;/h5&gt;&lt;p&gt;使用gcc -o test a.c b.c&lt;/p&gt;&#10;&lt;p&gt;前三步统称为编译，最后一步链接&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250808143112824" class="gallery-image" data-flex-basis="1473px" data-flex-grow="613" height="138" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-03/images/image-20250808143112824.png" srcset="https://zeseanblog.top/p/embedded-03/images/image-20250808143112824_hu_c4c70e93c1606991.png 800w, https://zeseanblog.top/p/embedded-03/images/image-20250808143112824.png 847w" width="847"&gt;&lt;/p&gt;&#10;&lt;p&gt;很简单，但是对所有文件都再处理一次，即使b.c没有修改，a.c修改了&lt;/p&gt;&#10;&lt;p&gt;优化上一步可以a.c和b.c分开编译，最后链接&lt;/p&gt;&#10;&lt;p&gt;gcc -c -o a.o a.c&lt;/p&gt;&#10;&lt;p&gt;gcc -c -o b.o b.c&lt;/p&gt;&#10;&lt;p&gt;gcc -o test a.o b.o&lt;/p&gt;&#10;&lt;p&gt;如何判断哪些文件被修改了？通过比较时间&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;目标文件(target)…: 依赖文件(prerequiries)…&#10;&amp;lt;tab&amp;gt;命令(command)&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;当依赖文件比目标文件信，就执行命令&lt;/p&gt;&#10;&lt;h5 id="2最简单的makefile"&gt;&lt;a href="#2%e6%9c%80%e7%ae%80%e5%8d%95%e7%9a%84makefile" class="header-anchor"&gt;&lt;/a&gt;2.最简单的Makefile&#13;&#10;&lt;/h5&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;test:a.o b.o&#10; gcc -o test a.o b.o &#10;a.o : a.c&#10; gcc -c -o a.o a.c&#10;b.o : b.c&#10; gcc -c -o b.o b.c&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;执行make命令，此时修改a.c，只执行两条gcc命令&lt;/p&gt;&#10;&lt;h5 id="3引入通配符"&gt;&lt;a href="#3%e5%bc%95%e5%85%a5%e9%80%9a%e9%85%8d%e7%ac%a6" class="header-anchor"&gt;&lt;/a&gt;3.引入通配符&#13;&#10;&lt;/h5&gt;&lt;p&gt;相似规则太多，可以使用通配符&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;test:a.o b.o c.o&#10;&#9;gcc -o test $^&#10;&#9;//$^表示所有依赖&#10;%.o:%.c&#10;&#9;gcc -c -o $@ $&amp;lt;&#10;&#9;//$@表示目标文件 $&amp;lt;表示依赖文件&#10;&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&#10;&lt;li&gt;%.o：通配符&lt;/li&gt;&#10;&lt;li&gt;$@：表示目标&lt;/li&gt;&#10;&lt;li&gt;$&amp;lt;：表示第一个依赖文件&lt;/li&gt;&#10;&lt;li&gt;$^：表示所有依赖文件&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h5 id="4引入cleanphony"&gt;&lt;a href="#4%e5%bc%95%e5%85%a5cleanphony" class="header-anchor"&gt;&lt;/a&gt;4.引入clean、.PHONY&#13;&#10;&lt;/h5&gt;&lt;p&gt;垃圾文件太多&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;test: a.o b.o c.o&#10;&#9;gcc -o test $^&#10;%.o : %.c&#10;&#9;gcc -c -o $@ $&amp;lt;&#10;clean:&#10;&#9;rm *.o test&#10;.PHONY: clean&#9;&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;make：执行第一个目标&lt;/p&gt;&#10;&lt;p&gt;make [目标]：执行指定目标&lt;/p&gt;&#10;&lt;p&gt;假想目标.PHONY&lt;/p&gt;&#10;&lt;h5 id="5即时变量延时变量"&gt;&lt;a href="#5%e5%8d%b3%e6%97%b6%e5%8f%98%e9%87%8f%e5%bb%b6%e6%97%b6%e5%8f%98%e9%87%8f" class="header-anchor"&gt;&lt;/a&gt;5.即时变量、延时变量&#13;&#10;&lt;/h5&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-makefile" data-lang="makefile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;A&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;C&lt;span class="k"&gt;)&lt;/span&gt;&#9;&#9;&#9;&#9;&lt;span class="c1"&gt;#A的值即时确定，在定义时即确定，赋值&#9;&#9;&#9;&#9;&#9;&#9; #为C，C现在为空&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;C&lt;span class="k"&gt;)&lt;/span&gt;&#9;&#9;&#9;&#9;&lt;span class="c1"&gt;#B的值使用到才确定&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; abc&#9;&#9;&#9;&#9;&#9;&lt;span class="c1"&gt;#C赋值字符串abc&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;#D = 100ask&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 若 D 未定义则设为 weidongshan，已定义则保持原值&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;?=&lt;/span&gt; weidongshan&#9;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 默认目标 all：打印各变量最终值&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;@echo &lt;span class="nv"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;A&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# A 为空（在第 1 行已固定）&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;@echo &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;B&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# B 为 abc123（C 后面被追加 123）&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;@echo &lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;D&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# D 为 weidongshan（未被覆盖）&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# C += 123 # 将 123 追加到 C 末尾，使 C 变成 abc123&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="m"&gt;123&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h5 id="6makefile函数"&gt;&lt;a href="#6makefile%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;6.Makefile函数&#13;&#10;&lt;/h5&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;span class="lnt"&gt;29&#10;&lt;/span&gt;&lt;span class="lnt"&gt;30&#10;&lt;/span&gt;&lt;span class="lnt"&gt;31&#10;&lt;/span&gt;&lt;span class="lnt"&gt;32&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-Makefile" data-lang="Makefile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;#A赋值 a b b&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; a b c &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;#对A中每一个元素，取出来赋值给f，把f改为这种形式&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;foreach f, &lt;span class="k"&gt;$(&lt;/span&gt;A&lt;span class="k"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;$(&lt;/span&gt;f&lt;span class="k"&gt;)&lt;/span&gt;.o&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;#C赋值&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; a b c d/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;#对C中符合%/格式的内容，过滤留下来&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;filter %/, &lt;span class="k"&gt;$(&lt;/span&gt;C&lt;span class="k"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;#对C中符合%/格式的内容，过滤出去&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;E&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;filter-out %/, &lt;span class="k"&gt;$(&lt;/span&gt;C&lt;span class="k"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;#*.c格式的文件是否存在，把存在的列出来&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;wildcard *.c&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;files2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; a.c b.c c.c d.c e.c abc&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;#找到file2中存在的文件列出来&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;files3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;wildcard &lt;span class="k"&gt;$(&lt;/span&gt;files2&lt;span class="k"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;#找到file2中符合%.c的文件，将其改为%.d&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;dep_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;patsubst %.c,%.d,&lt;span class="k"&gt;$(&lt;/span&gt;files2&lt;span class="k"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;@echo &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;B&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;@echo &lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;D&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;@echo &lt;span class="nv"&gt;E&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;E&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;@echo &lt;span class="nv"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;files&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;@echo &lt;span class="nv"&gt;files3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;files3&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;@echo &lt;span class="nv"&gt;dep_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;dep_files&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;&lt;img alt="image-20250808154303640" class="gallery-image" data-flex-basis="769px" data-flex-grow="320" height="125" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-03/images/image-20250808154303640.png" width="401"&gt;&lt;/p&gt;&#10;&lt;h3 id="32makefile实例"&gt;&lt;a href="#32makefile%e5%ae%9e%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;3.2Makefile实例&#13;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-Makefile" data-lang="Makefile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;objs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; a.o b.o c.o&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;#把objs所有文件加前缀.加后缀.d&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;dep_files&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;patsubst %,.%.d, &lt;span class="k"&gt;$(&lt;/span&gt;objs&lt;span class="k"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;#找到dep_files中存在的文件列出来&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;dep_files&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;wildcard &lt;span class="k"&gt;$(&lt;/span&gt;dep_files&lt;span class="k"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;#编译参数&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; -Werror -Iinclude&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;objs&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;gcc -o &lt;span class="nb"&gt;test&lt;/span&gt; $^&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;#如果dep_files不为空，就把这个文件包含&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;ifneq&lt;/span&gt; &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;dep_files&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="err"&gt;,)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;include&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;dep_files&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;endif&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;%.o &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; %.&lt;span class="n"&gt;c&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;gcc &lt;span class="k"&gt;$(&lt;/span&gt;CFLAGS&lt;span class="k"&gt;)&lt;/span&gt; -c -o &lt;span class="nv"&gt;$@&lt;/span&gt; $&amp;lt; -MD -MF .&lt;span class="nv"&gt;$@&lt;/span&gt;.d&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;rm *.o &lt;span class="nb"&gt;test&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;distclean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;rm &lt;span class="k"&gt;$(&lt;/span&gt;dep_files&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;</description></item><item><title>嵌入式 Linux 学习笔记（02）：环境搭建与开发板操作</title><link>https://zeseanblog.top/p/embedded-02/</link><pubDate>Sat, 13 Dec 2025 10:30:00 +0800</pubDate><guid>https://zeseanblog.top/p/embedded-02/</guid><description>&#13;&#10; &lt;blockquote&gt;&#13;&#10; &lt;p&gt;📚 本文是《&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux/" &gt;嵌入式 Linux 应用开发学习笔记&lt;/a&gt;》系列第 02 / 7 篇：环境搭建与开发板操作。返回&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux/" &gt;系列目录&lt;/a&gt;。&lt;/p&gt;&#10;&#13;&#10; &lt;/blockquote&gt;&#13;&#10;&lt;h1 id="第三篇-环境搭建与开发板操作"&gt;&lt;a href="#%e7%ac%ac%e4%b8%89%e7%af%87-%e7%8e%af%e5%a2%83%e6%90%ad%e5%bb%ba%e4%b8%8e%e5%bc%80%e5%8f%91%e6%9d%bf%e6%93%8d%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;第三篇 环境搭建与开发板操作&#13;&#10;&lt;/h1&gt;&lt;p&gt;windows：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;filezilla：传文件到ubuntu&lt;/li&gt;&#10;&lt;li&gt;mobaxterm：远程操作ubuntu，操作开发板串口&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;ubuntu：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;vmware运行ubuntu当做服务器&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;开发板：编辑编译运行&lt;/p&gt;&#10;&lt;h2 id="第2章-安装软件"&gt;&lt;a href="#%e7%ac%ac2%e7%ab%a0-%e5%ae%89%e8%a3%85%e8%bd%af%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;第2章 安装软件&#13;&#10;&lt;/h2&gt;&lt;h3 id="23mobaxterm-远程登录-ubuntu"&gt;&lt;a href="#23mobaxterm-%e8%bf%9c%e7%a8%8b%e7%99%bb%e5%bd%95-ubuntu" class="header-anchor"&gt;&lt;/a&gt;2.3MobaXterm 远程登录 Ubuntu&#13;&#10;&lt;/h3&gt;&lt;p&gt;ubuntu命令ifconfig&lt;/p&gt;&#10;&lt;p&gt;ens33：为NAT网卡ip&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250807175804834" class="gallery-image" data-flex-basis="1160px" data-flex-grow="483" height="55" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-02/images/image-20250807175804834.png" width="266"&gt;&lt;/p&gt;&#10;&lt;img src="images/image-20250807175927536.png" alt="image-20250807175927536" style="zoom: 50%;" /&gt;&#10;&lt;h3 id="24使用filezilla"&gt;&lt;a href="#24%e4%bd%bf%e7%94%a8filezilla" class="header-anchor"&gt;&lt;/a&gt;2.4使用FileZilla&#13;&#10;&lt;/h3&gt;&lt;p&gt;在Windows和ubuntu之间传文件&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250807190228916" class="gallery-image" data-flex-basis="4870px" data-flex-grow="2029" height="44" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-02/images/image-20250807190228916.png" srcset="https://zeseanblog.top/p/embedded-02/images/image-20250807190228916_hu_baf9e5a8d57d743.png 800w, https://zeseanblog.top/p/embedded-02/images/image-20250807190228916.png 893w" width="893"&gt;&lt;/p&gt;&#10;&lt;h3 id="25ubuntu上执行程序"&gt;&lt;a href="#25ubuntu%e4%b8%8a%e6%89%a7%e8%a1%8c%e7%a8%8b%e5%ba%8f" class="header-anchor"&gt;&lt;/a&gt;2.5Ubuntu上执行程序&#13;&#10;&lt;/h3&gt;&lt;p&gt;touch hello.c&lt;/p&gt;&#10;&lt;p&gt;gedit hello.c&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;span class="lnt"&gt;7&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;studio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;hello, world!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;gcc -o hello hello.c：编译&lt;/p&gt;&#10;&lt;p&gt;./hello：执行可执行文件&lt;/p&gt;&#10;&lt;h2 id="第3章-imx6ull开发板基本操作"&gt;&lt;a href="#%e7%ac%ac3%e7%ab%a0-imx6ull%e5%bc%80%e5%8f%91%e6%9d%bf%e5%9f%ba%e6%9c%ac%e6%93%8d%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;第3章 IMX6ULL开发板基本操作&#13;&#10;&lt;/h2&gt;&lt;h3 id="31开发板资源"&gt;&lt;a href="#31%e5%bc%80%e5%8f%91%e6%9d%bf%e8%b5%84%e6%ba%90" class="header-anchor"&gt;&lt;/a&gt;3.1开发板资源&#13;&#10;&lt;/h3&gt;&lt;img src="images/image-20250807191044640.png" alt="image-20250807191044640" style="zoom:67%;" /&gt;&#10;&lt;img src="images/image-20250807191059584.png" alt="image-20250807191059584" style="zoom:67%;" /&gt;&#10;&lt;h3 id="34串口连接"&gt;&lt;a href="#34%e4%b8%b2%e5%8f%a3%e8%bf%9e%e6%8e%a5" class="header-anchor"&gt;&lt;/a&gt;3.4串口连接&#13;&#10;&lt;/h3&gt;&lt;img src="images/image-20250807191303726.png" alt="image-20250807191303726" style="zoom:67%;" /&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;启动拨码EMMC启动&lt;/li&gt;&#10;&lt;li&gt;电源&lt;/li&gt;&#10;&lt;li&gt;Windows安装串口驱动&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4 id="341使用mobaxterm打开串口"&gt;&lt;a href="#341%e4%bd%bf%e7%94%a8mobaxterm%e6%89%93%e5%bc%80%e4%b8%b2%e5%8f%a3" class="header-anchor"&gt;&lt;/a&gt;3.4.1使用Mobaxterm打开串口&#13;&#10;&lt;/h4&gt;&lt;img src="images/image-20250807191747396.png" alt="image-20250807191747396" style="zoom:67%;" /&gt;&#10;&lt;p&gt;登录名：root&lt;/p&gt;&#10;&lt;p&gt;100ask login: root&lt;/p&gt;&#10;&lt;h3 id="36adb替代nfs传输文件"&gt;&lt;a href="#36adb%e6%9b%bf%e4%bb%a3nfs%e4%bc%a0%e8%be%93%e6%96%87%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;3.6ADB替代NFS传输文件&#13;&#10;&lt;/h3&gt;&lt;h4 id="361使用adb"&gt;&lt;a href="#361%e4%bd%bf%e7%94%a8adb" class="header-anchor"&gt;&lt;/a&gt;3.6.1使用adb&#13;&#10;&lt;/h4&gt;&lt;img src="images/image-20250807193315614.png" alt="image-20250807193315614" style="zoom: 67%;" /&gt;&#10;&lt;p&gt;就可以在ubuntu上使用adb操作开发板&lt;/p&gt;&#10;&lt;p&gt;可以上传、下载开发板文件、目录&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;adb devices&#10;adb push 1.txt /root # 把Ubuntu的文件放到开发板的/root目录&#10;adb pull /root/1.txt 2.tx # 把开发板的/root/1.txt下载并改名为2.txt&#10;adb shell # 登录开发板&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img alt="image-20250807193711516" class="gallery-image" data-flex-basis="359px" data-flex-grow="149" height="497" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-02/images/image-20250807193711516.png" width="745"&gt;&lt;/p&gt;&#10;&lt;h2 id="第4章-开发板的第一个app实验"&gt;&lt;a href="#%e7%ac%ac4%e7%ab%a0-%e5%bc%80%e5%8f%91%e6%9d%bf%e7%9a%84%e7%ac%ac%e4%b8%80%e4%b8%aaapp%e5%ae%9e%e9%aa%8c" class="header-anchor"&gt;&lt;/a&gt;第4章 开发板的第一个APP实验&#13;&#10;&lt;/h2&gt;&lt;h3 id="41源码"&gt;&lt;a href="#41%e6%ba%90%e7%a0%81" class="header-anchor"&gt;&lt;/a&gt;4.1源码&#13;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* 执行命令: ./hello weidongshan &#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * argc = 2&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * argv[0] = ./hello&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * argv[1] = weidongshan&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello, %s!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;else&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello, world!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h3 id="42编译"&gt;&lt;a href="#42%e7%bc%96%e8%af%91" class="header-anchor"&gt;&lt;/a&gt;4.2编译&#13;&#10;&lt;/h3&gt;&lt;p&gt;给ARM板的程序要使用交叉编译工具链编译&lt;/p&gt;&#10;&lt;p&gt;执行&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;arm-buildroot-linux-gnueabihf-gcc -o hello hello.c&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="43上传开发板运行"&gt;&lt;a href="#43%e4%b8%8a%e4%bc%a0%e5%bc%80%e5%8f%91%e6%9d%bf%e8%bf%90%e8%a1%8c" class="header-anchor"&gt;&lt;/a&gt;4.3上传开发板运行&#13;&#10;&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;adb push hello /root&#10;adb shell&#10;./root/hello&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="第5章-开发板第一个驱动实验"&gt;&lt;a href="#%e7%ac%ac5%e7%ab%a0-%e5%bc%80%e5%8f%91%e6%9d%bf%e7%ac%ac%e4%b8%80%e4%b8%aa%e9%a9%b1%e5%8a%a8%e5%ae%9e%e9%aa%8c" class="header-anchor"&gt;&lt;/a&gt;第5章 开发板第一个驱动实验&#13;&#10;&lt;/h2&gt;&lt;h3 id="51前提"&gt;&lt;a href="#51%e5%89%8d%e6%8f%90" class="header-anchor"&gt;&lt;/a&gt;5.1前提&#13;&#10;&lt;/h3&gt;&lt;p&gt;为什么编译驱动程序前先编译内核？&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;驱动程序要用到内核文件&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;比如驱动程序包含#include &amp;lt;asm/io.h&amp;gt;，其中asm是链接文件，指向asm-arm或asm-mips，需要先配置、编译内核才会生成asm的链接文件&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;编译驱动时用的内核、开发板上运行到内核，要一致&lt;/li&gt;&#10;&lt;li&gt;更换板子上的内核后，板子上的其他驱动也要更换&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;流程：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;配置编译内核、设备树、驱动&lt;/li&gt;&#10;&lt;li&gt;放到板子上&lt;/li&gt;&#10;&lt;li&gt;编译测试第一个驱动&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h3 id="52-编译内核"&gt;&lt;a href="#52-%e7%bc%96%e8%af%91%e5%86%85%e6%a0%b8" class="header-anchor"&gt;&lt;/a&gt;5.2 编译内核&#13;&#10;&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;cd /home/book/100ask_imx6ull-sdk/Linux-4.9.88&#10;make mrproper&#10;make 100ask_imx6ull_defconfig&#10;make zImage -j4&#10;make dtbs&#10;cp arch/arm/boot/zImage ~/nfs_rootfs&#10;cp arch/arm/boot/dts/100ask_imx6ull-14x14.dtb ~/nfs_rootfs/&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="53编译内核模块"&gt;&lt;a href="#53%e7%bc%96%e8%af%91%e5%86%85%e6%a0%b8%e6%a8%a1%e5%9d%97" class="header-anchor"&gt;&lt;/a&gt;5.3编译内核模块&#13;&#10;&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;make modules&#10;make ARCH=arm INSTALL_MOD_PATH=/home/book/nfs_rootfs modules_install&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="54安装内核和模块到开发板"&gt;&lt;a href="#54%e5%ae%89%e8%a3%85%e5%86%85%e6%a0%b8%e5%92%8c%e6%a8%a1%e5%9d%97%e5%88%b0%e5%bc%80%e5%8f%91%e6%9d%bf" class="header-anchor"&gt;&lt;/a&gt;5.4安装内核和模块到开发板&#13;&#10;&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;cd /home/book/nfs_rootfs&#10;adb push zImage /boot&#10;adb push 100ask_imx6ull-14x14.dtb /boot&#10;adb push lib/modules /lib&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;最后，在开发板上执行“sync”命令，再重启开发板，它就使用新的 zImage、dtb、模块了。&lt;/p&gt;&#10;&lt;h3 id="55编译led驱动"&gt;&lt;a href="#55%e7%bc%96%e8%af%91led%e9%a9%b1%e5%8a%a8" class="header-anchor"&gt;&lt;/a&gt;5.5编译led驱动&#13;&#10;&lt;/h3&gt;&lt;p&gt;01_all_series_quickstart\05_嵌入式Linux驱动开发基础知识\source\01_hello_drv&lt;/p&gt;&#10;&lt;p&gt;上传到/home/book/nfs_rootfs&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250807205838330" class="gallery-image" data-flex-basis="2574px" data-flex-grow="1072" height="40" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-02/images/image-20250807205838330.png" width="429"&gt;&lt;/p&gt;&#10;&lt;p&gt;修改Makefile指定内核源码/home/book/100ask_imx6ull-sdk/Linux-4.9.88&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250807211420056" class="gallery-image" data-flex-basis="2765px" data-flex-grow="1152" height="46" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-02/images/image-20250807211420056.png" width="530"&gt;&lt;/p&gt;&#10;&lt;p&gt;编译make，将这两个上传到开发板目录&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250807210541579" class="gallery-image" data-flex-basis="8451px" data-flex-grow="3521" height="42" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-02/images/image-20250807210541579.png" srcset="https://zeseanblog.top/p/embedded-02/images/image-20250807210541579_hu_cb74499ff0a32a8.png 800w, https://zeseanblog.top/p/embedded-02/images/image-20250807210541579.png 1479w" width="1479"&gt;&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;adb push hello_drv.ko /root&#10;adb push hello_drv_test /root&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="56安装驱动模块"&gt;&lt;a href="#56%e5%ae%89%e8%a3%85%e9%a9%b1%e5%8a%a8%e6%a8%a1%e5%9d%97" class="header-anchor"&gt;&lt;/a&gt;5.6安装驱动模块&#13;&#10;&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;insmod hello_drv.ko&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;lsmod：查看安装的模块&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250807210855818" class="gallery-image" data-flex-basis="1265px" data-flex-grow="527" height="84" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-02/images/image-20250807210855818.png" width="443"&gt;&lt;/p&gt;&#10;&lt;h3 id="57执行测试模块"&gt;&lt;a href="#57%e6%89%a7%e8%a1%8c%e6%b5%8b%e8%af%95%e6%a8%a1%e5%9d%97" class="header-anchor"&gt;&lt;/a&gt;5.7执行测试模块&#13;&#10;&lt;/h3&gt;&lt;p&gt;先看看有没有设备ls /dev&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250807211231446" class="gallery-image" data-flex-basis="1464px" data-flex-grow="610" height="40" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-02/images/image-20250807211231446.png" width="244"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250807211356346" class="gallery-image" data-flex-basis="1327px" data-flex-grow="553" height="62" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-02/images/image-20250807211356346.png" width="343"&gt;&lt;/p&gt;&#10;</description></item><item><title>嵌入式 Linux 学习笔记（01）：学习路线、资料下载与 Ubuntu 入门</title><link>https://zeseanblog.top/p/embedded-01/</link><pubDate>Sat, 06 Dec 2025 11:00:00 +0800</pubDate><guid>https://zeseanblog.top/p/embedded-01/</guid><description>&#13;&#10; &lt;blockquote&gt;&#13;&#10; &lt;p&gt;📚 本文是《&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux/" &gt;嵌入式 Linux 应用开发学习笔记&lt;/a&gt;》系列第 01 / 7 篇：学习路线、资料下载与 Ubuntu 入门。返回&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux/" &gt;系列目录&lt;/a&gt;。&lt;/p&gt;&#10;&#13;&#10; &lt;/blockquote&gt;&#13;&#10;&lt;h1 id="c第一篇-学习路线资料下载"&gt;&lt;a href="#c%e7%ac%ac%e4%b8%80%e7%af%87-%e5%ad%a6%e4%b9%a0%e8%b7%af%e7%ba%bf%e8%b5%84%e6%96%99%e4%b8%8b%e8%bd%bd" class="header-anchor"&gt;&lt;/a&gt;c第一篇 学习路线、资料下载&#13;&#10;&lt;/h1&gt;&lt;h2 id="000_课程链接"&gt;&lt;a href="#000_%e8%af%be%e7%a8%8b%e9%93%be%e6%8e%a5" class="header-anchor"&gt;&lt;/a&gt;000_课程链接&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://linux.100ask.net/" target="_blank" rel="noopener"&#13;&#10; &gt;https://linux.100ask.net/&lt;/a&gt;&lt;/p&gt;&#10;&lt;h2 id="第1章-linux路线"&gt;&lt;a href="#%e7%ac%ac1%e7%ab%a0-linux%e8%b7%af%e7%ba%bf" class="header-anchor"&gt;&lt;/a&gt;第1章 Linux路线&#13;&#10;&lt;/h2&gt;&lt;p&gt;与windows对标：&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250807155502008" class="gallery-image" data-flex-basis="518px" data-flex-grow="215" height="378" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-01/images/image-20250807155502008.png" srcset="https://zeseanblog.top/p/embedded-01/images/image-20250807155502008_hu_6b8a814b8325d69f.png 800w, https://zeseanblog.top/p/embedded-01/images/image-20250807155502008.png 816w" width="816"&gt;&lt;/p&gt;&#10;&lt;h2 id="第2章-资料下载"&gt;&lt;a href="#%e7%ac%ac2%e7%ab%a0-%e8%b5%84%e6%96%99%e4%b8%8b%e8%bd%bd" class="header-anchor"&gt;&lt;/a&gt;第2章 资料下载&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://download.100ask.net/boards/Nxp/100ask_imx6ull_pro/index.html" target="_blank" rel="noopener"&#13;&#10; &gt;🎫100ASK_IMX6ULL_PRO开发板 — 百问网资料下载中心 3.0 文档&lt;/a&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;开发板配套资料：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;百度云网盘&lt;/code&gt;：链接：https://pan.baidu.com/s/1NsAIRkQj0bOaPDWdSkBuXw 密码： root&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;实验班配套资料：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;实验班的虚拟机里装好了vscode、下载好了Linux源码&lt;/li&gt;&#10;&lt;li&gt;百度云网盘下载地址： &lt;a class="link" href="https://pan.baidu.com/s/1SjpWb0K-dL2C06DjUEuA_A?pwd=qjke" target="_blank" rel="noopener"&#13;&#10; &gt;https://pan.baidu.com/s/1SjpWb0K-dL2C06DjUEuA_A?pwd=qjke&lt;/a&gt; 密码： qjke&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;code&gt;配套资料&lt;/code&gt;：全系列Linux教程的配套资料(应用基础、驱动基础等)&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;1 git clone https://e.coding.net/weidongshan/01_all_series_quickstart.git&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="第二篇-ubuntu入门"&gt;&lt;a href="#%e7%ac%ac%e4%ba%8c%e7%af%87-ubuntu%e5%85%a5%e9%97%a8" class="header-anchor"&gt;&lt;/a&gt;第二篇 Ubuntu入门&#13;&#10;&lt;/h1&gt;&lt;p&gt;打开终端快捷键：Ctrl+Alt+T&lt;/p&gt;&#10;&lt;p&gt;文件树：&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250807161254960" class="gallery-image" data-flex-basis="412px" data-flex-grow="172" height="511" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-01/images/image-20250807161254960.png" srcset="https://zeseanblog.top/p/embedded-01/images/image-20250807161254960_hu_c79f0b9ab6afb5c0.png 800w, https://zeseanblog.top/p/embedded-01/images/image-20250807161254960.png 879w" width="879"&gt;&lt;/p&gt;&#10;&lt;h2 id="第2章ubuntu操作入门"&gt;&lt;a href="#%e7%ac%ac2%e7%ab%a0ubuntu%e6%93%8d%e4%bd%9c%e5%85%a5%e9%97%a8" class="header-anchor"&gt;&lt;/a&gt;第2章Ubuntu操作入门&#13;&#10;&lt;/h2&gt;&lt;h3 id="23linux常用命令"&gt;&lt;a href="#23linux%e5%b8%b8%e7%94%a8%e5%91%bd%e4%bb%a4" class="header-anchor"&gt;&lt;/a&gt;2.3Linux常用命令&#13;&#10;&lt;/h3&gt;&lt;img src="images/image-20250807162706384.png" alt="image-20250807162706384" style="zoom:50%;" /&gt;&#10;&lt;p&gt;&lt;strong&gt;命令格式&lt;/strong&gt;&lt;/p&gt;&#10;&lt;img src="images/image-20250807162828591.png" alt="image-20250807162828591" style="zoom:50%;" /&gt;&#10;&lt;p&gt;&lt;strong&gt;linux路径&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;根目录：/&lt;/p&gt;&#10;&lt;p&gt;家目录：~&lt;/p&gt;&#10;&lt;p&gt;当前路径：.&lt;/p&gt;&#10;&lt;p&gt;上一级路径：..&lt;/p&gt;&#10;&lt;p&gt;查看函数指令：man&lt;/p&gt;&#10;&lt;h4 id="231目录文件相关"&gt;&lt;a href="#231%e7%9b%ae%e5%bd%95%e6%96%87%e4%bb%b6%e7%9b%b8%e5%85%b3" class="header-anchor"&gt;&lt;/a&gt;2.3.1目录文件相关&#13;&#10;&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;pwd&lt;/strong&gt;：打印当前路径&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;cd&lt;/strong&gt;：改变路径&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;cd -：进入上次目录&lt;/li&gt;&#10;&lt;li&gt;cd ~：进入家目录&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;mkdir&lt;/strong&gt;：创建目录&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;mkdir dir0 ：创建dir0&lt;/li&gt;&#10;&lt;li&gt;mkdir -p dir1/dir2：创建目录dir1有子目录dir2&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;rmdir&lt;/strong&gt;：删除目录，空白目录&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;ls&lt;/strong&gt;：列出目录内容&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;ls&lt;/li&gt;&#10;&lt;li&gt;ls -l：显示完整信息&lt;/li&gt;&#10;&lt;li&gt;ls -a：显示隐藏文件&lt;/li&gt;&#10;&lt;li&gt;ls -la：所有文件、完整信息&lt;/li&gt;&#10;&lt;li&gt;ls -lh：h表示&amp;ndash;human-readable&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img alt="image-20250807163537016" class="gallery-image" data-flex-basis="692px" data-flex-grow="288" height="200" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-01/images/image-20250807163537016.png" width="577"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;cp&lt;/strong&gt;：复制文件夹&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;cp -r dir1 dir2：复制dir1文件夹&lt;/li&gt;&#10;&lt;li&gt;cp -rfd dir_a dir_b：-r为复制所有，-f强制覆盖，-d如果源文件为链接，也只复制链接&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;rm&lt;/strong&gt;：删除文件或目录&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;rm -rf dir_a：-r删除所有，-f强制删除&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;cat&lt;/strong&gt;：打印文件内容&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;cat file.txt&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;touch&lt;/strong&gt;：修改文件时间，如文件不存在则创建&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;touch file&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4 id="232文件权限属性"&gt;&lt;a href="#232%e6%96%87%e4%bb%b6%e6%9d%83%e9%99%90%e5%b1%9e%e6%80%a7" class="header-anchor"&gt;&lt;/a&gt;2.3.2文件权限属性&#13;&#10;&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;chgrp&lt;/strong&gt;：改变文件所属用户组&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;chgrp [-r] dirname/filename：-r递归更改，更新成为用户组&lt;/li&gt;&#10;&lt;li&gt;chgrp hy install.log：install.log更改为hy用户组&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;chowm&lt;/strong&gt;：改变文件所有者&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;chmod&lt;/strong&gt;：改变文件权限&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;权限对应数字r：4、0 w:2、0 x：1、0&lt;/li&gt;&#10;&lt;li&gt;权限对象：owner、group、others&lt;/li&gt;&#10;&lt;li&gt;权限值：owner=rwx=4+2+1=7，group=rwx=4+2+1=7，other=&amp;mdash;=0+0+0=0&lt;/li&gt;&#10;&lt;li&gt;chmod [-r] 777 文件或目录：数字改法&lt;/li&gt;&#10;&lt;li&gt;chmod [-r] u=rwx,go=rx 文件或目录：字母改法用 u、g、o 三个字母代表 user、group、others&lt;/li&gt;&#10;&lt;li&gt;chmod a+w .bashrc：a代表all，对.bashrc文件ugo增加w权限&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4 id="233查找搜索命令"&gt;&lt;a href="#233%e6%9f%a5%e6%89%be%e6%90%9c%e7%b4%a2%e5%91%bd%e4%bb%a4" class="header-anchor"&gt;&lt;/a&gt;2.3.3查找搜索命令&#13;&#10;&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;find&lt;/strong&gt;：搜索文件&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;find 目录名 [选项] 查找条件&lt;/li&gt;&#10;&lt;li&gt;find /home -name “test1.txt”：/home中以名字查找text1.txt&lt;/li&gt;&#10;&lt;li&gt;find /home -name &amp;quot; *.txt &amp;ldquo;：/home中以名字查找所有.txt文件&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;grep&lt;/strong&gt;：查找文件中符合条件的字符串&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;grep [选项] [查找模式] [文件名]&lt;/li&gt;&#10;&lt;li&gt;grep -rn &amp;ldquo;字符串&amp;rdquo; 文件名&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4 id="234压缩解压命令"&gt;&lt;a href="#234%e5%8e%8b%e7%bc%a9%e8%a7%a3%e5%8e%8b%e5%91%bd%e4%bb%a4" class="header-anchor"&gt;&lt;/a&gt;2.3.4压缩解压命令&#13;&#10;&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;gzip&lt;/strong&gt;：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;常用选项：-l列出压缩文件内容，-k在压缩和解压时保留输入文件，-d将压缩文件进行解压&lt;/li&gt;&#10;&lt;li&gt;gzip -l pwd.1.gz：查看压缩文件&lt;/li&gt;&#10;&lt;li&gt;gzip -kd pwd.1.gz：解压文件&lt;/li&gt;&#10;&lt;li&gt;gzip -k mypwd.1：得到一个.gz结尾的压缩文件&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img alt="image-20250807170420173" class="gallery-image" data-flex-basis="1178px" data-flex-grow="491" height="194" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-01/images/image-20250807170420173.png" srcset="https://zeseanblog.top/p/embedded-01/images/image-20250807170420173_hu_d7faaafb9abaacf8.png 800w, https://zeseanblog.top/p/embedded-01/images/image-20250807170420173.png 953w" width="953"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;bizp2&lt;/strong&gt;：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;常用选项：-k在压缩解压时保留文件，-d将压缩文件解压&lt;/li&gt;&#10;&lt;li&gt;bzip2 -k mypwd.1：得到一个.bz2后缀的压缩文件&lt;/li&gt;&#10;&lt;li&gt;bzip2 -kd mypwd.1.bz2：解压&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img alt="image-20250807170641538" class="gallery-image" data-flex-basis="934px" data-flex-grow="389" height="266" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-01/images/image-20250807170641538.png" srcset="https://zeseanblog.top/p/embedded-01/images/image-20250807170641538_hu_c7aa485423533286.png 800w, https://zeseanblog.top/p/embedded-01/images/image-20250807170641538.png 1036w" width="1036"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;tar&lt;/strong&gt;：&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250807170738329" class="gallery-image" data-flex-basis="1091px" data-flex-grow="454" height="226" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/embedded-01/images/image-20250807170738329.png" srcset="https://zeseanblog.top/p/embedded-01/images/image-20250807170738329_hu_f0974406f63155b8.png 800w, https://zeseanblog.top/p/embedded-01/images/image-20250807170738329.png 1028w" width="1028"&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;tar czvf dira.tar.gz dira：把目录dira压缩、打包为dira.tar.gz文件&lt;/li&gt;&#10;&lt;li&gt;tar tvf dira.tar.gz：查看压缩文件&lt;/li&gt;&#10;&lt;li&gt;tar xzvf dira.tar.gz：解压到当前目录&lt;/li&gt;&#10;&lt;li&gt;tar xzvf dira.tar.gz -c /home：解压到指定目录&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4 id="235vi编辑器"&gt;&lt;a href="#235vi%e7%bc%96%e8%be%91%e5%99%a8" class="header-anchor"&gt;&lt;/a&gt;2.3.5vi编辑器&#13;&#10;&lt;/h4&gt;&lt;img src="images/image-20250807171406196.png" alt="image-20250807171406196" style="zoom: 33%;" /&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;vi 1.txt：vim打开1.txt，不存在则新建&lt;/li&gt;&#10;&lt;li&gt;输入i开启编辑&lt;/li&gt;&#10;&lt;li&gt;：wq保存并退出&lt;/li&gt;&#10;&lt;li&gt;：q！不保存退出&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;vi快捷键&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;1.新建、移动、取消、保存&lt;/p&gt;&#10;&lt;p&gt;2.移动&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;上下左右箭头移动光标&lt;/li&gt;&#10;&lt;li&gt;ctrl+f：向前翻页，ctrl+b：向后翻页&lt;/li&gt;&#10;&lt;li&gt;：输入行号 ：跳到某行&lt;/li&gt;&#10;&lt;li&gt;：set number 显示行号&lt;/li&gt;&#10;&lt;li&gt;：set nonumber 隐藏行号&lt;/li&gt;&#10;&lt;li&gt;G：跳到文件结尾&lt;/li&gt;&#10;&lt;li&gt;0：跳到行首&lt;/li&gt;&#10;&lt;li&gt;$：跳到行尾&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;3.编辑&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;x：删除一个字母&lt;/li&gt;&#10;&lt;li&gt;dd：删除一行&lt;/li&gt;&#10;&lt;li&gt;ndd：删除当前行及后n-1行（n是数字）&lt;/li&gt;&#10;&lt;li&gt;o：当前行后新增行&lt;/li&gt;&#10;&lt;li&gt;u：撤销上一步&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;4.复制粘贴&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;yy：复制当前行&lt;/li&gt;&#10;&lt;li&gt;nyy：同理&lt;/li&gt;&#10;&lt;li&gt;p：粘贴&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>嵌入式 Linux 应用开发学习笔记（系列目录）</title><link>https://zeseanblog.top/p/embedded-linux/</link><pubDate>Sat, 06 Dec 2025 10:00:00 +0800</pubDate><guid>https://zeseanblog.top/p/embedded-linux/</guid><description>&lt;p&gt;本系列整理自嵌入式 Linux 应用开发的学习过程（基于 IMX6ULL 开发板），原文较长，现按主题拆分为 7 篇：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux-01/" &gt;学习路线、资料下载与 Ubuntu 入门&lt;/a&gt;&lt;/strong&gt; — 学习路线对比、开发板资料获取、Linux 常用命令与 vi 编辑器&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux-02/" &gt;环境搭建与开发板操作&lt;/a&gt;&lt;/strong&gt; — MobaXterm / FileZilla / ADB，交叉编译第一个 APP 与 LED 驱动实验&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux-03/" &gt;交叉编译、GCC 与 Makefile&lt;/a&gt;&lt;/strong&gt; — GCC 编译过程、动态/静态库制作、Makefile 从基本规则到工程实例&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux-04/" &gt;文件 IO 与系统调用&lt;/a&gt;&lt;/strong&gt; — open/read/write/lseek 函数详解及内核系统调用机制&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux-05/" &gt;Framebuffer 与文字显示&lt;/a&gt;&lt;/strong&gt; — LCD 操作原理、字符编码、点阵字库与 freetype 矢量字体&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux-06/" &gt;输入系统、网络编程与多线程&lt;/a&gt;&lt;/strong&gt; — input 子系统、TCP/UDP socket 编程、线程创建与信号量/互斥量同步&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;a class="link" href="https://zeseanblog.top/p/embedded-linux-07/" &gt;I2C 应用编程&lt;/a&gt;&lt;/strong&gt; — I2C 协议要点、I2C-Tools 操作 AP3216C 传感器、编写 APP 直接访问 EEPROM&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&#13;&#10; &lt;blockquote&gt;&#13;&#10; &lt;p&gt;注：原笔记中「串口 UART 编程」一章尚在学习整理中，内容补全后会更新到对应篇章。&lt;/p&gt;&#10;&#13;&#10; &lt;/blockquote&gt;&#13;&#10;</description></item><item><title>QT 入门学习笔记</title><link>https://zeseanblog.top/p/qt/</link><pubDate>Sat, 20 Sep 2025 15:00:00 +0800</pubDate><guid>https://zeseanblog.top/p/qt/</guid><description>&lt;h1 id="1qt创建项目"&gt;&lt;a href="#1qt%e5%88%9b%e5%bb%ba%e9%a1%b9%e7%9b%ae" class="header-anchor"&gt;&lt;/a&gt;1.QT创建项目&#13;&#10;&lt;/h1&gt;&lt;h2 id="11创建"&gt;&lt;a href="#11%e5%88%9b%e5%bb%ba" class="header-anchor"&gt;&lt;/a&gt;1.1创建：&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;img alt="image-20250706145407471" class="gallery-image" data-flex-basis="560px" data-flex-grow="233" height="258" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706145407471.png" width="602"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706145442718" class="gallery-image" data-flex-basis="1048px" data-flex-grow="436" height="141" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706145442718.png" width="616"&gt;&lt;/p&gt;&#10;&lt;p&gt;QMainWindow：窗口&lt;/p&gt;&#10;&lt;p&gt;QWidget：弹窗&lt;/p&gt;&#10;&lt;p&gt;QDialog：对话框&lt;/p&gt;&#10;&lt;h2 id="12文件体系"&gt;&lt;a href="#12%e6%96%87%e4%bb%b6%e4%bd%93%e7%b3%bb" class="header-anchor"&gt;&lt;/a&gt;1.2文件体系：&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;img alt="image-20250706145955234" class="gallery-image" data-flex-basis="230px" data-flex-grow="96" height="263" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706145955234.png" width="253"&gt;&lt;/p&gt;&#10;&lt;h2 id="13ui控件"&gt;&lt;a href="#13ui%e6%8e%a7%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;1.3UI控件&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;img alt="image-20250706150400621" class="gallery-image" data-flex-basis="321px" data-flex-grow="133" height="251" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706150400621.png" width="336"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;layout：布局&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;V垂直，H水平，G网格，F表单（组合控件）&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706150539864" class="gallery-image" data-flex-basis="460px" data-flex-grow="191" height="135" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706150539864.png" width="259"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;spacers：弹簧（占位）&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;把控件挤一挤H水平，V垂直&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706150748052" class="gallery-image" data-flex-basis="848px" data-flex-grow="353" height="75" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706150748052.png" width="265"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;button：按键&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;P.T差不读 R单选框 C多选&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706150848331" class="gallery-image" data-flex-basis="313px" data-flex-grow="130" height="193" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706150848331.png" width="252"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Item Views：单元视图（数据，显示分离）&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Item Widgets：&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Container：容器，容控件&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Input：输入&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Display：输出&lt;/strong&gt;&lt;/p&gt;&#10;&lt;h1 id="2信号与槽"&gt;&lt;a href="#2%e4%bf%a1%e5%8f%b7%e4%b8%8e%e6%a7%bd" class="header-anchor"&gt;&lt;/a&gt;2.信号与槽&#13;&#10;&lt;/h1&gt;&lt;p&gt;如点击按键发出一个信号，对信号响应，执行一个函数，这个函数叫槽函数（事件和回调）&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706153737334" class="gallery-image" data-flex-basis="232px" data-flex-grow="96" height="317" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706153737334.png" width="307"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706154516937" class="gallery-image" data-flex-basis="635px" data-flex-grow="264" height="205" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706154516937.png" width="543"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706163657876" class="gallery-image" data-flex-basis="666px" data-flex-grow="277" height="346" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706163657876.png" srcset="https://zeseanblog.top/p/qt/images/image-20250706163657876_hu_6c5bff7cfc3c3a0e.png 800w, https://zeseanblog.top/p/qt/images/image-20250706163657876.png 961w" width="961"&gt;&lt;/p&gt;&#10;&lt;p&gt;三种连接方式&lt;/p&gt;&#10;&lt;h1 id="3写计算器"&gt;&lt;a href="#3%e5%86%99%e8%ae%a1%e7%ae%97%e5%99%a8" class="header-anchor"&gt;&lt;/a&gt;3.写计算器&#13;&#10;&lt;/h1&gt;&lt;p&gt;&lt;strong&gt;设计ui&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706190331034" class="gallery-image" data-flex-basis="170px" data-flex-grow="71" height="301" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706190331034.png" width="214"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;添加槽函数&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;设计框尺寸，框标题、字体&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706191635487" class="gallery-image" data-flex-basis="200px" data-flex-grow="83" height="614" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706191635487.png" width="513"&gt;&lt;/p&gt;&#10;&lt;p&gt;各按钮槽函数类推&lt;/p&gt;&#10;&lt;p&gt;按键插图片&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706193648157" class="gallery-image" data-flex-basis="1839px" data-flex-grow="766" height="89" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706193648157.png" width="682"&gt;&lt;/p&gt;&#10;&lt;p&gt;退格功能&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706193704445" class="gallery-image" data-flex-basis="1112px" data-flex-grow="463" height="112" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706193704445.png" width="519"&gt;&lt;/p&gt;&#10;&lt;p&gt;计算功能太难，跳过&lt;/p&gt;&#10;&lt;h1 id="4定时器"&gt;&lt;a href="#4%e5%ae%9a%e6%97%b6%e5%99%a8" class="header-anchor"&gt;&lt;/a&gt;4.定时器&#13;&#10;&lt;/h1&gt;&lt;h2 id="qobject"&gt;&lt;a href="#qobject" class="header-anchor"&gt;&lt;/a&gt;&lt;strong&gt;QObject&lt;/strong&gt;：&#13;&#10;&lt;/h2&gt;&lt;p&gt;startTimer killTimer&lt;/p&gt;&#10;&lt;p&gt;启动定时器&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706203351198" class="gallery-image" data-flex-basis="414px" data-flex-grow="172" height="302" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706203351198.png" width="522"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706203408679" class="gallery-image" data-flex-basis="349px" data-flex-grow="145" height="380" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706203408679.png" width="554"&gt;&lt;/p&gt;&#10;&lt;p&gt;标签显示图片&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706205447485" class="gallery-image" data-flex-basis="3698px" data-flex-grow="1541" height="51" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706205447485.png" width="786"&gt;&lt;/p&gt;&#10;&lt;p&gt;轮换逻辑&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706205507239" class="gallery-image" data-flex-basis="526px" data-flex-grow="219" height="378" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706205507239.png" srcset="https://zeseanblog.top/p/qt/images/image-20250706205507239_hu_5d751925cf702bc6.png 800w, https://zeseanblog.top/p/qt/images/image-20250706205507239.png 830w" width="830"&gt;&lt;/p&gt;&#10;&lt;h2 id="qtimer"&gt;&lt;a href="#qtimer" class="header-anchor"&gt;&lt;/a&gt;QTimer：&#13;&#10;&lt;/h2&gt;&lt;p&gt;头文件&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706212306386" class="gallery-image" data-flex-basis="834px" data-flex-grow="347" height="71" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706212306386.png" width="247"&gt;&lt;/p&gt;&#10;&lt;p&gt;启动定时器&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706212322492" class="gallery-image" data-flex-basis="920px" data-flex-grow="383" height="114" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706212322492.png" width="437"&gt;&lt;/p&gt;&#10;&lt;p&gt;图片法二&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706213249026" class="gallery-image" data-flex-basis="1966px" data-flex-grow="819" height="88" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706213249026.png" width="721"&gt;&lt;/p&gt;&#10;&lt;p&gt;槽函数&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706213315451" class="gallery-image" data-flex-basis="1124px" data-flex-grow="468" height="79" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706213315451.png" width="370"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706213330314" class="gallery-image" data-flex-basis="1414px" data-flex-grow="589" height="102" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706213330314.png" width="601"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706213348467" class="gallery-image" data-flex-basis="507px" data-flex-grow="211" height="104" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706213348467.png" width="220"&gt;&lt;/p&gt;&#10;&lt;p&gt;转换逻辑&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706215101291" class="gallery-image" data-flex-basis="565px" data-flex-grow="235" height="327" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706215101291.png" width="770"&gt;&lt;/p&gt;&#10;&lt;p&gt;暂停&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250706215333265" class="gallery-image" data-flex-basis="868px" data-flex-grow="361" height="121" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706215333265.png" width="438"&gt;&lt;/p&gt;&#10;&lt;h1 id="5qt文件操作"&gt;&lt;a href="#5qt%e6%96%87%e4%bb%b6%e6%93%8d%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;5.QT文件操作&#13;&#10;&lt;/h1&gt;&lt;h2 id="ui设计"&gt;&lt;a href="#ui%e8%ae%be%e8%ae%a1" class="header-anchor"&gt;&lt;/a&gt;ui设计&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;img alt="image-20250706220550737" class="gallery-image" data-flex-basis="322px" data-flex-grow="134" height="620" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250706220550737.png" srcset="https://zeseanblog.top/p/qt/images/image-20250706220550737_hu_a6d7578cf81796f6.png 800w, https://zeseanblog.top/p/qt/images/image-20250706220550737.png 833w" width="833"&gt;&lt;/p&gt;&#10;&lt;h2 id="新建"&gt;&lt;a href="#%e6%96%b0%e5%bb%ba" class="header-anchor"&gt;&lt;/a&gt;新建&#13;&#10;&lt;/h2&gt;&lt;p&gt;添加槽函数&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250708002047710" class="gallery-image" data-flex-basis="2640px" data-flex-grow="1100" height="21" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708002047710.png" width="231"&gt;&lt;/p&gt;&#10;&lt;p&gt;实现槽函数&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250708002120089" class="gallery-image" data-flex-basis="976px" data-flex-grow="406" height="116" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708002120089.png" width="472"&gt;&lt;/p&gt;&#10;&lt;p&gt;连接功能&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250708002146473" class="gallery-image" data-flex-basis="2486px" data-flex-grow="1036" height="47" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708002146473.png" width="487"&gt;&lt;/p&gt;&#10;&lt;h2 id="打开"&gt;&lt;a href="#%e6%89%93%e5%bc%80" class="header-anchor"&gt;&lt;/a&gt;打开&#13;&#10;&lt;/h2&gt;&lt;p&gt;头文件&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;QFileDialog 开文件选择框&#10;&#10;QMessageBox 开警告盒子&#10;&#10;QDebug 输出文字到控制台&#10;&#10;QFile 读取文件内容&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img alt="image-20250708002225044" class="gallery-image" data-flex-basis="814px" data-flex-grow="339" height="86" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708002225044.png" width="292"&gt;&lt;/p&gt;&#10;&lt;p&gt;添加槽函数&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250708002447904" class="gallery-image" data-flex-basis="2246px" data-flex-grow="936" height="25" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708002447904.png" width="234"&gt;&lt;/p&gt;&#10;&lt;p&gt;连接功能&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250708002602720" class="gallery-image" data-flex-basis="2225px" data-flex-grow="927" height="55" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708002602720.png" width="510"&gt;&lt;/p&gt;&#10;&lt;p&gt;实现槽函数&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;void MainWindow::openActionSlot()&#10;{&#10; //括号里的参数分别是：指定父类、标题、默认打开后显示的目录、右下角的文件过滤器。&#10; QString filename =&#10; QFileDialog::getOpenFileName(this,&#10; &amp;#34;选择一个文件&amp;#34;,&#10; &amp;#34;.&amp;#34;,&#10; &amp;#34;*.txt&amp;#34;);&#10; qDebug() &amp;lt;&amp;lt; filename;&#10; if(filename.isEmpty())&#10; {&#10; QMessageBox::warning(this,&amp;#34;警告&amp;#34;,&amp;#34;请选择一个文件&amp;#34;);&#10; }&#10; else&#10; {&#10; qDebug()&amp;lt;&amp;lt;filename;&#10; QFile file(filename);&#10; file.open(QIODevice::ReadOnly);&#10; QByteArray array = file.readAll();&#9;//读取文件所有内容&#10; ui-&amp;gt;textEdit-&amp;gt;setText(QString(array));&#10; file.close();&#10; }&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="保存"&gt;&lt;a href="#%e4%bf%9d%e5%ad%98" class="header-anchor"&gt;&lt;/a&gt;保存&#13;&#10;&lt;/h2&gt;&lt;p&gt;添加槽函数&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250708143207152" class="gallery-image" data-flex-basis="2256px" data-flex-grow="940" height="25" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708143207152.png" width="235"&gt;&lt;/p&gt;&#10;&lt;p&gt;连接功能&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250708143223448" class="gallery-image" data-flex-basis="2080px" data-flex-grow="866" height="57" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708143223448.png" width="494"&gt;&lt;/p&gt;&#10;&lt;p&gt;实现槽函数&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;void MainWindow::saveActionSlot()&#10;{&#10; QString filename =&#10; QFileDialog::getSaveFileName(this,&#10; &amp;#34;选择一个文件&amp;#34;,&#10; &amp;#34;.&amp;#34; //当前路径的话是QCoreApplicationFilePath()&#10; ); //不写就是所有文件&#10; if(filename.isEmpty())&#10; {&#10; QMessageBox::warning(this,&amp;#34;警告&amp;#34;,&amp;#34;请选择一个文件&amp;#34;);&#10; }&#10; else&#10; {&#10; QFile file(filename);&#10; file.open(QIODevice::WriteOnly);&#10; QString str = ui-&amp;gt;textEdit-&amp;gt;toPlainText();&#10; QByteArray array = str.toLocal8Bit();&#10; //array.append(ui-&amp;gt;textEdit-&amp;gt;toPlainText());&#10; file.write(array);&#10; file.close();&#10; }&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="6qt事件"&gt;&lt;a href="#6qt%e4%ba%8b%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;6.QT事件&#13;&#10;&lt;/h1&gt;&lt;h2 id="键盘事件"&gt;&lt;a href="#%e9%94%ae%e7%9b%98%e4%ba%8b%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;键盘事件&#13;&#10;&lt;/h2&gt;&lt;p&gt;ctrl+s实现保存，即打开保存原文件&lt;/p&gt;&#10;&lt;p&gt;重写键盘事件虚函数&lt;/p&gt;&#10;&lt;p&gt;#include &lt;QKeyEvent&gt;&lt;/p&gt;&#10;&lt;p&gt;void keyPressEvent(QKeyEvent *k);&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;void MainWindow::keyPressEvent(QKeyEvent *k)&#10;{&#10; if(k-&amp;gt;modifiers() == Qt::ControlModifier) { // 如果按下了CTRL键&#10; if(k-&amp;gt;key() == Qt::Key_S){&#10; qDebug()&amp;lt;&amp;lt;&amp;#34;CTRL + S&amp;#34;;&#10; saveActionSlot();&#10; }&#10; }&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="鼠标事件"&gt;&lt;a href="#%e9%bc%a0%e6%a0%87%e4%ba%8b%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;鼠标事件&#13;&#10;&lt;/h2&gt;&lt;p&gt;#include &lt;QMouseEvent&gt;&lt;/p&gt;&#10;&lt;p&gt;void mousePressEvent(QMouseEvent *m);&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;void MainWindow::mousePressEvent(QMouseEvent *m)&#10;{&#10; QPoint pt = m-&amp;gt;pos();&#10; qDebug()&amp;lt;&amp;lt;pt;&#10; if(m-&amp;gt;button() == Qt::LeftButton)&#10; {&#10; qDebug()&amp;lt;&amp;lt;&amp;#34;左键被按下&amp;#34;;&#10; }&#10; if(m-&amp;gt;button() == Qt::RightButton)&#10; {&#10; qDebug()&amp;lt;&amp;lt;&amp;#34;右键被按下&amp;#34;;&#10; }&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="7qt-tcp"&gt;&lt;a href="#7qt-tcp" class="header-anchor"&gt;&lt;/a&gt;7.QT TCP&#13;&#10;&lt;/h1&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;服务器&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;客户端&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;socket&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;socket&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;bind&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;connect&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;listen&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;send/recv&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;accept&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;send/recv&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;与网络相关的在工程里加network&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250708155251043" class="gallery-image" data-flex-basis="1286px" data-flex-grow="536" height="86" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708155251043.png" width="461"&gt;&lt;/p&gt;&#10;&lt;p&gt;TCP前置&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250708155352062" class="gallery-image" data-flex-basis="2314px" data-flex-grow="964" height="28" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708155352062.png" width="270"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250708155438420" class="gallery-image" data-flex-basis="973px" data-flex-grow="405" height="73" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708155438420.png" width="296"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250708155636868" class="gallery-image" data-flex-basis="702px" data-flex-grow="292" height="174" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708155636868.png" width="509"&gt;&lt;/p&gt;&#10;&lt;h2 id="客户端"&gt;&lt;a href="#%e5%ae%a2%e6%88%b7%e7%ab%af" class="header-anchor"&gt;&lt;/a&gt;客户端&#13;&#10;&lt;/h2&gt;&lt;h3 id="ui设计-1"&gt;&lt;a href="#ui%e8%ae%be%e8%ae%a1-1" class="header-anchor"&gt;&lt;/a&gt;UI设计&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img alt="image-20250708155703484" class="gallery-image" data-flex-basis="463px" data-flex-grow="192" height="283" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708155703484.png" width="546"&gt;&lt;/p&gt;&#10;&lt;p&gt;编辑槽函数&lt;/p&gt;&#10;&lt;p&gt;#include &lt;QHostAddress&gt;&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;void Widget::on_connectButton_clicked()&#10;{&#10; //获取ip地址和端口号&#10; QString IP = ui-&amp;gt;ipLineEdit-&amp;gt;text();&#10; QString PORT = ui-&amp;gt;portLineEdit-&amp;gt;text();&#10;&#10; //连接服务器&#10; socket-&amp;gt;connectToHost(QHostAddress(IP),PORT.toShort());&#10;&#10; //连接服务器成功，socket对象发出信号&#10; connect(socket,&amp;amp;QTcpSocket::connected,[this]()&#10; {&#10; QMessageBox::information(this,&amp;#34;连接提示&amp;#34;,&amp;#34;连接服务器成功&amp;#34;);&#10; });&#10;&#10; //连接断开，socket也会发出信号&#10; connect(socket,&amp;amp;QTcpSocket::disconnected,[this](){&#10; QMessageBox::warning(this,&amp;#34;连接提示&amp;#34;,&amp;#34;连接异常 网络断开&amp;#34;);&#10; });&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="服务器"&gt;&lt;a href="#%e6%9c%8d%e5%8a%a1%e5%99%a8" class="header-anchor"&gt;&lt;/a&gt;服务器&#13;&#10;&lt;/h2&gt;&lt;h3 id="ui设计-2"&gt;&lt;a href="#ui%e8%ae%be%e8%ae%a1-2" class="header-anchor"&gt;&lt;/a&gt;UI设计&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img alt="image-20250708164301580" class="gallery-image" data-flex-basis="453px" data-flex-grow="188" height="224" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708164301580.png" width="423"&gt;&lt;/p&gt;&#10;&lt;h3 id="头文件"&gt;&lt;a href="#%e5%a4%b4%e6%96%87%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;头文件&#13;&#10;&lt;/h3&gt;&lt;p&gt;#include &lt;QTcpServer&gt;&#10;#include &lt;QTcpSocket&gt;&lt;/p&gt;&#10;&lt;h3 id="创建槽函数"&gt;&lt;a href="#%e5%88%9b%e5%bb%ba%e6%a7%bd%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;创建槽函数&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img alt="image-20250708164357300" class="gallery-image" data-flex-basis="671px" data-flex-grow="279" height="138" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708164357300.png" width="386"&gt;&lt;/p&gt;&#10;&lt;h3 id="监听"&gt;&lt;a href="#%e7%9b%91%e5%90%ac" class="header-anchor"&gt;&lt;/a&gt;监听&#13;&#10;&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;Widget::Widget(QWidget *parent)&#10; : QWidget(parent)&#10; , ui(new Ui::Widget)&#10;{&#10; ui-&amp;gt;setupUi(this);&#10; server = new QTcpServer;&#10;&#10; server-&amp;gt;listen(QHostAddress::AnyIPv4,PORT);&#10;&#10; //客户端发起连接，server发出信号&#10; connect(server,&amp;amp;QTcpServer::newConnection,this,&amp;amp;Widget::newClientHandler);&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="实现槽函数"&gt;&lt;a href="#%e5%ae%9e%e7%8e%b0%e6%a7%bd%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;实现槽函数&#13;&#10;&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;void Widget::newClientHandler()&#10;{&#10; //建立TCP连接&#10; QTcpSocket *socket = server-&amp;gt;nextPendingConnection();&#10; //socket-&amp;gt;peerAddress(); //获取客户端地址&#10; //socket-&amp;gt;peerPort();//获取端口号&#10; ui-&amp;gt;iplineEdit-&amp;gt;setText(socket-&amp;gt;peerAddress().toString());&#10; ui-&amp;gt;portlineEdit-&amp;gt;setText(QString::number(socket-&amp;gt;peerPort()));&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="8qt启动新窗口接服务器实现发数据"&gt;&lt;a href="#8qt%e5%90%af%e5%8a%a8%e6%96%b0%e7%aa%97%e5%8f%a3%e6%8e%a5%e6%9c%8d%e5%8a%a1%e5%99%a8%e5%ae%9e%e7%8e%b0%e5%8f%91%e6%95%b0%e6%8d%ae" class="header-anchor"&gt;&lt;/a&gt;8.QT启动新窗口（接服务器，实现发数据）&#13;&#10;&lt;/h1&gt;&lt;h2 id="客户端-1"&gt;&lt;a href="#%e5%ae%a2%e6%88%b7%e7%ab%af-1" class="header-anchor"&gt;&lt;/a&gt;客户端&#13;&#10;&lt;/h2&gt;&lt;p&gt;对原串口对象连接成功后可以使用&lt;/p&gt;&#10;&lt;p&gt;this-&amp;gt;hide();隐藏&lt;/p&gt;&#10;&lt;p&gt;在原界面头文件引入新界面对象头文件&lt;/p&gt;&#10;&lt;p&gt;#include &amp;lt;chat.h&amp;gt;&lt;/p&gt;&#10;&lt;p&gt;在原界面需要显示新界面的时候声明对象，像Widget w; w.show()一样&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250708165731756" class="gallery-image" data-flex-basis="693px" data-flex-grow="289" height="237" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708165731756.png" width="685"&gt;&lt;/p&gt;&#10;&lt;p&gt;但是新对象要使用socket,因此要传入&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;Chat *c =new Chat(socket);//堆空间创建&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;此时需要添加类Chat头文件和成员&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;#include &amp;lt;QTcpSocket&amp;gt;&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img alt="image-20250708170221202" class="gallery-image" data-flex-basis="476px" data-flex-grow="198" height="345" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708170221202.png" width="685"&gt;&lt;/p&gt;&#10;&lt;p&gt;构造函数进行一个赋值&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;Chat::Chat(QTcpSocket *s,QWidget *parent)&#10; : QWidget(parent)&#10; , ui(new Ui::Chat)&#10;{&#10; ui-&amp;gt;setupUi(this);&#10; socket = s;&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="服务器-1"&gt;&lt;a href="#%e6%9c%8d%e5%8a%a1%e5%99%a8-1" class="header-anchor"&gt;&lt;/a&gt;服务器&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;img alt="image-20250708171553246" class="gallery-image" data-flex-basis="614px" data-flex-grow="256" height="301" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708171553246.png" width="771"&gt;&lt;/p&gt;&#10;&lt;p&gt;实现槽函数&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;void Widget::clientInfoSlot()&#10;{&#10; &#10; QTcpSocket *s = (QTcpSocket *)sender();//获取信号的发出者&#10;&#10; QString str = QString(s-&amp;gt;readAll());&#10; ui-&amp;gt;mainlineEdit-&amp;gt;setText(str);&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;实现了客户端发送，服务器接收并显示&lt;/p&gt;&#10;&lt;h1 id="9qt多线程"&gt;&lt;a href="#9qt%e5%a4%9a%e7%ba%bf%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;9.QT多线程&#13;&#10;&lt;/h1&gt;&lt;p&gt;接TCP，实现服务器多线程，多客户端连接一个服务器&lt;/p&gt;&#10;&lt;h2 id="创建线程类"&gt;&lt;a href="#%e5%88%9b%e5%bb%ba%e7%ba%bf%e7%a8%8b%e7%b1%bb" class="header-anchor"&gt;&lt;/a&gt;创建线程类&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;img alt="image-20250708194229897" class="gallery-image" data-flex-basis="417px" data-flex-grow="173" height="336" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708194229897.png" width="584"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250708203427019" class="gallery-image" data-flex-basis="347px" data-flex-grow="144" height="554" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708203427019.png" srcset="https://zeseanblog.top/p/qt/images/image-20250708203427019_hu_47b7245c9b5aa081.png 800w, https://zeseanblog.top/p/qt/images/image-20250708203427019.png 802w" width="802"&gt;&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;#include &amp;lt;QThread&amp;gt;&#10;//继承自QThread&#10;class my_thread : public QThread&#10;{&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="启动线程"&gt;&lt;a href="#%e5%90%af%e5%8a%a8%e7%ba%bf%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;启动线程&#13;&#10;&lt;/h2&gt;&lt;pre tabindex="0"&gt;&lt;code&gt; //启动线程在widget.cpp&#10; my_thread *t = new my_thread(socket);//创建线程对象&#10; t-&amp;gt;start();//开始线程&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="重写虚函数"&gt;&lt;a href="#%e9%87%8d%e5%86%99%e8%99%9a%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;重写虚函数&#13;&#10;&lt;/h2&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;public:&#10; explicit my_thread(QTcpSocket *s,QThread *parent = nullptr);&#10; //重写虚函数&#10; void run();&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="修改类"&gt;&lt;a href="#%e4%bf%ae%e6%94%b9%e7%b1%bb" class="header-anchor"&gt;&lt;/a&gt;修改类&#13;&#10;&lt;/h2&gt;&lt;p&gt;添加成员，修改构造函数参数，在构造函数进行赋值&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;.h&#10;&#10;class my_thread : public QThread&#10;{&#10; Q_OBJECT&#10;public:&#10; explicit my_thread(QTcpSocket *s,QThread *parent = nullptr);&#10; //重写虚函数&#10; void run();&#10;private slots:&#10; void clientInfoSlot();&#10;&#10;private:&#10; QTcpSocket *socket;&#10;};&#10;&#10;.cpp&#10;my_thread::my_thread(QTcpSocket *s,QThread *parent)&#10; : QThread{parent}&#10;{&#10; socket = s;&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="实现虚函数和槽函数"&gt;&lt;a href="#%e5%ae%9e%e7%8e%b0%e8%99%9a%e5%87%bd%e6%95%b0%e5%92%8c%e6%a7%bd%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;实现虚函数和槽函数&#13;&#10;&lt;/h2&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;&#10;void my_thread::run()&#10;{&#10; connect(socket,&amp;amp;QTcpSocket::readyRead,this,&amp;amp;my_thread::clientInfoSlot);&#10;&#10;}&#10;&#10;void my_thread::clientInfoSlot()&#10;{&#10; qDebug()&amp;lt;&amp;lt;socket-&amp;gt;readAll();&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="10自定义信号"&gt;&lt;a href="#10%e8%87%aa%e5%ae%9a%e4%b9%89%e4%bf%a1%e5%8f%b7" class="header-anchor"&gt;&lt;/a&gt;10.自定义信号&#13;&#10;&lt;/h1&gt;&lt;p&gt;继QT多线程&lt;/p&gt;&#10;&lt;h2 id="子线程"&gt;&lt;a href="#%e5%ad%90%e7%ba%bf%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;子线程&#13;&#10;&lt;/h2&gt;&lt;p&gt;在my_thread类中创建自定义信号&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;signals:&#10;&#9;void sendToWidget(QByteArray b);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;//my_thread.cpp&#10;&#10;void my_thread::clientInfoSlot()&#10;{&#10; //qDebug()&amp;lt;&amp;lt;socket-&amp;gt;readAll();&#10; QByteArray ba = socket -&amp;gt;readAll();&#10; emit sendToWidget(ba);//发送信号&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="主线程"&gt;&lt;a href="#%e4%b8%bb%e7%ba%bf%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;主线程&#13;&#10;&lt;/h2&gt;&lt;p&gt;接收数据链接槽函数&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250708205723802" class="gallery-image" data-flex-basis="1864px" data-flex-grow="776" height="103" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708205723802.png" width="800"&gt;&lt;/p&gt;&#10;&lt;p&gt;实现槽函数&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250708205757077" class="gallery-image" data-flex-basis="1092px" data-flex-grow="455" height="121" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708205757077.png" width="551"&gt;&lt;/p&gt;&#10;&lt;h1 id="11mysql数据库"&gt;&lt;a href="#11mysql%e6%95%b0%e6%8d%ae%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;11.MySQL数据库&#13;&#10;&lt;/h1&gt;&lt;h2 id="mysql部分"&gt;&lt;a href="#mysql%e9%83%a8%e5%88%86" class="header-anchor"&gt;&lt;/a&gt;MySQL部分&#13;&#10;&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;span class="lnt"&gt;7&#10;&lt;/span&gt;&lt;span class="lnt"&gt;8&#10;&lt;/span&gt;&lt;span class="lnt"&gt;9&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-mysql" data-lang="mysql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;create&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mydatabase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;create&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;student&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;integer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;primary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;birth&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;date&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="kp"&gt;charset&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;utf8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;student&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h2 id="qt部分"&gt;&lt;a href="#qt%e9%83%a8%e5%88%86" class="header-anchor"&gt;&lt;/a&gt;QT部分&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;img alt="image-20250708213548476" class="gallery-image" data-flex-basis="2302px" data-flex-grow="959" height="32" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/qt/images/image-20250708213548476.png" width="307"&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;span class="lnt"&gt;29&#10;&lt;/span&gt;&lt;span class="lnt"&gt;30&#10;&lt;/span&gt;&lt;span class="lnt"&gt;31&#10;&lt;/span&gt;&lt;span class="lnt"&gt;32&#10;&lt;/span&gt;&lt;span class="lnt"&gt;33&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c++" data-lang="c++"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//.h&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;QSqlDatabase&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;QMessageBox&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;QSqlDatabase&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//.cpp&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Widget&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Widget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QWidget&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;QWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Ui&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Widget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;setupUi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;//连接数据库&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QSqlDatabase&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;addDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;QMYSQL&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="c1"&gt;//加载MySQL数据库驱动&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setDatabaseName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;mydatabase&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setHostName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;localhost&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setUserName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;194910&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;QMessageBox&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;information&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;连接提示&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;连接成功&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;QMessageBox&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;连接提示&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;连接失败&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;</description></item><item><title>STM32 BootLoader 学习笔记</title><link>https://zeseanblog.top/p/stm32-bootloader/</link><pubDate>Sat, 30 Aug 2025 14:00:00 +0800</pubDate><guid>https://zeseanblog.top/p/stm32-bootloader/</guid><description>&lt;h1 id="bootloader-学习"&gt;&lt;a href="#bootloader-%e5%ad%a6%e4%b9%a0" class="header-anchor"&gt;&lt;/a&gt;BootLoader 学习&#13;&#10;&lt;/h1&gt;&lt;p&gt;硬件：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;stm32f407(嘉立创天空星)&lt;/li&gt;&#10;&lt;li&gt;HC-05蓝牙模块&#10;软件：&lt;/li&gt;&#10;&lt;li&gt;暂时使用python简陋演示功能&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="为什么要有bootloader"&gt;&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e6%9c%89bootloader" class="header-anchor"&gt;&lt;/a&gt;为什么要有bootloader&#13;&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;类似于电脑的boot，可以让我们很方便的去重装系统，可以用u盘重装系统，可以在线重装系统等&lt;/li&gt;&#10;&lt;li&gt;可以把一些固定参数放到bootloader里，比如屏幕亮度，初始参数等等，可以专注于APP的开发&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="前置知识"&gt;&lt;a href="#%e5%89%8d%e7%bd%ae%e7%9f%a5%e8%af%86" class="header-anchor"&gt;&lt;/a&gt;前置知识&#13;&#10;&lt;/h2&gt;&lt;h3 id="单片机组成"&gt;&lt;a href="#%e5%8d%95%e7%89%87%e6%9c%ba%e7%bb%84%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;单片机组成&#13;&#10;&lt;/h3&gt;&lt;p&gt;电脑组成&#10;&lt;img class="gallery-image" data-flex-basis="415px" data-flex-grow="173" height="997" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/stm32-bootloader/images/file-20250918142600489.png" srcset="https://zeseanblog.top/p/stm32-bootloader/images/file-20250918142600489_hu_482bceecae9c565.png 800w, https://zeseanblog.top/p/stm32-bootloader/images/file-20250918142600489_hu_8f8c4d3c0cccca90.png 1600w, https://zeseanblog.top/p/stm32-bootloader/images/file-20250918142600489.png 1728w" width="1728"&gt;&#10;stm32内部，与电脑组成类似，主要强调：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;片内Flash：相当于电脑硬盘&lt;/li&gt;&#10;&lt;li&gt;嵌入式 SRAM：相当与电脑内存条&#10;&lt;img class="gallery-image" data-flex-basis="467px" data-flex-grow="194" height="984" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/stm32-bootloader/images/file-20250918142716567.png" srcset="https://zeseanblog.top/p/stm32-bootloader/images/file-20250918142716567_hu_a16056c0c5f19165.png 800w, https://zeseanblog.top/p/stm32-bootloader/images/file-20250918142716567_hu_7735bb6a2fdca4bc.png 1600w, https://zeseanblog.top/p/stm32-bootloader/images/file-20250918142716567.png 1915w" width="1915"&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4 id="你需要知道"&gt;&lt;a href="#%e4%bd%a0%e9%9c%80%e8%a6%81%e7%9f%a5%e9%81%93" class="header-anchor"&gt;&lt;/a&gt;你需要知道：&#13;&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;嵌入式SRAM是被映射在$0x2000 0000$上的&#10;&lt;img class="gallery-image" data-flex-basis="589px" data-flex-grow="245" height="673" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/stm32-bootloader/images/file-20251007165048150.png" srcset="https://zeseanblog.top/p/stm32-bootloader/images/file-20251007165048150_hu_1aa8dcc6e31e9028.png 800w, https://zeseanblog.top/p/stm32-bootloader/images/file-20251007165048150_hu_87c3aa6ab84ed6e9.png 1600w, https://zeseanblog.top/p/stm32-bootloader/images/file-20251007165048150.png 1652w" width="1652"&gt;&lt;/li&gt;&#10;&lt;li&gt;嵌入式flash是被映射在$0x0800 0000$&#10;&lt;img class="gallery-image" data-flex-basis="364px" data-flex-grow="151" height="1195" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/stm32-bootloader/images/file-20251007165329427.png" srcset="https://zeseanblog.top/p/stm32-bootloader/images/file-20251007165329427_hu_cd167254a77522ca.png 800w, https://zeseanblog.top/p/stm32-bootloader/images/file-20251007165329427_hu_15dd6764340d02d1.png 1600w, https://zeseanblog.top/p/stm32-bootloader/images/file-20251007165329427.png 1814w" width="1814"&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="stm32启动流程"&gt;&lt;a href="#stm32%e5%90%af%e5%8a%a8%e6%b5%81%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;stm32启动流程&#13;&#10;&lt;/h3&gt;&lt;p&gt;STM32微控制器从&lt;strong&gt;上电或复位&lt;/strong&gt;到执行你编写的 &lt;strong&gt;&lt;code&gt;main()&lt;/code&gt; 函数&lt;/strong&gt; 之前，会经历一系列&lt;strong&gt;由硬件和启动代码&lt;/strong&gt;（通常是汇编语言编写的）完成的初始化步骤&lt;/p&gt;&#10;&lt;p&gt;下面是 STM32 从上电到进入 &lt;code&gt;main()&lt;/code&gt; 函数的详细过程：&lt;/p&gt;&#10;&lt;h4 id="一硬件复位与启动模式选择"&gt;&lt;a href="#%e4%b8%80%e7%a1%ac%e4%bb%b6%e5%a4%8d%e4%bd%8d%e4%b8%8e%e5%90%af%e5%8a%a8%e6%a8%a1%e5%bc%8f%e9%80%89%e6%8b%a9" class="header-anchor"&gt;&lt;/a&gt;一、硬件复位与启动模式选择&#13;&#10;&lt;/h4&gt;&lt;h5 id="1-上电复位-por-或硬件复位"&gt;&lt;a href="#1-%e4%b8%8a%e7%94%b5%e5%a4%8d%e4%bd%8d-por-%e6%88%96%e7%a1%ac%e4%bb%b6%e5%a4%8d%e4%bd%8d" class="header-anchor"&gt;&lt;/a&gt;1. &lt;strong&gt;上电复位 (POR) 或硬件复位&lt;/strong&gt;&#13;&#10;&lt;/h5&gt;&lt;p&gt;当STM32芯片&lt;strong&gt;上电&lt;/strong&gt;或者&lt;strong&gt;复位引脚&lt;/strong&gt;（NRST）被置为低电平并释放时，微控制器会进入&lt;strong&gt;复位状态&lt;/strong&gt;。在复位期间，所有内部寄存器会被设置为预设的初始值，确保系统处于一个确定的、已知的状态。&lt;/p&gt;&#10;&lt;h5 id="2-选择启动模式-boot-pins"&gt;&lt;a href="#2-%e9%80%89%e6%8b%a9%e5%90%af%e5%8a%a8%e6%a8%a1%e5%bc%8f-boot-pins" class="header-anchor"&gt;&lt;/a&gt;2. &lt;strong&gt;选择启动模式 (BOOT Pins)&lt;/strong&gt;&#13;&#10;&lt;/h5&gt;&lt;p&gt;CPU内核在复位结束后，首先会采样特定的&lt;strong&gt;启动引脚&lt;/strong&gt;（如 &lt;code&gt;BOOT0&lt;/code&gt; 和 &lt;code&gt;BOOT1&lt;/code&gt;，具体名称和数量可能因型号而异）。这些引脚的状态决定了微控制器从哪个存储器空间开始执行代码：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;主闪存启动 (Main Flash Memory)&lt;/strong&gt;：最常用的模式，运行用户编写的程序。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;系统存储器启动 (System Memory)&lt;/strong&gt;：运行内置的 Bootloader，用于通过串口、USB等接口烧录程序。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;SRAM 启动 (Embedded SRAM)&lt;/strong&gt;：运行驻留在SRAM中的代码，不常用。&#10;通常，在运行用户程序时，会配置为从&lt;strong&gt;主闪存&lt;/strong&gt;启动。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h4 id="二cortex-m-内核的初始寻址"&gt;&lt;a href="#%e4%ba%8ccortex-m-%e5%86%85%e6%a0%b8%e7%9a%84%e5%88%9d%e5%a7%8b%e5%af%bb%e5%9d%80" class="header-anchor"&gt;&lt;/a&gt;二、Cortex-M 内核的初始寻址&#13;&#10;&lt;/h4&gt;&lt;p&gt;STM32 的核心是 &lt;strong&gt;Cortex-M&lt;/strong&gt; 系列内核（如 M0、M3、M4、M7），它们遵循一个标准化的启动流程，这部分是由硬件自动完成的。&lt;/p&gt;&#10;&lt;h5 id="3-读取中断向量表"&gt;&lt;a href="#3-%e8%af%bb%e5%8f%96%e4%b8%ad%e6%96%ad%e5%90%91%e9%87%8f%e8%a1%a8" class="header-anchor"&gt;&lt;/a&gt;3. &lt;strong&gt;读取中断向量表&lt;/strong&gt;&#13;&#10;&lt;/h5&gt;&lt;p&gt;微控制器根据启动模式，确定&lt;strong&gt;中断向量表&lt;/strong&gt;的起始地址（在主闪存启动模式下，通常是 &lt;strong&gt;&lt;code&gt;0x0800 0000&lt;/code&gt;&lt;/strong&gt;）。中断向量表是存储了各种异常和中断服务程序入口地址的表格。&lt;/p&gt;&#10;&lt;h5 id="4-初始化栈指针-sp"&gt;&lt;a href="#4-%e5%88%9d%e5%a7%8b%e5%8c%96%e6%a0%88%e6%8c%87%e9%92%88-sp" class="header-anchor"&gt;&lt;/a&gt;4. &lt;strong&gt;初始化栈指针 (SP)&lt;/strong&gt;&#13;&#10;&lt;/h5&gt;&lt;p&gt;CPU 从向量表的&lt;strong&gt;第一个 32 位字&lt;/strong&gt;（地址 &lt;code&gt;Boot_Address + 0x00&lt;/code&gt;）中读取初始的 &lt;strong&gt;主栈指针 (MSP)&lt;/strong&gt; 的值。这是程序中栈区的最高地址，用于存储局部变量、函数调用返回地址等。&lt;/p&gt;&#10;&lt;h5 id="5-设置程序计数器-pc"&gt;&lt;a href="#5-%e8%ae%be%e7%bd%ae%e7%a8%8b%e5%ba%8f%e8%ae%a1%e6%95%b0%e5%99%a8-pc" class="header-anchor"&gt;&lt;/a&gt;5. &lt;strong&gt;设置程序计数器 (PC)&lt;/strong&gt;&#13;&#10;&lt;/h5&gt;&lt;p&gt;CPU 从向量表的&lt;strong&gt;第二个 32 位字&lt;/strong&gt;（地址 &lt;code&gt;Boot_Address + 0x04&lt;/code&gt;）中读取 &lt;strong&gt;复位处理程序&lt;/strong&gt;（&lt;strong&gt;&lt;code&gt;Reset_Handler&lt;/code&gt;&lt;/strong&gt;）的地址，并将这个地址加载到 &lt;strong&gt;程序计数器 (PC)&lt;/strong&gt; 中。&#10;&lt;strong&gt;至此，硬件初始化完成，程序控制权正式移交给 &lt;code&gt;Reset_Handler&lt;/code&gt;。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h4 id="三执行启动文件代码-reset_handler"&gt;&lt;a href="#%e4%b8%89%e6%89%a7%e8%a1%8c%e5%90%af%e5%8a%a8%e6%96%87%e4%bb%b6%e4%bb%a3%e7%a0%81-reset_handler" class="header-anchor"&gt;&lt;/a&gt;三、执行启动文件代码 (&lt;code&gt;Reset_Handler&lt;/code&gt;)&#13;&#10;&lt;/h4&gt;&lt;p&gt;&lt;code&gt;Reset_Handler&lt;/code&gt; 是由编译器和芯片厂商提供的一个&lt;strong&gt;汇编语言函数&lt;/strong&gt;，通常位于项目中的 &lt;strong&gt;&lt;code&gt;startup_stm32xxx.s&lt;/code&gt;&lt;/strong&gt; 文件（即&lt;strong&gt;启动文件&lt;/strong&gt;）中。它的任务是为C/C++程序的运行准备好环境，包括内存、时钟和库函数等。&lt;/p&gt;&#10;&lt;h5 id="6-调用"&gt;&lt;a href="#6-%e8%b0%83%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;6. &lt;strong&gt;调用 &lt;code&gt;SystemInit()&lt;/code&gt;&lt;/strong&gt;&#13;&#10;&lt;/h5&gt;&lt;p&gt;&lt;code&gt;Reset_Handler&lt;/code&gt; 做的第一件大事是调用 &lt;strong&gt;&lt;code&gt;SystemInit()&lt;/code&gt;&lt;/strong&gt; 函数（通常在 &lt;code&gt;system_stm32xxx.c&lt;/code&gt; 文件中）。该函数主要完成：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;配置系统时钟&lt;/strong&gt;：设置主时钟源、PLL 倍频等，将系统时钟配置到所需的工作频率（但此时还不涉及用户外设时钟）。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;配置存储器&lt;/strong&gt;：如设置 Flash 访问等待周期等。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h5 id="7-初始化-ram-中的数据段"&gt;&lt;a href="#7-%e5%88%9d%e5%a7%8b%e5%8c%96-ram-%e4%b8%ad%e7%9a%84%e6%95%b0%e6%8d%ae%e6%ae%b5" class="header-anchor"&gt;&lt;/a&gt;7. &lt;strong&gt;初始化 RAM 中的数据段&lt;/strong&gt;&#13;&#10;&lt;/h5&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;初始化 &lt;code&gt;.data&lt;/code&gt; 段&lt;/strong&gt;：&lt;code&gt;.data&lt;/code&gt; 段存储了&lt;strong&gt;已初始化&lt;/strong&gt;的全局变量和静态变量。这些变量的初始值存储在 Flash 中，&lt;code&gt;Reset_Handler&lt;/code&gt; 会将这些值从 &lt;strong&gt;Flash 复制到 RAM&lt;/strong&gt; 中。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;初始化 &lt;code&gt;.bss&lt;/code&gt; 段&lt;/strong&gt;：&lt;code&gt;.bss&lt;/code&gt; 段存储了&lt;strong&gt;未初始化&lt;/strong&gt;的全局变量和静态变量。C 语言标准要求它们在程序开始时必须被清零。&lt;code&gt;Reset_Handler&lt;/code&gt; 会将 &lt;code&gt;.bss&lt;/code&gt; 段在 &lt;strong&gt;RAM 中的区域清零&lt;/strong&gt;。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h5 id="8-调用-c-库初始化函数"&gt;&lt;a href="#8-%e8%b0%83%e7%94%a8-c-%e5%ba%93%e5%88%9d%e5%a7%8b%e5%8c%96%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;8. &lt;strong&gt;调用 C 库初始化函数&lt;/strong&gt;&#13;&#10;&lt;/h5&gt;&lt;p&gt;对于标准 C/C++ 环境，&lt;code&gt;Reset_Handler&lt;/code&gt; 还会调用 C 库的初始化函数（例如 &lt;code&gt;__libc_init_array&lt;/code&gt;），用于：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;初始化 C 运行时环境。&lt;/li&gt;&#10;&lt;li&gt;调用 C++ 程序的&lt;strong&gt;静态构造函数&lt;/strong&gt;（如果你的代码中有使用）。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h5 id="9-跳转到"&gt;&lt;a href="#9-%e8%b7%b3%e8%bd%ac%e5%88%b0" class="header-anchor"&gt;&lt;/a&gt;9. &lt;strong&gt;跳转到 &lt;code&gt;main()&lt;/code&gt;&lt;/strong&gt;&#13;&#10;&lt;/h5&gt;&lt;p&gt;在完成所有必要的硬件和软件环境准备后，&lt;code&gt;Reset_Handler&lt;/code&gt; 的最后一步就是执行一条跳转指令，&lt;strong&gt;调用用户编写的 &lt;code&gt;main()&lt;/code&gt; 函数&lt;/strong&gt;。&#10;代码段&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;; 假设这是 Reset_Handler 的最后几行伪汇编代码&#10;; ...&#10;BL SystemInit ; 调用系统时钟初始化函数&#10;BL __libc_init_array ; 调用 C 库初始化函数&#10;LDR R0, =main ; 将 main 函数地址加载到 R0&#10;BX R0 ; 跳转到 main 函数执行&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;至此，STM32 终于进入了你的应用程序，开始执行用户代码。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h4 id="总结流程图"&gt;&lt;a href="#%e6%80%bb%e7%bb%93%e6%b5%81%e7%a8%8b%e5%9b%be" class="header-anchor"&gt;&lt;/a&gt;总结流程图&#13;&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;上电后检查boot引脚的高低决定从哪启动（在哪寻找代码）&lt;/li&gt;&#10;&lt;li&gt;读取代码(编译后的2进制文件)的第一个字(主堆栈的地址)，（工厂的工作地点）&lt;/li&gt;&#10;&lt;li&gt;寻找第二个字以运行到main();&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;步骤&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;执行者&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;动作描述&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;目标&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;1&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;硬件/CPU&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;上电复位 (POR)&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;强制所有硬件到初始状态。&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;2&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;硬件/CPU&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;检查 BOOT 引脚&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;确定代码的启动位置（如主 Flash）。&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;3&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;硬件/CPU&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;读取向量表&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;确定 SP 和 PC 的初始值。&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;4&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;硬件/CPU&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;设置初始 SP/PC&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;初始化主栈指针，跳转到 &lt;code&gt;Reset_Handler&lt;/code&gt;。&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;启动文件&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;调用 &lt;code&gt;SystemInit()&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;配置系统时钟和 Flash 等基础硬件。&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;6&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;启动文件&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;初始化数据段&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;从 Flash 复制 &lt;code&gt;.data&lt;/code&gt; 到 RAM，将 &lt;code&gt;.bss&lt;/code&gt; 段清零。&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;7&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;启动文件&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;调用库初始化&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;初始化 C 运行时环境和静态构造函数。&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;8&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;启动文件&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;调用 &lt;code&gt;main()&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;进入用户应用程序的起点&lt;/strong&gt;。&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h4 id="问题"&gt;&lt;a href="#%e9%97%ae%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;问题：&#13;&#10;&lt;/h4&gt;&lt;h5 id="question1为什么启动后需要先找到中断向量表呢很重要吗"&gt;&lt;a href="#question1%e4%b8%ba%e4%bb%80%e4%b9%88%e5%90%af%e5%8a%a8%e5%90%8e%e9%9c%80%e8%a6%81%e5%85%88%e6%89%be%e5%88%b0%e4%b8%ad%e6%96%ad%e5%90%91%e9%87%8f%e8%a1%a8%e5%91%a2%e5%be%88%e9%87%8d%e8%a6%81%e5%90%97" class="header-anchor"&gt;&lt;/a&gt;Question1为什么启动后需要先找到中断向量表呢，很重要吗?&#13;&#10;&lt;/h5&gt;&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="141px" data-flex-grow="58" height="2083" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/stm32-bootloader/images/file-20251005202856356.png" srcset="https://zeseanblog.top/p/stm32-bootloader/images/file-20251005202856356_hu_fcd9f48efa3e88a4.png 800w, https://zeseanblog.top/p/stm32-bootloader/images/file-20251005202856356.png 1224w" width="1224"&gt;&lt;/p&gt;&#10;&lt;h5 id="question2堆栈是用来干嘛的为什么要先初始化它不初始化会怎么样"&gt;&lt;a href="#question2%e5%a0%86%e6%a0%88%e6%98%af%e7%94%a8%e6%9d%a5%e5%b9%b2%e5%98%9b%e7%9a%84%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e5%85%88%e5%88%9d%e5%a7%8b%e5%8c%96%e5%ae%83%e4%b8%8d%e5%88%9d%e5%a7%8b%e5%8c%96%e4%bc%9a%e6%80%8e%e4%b9%88%e6%a0%b7" class="header-anchor"&gt;&lt;/a&gt;Question2:堆栈是用来干嘛的，为什么要先初始化它，不初始化会怎么样&#13;&#10;&lt;/h5&gt;&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="94px" data-flex-grow="39" height="3005" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/stm32-bootloader/images/file-20251005202932179.png" srcset="https://zeseanblog.top/p/stm32-bootloader/images/file-20251005202932179_hu_22adc0851ef297df.png 800w, https://zeseanblog.top/p/stm32-bootloader/images/file-20251005202932179.png 1182w" width="1182"&gt;&lt;/p&gt;&#10;&lt;h5 id="question3为什么会映射成0x08000000呢"&gt;&lt;a href="#question3%e4%b8%ba%e4%bb%80%e4%b9%88%e4%bc%9a%e6%98%a0%e5%b0%84%e6%88%900x08000000%e5%91%a2" class="header-anchor"&gt;&lt;/a&gt;Question3：为什么会映射成0x08000000呢&#13;&#10;&lt;/h5&gt;&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="86px" data-flex-grow="36" height="3289" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/stm32-bootloader/images/file-20251005212337607.png" srcset="https://zeseanblog.top/p/stm32-bootloader/images/file-20251005212337607_hu_e222a6b9e0a291d9.png 800w, https://zeseanblog.top/p/stm32-bootloader/images/file-20251005212337607.png 1192w" width="1192"&gt;&lt;/p&gt;&#10;&lt;h2 id="简单跳转代码"&gt;&lt;a href="#%e7%ae%80%e5%8d%95%e8%b7%b3%e8%bd%ac%e4%bb%a3%e7%a0%81" class="header-anchor"&gt;&lt;/a&gt;简单跳转代码&#13;&#10;&lt;/h2&gt;&lt;p&gt;使用O3优化可以减小boot大小&#10;&lt;img class="gallery-image" data-flex-basis="488px" data-flex-grow="203" height="455" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/stm32-bootloader/images/file-20251007185245764.png" srcset="https://zeseanblog.top/p/stm32-bootloader/images/file-20251007185245764_hu_c0851c9ad5184360.png 800w, https://zeseanblog.top/p/stm32-bootloader/images/file-20251007185245764.png 926w" width="926"&gt;&#10;fromelf &amp;ndash;bin -o &amp;ldquo;$L@L.bin&amp;rdquo; &amp;ldquo;#L&#10;&lt;img class="gallery-image" data-flex-basis="322px" data-flex-grow="134" height="691" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/stm32-bootloader/images/file-20251007185024809.png" srcset="https://zeseanblog.top/p/stm32-bootloader/images/file-20251007185024809_hu_4513aa91a47f8252.png 800w, https://zeseanblog.top/p/stm32-bootloader/images/file-20251007185024809.png 928w" width="928"&gt;&lt;/p&gt;&#10;&lt;h3 id="boot"&gt;&lt;a href="#boot" class="header-anchor"&gt;&lt;/a&gt;Boot&#13;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="nf"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pFunction&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;JumpToApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 1. 检查应用程序地址是否有效&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 应用程序的栈顶地址位于其起始地址的第一个字&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__IO&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;APP_ADDRESS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x2FFE0000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mh"&gt;0x20000000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 2. 将中断向量表重定向到应用程序地址&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SCB&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;VTOR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APP_ADDRESS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 3. 获取应用程序的栈顶地址和复位处理函数地址&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pFunction&lt;/span&gt; &lt;span class="n"&gt;app_reset_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pFunction&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__IO&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;APP_ADDRESS&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;__set_MSP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__IO&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;APP_ADDRESS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 4. 跳转到应用程序&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;app_reset_handler&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h3 id="app"&gt;&lt;a href="#app" class="header-anchor"&gt;&lt;/a&gt;APP&#13;&#10;&lt;/h3&gt;&lt;p&gt;随便，但是：&#10;&lt;img class="gallery-image" data-flex-basis="335px" data-flex-grow="139" height="670" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/stm32-bootloader/images/file-20251007184927290.png" srcset="https://zeseanblog.top/p/stm32-bootloader/images/file-20251007184927290_hu_fd8f4bc16e36c4c5.png 800w, https://zeseanblog.top/p/stm32-bootloader/images/file-20251007184927290.png 937w" width="937"&gt;&lt;/p&gt;&#10;&lt;h3 id="问题-1"&gt;&lt;a href="#%e9%97%ae%e9%a2%98-1" class="header-anchor"&gt;&lt;/a&gt;问题&#13;&#10;&lt;/h3&gt;&lt;h4 id="question1--scb是什么"&gt;&lt;a href="#question1--scb%e6%98%af%e4%bb%80%e4%b9%88" class="header-anchor"&gt;&lt;/a&gt;question1 SCB是什么：&#13;&#10;&lt;/h4&gt;&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="114px" data-flex-grow="47" height="2534" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/stm32-bootloader/images/file-20251007184755441.png" srcset="https://zeseanblog.top/p/stm32-bootloader/images/file-20251007184755441_hu_cfd30c48269d8ff.png 800w, https://zeseanblog.top/p/stm32-bootloader/images/file-20251007184755441.png 1205w" width="1205"&gt;&lt;/p&gt;&#10;&lt;h2 id="远程下载讲解"&gt;&lt;a href="#%e8%bf%9c%e7%a8%8b%e4%b8%8b%e8%bd%bd%e8%ae%b2%e8%a7%a3" class="header-anchor"&gt;&lt;/a&gt;远程下载讲解&#13;&#10;&lt;/h2&gt;&lt;p&gt;注意事项：HC-05的VCC接3V3，实测5V无法使用&#10;蓝牙模块只有在通信状态才会显示已连接蓝牙，打不开蓝牙串口参考：&lt;a class="link" href="https://blog.csdn.net/Argon_Ghost/article/details/121734788" target="_blank" rel="noopener"&#13;&#10; &gt;HC05和电脑蓝牙通讯&lt;/a&gt;&#10;HC05-python-stm32的波特率必须都设置为同样的速率，我这里为9600&lt;/p&gt;&#10;&lt;h3 id="蓝牙模块讲解"&gt;&lt;a href="#%e8%93%9d%e7%89%99%e6%a8%a1%e5%9d%97%e8%ae%b2%e8%a7%a3" class="header-anchor"&gt;&lt;/a&gt;蓝牙模块讲解&#13;&#10;&lt;/h3&gt;&lt;p&gt;总结：当成远程串口用就行&lt;/p&gt;&#10;&lt;h4 id="常用at指令"&gt;&lt;a href="#%e5%b8%b8%e7%94%a8at%e6%8c%87%e4%bb%a4" class="header-anchor"&gt;&lt;/a&gt;常用AT指令&#13;&#10;&lt;/h4&gt;&lt;p&gt;波特率为38400&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;指令&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;返回&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;意义&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;AT&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ok&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;检测固件是否可用&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;AT+RESET&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ok&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;模块软件复位&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;AT+VERSION?&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;+VERSION:&amp;lt;Param&amp;gt; OK&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;获取固件版本&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;AT+NAME=name&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ok&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;设置模块名字&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;AT+NAME?&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;+NAME:&amp;lt;Param&amp;gt; OK&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;返回模块名字&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;AT+PSWD=&amp;ldquo;passwd&amp;rdquo;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;OK&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;设置模块密码&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;AT+PSWD?&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;+PSWD:&amp;lt;Param&amp;gt; OK&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;获取模块密码&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;AT+UART=115200,0,0&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ok&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;设置通信时的波特率&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;AT+UART?&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;+UART:&amp;lt;Param1&amp;gt;,&amp;lt;Param2&amp;gt;,&amp;lt;Param3&amp;gt;&lt;br&gt;OK&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;获取串口参数&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h4 id="模块指示灯标志"&gt;&lt;a href="#%e6%a8%a1%e5%9d%97%e6%8c%87%e7%a4%ba%e7%81%af%e6%a0%87%e5%bf%97" class="header-anchor"&gt;&lt;/a&gt;模块指示灯标志&#13;&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;定时闪两下：已经连接蓝牙，处于通信状态&lt;/li&gt;&#10;&lt;li&gt;快闪：未连接&lt;/li&gt;&#10;&lt;li&gt;慢闪：工作模式，可使用AT指令调整参数（进入：保持按键按下，通电后松开按键即可）&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4 id="测试流程"&gt;&lt;a href="#%e6%b5%8b%e8%af%95%e6%b5%81%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;测试流程&#13;&#10;&lt;/h4&gt;&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="405px" data-flex-grow="169" height="581" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/stm32-bootloader/images/file-20251011201852607.png" srcset="https://zeseanblog.top/p/stm32-bootloader/images/file-20251011201852607_hu_cd8f7eb3d5f1e9f9.png 800w, https://zeseanblog.top/p/stm32-bootloader/images/file-20251011201852607.png 982w" width="982"&gt;&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;先进入工作模式，使用&lt;code&gt;AT&lt;/code&gt;检查是否可用，&lt;/li&gt;&#10;&lt;li&gt;设置模块名字：&lt;code&gt;AT+NAME=MyBluetooth&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;获取密码：&lt;code&gt;AT+PSWD?&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;查看波特率：&lt;code&gt;AT+UART?&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h3 id="嵌入式flash操作"&gt;&lt;a href="#%e5%b5%8c%e5%85%a5%e5%bc%8fflash%e6%93%8d%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;嵌入式Flash操作&#13;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;span class="lnt"&gt;29&#10;&lt;/span&gt;&lt;span class="lnt"&gt;30&#10;&lt;/span&gt;&lt;span class="lnt"&gt;31&#10;&lt;/span&gt;&lt;span class="lnt"&gt;32&#10;&lt;/span&gt;&lt;span class="lnt"&gt;33&#10;&lt;/span&gt;&lt;span class="lnt"&gt;34&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Flash_Erase_App&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;FLASH_EraseInitTypeDef&lt;/span&gt; &lt;span class="n"&gt;EraseInit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;PageError&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 解除Flash保护&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;HAL_FLASH_Unlock&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// F407: sector2(扇区2) = 0x08008000 开始&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;EraseInit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TypeErase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FLASH_TYPEERASE_SECTORS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;EraseInit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FLASH_SECTOR_2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;EraseInit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NbSectors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 到 sector7(扇区7)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;EraseInit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VoltageRange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FLASH_VOLTAGE_RANGE_3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;HAL_FLASHEx_Erase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;EraseInit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;PageError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;HAL_OK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 错误处理&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 开启保护&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;HAL_FLASH_Lock&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;HAL_StatusTypeDef&lt;/span&gt; &lt;span class="nf"&gt;Flash_Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;HAL_StatusTypeDef&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;HAL_FLASH_Unlock&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;HAL_FLASH_Program&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FLASH_TYPEPROGRAM_WORD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;HAL_OK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;HAL_FLASH_Lock&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h3 id="主要逻辑"&gt;&lt;a href="#%e4%b8%bb%e8%a6%81%e9%80%bb%e8%be%91" class="header-anchor"&gt;&lt;/a&gt;主要逻辑&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="765px" data-flex-grow="318" height="529" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/stm32-bootloader/images/file-20251018141930738.png" srcset="https://zeseanblog.top/p/stm32-bootloader/images/file-20251018141930738_hu_54c76ab6edaf17da.png 800w, https://zeseanblog.top/p/stm32-bootloader/images/file-20251018141930738_hu_178f00e71dce5d6.png 1600w, https://zeseanblog.top/p/stm32-bootloader/images/file-20251018141930738.png 1687w" width="1687"&gt;&lt;/p&gt;&#10;&lt;h3 id="固件发送与接收"&gt;&lt;a href="#%e5%9b%ba%e4%bb%b6%e5%8f%91%e9%80%81%e4%b8%8e%e6%8e%a5%e6%94%b6" class="header-anchor"&gt;&lt;/a&gt;固件发送与接收&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="438px" data-flex-grow="182" height="828" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/stm32-bootloader/images/file-20251011211739002.png" srcset="https://zeseanblog.top/p/stm32-bootloader/images/file-20251011211739002_hu_a388e10cc98e4c16.png 800w, https://zeseanblog.top/p/stm32-bootloader/images/file-20251011211739002.png 1514w" width="1514"&gt;&lt;/p&gt;&#10;&lt;h4 id="bootloader代码逻辑"&gt;&lt;a href="#bootloader%e4%bb%a3%e7%a0%81%e9%80%bb%e8%be%91" class="header-anchor"&gt;&lt;/a&gt;Bootloader代码逻辑&#13;&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Bootloader_Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APP_ADDR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;Flash_Erase_App&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;HAL_UART_Receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;huart1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HAL_MAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;CMD_DATA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;HAL_UART_Receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;huart1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HAL_MAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;HAL_UART_Receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;huart1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HAL_MAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;Flash_Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;HAL_UART_Transmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;huart1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;OK&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HAL_MAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;CMD_END&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;HAL_UART_Transmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;huart1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;DONE&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HAL_MAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="电脑_python发送"&gt;&lt;a href="#%e7%94%b5%e8%84%91_python%e5%8f%91%e9%80%81" class="header-anchor"&gt;&lt;/a&gt;电脑_python&amp;ndash;发送&#13;&#10;&lt;/h4&gt;&lt;p&gt;python要先安装pyserial跑：&lt;code&gt;pip install pyserial&lt;/code&gt;&#10;固件采用分批的形式发送，使用python脚本进行发送&#10;&lt;code&gt;ser = serial.Serial(&amp;quot;COM4&amp;quot;, 9600)&lt;/code&gt;这里的COM4需要改成你的com端口&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;serial&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;struct&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 初始化一个串口对象&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;COM4&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9600&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="se"&gt;\x02&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# CMD_DATA&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 把当前数据块的长度打包成两个字节的无符号整数（小端序）。&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 比如 len(data) = 256，那么结果是 b&amp;#39;\x00\x01&amp;#39;，开发板端可以据此知道这包数据有多长。&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;lt;H&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 阻塞读取开发板发送的信息，确保是否传递成功&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# OK&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;app.bin&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;rb&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 每次循环读取256个数据&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;send_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="se"&gt;\x03&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# CMD_END&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# DONE&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="stm32_蓝牙接收"&gt;&lt;a href="#stm32_%e8%93%9d%e7%89%99%e6%8e%a5%e6%94%b6" class="header-anchor"&gt;&lt;/a&gt;stm32_蓝牙&amp;ndash;接收&#13;&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;span class="lnt"&gt;29&#10;&lt;/span&gt;&lt;span class="lnt"&gt;30&#10;&lt;/span&gt;&lt;span class="lnt"&gt;31&#10;&lt;/span&gt;&lt;span class="lnt"&gt;32&#10;&lt;/span&gt;&lt;span class="lnt"&gt;33&#10;&lt;/span&gt;&lt;span class="lnt"&gt;34&#10;&lt;/span&gt;&lt;span class="lnt"&gt;35&#10;&lt;/span&gt;&lt;span class="lnt"&gt;36&#10;&lt;/span&gt;&lt;span class="lnt"&gt;37&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define APP_ADDR 0x08008000&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define CMD_START 0x01&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define CMD_DATA 0x02&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define CMD_END 0x03&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Bootloader_Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APP_ADDR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 擦除老APP,准备迎接新王&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;Flash_Erase_App&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 堵塞接收，根据先接收到的命令决定怎么做&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;HAL_UART_Receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;huart1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HAL_MAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 数据命令，表示接收到的是数据&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;CMD_DATA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 获取长度&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;HAL_UART_Receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;huart1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HAL_MAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 获取内容&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;HAL_UART_Receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;huart1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HAL_MAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 写入内容&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;Flash_Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 位移地址，准备写入后续内容&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 回应OK&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;HAL_UART_Transmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;huart1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;OK&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HAL_MAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 结束命令，表示接收完成，退出该函数&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;CMD_END&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;HAL_UART_Transmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;huart1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;DONE&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HAL_MAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h3 id="增加校验-crc32"&gt;&lt;a href="#%e5%a2%9e%e5%8a%a0%e6%a0%a1%e9%aa%8c-crc32" class="header-anchor"&gt;&lt;/a&gt;增加校验-CRC32&#13;&#10;&lt;/h3&gt;&lt;h4 id="一crc32-是什么"&gt;&lt;a href="#%e4%b8%80crc32-%e6%98%af%e4%bb%80%e4%b9%88" class="header-anchor"&gt;&lt;/a&gt;一、CRC32 是什么&#13;&#10;&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;CRC&lt;/strong&gt; 全称 &lt;strong&gt;Cyclic Redundancy Check（循环冗余校验）&lt;/strong&gt;。&lt;br&gt;&#10;&lt;code&gt;CRC32&lt;/code&gt; 表示它使用的是 &lt;strong&gt;32位的多项式运算结果&lt;/strong&gt;。&#10;它不是“加法求和”那种简单校验，而是用一种&lt;strong&gt;二进制多项式除法&lt;/strong&gt;的思想：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;把整个数据看作一个很长的二进制数；&lt;/li&gt;&#10;&lt;li&gt;用一个固定的“生成多项式”去做模2除法；&lt;/li&gt;&#10;&lt;li&gt;最后得到一个 32 位的余数；&lt;/li&gt;&#10;&lt;li&gt;这个余数就是 &lt;strong&gt;CRC 校验码&lt;/strong&gt;。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&#13;&#10; &lt;blockquote&gt;&#13;&#10; &lt;p&gt;🧠 模2除法：相当于普通除法，但所有加减都用“异或（XOR）”。&lt;/p&gt;&#10;&#13;&#10; &lt;/blockquote&gt;&#13;&#10;&lt;h4 id="二crc32-的作用"&gt;&lt;a href="#%e4%ba%8ccrc32-%e7%9a%84%e4%bd%9c%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;二、CRC32 的作用&#13;&#10;&lt;/h4&gt;&lt;p&gt;CRC32 不是用来“防黑客”或“加密”的，而是为了 &lt;strong&gt;检测传输或存储过程中的错误&lt;/strong&gt;。&#10;例如：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;你通过串口发送 100KB 的固件；&lt;/li&gt;&#10;&lt;li&gt;中途某一字节丢了、翻转了；&lt;/li&gt;&#10;&lt;li&gt;STM32 收到的文件计算出的 CRC 不等于原始文件的 CRC；&lt;/li&gt;&#10;&lt;li&gt;→ 说明传输错误，不执行更新。&#10;可以检测出几乎所有单比特错误、突发错误，非常可靠。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4 id="电脑端-python增加校验"&gt;&lt;a href="#%e7%94%b5%e8%84%91%e7%ab%af-python%e5%a2%9e%e5%8a%a0%e6%a0%a1%e9%aa%8c" class="header-anchor"&gt;&lt;/a&gt;电脑端-python增加校验&#13;&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;span class="lnt"&gt;29&#10;&lt;/span&gt;&lt;span class="lnt"&gt;30&#10;&lt;/span&gt;&lt;span class="lnt"&gt;31&#10;&lt;/span&gt;&lt;span class="lnt"&gt;32&#10;&lt;/span&gt;&lt;span class="lnt"&gt;33&#10;&lt;/span&gt;&lt;span class="lnt"&gt;34&#10;&lt;/span&gt;&lt;span class="lnt"&gt;35&#10;&lt;/span&gt;&lt;span class="lnt"&gt;36&#10;&lt;/span&gt;&lt;span class="lnt"&gt;37&#10;&lt;/span&gt;&lt;span class="lnt"&gt;38&#10;&lt;/span&gt;&lt;span class="lnt"&gt;39&#10;&lt;/span&gt;&lt;span class="lnt"&gt;40&#10;&lt;/span&gt;&lt;span class="lnt"&gt;41&#10;&lt;/span&gt;&lt;span class="lnt"&gt;42&#10;&lt;/span&gt;&lt;span class="lnt"&gt;43&#10;&lt;/span&gt;&lt;span class="lnt"&gt;44&#10;&lt;/span&gt;&lt;span class="lnt"&gt;45&#10;&lt;/span&gt;&lt;span class="lnt"&gt;46&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="n"&gt;serial&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="n"&gt;binascii&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;tqdm&lt;/span&gt; &lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tqdm&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;tqdm&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# 打开串口&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;COM4&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cp"&gt;# 发送数据包&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="se"&gt;\x02&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;CMD_DATA&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;lt;H&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="err"&gt;长度&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="err"&gt;数据本体&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Bootloader&lt;/span&gt; &lt;span class="err"&gt;回复&lt;/span&gt; &lt;span class="n"&gt;OK&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;OK&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;raise&lt;/span&gt; &lt;span class="nf"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Bootloader写入失败，返回: %s&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crc32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cp"&gt;# 通知 Bootloader 固件结束 + CRC&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="se"&gt;\x03&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;CMD_END&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;lt;I&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crc32&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="err"&gt;字节&lt;/span&gt; &lt;span class="n"&gt;CRC32&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;lt;I&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total_size&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="err"&gt;固件总长度（可选）&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;DONE&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;raise&lt;/span&gt; &lt;span class="nf"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Bootloader校验失败，返回: %s&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# ---------------- 主流程 -----------------&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;app.bin&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;rb&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt; &lt;span class="nl"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# 计算 CRC32（和 Bootloader 保持一致）&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;crc32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;binascii&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;crc32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xFFFFFFFF&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;total_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;固件大小: {total_size} 字节, CRC32 = 0x{crc32:08X}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# 分块发送（带进度条）&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;chunk_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;tqdm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;total_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;B&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unit_scale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;desc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;升级中&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt; &lt;span class="nl"&gt;pbar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nl"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;send_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pbar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# 通知结束&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;send_end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crc32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;固件升级完成 ✅&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="stm32端-增加校验"&gt;&lt;a href="#stm32%e7%ab%af-%e5%a2%9e%e5%8a%a0%e6%a0%a1%e9%aa%8c" class="header-anchor"&gt;&lt;/a&gt;stm32端-增加校验&#13;&#10;&lt;/h4&gt;&lt;p&gt;在CRC校验算法中，数据被视为一个巨大的二进制数，代表一个多项式的系数。生成多项式（&lt;code&gt;CRC32_POLY&lt;/code&gt;）就是用来与这个数据多项式进行“模2除法”运算的除数，最终得到的余数就是CRC校验值。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 多项式 (Ethernet, ZIP, etc. 通用): 0x04C11DB7&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define CRC32_POLY 0xEDB88320UL&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="nf"&gt;crc32_calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;crc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xFFFFFFFFUL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;crc&lt;/span&gt; &lt;span class="o"&gt;^=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crc&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;crc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crc&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;CRC32_POLY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;crc&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;crc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;bootloader逻辑改变&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;span class="lnt"&gt;29&#10;&lt;/span&gt;&lt;span class="lnt"&gt;30&#10;&lt;/span&gt;&lt;span class="lnt"&gt;31&#10;&lt;/span&gt;&lt;span class="lnt"&gt;32&#10;&lt;/span&gt;&lt;span class="lnt"&gt;33&#10;&lt;/span&gt;&lt;span class="lnt"&gt;34&#10;&lt;/span&gt;&lt;span class="lnt"&gt;35&#10;&lt;/span&gt;&lt;span class="lnt"&gt;36&#10;&lt;/span&gt;&lt;span class="lnt"&gt;37&#10;&lt;/span&gt;&lt;span class="lnt"&gt;38&#10;&lt;/span&gt;&lt;span class="lnt"&gt;39&#10;&lt;/span&gt;&lt;span class="lnt"&gt;40&#10;&lt;/span&gt;&lt;span class="lnt"&gt;41&#10;&lt;/span&gt;&lt;span class="lnt"&gt;42&#10;&lt;/span&gt;&lt;span class="lnt"&gt;43&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define APP_ADDR 0x08008000&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define CMD_START 0x01&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define CMD_DATA 0x02&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define CMD_END 0x03&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Bootloader_Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;APP_ADDR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;Flash_Erase_App&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;HAL_UART_Receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;huart1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HAL_MAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;CMD_DATA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;HAL_UART_Receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;huart1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HAL_MAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;HAL_UART_Receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;huart1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HAL_MAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;Flash_Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;HAL_UART_Transmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;huart1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;OK&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HAL_MAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;CMD_END&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;host_crc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;host_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="nf"&gt;HAL_UART_Receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;huart1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;host_crc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HAL_MAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="nf"&gt;HAL_UART_Receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;huart1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;host_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HAL_MAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="c1"&gt;// 自己计算 CRC32&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;calc_crc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;crc32_calc&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;APP_ADDR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;host_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calc_crc&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;host_crc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&lt;span class="nf"&gt;HAL_UART_Transmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;huart1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;DONE&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HAL_MAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&lt;span class="nf"&gt;HAL_UART_Transmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;huart1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;FAIL&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HAL_MAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;</description></item><item><title>FreeRTOS 源码解析笔记</title><link>https://zeseanblog.top/p/freertos-source/</link><pubDate>Sat, 09 Aug 2025 10:00:00 +0800</pubDate><guid>https://zeseanblog.top/p/freertos-source/</guid><description>&lt;h1 id="1动态创建详细过程"&gt;&lt;a href="#1%e5%8a%a8%e6%80%81%e5%88%9b%e5%bb%ba%e8%af%a6%e7%bb%86%e8%bf%87%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;1.动态创建详细过程&#13;&#10;&lt;/h1&gt;&lt;h2 id="动态创建"&gt;&lt;a href="#%e5%8a%a8%e6%80%81%e5%88%9b%e5%bb%ba" class="header-anchor"&gt;&lt;/a&gt;动态创建&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;1.首先tasks.c中&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;结构体并给别名，所以初始化可以用TCB_t&lt;/p&gt;&#10;&lt;p&gt;typedef struct tskTaskControlBlock&lt;/p&gt;&#10;&lt;p&gt;{&lt;/p&gt;&#10;&lt;p&gt;&amp;hellip;&lt;/p&gt;&#10;&lt;p&gt;}tskTCB;&#10;typedef tskTCB TCB_t;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;2.因此在xTaskCreate()实现中&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;TCB_t * pxNewTCB;创建了任务控制块&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;3.任务控制块的结构体中&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;状态列表 事件列表 优先级 栈指针 任务名&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802183613953" class="gallery-image" data-flex-basis="1029px" data-flex-grow="428" height="90" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos-source/images/image-20250802183613953.png" width="386"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;4.回到xTaskCreate&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;判断生长方向，STM32栈区向下生长&lt;/p&gt;&#10;&lt;p&gt;#if ( portSTACK_GROWTH &amp;gt; 0 )&lt;/p&gt;&#10;&lt;p&gt;进入的&lt;/p&gt;&#10;&lt;p&gt;#else中&lt;/p&gt;&#10;&lt;p&gt;其中先定义任务堆栈大小：&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;StackType_t * pxStack;//这个申请的代表首地址&#10;&#10;pxStack = pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) );//如128*4字节，128字×每字字节数=字节数&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;判断是否申请成功任务堆栈，成功则进入&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt; if( pxStack != NULL )&#10; {&#10; pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); //任务控制块信息也需要空间，因此申请&#10; if( pxNewTCB != NULL ) //如果申请了一块&#10; {&#10; memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );&#10; pxNewTCB-&amp;gt;pxStack = pxStack;//然后将首地址给到任务控制块的这个成员变量&#10; }&#10; else&#10; {&#10; vPortFreeStack( pxStack );//否则就释放掉任务堆栈&#10; }&#10; }&#10; else&#10; {&#10; pxNewTCB = NULL;&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;再下面判断是否申请成功任务控制块&lt;/p&gt;&#10;&lt;p&gt;prvInitialiseNewTask：这个用来初始化任务控制块中的成员&lt;/p&gt;&#10;&lt;p&gt;prvAddNewTaskToReadyList：将任务添加到就绪列表&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt; if( pxNewTCB != NULL )&#10; {&#10; prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );&#10; prvAddNewTaskToReadyList( pxNewTCB );&#10; xReturn = pdPASS;//就是成功的返回值&#10; }&#10; else&#10; {&#10; xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;5.到prvInitialiseNewTask&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;( void ) memset( pxNewTCB-&amp;gt;pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );&lt;/p&gt;&#10;&lt;p&gt;这句pxStack是任务堆栈的首地址，将( size_t ) ulStackDepth * sizeof( StackType_t )大小的地址赋值为( int ) tskSTACK_FILL_BYTE&lt;/p&gt;&#10;&lt;p&gt;而这个值是&lt;/p&gt;&#10;&lt;p&gt;#define tskSTACK_FILL_BYTE ( 0xa5U )&lt;/p&gt;&#10;&lt;p&gt;意思就是整个任务堆栈赋值成a5，那就可以通过判断多少a5被改变，得到剩下的空间&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;6.判断 #if ( portSTACK_GROWTH &amp;lt; 0 )&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;是否向下生长？&lt;/p&gt;&#10;&lt;p&gt;STM32:是的&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;//首地址的最低位，取得栈顶&#10;pxTopOfStack = &amp;amp;( pxNewTCB-&amp;gt;pxStack[ ulStackDepth - ( uint32_t ) 1 ] );&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;判断名字是否为空&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;//pcName是一个入口参数&#10;if( pcName != NULL )&#10; {&#10; for( x = ( UBaseType_t ) 0; x &amp;lt; ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )&#10; {&#10; pxNewTCB-&amp;gt;pcTaskName[ x ] = pcName[ x ]; //给到任务控制块的这个成员里&#10; if( pcName[ x ] == ( char ) 0x00 )&#10; {&#10; break;&#10; }&#10; else&#10; {&#10; mtCOVERAGE_TEST_MARKER();&#10; }&#10; }&#10; pxNewTCB-&amp;gt;pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = &amp;#39;\0&amp;#39;;&#10; }&#10; else&#10; {&#10; mtCOVERAGE_TEST_MARKER();&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;判断优先级&lt;/p&gt;&#10;&lt;p&gt;优先级大于最大优先级，就改为最大优先级&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;if( uxPriority &amp;gt;= ( UBaseType_t ) configMAX_PRIORITIES )&#10; {&#10; uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;&#10; }&#10;&#10;pxNewTCB-&amp;gt;uxPriority = uxPriority;&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;然后初始化状态列表项和事件列表项&lt;/p&gt;&#10;&lt;p&gt;vListInitialiseItem( &amp;amp;( pxNewTCB-&amp;gt;xStateListItem ) );&#10;vListInitialiseItem( &amp;amp;( pxNewTCB-&amp;gt;xEventListItem ) );&lt;/p&gt;&#10;&lt;p&gt;将状态列表项所有权给到任务控制块，就可以得到任务当前状态&lt;/p&gt;&#10;&lt;p&gt;listSET_LIST_ITEM_OWNER( &amp;amp;( pxNewTCB-&amp;gt;xStateListItem ), pxNewTCB );&lt;/p&gt;&#10;&lt;p&gt;下面是事件列表项&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;listSET_LIST_ITEM_VALUE( &amp;amp;( pxNewTCB-&amp;gt;xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); &#10; listSET_LIST_ITEM_OWNER( &amp;amp;( pxNewTCB-&amp;gt;xEventListItem ), pxNewTCB );&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;下面来到&lt;/p&gt;&#10;&lt;p&gt;pxNewTCB-&amp;gt;pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;7.进入pxPortInitialiseStack&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;里面栈顶陆续减，就可以往下陆续给赋值。&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,&#10; TaskFunction_t pxCode,&#10; void * pvParameters )&#10;{&#10; &#10; pxTopOfStack--; &#10; *pxTopOfStack = portINITIAL_XPSR; /* xPSR */&#10; pxTopOfStack--;&#10; *pxTopOfStack = ( ( StackType_t ) pxCode ) &amp;amp; portSTART_ADDRESS_MASK; /* PC */&#10; pxTopOfStack--;&#10; *pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */&#10;&#10; pxTopOfStack -= 5; /* R12, R3, R2 and R1. */&#10; *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */&#10; pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */&#10;&#10; return pxTopOfStack;&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;PC是任务函数指针&lt;/strong&gt;，切换到A任务时，就通过这个指针切换到任务函数A&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802194920338" class="gallery-image" data-flex-basis="545px" data-flex-grow="227" height="708" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos-source/images/image-20250802194920338.png" srcset="https://zeseanblog.top/p/freertos-source/images/image-20250802194920338_hu_381901ee71d0b455.png 800w, https://zeseanblog.top/p/freertos-source/images/image-20250802194920338_hu_50975814e2aa1c3e.png 1600w, https://zeseanblog.top/p/freertos-source/images/image-20250802194920338.png 1610w" width="1610"&gt;&lt;/p&gt;&#10;&lt;p&gt;这个实际就是最初传入的函数指针&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802195354593" class="gallery-image" data-flex-basis="1260px" data-flex-grow="525" height="119" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos-source/images/image-20250802195354593.png" width="625"&gt;&lt;/p&gt;&#10;&lt;p&gt;而R0传入的是任务函数参数&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802195543474" class="gallery-image" data-flex-basis="1208px" data-flex-grow="503" height="118" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos-source/images/image-20250802195543474.png" width="594"&gt;&lt;/p&gt;&#10;&lt;p&gt;程序结束后返回更新后的pxTopOfStack&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;8.回到prvInitialiseNewTask&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;将任务句柄给到任务控制块&lt;/p&gt;&#10;&lt;p&gt;if( pxCreatedTask != NULL )&#10;{&#10;*pxCreatedTask = ( TaskHandle_t ) pxNewTCB;&#10;}&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;9.再到prvAddNewTaskToReadyList()&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;这是将任务添加到就绪列表&lt;/p&gt;&#10;&lt;p&gt;先进入临界区 taskENTER_CRITICAL();&lt;/p&gt;&#10;&lt;p&gt;增加任务数量uxCurrentNumberOfTasks++;&lt;/p&gt;&#10;&lt;p&gt;如果当前没有任务，这是第一个任务pxCurrentTCB = pxNewTCB;&lt;/p&gt;&#10;&lt;p&gt;如果这确实是第一个if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )&lt;/p&gt;&#10;&lt;p&gt;就初始化任务列表prvInitialiseTaskLists()&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802201105871" class="gallery-image" data-flex-basis="491px" data-flex-grow="204" height="303" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos-source/images/image-20250802201105871.png" width="620"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;10.进入prvInitialiseTaskLists()&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;初始化32个就绪列表0~31&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;for( uxPriority = ( UBaseType_t ) 0U; uxPriority &amp;lt; ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )&#10; {&#10; vListInitialise( &amp;amp;( pxReadyTasksLists[ uxPriority ] ) );&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果使能删除列表，就初始化一个等待删除列表&lt;/p&gt;&#10;&lt;p&gt;如果使能挂起列表，就初始化一个挂起列表&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;#if ( INCLUDE_vTaskDelete == 1 )&#10; {&#10; vListInitialise( &amp;amp;xTasksWaitingTermination );&#10; }&#10; #endif /* INCLUDE_vTaskDelete */&#10;&#10; #if ( INCLUDE_vTaskSuspend == 1 )&#10; {&#10; vListInitialise( &amp;amp;xSuspendedTaskList );&#10; }&#10; #endif /* INCLUDE_vTaskSuspend */&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;11.继续prvAddNewTaskToReadyList()&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;否则的话，如果当前任务控制块优先级小于新创建的任务控制块&lt;/p&gt;&#10;&lt;p&gt;那新创建的就赋给当前&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;if( xSchedulerRunning == pdFALSE )&#10; {&#10; if( pxCurrentTCB-&amp;gt;uxPriority &amp;lt;= pxNewTCB-&amp;gt;uxPriority )&#10; {&#10; pxCurrentTCB = pxNewTCB;&#10; }&#10; else&#10; {&#10; mtCOVERAGE_TEST_MARKER();&#10; }&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;下面是任务标号，就可以通过这个查询这是第几个创建的任务&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802201852893" class="gallery-image" data-flex-basis="967px" data-flex-grow="403" height="121" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos-source/images/image-20250802201852893.png" width="488"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;12.进入prvAddTaskToReadyList( pxNewTCB );&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;进入 taskRECORD_READY_PRIORITY( ( pxTCB )-&amp;gt;uxPriority );&lt;/p&gt;&#10;&lt;p&gt;进如portRECORD_READY_PRIORITY&lt;/p&gt;&#10;&lt;p&gt;得到&lt;/p&gt;&#10;&lt;p&gt;#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL &amp;laquo; ( uxPriority ) )&lt;/p&gt;&#10;&lt;p&gt;表示就绪列表，哪个位置一，哪个位就有任务，从上往下读就知道哪个任务优先级最高&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802202706272" class="gallery-image" data-flex-basis="382px" data-flex-grow="159" height="301" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos-source/images/image-20250802202706272.png" width="480"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;13.继续prvAddNewTaskToReadyList()&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;退出临界区taskEXIT_CRITICAL();&lt;/p&gt;&#10;&lt;p&gt;如果任务调度器开启，当前任务优先级，小于新的优先级，执行任务切换，到优先级最高的&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802202950218" class="gallery-image" data-flex-basis="750px" data-flex-grow="312" height="210" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos-source/images/image-20250802202950218.png" width="657"&gt;&lt;/p&gt;&#10;&lt;h1 id="2任务挂起与恢复详细过程"&gt;&lt;a href="#2%e4%bb%bb%e5%8a%a1%e6%8c%82%e8%b5%b7%e4%b8%8e%e6%81%a2%e5%a4%8d%e8%af%a6%e7%bb%86%e8%bf%87%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;2.任务挂起与恢复详细过程&#13;&#10;&lt;/h1&gt;&lt;h2 id="任务挂起"&gt;&lt;a href="#%e4%bb%bb%e5%8a%a1%e6%8c%82%e8%b5%b7" class="header-anchor"&gt;&lt;/a&gt;任务挂起&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;1.进入prvGetTCBFromHandle&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;如果句柄为NULL，返回当前任务控制块句柄，否则返回传入任务控制块句柄&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? pxCurrentTCB : ( pxHandle ) )&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;2.回到vTaskSuspend&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;if内是不管当前状态是什么，并移除列表项，移除成功则进入&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt; if( uxListRemove( &amp;amp;( pxTCB-&amp;gt;xStateListItem ) ) == ( UBaseType_t ) 0 )&#10; {&#10; taskRESET_READY_PRIORITY( pxTCB-&amp;gt;uxPriority );&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;3.进入taskRESET_READY_PRIORITY&lt;/strong&gt;&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;if(listCURRENT_LIST_LENGTH(&amp;amp;(pxReadyTasksLists[( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) &#10; { &#10; portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); &#10; } &#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;4.回到vTaskSuspend&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;移除事件列表项&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;if( listLIST_ITEM_CONTAINER( &amp;amp;( pxTCB-&amp;gt;xEventListItem ) ) != NULL )&#10; {&#10; ( void ) uxListRemove( &amp;amp;( pxTCB-&amp;gt;xEventListItem ) );&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;插入挂起列表项末尾&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;vListInsertEnd( &amp;amp;xSuspendedTaskList, &amp;amp;( pxTCB-&amp;gt;xStateListItem ) );&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果带挂起的任务控制块在等待消息通知，清除消息通知&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;for( x = 0; x &amp;lt; configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )&#10; {&#10; if( pxTCB-&amp;gt;ucNotifyState[ x ] == taskWAITING_NOTIFICATION )&#10; {&#10; pxTCB-&amp;gt;ucNotifyState[ x ] = taskNOT_WAITING_NOTIFICATION;&#10; }&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;判断调度器是否正在运行&lt;/p&gt;&#10;&lt;p&gt;如果正在运行，更新下一个阻塞超时时间&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;if( xSchedulerRunning != pdFALSE )&#10; {&#10; taskENTER_CRITICAL();&#10; {&#10; prvResetNextTaskUnblockTime();&#10; }&#10; taskEXIT_CRITICAL();&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;判断挂起是否为任务自己，如果挂起的是自己，强制进行任务切换。&lt;/p&gt;&#10;&lt;p&gt;如果不是，判断当前挂起的任务总数等于创建的任务总数，表明全部在挂起，则将任务控制块赋值为NULL，&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;if( pxTCB == pxCurrentTCB )&#10; {&#10; if( xSchedulerRunning != pdFALSE )&#10; {&#10; configASSERT( uxSchedulerSuspended == 0 );&#10; portYIELD_WITHIN_API();&#10; }&#10; else&#10; {&#10; if( listCURRENT_LIST_LENGTH( &amp;amp;xSuspendedTaskList ) == uxCurrentNumberOfTasks ) &#10; {&#10; pxCurrentTCB = NULL;&#10; }&#10; else&#10; {&#10; vTaskSwitchContext();&#9;&#9;//查找下一个最高优先级任务&#10; }&#10; }&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="任务恢复"&gt;&lt;a href="#%e4%bb%bb%e5%8a%a1%e6%81%a2%e5%a4%8d" class="header-anchor"&gt;&lt;/a&gt;任务恢复&#13;&#10;&lt;/h2&gt;&lt;p&gt;任务句柄赋值给任务控制块&lt;/p&gt;&#10;&lt;p&gt;TCB_t * const pxTCB = xTaskToResume;&lt;/p&gt;&#10;&lt;p&gt;恢复的任务控制块不能等于当前任务和NULL&lt;/p&gt;&#10;&lt;p&gt;if( ( pxTCB != pxCurrentTCB ) &amp;amp;&amp;amp; ( pxTCB != NULL ) )&lt;/p&gt;&#10;&lt;p&gt;如果成立进入，判断任务控制块是否在挂起列表中&lt;/p&gt;&#10;&lt;p&gt;if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )&lt;/p&gt;&#10;&lt;p&gt;如果成立进入，在挂起列表中移除&lt;/p&gt;&#10;&lt;p&gt;( void ) uxListRemove( &amp;amp;( pxTCB-&amp;gt;xStateListItem ) );&lt;/p&gt;&#10;&lt;p&gt;并添加到就绪列表&lt;/p&gt;&#10;&lt;p&gt;prvAddTaskToReadyList( pxTCB );&lt;/p&gt;&#10;&lt;p&gt;在判断优先级是否大于当前优先级，如果是，则任务切换&lt;/p&gt;&#10;&lt;p&gt;taskYIELD_IF_USING_PREEMPTION();&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt; if( ( pxTCB != pxCurrentTCB ) &amp;amp;&amp;amp; ( pxTCB != NULL ) )&#10; {&#10; taskENTER_CRITICAL();&#10; {&#10; if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )&#10; {&#10; traceTASK_RESUME( pxTCB );&#10; ( void ) uxListRemove( &amp;amp;( pxTCB-&amp;gt;xStateListItem ) );&#10; prvAddTaskToReadyList( pxTCB );&#10; if( pxTCB-&amp;gt;uxPriority &amp;gt;= pxCurrentTCB-&amp;gt;uxPriority )&#10; {&#10; taskYIELD_IF_USING_PREEMPTION();&#10; }&#10; else&#10; {&#10; mtCOVERAGE_TEST_MARKER();&#10; }&#10; }&#10; else&#10; {&#10; mtCOVERAGE_TEST_MARKER();&#10; }&#10; }&#10; taskEXIT_CRITICAL();&#10; }&#10; else&#10; {&#10; mtCOVERAGE_TEST_MARKER();&#10; }&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="3临界段代码保护"&gt;&lt;a href="#3%e4%b8%b4%e7%95%8c%e6%ae%b5%e4%bb%a3%e7%a0%81%e4%bf%9d%e6%8a%a4" class="header-anchor"&gt;&lt;/a&gt;3.临界段代码保护&#13;&#10;&lt;/h1&gt;&lt;p&gt;通过++，&amp;ndash;实现了嵌套，本质还是基于portDISABLE_INTERRUPTS();和portENABLE_INTERRUPTS();&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;/*进入临界段*/&#10;#define taskENTER_CRITICAL() portENTER_CRITICAL()&#10;#define portENTER_CRITICAL() vPortEnterCritical()&#10;&#10;void vPortEnterCritical( void )&#10;{&#10; portDISABLE_INTERRUPTS();&#10; uxCriticalNesting++;&#10; if( uxCriticalNesting == 1 )&#10; {&#10; configASSERT( ( portNVIC_INT_CTRL_REG &amp;amp; portVECTACTIVE_MASK ) == 0 );&#10; }&#10;}&#10;&#10;/*退出临界段*/&#10;void vPortExitCritical( void )&#10;{&#10; configASSERT( uxCriticalNesting );&#10; uxCriticalNesting--;&#10; if( uxCriticalNesting == 0 )&#10; {&#10; portENABLE_INTERRUPTS();&#10; }&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="4任务调度"&gt;&lt;a href="#4%e4%bb%bb%e5%8a%a1%e8%b0%83%e5%ba%a6" class="header-anchor"&gt;&lt;/a&gt;4.任务调度&#13;&#10;&lt;/h1&gt;</description></item><item><title>FreeRTOS 常用 API 手册</title><link>https://zeseanblog.top/p/freertos-api/</link><pubDate>Sat, 26 Jul 2025 10:30:00 +0800</pubDate><guid>https://zeseanblog.top/p/freertos-api/</guid><description>&lt;h1 id="任务内核"&gt;&lt;a href="#%e4%bb%bb%e5%8a%a1%e5%86%85%e6%a0%b8" class="header-anchor"&gt;&lt;/a&gt;任务内核&#13;&#10;&lt;/h1&gt;&lt;h2 id="portdisable_interrupts-portenable_interrupts"&gt;&lt;a href="#portdisable_interrupts-portenable_interrupts" class="header-anchor"&gt;&lt;/a&gt;portDISABLE_INTERRUPTS() portENABLE_INTERRUPTS()&#13;&#10;&lt;/h2&gt;&lt;p&gt;关闭FreeRTOS可管理的5-15优先级的中断&lt;/p&gt;&#10;&lt;p&gt;开启FreeRTOS可管理的5-15优先级的中断&lt;/p&gt;&#10;&lt;h2 id="taskenter_critical-taskexit_critical"&gt;&lt;a href="#taskenter_critical-taskexit_critical" class="header-anchor"&gt;&lt;/a&gt;taskENTER_CRITICAL() taskEXIT_CRITICAL()&#13;&#10;&lt;/h2&gt;&lt;p&gt;任务中进入临界段&lt;/p&gt;&#10;&lt;p&gt;任务中退出临界段&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;taskENTER_CRITICAL() ;&#10;{&#10;… … /* 临界区 */&#10;}&#10;taskEXIT_CRITICAL() ;&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="taskenter_critical_from_isr-taskexit_critical_from_isr"&gt;&lt;a href="#taskenter_critical_from_isr-taskexit_critical_from_isr" class="header-anchor"&gt;&lt;/a&gt;taskENTER_CRITICAL_FROM_ISR() taskEXIT_CRITICAL_FROM_ISR()&#13;&#10;&lt;/h2&gt;&lt;p&gt;中断中进入临界段&lt;/p&gt;&#10;&lt;p&gt;中断中退出临界段&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;uint32_t save_status;&#10;save_status = taskENTER_CRITICAL_FROM_ISR() ；&#10;{&#10;… … /* 临界区 */&#10;}&#10;taskEXIT_CRITICAL_FROM_ISR(save_status );&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="vtasksuspendall-xtaskresumeall"&gt;&lt;a href="#vtasksuspendall-xtaskresumeall" class="header-anchor"&gt;&lt;/a&gt;vTaskSuspendAll() xTaskResumeAll()&#13;&#10;&lt;/h2&gt;&lt;p&gt;实现任务调度器挂起与恢复&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;vTaskSuspendAll() ;&#10;{&#10;… … /* 内容 */&#10;}&#10;xTaskResumeAll();&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="void-vtaskstartscheduler"&gt;&lt;a href="#void-vtaskstartscheduler" class="header-anchor"&gt;&lt;/a&gt;void vTaskStartScheduler()&#13;&#10;&lt;/h2&gt;&lt;p&gt;vTaskStartScheduler();&lt;/p&gt;&#10;&lt;h1 id="任务创建与删除"&gt;&lt;a href="#%e4%bb%bb%e5%8a%a1%e5%88%9b%e5%bb%ba%e4%b8%8e%e5%88%a0%e9%99%a4" class="header-anchor"&gt;&lt;/a&gt;任务创建与删除&#13;&#10;&lt;/h1&gt;&lt;h2 id="1xtaskcreate"&gt;&lt;a href="#1xtaskcreate" class="header-anchor"&gt;&lt;/a&gt;1.xTaskCreate&#13;&#10;&lt;/h2&gt;&lt;h3 id="参数和返回值"&gt;&lt;a href="#%e5%8f%82%e6%95%b0%e5%92%8c%e8%bf%94%e5%9b%9e%e5%80%bc" class="header-anchor"&gt;&lt;/a&gt;参数和返回值&#13;&#10;&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;BaseType_t xTaskCreate&#10;(&#10;&#9;TaskFunction_t pxTaskCode, &#9;&#9;&#9;&#9;&#9;/* 指向任务函数的指针 */&#10;&#9;const char * const pcName, &#9;&#9;&#9;&#9;&#9;/* 任务名字，最大长度 configMAX_TASK_NAME_LEN */&#10;&#9;const configSTACK_DEPTH_TYPE usStackDepth, &#9;/* 任务堆栈大小，注意字为单位 */&#10;&#9;void * const pvParameters, &#9;&#9;&#9;&#9;&#9;/* 传递给任务函数的参数 */&#10;&#9;UBaseType_t uxPriority, &#9;&#9;&#9;&#9;&#9;/* 任务优先级，范围： 0 ~ configMAX_PRIORITIES - 1 */&#10;&#9;TaskHandle_t * const pxCreatedTask &#9;&#9;&#9;/* 任务句柄，就是任务的任务控制块 */&#10;)&#10;&#10;返回:&#10;pdPASS 任务创建成功&#10;errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY 任务创建失败&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="实现例程"&gt;&lt;a href="#%e5%ae%9e%e7%8e%b0%e4%be%8b%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;实现例程&#13;&#10;&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;#define START_TASK_STACK_SIZE &#9;128&#9;&#9;&#9;&#9;&#9;//栈大小&#10;#define START_TASK_PRIO &#9; &#9;1&#9;&#9;&#9;&#9;&#9;//优先级&#10;TaskHandle_t &#9;&#9;&#9;&#9;&#9;start_task_handle;&#9;//句柄&#10;void startTask(void* pvParamenters);&#10;&#10;#define TASK1_STACK_SIZE &#9;&#9;128&#10;#define TASK1_PRIO &#9; &#9;&#9;&#9;2&#10;TaskHandle_t &#9;&#9;&#9;&#9;&#9;task1_handle;&#10;void task1(void* pvParamenters);&#10;&#10;void freertos_demo(void)&#10;{&#10;&#9;xTaskCreate( (TaskFunction_t&#9; ) startTask,&#10;&#9; &#9;&#9;&#9; (char *&#9;&#9; ) &amp;#34;startTask&amp;#34;, &#10;&#9;&#9;&#9;&#9; (configSTACK_DEPTH_TYPE) START_TASK_STACK_SIZE,&#10;&#9;&#9;&#9;&#9; (void * &#9;&#9;&#9; ) NULL,&#10;&#9;&#9;&#9;&#9; (UBaseType_t ) START_TASK_PRIO,&#10;&#9;&#9;&#9;&#9; (TaskHandle_t * &#9; ) &amp;amp;start_task_handle );&#10;&#10;&#9;vTaskStartScheduler();&#10;}&#10;&#10;void startTask(void* pvParamenters)&#10;{&#10;&#9;taskENTER_CRITICAL();&#10;&#9;xTaskCreate( (TaskFunction_t &#9; ) task1,&#9;&#9;&#9;//任务函数&#10;&#9;&#9;&#9;&#9; (char *&#9;&#9; &#9; ) &amp;#34;task1&amp;#34;, &#9;&#9;&#9;//任务名&#10;&#9;&#9;&#9; &#9; (configSTACK_DEPTH_TYPE) TASK1_STACK_SIZE,&#9;//任务堆栈&#10;&#9;&#9;&#9;&#9; (void * &#9;&#9; &#9; ) NULL,&#9;&#9;&#9;&#9;//任务函数参数&#10;&#9;&#9;&#9;&#9; (UBaseType_t ) TASK1_PRIO,&#9;&#9;//优先级&#10;&#9;&#9;&#9;&#9; (TaskHandle_t * &#9; ) &amp;amp;task1_handle );&#9;//任务句柄（就是指向任务控制块头的指针）&#10;&#10;&#9;vTaskDelete(start_task_handle);&#10;&#9;taskEXIT_CRITICAL();&#10;}&#10;&#10;void task1(void* pvParamenters){&#10;&#9;while(1){&#10;&#9;}&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="2xtaskcreatestatic"&gt;&lt;a href="#2xtaskcreatestatic" class="header-anchor"&gt;&lt;/a&gt;2.xTaskCreateStatic&#13;&#10;&lt;/h2&gt;&lt;h3 id="参数和返回值-1"&gt;&lt;a href="#%e5%8f%82%e6%95%b0%e5%92%8c%e8%bf%94%e5%9b%9e%e5%80%bc-1" class="header-anchor"&gt;&lt;/a&gt;参数和返回值&#13;&#10;&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;TaskHandle_t xTaskCreateStatic&#10;(&#10;&#9;TaskFunction_t pxTaskCode, &#9;&#9;&#9;/* 指向任务函数的指针 */&#10;&#9;const char * const pcName, &#9;&#9;&#9;/* 任务函数名 */&#10;&#9;const uint32_t ulStackDepth, &#9;&#9;/* 任务堆栈大小注意字为单位 */&#10;&#9;void * const pvParameters, &#9;&#9;&#9;/* 传递的任务函数参数 */&#10;&#9;UBaseType_t uxPriority, &#9;&#9;&#9;/* 任务优先级 */&#10;&#9;StackType_t * const puxStackBuffer, /* 任务堆栈，一般为数组，由用户分配 */&#10;&#9;StaticTask_t * const pxTaskBuffer &#9;/* 任务控制块指针，由用户分配 */&#10;);&#10;&#10;返回:&#10;NULL 用户没有提供相应的内存，任务创建失败&#10;其他值 任务句柄，任务创建成功&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="实现例程-1"&gt;&lt;a href="#%e5%ae%9e%e7%8e%b0%e4%be%8b%e7%a8%8b-1" class="header-anchor"&gt;&lt;/a&gt;实现例程&#13;&#10;&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;#define START_TASK_STACK_SIZE &#9;128&#10;#define START_TASK_PRIO &#9; &#9;1&#10;TaskHandle_t &#9;&#9;&#9;&#9;&#9;start_task_handle;&#10;StackType_t&#9;&#9;&#9;&#9;&#9;&#9;start_task_stack[START_TASK_STACK_SIZE];&#10;StaticTask_t&#9;&#9;&#9;&#9;&#9;start_task_buffer;&#10;void startTask(void* pvParamenters);&#10;&#10;#define TASK1_STACK_SIZE &#9;&#9;128&#10;#define TASK1_PRIO &#9; &#9;&#9;&#9;2&#10;TaskHandle_t &#9;&#9;&#9;&#9;&#9;task1_handle;&#10;StackType_t&#9;&#9;&#9;&#9;&#9;&#9;task1_stack[TASK1_STACK_SIZE];&#10;StaticTask_t&#9;&#9;&#9;&#9;&#9;task1_buffer;&#10;void task1(void* pvParamenters);&#10;&#10;/*空闲任务配置*/&#10;StaticTask_t idle_task_tcb;&#10;StackType_t idle_task_stack[configMINIMAL_STACK_SIZE];&#10;&#10;/*软件定时器任务配置*/&#10;StaticTask_t timer_task_tcb;&#10;StackType_t timer_task_stack[configTIMER_TASK_STACK_DEPTH];&#10;&#10;/*空闲任务内存分配*/&#10;void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,&#10; StackType_t ** ppxIdleTaskStackBuffer,&#10; uint32_t * pulIdleTaskStackSize )&#10;{&#10;&#9;*ppxIdleTaskTCBBuffer = &amp;amp;idle_task_tcb;&#10;&#9;*ppxIdleTaskStackBuffer = idle_task_stack;&#10;&#9;*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;&#10;}&#10;&#10;/*软件定时器内存分配*/&#10;void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,&#10; StackType_t ** ppxTimerTaskStackBuffer,&#10; uint32_t * pulTimerTaskStackSize )&#10;{&#10;&#9;*ppxTimerTaskTCBBuffer = &amp;amp;timer_task_tcb;&#10;&#9;*ppxTimerTaskStackBuffer = timer_task_stack;&#10;&#9;*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;&#10;}&#10;&#10;void freertos_demo(void)&#10;{&#10;&#9;&#10;&#9;start_task_handle = xTaskCreateStatic( (TaskFunction_t) startTask,&#10;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; (char* &#9;&#9; ) &amp;#34;startTask&amp;#34;, &#10;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; (uint32_t&#9; ) START_TASK_STACK_SIZE,&#10;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; (void*&#9;&#9; ) NULL,&#10;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; (UBaseType_t&#9; ) START_TASK_PRIO,&#10;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; (StackType_t* ) start_task_stack,&#10;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; (StaticTask_t* ) &amp;amp;start_task_buffer );&#10;&#9;vTaskStartScheduler();&#10;}&#10;&#10;void startTask(void* pvParamenters)&#10;{&#10;&#9;taskENTER_CRITICAL();&#10;&#9;task1_handle = xTaskCreateStatic( (TaskFunction_t) task1,&#10;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; (char* &#9;&#9; ) &amp;#34;task1&amp;#34;, &#10;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; (uint32_t&#9; ) TASK1_STACK_SIZE,&#10;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; (void*&#9;&#9; ) NULL,&#10;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; (UBaseType_t&#9; ) TASK1_PRIO,&#10;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; (StackType_t* ) task1_stack,&#10;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; (StaticTask_t* ) &amp;amp;task1_buffer );&#10;&#9;vTaskDelete(start_task_handle);&#10;&#9;taskEXIT_CRITICAL();&#10;}&#10;&#10;void task1(void* pvParamenters)&#10;{&#10;&#9;while(1)&#10;&#9;{&#10;&#9;}&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="3vtaskdelete"&gt;&lt;a href="#3vtaskdelete" class="header-anchor"&gt;&lt;/a&gt;3.vTaskDelete&#13;&#10;&lt;/h2&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;void vTaskDelete(TaskHandle_t xTaskToDelete);//xTaskToDelete 待删除任务的任务句柄&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="任务挂起与恢复"&gt;&lt;a href="#%e4%bb%bb%e5%8a%a1%e6%8c%82%e8%b5%b7%e4%b8%8e%e6%81%a2%e5%a4%8d" class="header-anchor"&gt;&lt;/a&gt;任务挂起与恢复&#13;&#10;&lt;/h1&gt;&lt;h2 id="1vtasksuspend"&gt;&lt;a href="#1vtasksuspend" class="header-anchor"&gt;&lt;/a&gt;1.vTaskSuspend&#13;&#10;&lt;/h2&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;void vTaskSuspend( TaskHandle_t xTaskToSuspend );&#10;vTaskSuspend(任务句柄);&#10;vTaskSuspend(NULL);//挂起本任务&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="2vtaskresume"&gt;&lt;a href="#2vtaskresume" class="header-anchor"&gt;&lt;/a&gt;2.vTaskResume&#13;&#10;&lt;/h2&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;void vTaskResume( TaskHandle_t xTaskToResume );&#10;vTaskResume(任务句柄);&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="3xtaskresumefromisr"&gt;&lt;a href="#3xtaskresumefromisr" class="header-anchor"&gt;&lt;/a&gt;3.xTaskResumeFromISR&#13;&#10;&lt;/h2&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume );&#10;&#10;void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)&#10;{&#10;&#9;BaseType_t xYieldRequired;&#10;&#9;switch(GPIO_Pin)&#10;&#9;{&#10;&#9;case GPIO_PIN_0:&#10;&#9;&#9;delay_ms(20); /* 消抖 */&#10;&#9;&#9;flag2_suspend++;&#10;&#9;&#9;if(flag2_suspend%2==1) vTaskSuspend(task2_handle);&#10;&#9;&#9;else xYieldRequired = xTaskResumeFromISR(task2_handle);&#10;&#9;&#9;portYIELD_FROM_ISR( xYieldRequired );&#9;&#9;//任务恢复后需要进行任务切换&#10;&#9;&#9;&#10;&#9;&#9;break;&#10;&#9;}&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="列表与列表项"&gt;&lt;a href="#%e5%88%97%e8%a1%a8%e4%b8%8e%e5%88%97%e8%a1%a8%e9%a1%b9" class="header-anchor"&gt;&lt;/a&gt;列表与列表项&#13;&#10;&lt;/h1&gt;&lt;h2 id="1vlistinitialise"&gt;&lt;a href="#1vlistinitialise" class="header-anchor"&gt;&lt;/a&gt;1.vListInitialise&#13;&#10;&lt;/h2&gt;&lt;p&gt;初始化列表&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/*pxList 是待初始化列表*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;vListInitialise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;List_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;pxList&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;//初始化时，列表只有xListEnd，pxIndex指向xListEnd&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pxList&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;pxIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;ListItem_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;pxList&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;xListEnd&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="c1"&gt;//末尾列表项默认最大值，升序排序在最后&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;pxList&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;xListEnd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xItemValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;portMAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="c1"&gt;//初始化时，列表中只有xListEnd，因此上下都是本身&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;pxList&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;xListEnd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pxNext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;ListItem_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;pxList&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;xListEnd&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;pxList&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;xListEnd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pxPrevious&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;ListItem_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;pxList&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;xListEnd&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="c1"&gt;//初始化时列表项数量为0（不包含xListEnd）&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;pxList&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;uxNumberOfItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;UBaseType_t&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;0U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="c1"&gt;//初始化校验&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;listSET_LIST_INTEGRITY_CHECK_1_VALUE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;pxList&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;listSET_LIST_INTEGRITY_CHECK_2_VALUE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;pxList&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h2 id="2vlistinitialiseitem"&gt;&lt;a href="#2vlistinitialiseitem" class="header-anchor"&gt;&lt;/a&gt;2.vListInitialiseItem&#13;&#10;&lt;/h2&gt;&lt;p&gt;初始化列表项&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;span class="lnt"&gt;7&#10;&lt;/span&gt;&lt;span class="lnt"&gt;8&#10;&lt;/span&gt;&lt;span class="lnt"&gt;9&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/*pxItem是待初始化列表项*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;vListInitialiseItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;ListItem_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;pxItem&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="c1"&gt;//初始化时，列表项所在列表为空&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pxItem&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;pxContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;pxItem&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;pxItem&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h2 id="3vlistinsertend"&gt;&lt;a href="#3vlistinsertend" class="header-anchor"&gt;&lt;/a&gt;3.vListInsertEnd&#13;&#10;&lt;/h2&gt;&lt;p&gt;列表末尾插入列表项&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//目标列表，目标列表项&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;vListInsertEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;List_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;pxList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;ListItem_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;pxNewListItem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h2 id="4vlistinsert"&gt;&lt;a href="#4vlistinsert" class="header-anchor"&gt;&lt;/a&gt;4.vListInsert&#13;&#10;&lt;/h2&gt;&lt;p&gt;列表插入列表项&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//目标列表，目标列表项&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;vListInsert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;List_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;pxList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;ListItem_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;pxNewListItem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h2 id="5uxlistremove"&gt;&lt;a href="#5uxlistremove" class="header-anchor"&gt;&lt;/a&gt;5.uxListRemove&#13;&#10;&lt;/h2&gt;&lt;p&gt;列表移除列表项&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//pxItemToRemove 待移除的列表项&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;UBaseType_t&lt;/span&gt; &lt;span class="nf"&gt;uxListRemove&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;ListItem_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;pxItemToRemove&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//返回值，移除后所剩列表项&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h2 id="插入删除实验"&gt;&lt;a href="#%e6%8f%92%e5%85%a5%e5%88%a0%e9%99%a4%e5%ae%9e%e9%aa%8c" class="header-anchor"&gt;&lt;/a&gt;插入删除实验&#13;&#10;&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/*创建列表*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;List_t&lt;/span&gt; &#9; &lt;span class="n"&gt;TestList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ListItem_t&lt;/span&gt; &lt;span class="n"&gt;ListItem1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/*初始化列表，列表项*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;vListInitialise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;TestList&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;vListInitialiseItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ListItem1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ListItem1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xItemValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/*插入列表项*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;vListInsert&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;List_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;TestList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* 列表 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListItem_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ListItem1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="cm"&gt;/* 列表项 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h1 id="任务相关api"&gt;&lt;a href="#%e4%bb%bb%e5%8a%a1%e7%9b%b8%e5%85%b3api" class="header-anchor"&gt;&lt;/a&gt;任务相关API&#13;&#10;&lt;/h1&gt;&lt;p&gt;&lt;img alt="image-20250805151211347" class="gallery-image" data-flex-basis="376px" data-flex-grow="156" height="693" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos-api/images/image-20250805151211347.png" srcset="https://zeseanblog.top/p/freertos-api/images/image-20250805151211347_hu_e2de76a4f0a3fb67.png 800w, https://zeseanblog.top/p/freertos-api/images/image-20250805151211347.png 1086w" width="1086"&gt;&lt;/p&gt;&#10;&lt;h2 id="1uxtaskpriorityget"&gt;&lt;a href="#1uxtaskpriorityget" class="header-anchor"&gt;&lt;/a&gt;1.uxTaskPriorityGet&#13;&#10;&lt;/h2&gt;&lt;p&gt;获取任务优先级&lt;/p&gt;&#10;&lt;p&gt;打开宏INCLUDE_uxTaskPriorityGet&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;//xTask要查找的任务句柄， NULL 代表任务自身&#10;UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask )&#10;//返回无符号整数，为任务优先级&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="2vtaskpriorityset"&gt;&lt;a href="#2vtaskpriorityset" class="header-anchor"&gt;&lt;/a&gt;2.vTaskPrioritySet&#13;&#10;&lt;/h2&gt;&lt;p&gt;改变任务优先级&lt;/p&gt;&#10;&lt;p&gt;宏 INCLUDE_vTaskPrioritySet 为 1&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;//xTask任务句柄 uxNewPriority优先级&#10;void vTaskPrioritySet( TaskHandle_t xTask , UBaseType_t uxNewPriority )&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="3uxtaskgetnumberoftasks"&gt;&lt;a href="#3uxtaskgetnumberoftasks" class="header-anchor"&gt;&lt;/a&gt;3.uxTaskGetNumberOfTasks&#13;&#10;&lt;/h2&gt;&lt;p&gt;此函数用于获取系统中任务的任务数量&lt;/p&gt;&#10;&lt;p&gt;UBaseType_t uxTaskGetNumberOfTasks( void )&lt;/p&gt;&#10;&lt;h2 id="4uxtaskgetsystemstate"&gt;&lt;a href="#4uxtaskgetsystemstate" class="header-anchor"&gt;&lt;/a&gt;4.uxTaskGetSystemState&#13;&#10;&lt;/h2&gt;&lt;p&gt;获取系统中所有任务的任务状态信息&lt;/p&gt;&#10;&lt;h1 id="消息队列api"&gt;&lt;a href="#%e6%b6%88%e6%81%af%e9%98%9f%e5%88%97api" class="header-anchor"&gt;&lt;/a&gt;消息队列API&#13;&#10;&lt;/h1&gt;&lt;p&gt;例子&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;span class="lnt"&gt;29&#10;&lt;/span&gt;&lt;span class="lnt"&gt;30&#10;&lt;/span&gt;&lt;span class="lnt"&gt;31&#10;&lt;/span&gt;&lt;span class="lnt"&gt;32&#10;&lt;/span&gt;&lt;span class="lnt"&gt;33&#10;&lt;/span&gt;&lt;span class="lnt"&gt;34&#10;&lt;/span&gt;&lt;span class="lnt"&gt;35&#10;&lt;/span&gt;&lt;span class="lnt"&gt;36&#10;&lt;/span&gt;&lt;span class="lnt"&gt;37&#10;&lt;/span&gt;&lt;span class="lnt"&gt;38&#10;&lt;/span&gt;&lt;span class="lnt"&gt;39&#10;&lt;/span&gt;&lt;span class="lnt"&gt;40&#10;&lt;/span&gt;&lt;span class="lnt"&gt;41&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;QueueHandle_t&lt;/span&gt; &lt;span class="n"&gt;key_quque&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/*小数据句柄*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;QueueHandle_t&lt;/span&gt; &lt;span class="n"&gt;big_date_queue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="cm"&gt;/*大数据句柄*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;buff&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;This is a big data queue&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;key_quque&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;xQueueCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key_quque&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;key_queue队列创建成功&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;key_queue队列创建失败&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;big_date_queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;xQueueCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key_quque&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;big_date_queue队列创建成功&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;big_date_queue队列创建失败&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/*入队，发送*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;task1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;key_val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;key_scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key_val&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;KEY0_PRES&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;key_val&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;KEY1_PRES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;xQueueSend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key_quque&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;key_val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;portMAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="n"&gt;pdTRUE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;key_queue队列发送失败&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/*出队，读取*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;task2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;xQueueReceive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;big_date_queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;portMAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="n"&gt;pdTRUE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;big_date_queue队列接收失败&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;big_date_queue读取队列成功,数据%s&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;</description></item><item><title>FreeRTOS 学习笔记：从入门到内核机制</title><link>https://zeseanblog.top/p/freertos/</link><pubDate>Sat, 12 Jul 2025 10:00:00 +0800</pubDate><guid>https://zeseanblog.top/p/freertos/</guid><description>&lt;h1 id="序freertos函数名前缀"&gt;&lt;a href="#%e5%ba%8ffreertos%e5%87%bd%e6%95%b0%e5%90%8d%e5%89%8d%e7%bc%80" class="header-anchor"&gt;&lt;/a&gt;序、FreeRTOS函数名前缀&#13;&#10;&lt;/h1&gt;&lt;img src="images/image-20250804213757624.png" alt="image-20250804213757624" style="zoom:67%;" /&gt;&#10;&lt;h1 id="一单片机程序设计模式"&gt;&lt;a href="#%e4%b8%80%e5%8d%95%e7%89%87%e6%9c%ba%e7%a8%8b%e5%ba%8f%e8%ae%be%e8%ae%a1%e6%a8%a1%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;一、单片机程序设计模式&#13;&#10;&lt;/h1&gt;&lt;p&gt;&lt;strong&gt;1.轮询模式&lt;/strong&gt;&lt;/p&gt;&#10; &lt;img src="images/image-20250802143036241.png" alt="image-20250802143036241" style="zoom: 50%;" /&gt;&#10;&lt;p&gt;&lt;strong&gt;2.前后台&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;后台：执行在main&lt;/p&gt;&#10;&lt;p&gt;前台：执行在中断，但不能执行太多&lt;/p&gt;&#10;&lt;p&gt;可以在中断中用标志位，将任务放在主函数&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;3.定时器驱动&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;函数执行不能太长&lt;/p&gt;&#10; &lt;img src="images/image-20250802143221867.png" alt="image-20250802143221867" style="zoom:50%;" /&gt;&#10;&lt;p&gt;&lt;strong&gt;4.状态机&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;基于轮询，将单个任务分解成多个任务，减少每个任务需要的时间，降低造成的相互影响&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;5.多任务系统&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;交替执行，基于时间片和任务优先级调度&lt;/p&gt;&#10;&lt;p&gt;对于重要的任务可以提高优先级，在高优先级处于延时中执行低优先级任务&lt;/p&gt;&#10; &lt;img src="images/image-20250802144931000.png" alt="image-20250802144931000" style="zoom:50%;" /&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802143633146" class="gallery-image" data-flex-basis="1053px" data-flex-grow="439" height="202" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250802143633146.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250802143633146_hu_57a937242619cb17.png 800w, https://zeseanblog.top/p/freertos/images/image-20250802143633146.png 887w" width="887"&gt;&lt;/p&gt;&#10;&lt;p&gt;伪代码实现&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;void main()&#10;{&#10;// 创建 2 个任务&#10;create_task(task1);&#10;create_task(task2);&#10;// 启动调度器&#10;start_scheduler();&#10;}&#10;task1()&#10;{&#10;while(1)&#10;{&#10;&#9;do_task1();&#10;}&#10;}&#10;task2()&#10;{&#10;while(1)&#10;{&#10;&#9;do_task2();&#10;}&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="二freertos基础知识"&gt;&lt;a href="#%e4%ba%8cfreertos%e5%9f%ba%e7%a1%80%e7%9f%a5%e8%af%86" class="header-anchor"&gt;&lt;/a&gt;二、FreeRTOS基础知识&#13;&#10;&lt;/h1&gt;&lt;h2 id="1任务调度简介熟悉"&gt;&lt;a href="#1%e4%bb%bb%e5%8a%a1%e8%b0%83%e5%ba%a6%e7%ae%80%e4%bb%8b%e7%86%9f%e6%82%89" class="header-anchor"&gt;&lt;/a&gt;1.任务调度简介(熟悉)&#13;&#10;&lt;/h2&gt;&lt;h5 id="抢占式每个任务有优先级优先级高抢占优先级低"&gt;&lt;a href="#%e6%8a%a2%e5%8d%a0%e5%bc%8f%e6%af%8f%e4%b8%aa%e4%bb%bb%e5%8a%a1%e6%9c%89%e4%bc%98%e5%85%88%e7%ba%a7%e4%bc%98%e5%85%88%e7%ba%a7%e9%ab%98%e6%8a%a2%e5%8d%a0%e4%bc%98%e5%85%88%e7%ba%a7%e4%bd%8e" class="header-anchor"&gt;&lt;/a&gt;抢占式：每个任务有优先级，优先级高抢占优先级低&#13;&#10;&lt;/h5&gt;&lt;p&gt;FreeRTOS数值越大，优先级越高&lt;/p&gt;&#10;&lt;p&gt;Task1 、 Task2 、 Task3 的优先级分别为 1 、 2 、 3 ；在FreeRTOS 中任务设置的数值越大，优先级越高，所以 TASK3 的优先级最高&lt;/p&gt;&#10; &lt;img src="images/image-20250802145631062.png" alt="image-20250802145631062" style="zoom:67%;" /&gt;&#10;&lt;h5 id="时间片同优先级每个时钟节拍切换任务"&gt;&lt;a href="#%e6%97%b6%e9%97%b4%e7%89%87%e5%90%8c%e4%bc%98%e5%85%88%e7%ba%a7%e6%af%8f%e4%b8%aa%e6%97%b6%e9%92%9f%e8%8a%82%e6%8b%8d%e5%88%87%e6%8d%a2%e4%bb%bb%e5%8a%a1" class="header-anchor"&gt;&lt;/a&gt;时间片：同优先级，每个时钟节拍切换任务&#13;&#10;&lt;/h5&gt;&lt;p&gt;同等优先级任务轮流地享有相同的 CPU 时间 ( 可设置 ) ， 叫时间片，在 FreeRTOS 中，一个时间片就等于 SysTick 中断周期&lt;/p&gt;&#10;&lt;p&gt;没用完的时间片抛弃&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802145838370" class="gallery-image" data-flex-basis="595px" data-flex-grow="248" height="206" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250802145838370.png" width="511"&gt;&lt;/p&gt;&#10;&lt;h5 id="协程式当前执行任务一直执行高优先级不抢占低优先级不常用"&gt;&lt;a href="#%e5%8d%8f%e7%a8%8b%e5%bc%8f%e5%bd%93%e5%89%8d%e6%89%a7%e8%a1%8c%e4%bb%bb%e5%8a%a1%e4%b8%80%e7%9b%b4%e6%89%a7%e8%a1%8c%e9%ab%98%e4%bc%98%e5%85%88%e7%ba%a7%e4%b8%8d%e6%8a%a2%e5%8d%a0%e4%bd%8e%e4%bc%98%e5%85%88%e7%ba%a7%e4%b8%8d%e5%b8%b8%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;协程式：当前执行任务一直执行，高优先级不抢占低优先级（不常用）&#13;&#10;&lt;/h5&gt;&lt;h2 id="2任务状态熟悉"&gt;&lt;a href="#2%e4%bb%bb%e5%8a%a1%e7%8a%b6%e6%80%81%e7%86%9f%e6%82%89" class="header-anchor"&gt;&lt;/a&gt;2.任务状态(熟悉)&#13;&#10;&lt;/h2&gt;&lt;p&gt;1.运行态&lt;/p&gt;&#10;&lt;p&gt;正在执行，同一时间仅一个&lt;/p&gt;&#10;&lt;p&gt;2.就绪态&lt;/p&gt;&#10;&lt;p&gt;能够被执行，但还未执行&lt;/p&gt;&#10;&lt;p&gt;3.阻塞态&lt;/p&gt;&#10;&lt;p&gt;任务在延时或等待外部事件发生&lt;/p&gt;&#10;&lt;p&gt;4.挂起态&lt;/p&gt;&#10;&lt;p&gt;类似暂停，不参与调度，需要解挂才能进就绪vTaskResume()；&lt;/p&gt;&#10; &lt;img src="images/image-20250802150415156.png" alt="image-20250802150415156" style="zoom: 50%;" /&gt;&#10;&lt;p&gt;注：只有就绪态可以转运行态，挂起要解挂，阻塞要变成就绪&lt;/p&gt;&#10;&lt;h3 id="任务状态列表"&gt;&lt;a href="#%e4%bb%bb%e5%8a%a1%e7%8a%b6%e6%80%81%e5%88%97%e8%a1%a8" class="header-anchor"&gt;&lt;/a&gt;任务状态列表&#13;&#10;&lt;/h3&gt;&lt;p&gt;1.就绪列表：pxReadyTasksLists[x]，其中 x 代表任务优先级数值。0~31，31最高&lt;/p&gt;&#10;&lt;p&gt;32位变量，当某个位置一说明对应优先级有任务存在&lt;/p&gt;&#10; &lt;img src="images/image-20250802151219493.png" alt="image-20250802151219493" style="zoom:60%;" /&gt;&#10;&lt;p&gt;2.阻塞列表：pxDelayedTaskList&lt;/p&gt;&#10;&lt;p&gt;3.挂起列表：xSuspendedTaskList&lt;/p&gt;&#10;&lt;p&gt;调度器取就绪列表最高优先级任务来执行&lt;/p&gt;&#10;&lt;p&gt;相同优先级的任务会连接在同一个就绪列表&lt;/p&gt;&#10;&lt;h1 id="三freertos移植"&gt;&lt;a href="#%e4%b8%89freertos%e7%a7%bb%e6%a4%8d" class="header-anchor"&gt;&lt;/a&gt;三、FreeRTOS移植&#13;&#10;&lt;/h1&gt;&lt;p&gt;源码：https://www.freertos.org/&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802152204321" class="gallery-image" data-flex-basis="195px" data-flex-grow="81" height="365" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250802152204321.png" width="297"&gt;&lt;/p&gt;&#10;&lt;p&gt;FreeRTOS：内核有用&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802152338698" class="gallery-image" data-flex-basis="524px" data-flex-grow="218" height="178" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250802152338698.png" width="389"&gt;&lt;/p&gt;&#10;&lt;p&gt;Demo和Source&lt;/p&gt;&#10;&lt;h4 id="source文件夹"&gt;&lt;a href="#source%e6%96%87%e4%bb%b6%e5%a4%b9" class="header-anchor"&gt;&lt;/a&gt;Source文件夹&#13;&#10;&lt;/h4&gt; &lt;img src="images/image-20250802152630841.png" alt="image-20250802152630841" style="zoom:50%;" /&gt;&#10;&lt;p&gt;include,portable,list,queue,task必须&lt;/p&gt;&#10;&lt;h4 id="portable文件夹"&gt;&lt;a href="#portable%e6%96%87%e4%bb%b6%e5%a4%b9" class="header-anchor"&gt;&lt;/a&gt;portable文件夹&#13;&#10;&lt;/h4&gt;&lt;p&gt;与硬件连接桥梁&lt;/p&gt;&#10;&lt;p&gt;由于使用MDK开发，只要&lt;/p&gt;&#10; &lt;img src="images/image-20250802152913833.png" alt="image-20250802152913833" style="zoom:67%;" /&gt;&#10;&lt;h2 id="手把手移植"&gt;&lt;a href="#%e6%89%8b%e6%8a%8a%e6%89%8b%e7%a7%bb%e6%a4%8d" class="header-anchor"&gt;&lt;/a&gt;手把手移植&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;img alt="image-20250802153157922" class="gallery-image" data-flex-basis="537px" data-flex-grow="223" height="326" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250802153157922.png" width="730"&gt;&lt;/p&gt;&#10;&lt;p&gt;1.基础工程的Middlewares文件夹中新建一个FreeRTOS子文件夹&lt;/p&gt;&#10; &lt;img src="images/image-20250802153620409.png" alt="image-20250802153620409" style="zoom:50%;" /&gt;&#10;&lt;p&gt;将FreeRTOS内核源码的Source文件夹下的所有文件添加到工程的FreeRTOS文件夹中&lt;/p&gt;&#10; &lt;img src="images/image-20250802153705681.png" alt="image-20250802153705681" style="zoom:67%;" /&gt;&#10;&lt;p&gt;CORE中是源码&lt;/p&gt;&#10;&lt;p&gt;heap_4是内存管理算法4&lt;/p&gt;&#10;&lt;p&gt;port是软硬件连接桥梁&lt;/p&gt;&#10; &lt;img src="images/image-20250802153948337.png" alt="image-20250802153948337" style="zoom:67%;" /&gt;&#10;&lt;p&gt;port根据芯片选择&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802154239833" class="gallery-image" data-flex-basis="1065px" data-flex-grow="443" height="207" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250802154239833.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250802154239833_hu_c51e4769a0691ebc.png 800w, https://zeseanblog.top/p/freertos/images/image-20250802154239833.png 919w" width="919"&gt;&lt;/p&gt;&#10;&lt;p&gt;头文件哪有就加什么路径&lt;/p&gt;&#10;&lt;p&gt;2.添加 FreeRTOSConfig.h 文件&lt;/p&gt;&#10;&lt;p&gt;这个可裁剪，用不到的功能可以裁剪，Demo里有，或者例程&lt;/p&gt;&#10;&lt;p&gt;3.修改SYSTEM&lt;/p&gt;&#10;&lt;p&gt;详阅《FreeRTOS开发指南》&lt;/p&gt;&#10;&lt;h2 id="系统配置详解"&gt;&lt;a href="#%e7%b3%bb%e7%bb%9f%e9%85%8d%e7%bd%ae%e8%af%a6%e8%a7%a3" class="header-anchor"&gt;&lt;/a&gt;系统配置详解&#13;&#10;&lt;/h2&gt;&lt;p&gt;FreeRTOSConfig.h 配置文件作用：对 FreeRTOS 的功能进行配置和裁剪，以及 API 函数的使能&lt;/p&gt;&#10; &lt;img src="images/image-20250802163812620.png" alt="image-20250802163812620" style="zoom:67%;" /&gt;&#10;&lt;p&gt;详看注释&lt;/p&gt;&#10;&lt;h1 id="四freertos任务创建和删除"&gt;&lt;a href="#%e5%9b%9bfreertos%e4%bb%bb%e5%8a%a1%e5%88%9b%e5%bb%ba%e5%92%8c%e5%88%a0%e9%99%a4" class="header-anchor"&gt;&lt;/a&gt;四、FreeRTOS任务创建和删除&#13;&#10;&lt;/h1&gt;&lt;h2 id="1任务创建和删除的-api-函数"&gt;&lt;a href="#1%e4%bb%bb%e5%8a%a1%e5%88%9b%e5%bb%ba%e5%92%8c%e5%88%a0%e9%99%a4%e7%9a%84-api-%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;1.任务创建和删除的 API 函数&#13;&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;API&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;描述&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;xTaskCreate()&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;动态创建&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;xTaskCreateStatic()&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;静态创建&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;vTaskDelete()&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;删除&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;动态创建：任务控制块以及任务栈空间所需内存，有FreeRTOS自动分配&lt;/p&gt;&#10;&lt;p&gt;静态创建：用户分配&lt;/p&gt;&#10;&lt;h3 id="动态创建"&gt;&lt;a href="#%e5%8a%a8%e6%80%81%e5%88%9b%e5%bb%ba" class="header-anchor"&gt;&lt;/a&gt;动态创建&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img alt="image-20250802165520234" class="gallery-image" data-flex-basis="799px" data-flex-grow="333" height="563" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250802165520234.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250802165520234_hu_b794bc9ec6868604.png 800w, https://zeseanblog.top/p/freertos/images/image-20250802165520234_hu_1b5b49cbbc61b1d0.png 1600w, https://zeseanblog.top/p/freertos/images/image-20250802165520234.png 1875w" width="1875"&gt;&lt;/p&gt;&#10;&lt;p&gt;返回pdPass：创建成功&lt;/p&gt;&#10;&lt;p&gt;返回errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY：创建失败&lt;/p&gt;&#10;&lt;h4 id="流程"&gt;&lt;a href="#%e6%b5%81%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;流程：&#13;&#10;&lt;/h4&gt;&lt;p&gt;1、将宏 configSUPPORT_DYNAMIC_ALLOCATION 配置为 1&lt;/p&gt;&#10;&lt;p&gt;2 、定义函数入口参数&lt;/p&gt;&#10;&lt;p&gt;3 、编写任务函数&lt;/p&gt;&#10;&lt;p&gt;创建后进入就绪态，然后启动任务调度器运行&lt;/p&gt;&#10;&lt;h4 id="内部实现"&gt;&lt;a href="#%e5%86%85%e9%83%a8%e5%ae%9e%e7%8e%b0" class="header-anchor"&gt;&lt;/a&gt;内部实现：&#13;&#10;&lt;/h4&gt; &lt;img src="images/image-20250802170201003.png" alt="image-20250802170201003" style="zoom:67%;" /&gt;&#10;&lt;p&gt;任务控制块就是任务的身份证，保留任务的信息&lt;/p&gt;&#10;&lt;img src="images/image-20250802170649880.png" alt="image-20250802170649880" style="zoom:50%;" /&gt;&#10;&lt;h3 id="静态创建"&gt;&lt;a href="#%e9%9d%99%e6%80%81%e5%88%9b%e5%bb%ba" class="header-anchor"&gt;&lt;/a&gt;静态创建&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img alt="image-20250802170921182" class="gallery-image" data-flex-basis="647px" data-flex-grow="269" height="362" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250802170921182.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250802170921182_hu_40abea609d88a3e.png 800w, https://zeseanblog.top/p/freertos/images/image-20250802170921182.png 976w" width="976"&gt;&lt;/p&gt;&#10;&lt;p&gt;返回NULL：创建成功&lt;/p&gt;&#10;&lt;p&gt;其他值：任务句柄，任务创建成功&lt;/p&gt;&#10;&lt;h4 id="流程-1"&gt;&lt;a href="#%e6%b5%81%e7%a8%8b-1" class="header-anchor"&gt;&lt;/a&gt;流程：&#13;&#10;&lt;/h4&gt;&lt;p&gt;1 、需将宏 configSUPPORT_STATIC_ALLOCATION 配置为 1&lt;/p&gt;&#10;&lt;p&gt;2 、定义空闲任务 &amp;amp; 定时器任务的任务堆栈及TCB&lt;/p&gt;&#10;&lt;p&gt;3 、实现两个接口函数&lt;/p&gt;&#10;&lt;p&gt;vApplicationGetIdleTaskMemory( )必须&lt;/p&gt;&#10;&lt;p&gt;vApplicationGetTimerTaskMemory ()可选&lt;/p&gt;&#10;&lt;p&gt;4 、定义函数入口参数&lt;/p&gt;&#10;&lt;p&gt;5 、编写任务函数&lt;/p&gt;&#10;&lt;h3 id="任务删除"&gt;&lt;a href="#%e4%bb%bb%e5%8a%a1%e5%88%a0%e9%99%a4" class="header-anchor"&gt;&lt;/a&gt;任务删除&#13;&#10;&lt;/h3&gt;&lt;p&gt;xTaskDelete(TaskHandle_t xTaskToDelete);&lt;/p&gt;&#10;&lt;p&gt;实际是通过传入的任务句柄获取任务控制块，从四个任务列表中移除&lt;/p&gt;&#10;&lt;p&gt;注意：1.当传入NULL，删除任务自身&lt;/p&gt;&#10;&lt;p&gt;​&#9;&#9;&#9;2.空闲任务会释放被删除任务中有系统分配的内存，但是用户在任务&#9;&#9;&#9;&#9;删除前申请的内存，需要手动释放，否则内存泄漏&lt;/p&gt;&#10;&lt;h1 id="五freertos任务挂起与恢复"&gt;&lt;a href="#%e4%ba%94freertos%e4%bb%bb%e5%8a%a1%e6%8c%82%e8%b5%b7%e4%b8%8e%e6%81%a2%e5%a4%8d" class="header-anchor"&gt;&lt;/a&gt;五、FreeRTOS任务挂起与恢复&#13;&#10;&lt;/h1&gt;&lt;h2 id="1任务挂起与恢复的api函数"&gt;&lt;a href="#1%e4%bb%bb%e5%8a%a1%e6%8c%82%e8%b5%b7%e4%b8%8e%e6%81%a2%e5%a4%8d%e7%9a%84api%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;1.任务挂起与恢复的API函数&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;img alt="image-20250802212436605" class="gallery-image" data-flex-basis="811px" data-flex-grow="338" height="263" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250802212436605.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250802212436605_hu_8171aa08c628cf52.png 800w, https://zeseanblog.top/p/freertos/images/image-20250802212436605.png 889w" width="889"&gt;&lt;/p&gt;&#10;&lt;p&gt;挂起：暂停&lt;/p&gt;&#10;&lt;p&gt;恢复：继续&lt;/p&gt;&#10;&lt;p&gt;FromISR：从中断中恢复&lt;/p&gt;&#10;&lt;h3 id="任务挂起"&gt;&lt;a href="#%e4%bb%bb%e5%8a%a1%e6%8c%82%e8%b5%b7" class="header-anchor"&gt;&lt;/a&gt;任务挂起&#13;&#10;&lt;/h3&gt;&lt;p&gt;将宏 INCLUDE_vTaskSuspend 配置为 1&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802212603585" class="gallery-image" data-flex-basis="996px" data-flex-grow="415" height="277" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250802212603585.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250802212603585_hu_26b7ca17e36e60be.png 800w, https://zeseanblog.top/p/freertos/images/image-20250802212603585.png 1150w" width="1150"&gt;&lt;/p&gt;&#10;&lt;h3 id="任务恢复"&gt;&lt;a href="#%e4%bb%bb%e5%8a%a1%e6%81%a2%e5%a4%8d" class="header-anchor"&gt;&lt;/a&gt;任务恢复&#13;&#10;&lt;/h3&gt;&lt;p&gt;将宏 INCLUDE_vTaskSuspend 必须定义为 1&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802212618152" class="gallery-image" data-flex-basis="1036px" data-flex-grow="431" height="266" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250802212618152.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250802212618152_hu_5d019b8026ccc3bb.png 800w, https://zeseanblog.top/p/freertos/images/image-20250802212618152.png 1149w" width="1149"&gt;&lt;/p&gt;&#10;&lt;h3 id="中断中恢复"&gt;&lt;a href="#%e4%b8%ad%e6%96%ad%e4%b8%ad%e6%81%a2%e5%a4%8d" class="header-anchor"&gt;&lt;/a&gt;中断中恢复&#13;&#10;&lt;/h3&gt;&lt;p&gt;INCLUDE_vTaskSuspend 和 INCLUDE_xTaskResumeFromISR 必须定义为 1&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250802212911425" class="gallery-image" data-flex-basis="830px" data-flex-grow="346" height="405" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250802212911425.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250802212911425_hu_7f879aa76b6f8642.png 800w, https://zeseanblog.top/p/freertos/images/image-20250802212911425.png 1402w" width="1402"&gt;&lt;/p&gt;&#10;&lt;p&gt;注意：中断服务程序中要调用FreeRTOS的API，中断优先级不能高于FreeRTOS所管理的优先级&lt;/p&gt;&#10;&lt;p&gt;因为FreeRTOS管理的5&lt;del&gt;15的优先级，所有中断优先级不能在0&lt;/del&gt;4，因为中断优先级数字越低优先级越高&lt;/p&gt;&#10;&lt;h1 id="六freertos中断管理"&gt;&lt;a href="#%e5%85%adfreertos%e4%b8%ad%e6%96%ad%e7%ae%a1%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;六、FreeRTOS中断管理&#13;&#10;&lt;/h1&gt;&lt;h2 id="1中断"&gt;&lt;a href="#1%e4%b8%ad%e6%96%ad" class="header-anchor"&gt;&lt;/a&gt;1.中断&#13;&#10;&lt;/h2&gt;&lt;p&gt;中断请求，响应中断（转中断处理ISR），退出中断&lt;/p&gt;&#10;&lt;h2 id="2中断优先级"&gt;&lt;a href="#2%e4%b8%ad%e6%96%ad%e4%bc%98%e5%85%88%e7%ba%a7" class="header-anchor"&gt;&lt;/a&gt;2.中断优先级&#13;&#10;&lt;/h2&gt;&lt;p&gt;8位宽寄存器来配置中断优先级&lt;/p&gt;&#10;&lt;p&gt;ARM Cortex-M支持2^8=256个中断优先级&lt;/p&gt;&#10;&lt;p&gt;STM32只用高四位[7:4]，所以STM32提供2^4=16个中断优先级&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250804141722815" class="gallery-image" data-flex-basis="1116px" data-flex-grow="465" height="133" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250804141722815.png" width="619"&gt;&lt;/p&gt;&#10;&lt;p&gt;STM32中断分为抢占优先级和子优先级&lt;/p&gt;&#10;&lt;p&gt;抢占优先级： 抢占优先级高的中断可以打断正在执行但抢占优先级低的中断&lt;/p&gt;&#10;&lt;p&gt;子优先级：当同时发生具有相同抢占优先级的两个中断时，子优先级数值小的优先执行&lt;/p&gt;&#10;&lt;p&gt;（中断优先级数字越小越优先）&lt;/p&gt;&#10;&lt;h3 id="分配方式"&gt;&lt;a href="#%e5%88%86%e9%85%8d%e6%96%b9%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;分配方式&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img alt="image-20250804141852953" class="gallery-image" data-flex-basis="598px" data-flex-grow="249" height="534" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250804141852953.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250804141852953_hu_86ca46c2a8d03dc.png 800w, https://zeseanblog.top/p/freertos/images/image-20250804141852953.png 1331w" width="1331"&gt;&lt;/p&gt;&#10;&lt;p&gt;如：HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4 ）设置优先级分组4&lt;/p&gt;&#10;&lt;h3 id="注意"&gt;&lt;a href="#%e6%b3%a8%e6%84%8f" class="header-anchor"&gt;&lt;/a&gt;注意&#13;&#10;&lt;/h3&gt;&lt;p&gt;1 、低于 configMAX_SYSCALL_INTERRUPT_PRIORITY 优先级的中断里才允许调FreeRTOS 的 API 函数&lt;/p&gt;&#10;&lt;p&gt;2 、建议将所有优先级位指定为抢占优先级位，方便 FreeRTOS 管理&lt;/p&gt;&#10;&lt;p&gt;HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4 ）&lt;/p&gt;&#10;&lt;p&gt;3 、中断优先级数值越小越优先，任务优先级数值越大越优先&lt;/p&gt;&#10;&lt;h1 id="七临界段代码保护-任务调度器挂起和恢复"&gt;&lt;a href="#%e4%b8%83%e4%b8%b4%e7%95%8c%e6%ae%b5%e4%bb%a3%e7%a0%81%e4%bf%9d%e6%8a%a4-%e4%bb%bb%e5%8a%a1%e8%b0%83%e5%ba%a6%e5%99%a8%e6%8c%82%e8%b5%b7%e5%92%8c%e6%81%a2%e5%a4%8d" class="header-anchor"&gt;&lt;/a&gt;七、临界段代码保护 任务调度器挂起和恢复&#13;&#10;&lt;/h1&gt;&lt;h2 id="1临界段代码保护"&gt;&lt;a href="#1%e4%b8%b4%e7%95%8c%e6%ae%b5%e4%bb%a3%e7%a0%81%e4%bf%9d%e6%8a%a4" class="header-anchor"&gt;&lt;/a&gt;1.临界段代码保护&#13;&#10;&lt;/h2&gt;&lt;p&gt;临界段：指那些必须完整运行，不能被（中断、任务调度PendSV）打断的代码段&lt;/p&gt;&#10;&lt;p&gt;需要保护：&lt;/p&gt;&#10;&lt;p&gt;1.严格时序初始化的外设&lt;/p&gt;&#10;&lt;p&gt;2.系统自身需求&lt;/p&gt;&#10;&lt;p&gt;3.用户需求&lt;/p&gt;&#10;&lt;h2 id="2临界段代码保护函数"&gt;&lt;a href="#2%e4%b8%b4%e7%95%8c%e6%ae%b5%e4%bb%a3%e7%a0%81%e4%bf%9d%e6%8a%a4%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;2.临界段代码保护函数&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;img alt="image-20250804145449284" class="gallery-image" data-flex-basis="892px" data-flex-grow="371" height="163" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250804145449284.png" width="606"&gt;&lt;/p&gt;&#10;&lt;p&gt;临界区屏蔽中断，系统任务调度和ISR都靠中断，因此临界区不能长&lt;/p&gt;&#10;&lt;h3 id="3任务调度器挂起和恢复"&gt;&lt;a href="#3%e4%bb%bb%e5%8a%a1%e8%b0%83%e5%ba%a6%e5%99%a8%e6%8c%82%e8%b5%b7%e5%92%8c%e6%81%a2%e5%a4%8d" class="header-anchor"&gt;&lt;/a&gt;3.任务调度器挂起和恢复&#13;&#10;&lt;/h3&gt;&lt;p&gt;挂起任务调度器，就是不许任务切换，不需要关闭中断&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250804151438414" class="gallery-image" data-flex-basis="1387px" data-flex-grow="578" height="106" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250804151438414.png" width="613"&gt;&lt;/p&gt;&#10;&lt;p&gt;1.挂起任务调度器未关闭中断&lt;/p&gt;&#10;&lt;p&gt;2.防止任务间资源争夺，中断照样响应&lt;/p&gt;&#10;&lt;h1 id="八freertos列表和列表项"&gt;&lt;a href="#%e5%85%abfreertos%e5%88%97%e8%a1%a8%e5%92%8c%e5%88%97%e8%a1%a8%e9%a1%b9" class="header-anchor"&gt;&lt;/a&gt;八、FreeRTOS列表和列表项&#13;&#10;&lt;/h1&gt;&lt;h2 id="1列表和列表项"&gt;&lt;a href="#1%e5%88%97%e8%a1%a8%e5%92%8c%e5%88%97%e8%a1%a8%e9%a1%b9" class="header-anchor"&gt;&lt;/a&gt;1.列表和列表项&#13;&#10;&lt;/h2&gt;&lt;p&gt;列表是FreeRTOS的一个数据结构，类似链表，用于跟踪FreeRTOS的任务&lt;/p&gt;&#10;&lt;p&gt;列表项是在列表中的项目&lt;/p&gt;&#10;&lt;p&gt;FreeRTOS中列表是&lt;strong&gt;双向环形链表&lt;/strong&gt;&lt;/p&gt;&#10; &lt;img src="images/image-20250804155007010.png" alt="image-20250804155007010" style="zoom:67%;" /&gt;&#10;&lt;p&gt;非连续地址，人为连接到一起，数目后期添加，随时可以改变&lt;/p&gt;&#10;&lt;h3 id="列表相关结构体"&gt;&lt;a href="#%e5%88%97%e8%a1%a8%e7%9b%b8%e5%85%b3%e7%bb%93%e6%9e%84%e4%bd%93" class="header-anchor"&gt;&lt;/a&gt;列表相关结构体&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img alt="image-20250804155613541" class="gallery-image" data-flex-basis="729px" data-flex-grow="304" height="347" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250804155613541.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250804155613541_hu_e4faf885689f2471.png 800w, https://zeseanblog.top/p/freertos/images/image-20250804155613541.png 1055w" width="1055"&gt;&lt;/p&gt;&#10;&lt;p&gt;1.校验值：用于调试，默认不开启&lt;/p&gt;&#10;&lt;p&gt;2.uxNumberOfltems，记录列表项的个数&lt;/p&gt;&#10;&lt;p&gt;3.pxIndex：指向列表中的某个列表项，用于遍历列表项&lt;/p&gt;&#10;&lt;p&gt;4.xListEnd是迷你列表项，排在末尾&lt;/p&gt;&#10;&lt;img src="images/image-20250804160002038.png" alt="image-20250804160002038" style="zoom:50%;" /&gt;&#10;&lt;h3 id="列表项结构体"&gt;&lt;a href="#%e5%88%97%e8%a1%a8%e9%a1%b9%e7%bb%93%e6%9e%84%e4%bd%93" class="header-anchor"&gt;&lt;/a&gt;列表项结构体&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img alt="image-20250804160223478" class="gallery-image" data-flex-basis="800px" data-flex-grow="333" height="354" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250804160223478.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250804160223478_hu_2ac780c1efa8030e.png 800w, https://zeseanblog.top/p/freertos/images/image-20250804160223478.png 1180w" width="1180"&gt;&lt;/p&gt;&#10;&lt;p&gt;1.xItemValue为列表项的值，对列表项进行排序（升序）&lt;/p&gt;&#10;&lt;p&gt;2.pxNext 和 pxPrevious 分别用于指向列表中列表项的下一个列表项和上一个列表项&lt;/p&gt;&#10;&lt;p&gt;3.pxOwner指向包含列表项的对象（通常是任务控制块）&lt;/p&gt;&#10;&lt;p&gt;3.pxContainer指向列表项所在列表&lt;/p&gt;&#10;&lt;img src="images/image-20250804160559934.png" alt="image-20250804160559934" style="zoom:50%;" /&gt;&#10;&lt;h3 id="迷你列表项结构体"&gt;&lt;a href="#%e8%bf%b7%e4%bd%a0%e5%88%97%e8%a1%a8%e9%a1%b9%e7%bb%93%e6%9e%84%e4%bd%93" class="header-anchor"&gt;&lt;/a&gt;迷你列表项结构体&#13;&#10;&lt;/h3&gt;&lt;p&gt;用于标记列表的末尾和挂载其他插入列表中的列表项&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250804160919917" class="gallery-image" data-flex-basis="928px" data-flex-grow="387" height="285" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250804160919917.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250804160919917_hu_e3d1ae42f8419d36.png 800w, https://zeseanblog.top/p/freertos/images/image-20250804160919917.png 1103w" width="1103"&gt;&lt;/p&gt;&#10;&lt;p&gt;少了pxOwner和pxContainer&lt;/p&gt;&#10;&lt;h3 id="列表和列表项的关系"&gt;&lt;a href="#%e5%88%97%e8%a1%a8%e5%92%8c%e5%88%97%e8%a1%a8%e9%a1%b9%e7%9a%84%e5%85%b3%e7%b3%bb" class="header-anchor"&gt;&lt;/a&gt;列表和列表项的关系&#13;&#10;&lt;/h3&gt;&lt;p&gt;列表初始化就有末尾列表项，而无列表项&lt;/p&gt;&#10;&lt;img src="images/image-20250804161344141.png" alt="image-20250804161344141" style="zoom: 50%;" /&gt;&#10;&lt;p&gt;初始末尾列表项的xItemValue=0xFFFFFFFF&lt;/p&gt;&#10;&lt;p&gt;*pxPrevious，*pxNext都是指向的列表项的头指针（首地址）&lt;/p&gt;&#10;&lt;p&gt;pxIndex不遍历时不指向&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250804162946703" class="gallery-image" data-flex-basis="625px" data-flex-grow="260" height="465" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250804162946703.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250804162946703_hu_df53ed6185858f5d.png 800w, https://zeseanblog.top/p/freertos/images/image-20250804162946703.png 1212w" width="1212"&gt;&lt;/p&gt;&#10;&lt;h2 id="2列表及列表项api"&gt;&lt;a href="#2%e5%88%97%e8%a1%a8%e5%8f%8a%e5%88%97%e8%a1%a8%e9%a1%b9api" class="header-anchor"&gt;&lt;/a&gt;2.列表及列表项API&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;img alt="image-20250804170048461" class="gallery-image" data-flex-basis="632px" data-flex-grow="263" height="379" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250804170048461.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250804170048461_hu_77542b2874a6634f.png 800w, https://zeseanblog.top/p/freertos/images/image-20250804170048461.png 999w" width="999"&gt;&lt;/p&gt;&#10;&lt;h1 id="九任务调度机制"&gt;&lt;a href="#%e4%b9%9d%e4%bb%bb%e5%8a%a1%e8%b0%83%e5%ba%a6%e6%9c%ba%e5%88%b6" class="header-anchor"&gt;&lt;/a&gt;九、任务调度机制*&#13;&#10;&lt;/h1&gt;&lt;h2 id="1开启任务调度器"&gt;&lt;a href="#1%e5%bc%80%e5%90%af%e4%bb%bb%e5%8a%a1%e8%b0%83%e5%ba%a6%e5%99%a8" class="header-anchor"&gt;&lt;/a&gt;1.开启任务调度器&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;vTaskStartScheduler()中&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;启动任务调度器&lt;/p&gt;&#10;&lt;h3 id="1创建空闲任务"&gt;&lt;a href="#1%e5%88%9b%e5%bb%ba%e7%a9%ba%e9%97%b2%e4%bb%bb%e5%8a%a1" class="header-anchor"&gt;&lt;/a&gt;1.创建空闲任务&#13;&#10;&lt;/h3&gt;&lt;p&gt;先判断创建方式：静态创建、动态创建；根据宏configSUPPORT_STATIC_ALLOCATION选择&lt;/p&gt;&#10;&lt;h3 id="2定时器任务"&gt;&lt;a href="#2%e5%ae%9a%e6%97%b6%e5%99%a8%e4%bb%bb%e5%8a%a1" class="header-anchor"&gt;&lt;/a&gt;2.定时器任务&#13;&#10;&lt;/h3&gt;&lt;p&gt;如果使能软件定时器，创建定时器任务&lt;/p&gt;&#10;&lt;p&gt;根据宏configUSE_TIMERS；xTimerCreateTimerTask()&lt;/p&gt;&#10;&lt;p&gt;若创建成功&lt;/p&gt;&#10;&lt;h3 id="3关闭中断"&gt;&lt;a href="#3%e5%85%b3%e9%97%ad%e4%b8%ad%e6%96%ad" class="header-anchor"&gt;&lt;/a&gt;3.关闭中断&#13;&#10;&lt;/h3&gt;&lt;p&gt;防止调度器开启之前或过程中，受中断干扰，会在运行第一个任务时打开中断&lt;/p&gt;&#10;&lt;p&gt;portDISABLE_INTERRUPTS();&lt;/p&gt;&#10;&lt;h3 id="4初始化全局变量"&gt;&lt;a href="#4%e5%88%9d%e5%a7%8b%e5%8c%96%e5%85%a8%e5%b1%80%e5%8f%98%e9%87%8f" class="header-anchor"&gt;&lt;/a&gt;4.初始化全局变量&#13;&#10;&lt;/h3&gt;&lt;p&gt;并将任务调度器设置为已运行&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;//阻塞时间默认最大值&#10;xNextTaskUnblockTime = portMAX_DELAY;&#10;//调度器运行状态&#10;xSchedulerRunning = pdTRUE;&#10;//初始节拍 0&#10;xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="5调用xportstartscheduler"&gt;&lt;a href="#5%e8%b0%83%e7%94%a8xportstartscheduler" class="header-anchor"&gt;&lt;/a&gt;5.调用xPortStartScheduler();&#13;&#10;&lt;/h3&gt;&lt;p&gt;作用：该函数用于完成启动任务调度器中与硬件架构相关的配置部分，以及启动第一个任务&lt;/p&gt;&#10;&lt;h4 id="51检测配置是否有误"&gt;&lt;a href="#51%e6%a3%80%e6%b5%8b%e9%85%8d%e7%bd%ae%e6%98%af%e5%90%a6%e6%9c%89%e8%af%af" class="header-anchor"&gt;&lt;/a&gt;5.1检测配置是否有误&#13;&#10;&lt;/h4&gt;&lt;p&gt;用户在 FreeRTOSConfig.h 文件中对中断的相关配置&lt;/p&gt;&#10;&lt;h4 id="52配置-pendsv-和-systick"&gt;&lt;a href="#52%e9%85%8d%e7%bd%ae-pendsv-%e5%92%8c-systick" class="header-anchor"&gt;&lt;/a&gt;5.2配置 PendSV 和 SysTick&#13;&#10;&lt;/h4&gt;&lt;p&gt;配置 PendSV 和 SysTick 的中断优先级为最低优先级&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;&#10;portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h4 id="53调用vportsetuptimerinterrupt"&gt;&lt;a href="#53%e8%b0%83%e7%94%a8vportsetuptimerinterrupt" class="header-anchor"&gt;&lt;/a&gt;5.3调用vPortSetupTimerInterrupt()；&#13;&#10;&lt;/h4&gt;&lt;p&gt;函数中在配置SysTick&lt;/p&gt;&#10;&lt;p&gt;SysTick控制及状态寄存器（地址：0xE000_E010）&lt;/p&gt;&#10;&lt;p&gt;SysTick当前数值寄存器（地址：0xE000_E018）&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;span class="lnt"&gt;7&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/*&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;配置寄存器&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;portNVIC_SYSTICK_CTRL_REG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0UL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;portNVIC_SYSTICK_CURRENT_VALUE_REG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0UL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;img src="images/image-20250804202454119.png" alt="image-20250804202454119" style="zoom:67%;" /&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/*&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/*&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;F103C8中&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;uint32_t SystemCoreClock = 16000000;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;#define configCPU_CLOCK_HZ &#9;SystemCoreClock //定义CPU主频, 单位: Hz, 无默认需定义&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;#define configSYSTICK_CLOCK_HZ (configCPU_CLOCK_HZ / 8)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;#define configTICK_RATE_HZ 20&#9;&#9;&#9;&#9;&#9;/* 定义系统时钟节拍频率, 单位: Hz, 无默认需定义 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;portNVIC_SYSTICK_LOAD_REG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;configSYSTICK_CLOCK_HZ&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;configTICK_RATE_HZ&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1UL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;portNVIC_SYSTICK_CTRL_REG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;portNVIC_SYSTICK_CLK_BIT_CONFIG&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;portNVIC_SYSTICK_INT_BIT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;portNVIC_SYSTICK_ENABLE_BIT&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;5.4初始化临界区嵌套计数器为 0&lt;/p&gt;&#10;&lt;p&gt;uxCriticalNesting = 0;&lt;/p&gt;&#10;&lt;p&gt;5.5调用函数 prvEnableVFP() 使能 FPU&lt;/p&gt;&#10;&lt;p&gt;Cortex M3没有FPU&lt;/p&gt;&#10;&lt;p&gt;5.6调用函数 prvStartFirstTask() 启动第一个任务&lt;/p&gt;&#10;&lt;h2 id="2启动第一个任务"&gt;&lt;a href="#2%e5%90%af%e5%8a%a8%e7%ac%ac%e4%b8%80%e4%b8%aa%e4%bb%bb%e5%8a%a1" class="header-anchor"&gt;&lt;/a&gt;2.启动第一个任务&#13;&#10;&lt;/h2&gt;&lt;p&gt;要启动的第一个任务是任务 A，那么就需要将任务A的寄存器值恢复到CPU寄存器&lt;/p&gt;&#10;&lt;p&gt;任务 A 的寄存器值，在一开始创建任务时就保存在任务堆栈里&lt;/p&gt;&#10;&lt;p&gt;注意：&lt;/p&gt;&#10;&lt;p&gt;1、中断产生时，硬件自动将 xPSR，PC(R15) ，LR(R14) ，R12 ，R3-R0出/入栈；而 R4~R11需要手动出/入栈&lt;/p&gt;&#10;&lt;p&gt;2 、进入中断后硬件会强制使用 MSP 指针 ，此时 LR(R14 ）的值将会被自动被更新为特殊的 EXC_RETURN&lt;/p&gt;&#10;&lt;p&gt;prvStartFirstTask()&lt;/p&gt;&#10;&lt;p&gt;&amp;hellip;.&lt;/p&gt;&#10;&lt;p&gt;/* Call SVC to start the first task. */&#10;svc 0&lt;/p&gt;&#10;&lt;p&gt;触发SVC中断，启动第一个任务&lt;/p&gt;&#10;&lt;p&gt;#define vPortSVCHandler SVC_Handler&lt;/p&gt;&#10;&lt;h3 id="svc中断"&gt;&lt;a href="#svc%e4%b8%ad%e6%96%ad" class="header-anchor"&gt;&lt;/a&gt;SVC中断&#13;&#10;&lt;/h3&gt;&lt;p&gt;只在启动第一次任务时会调用一次，以后不调用&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250804212919268" class="gallery-image" data-flex-basis="212px" data-flex-grow="88" height="569" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250804212919268.png" width="503"&gt;&lt;/p&gt;&#10;&lt;h3 id="出栈压栈汇编指令详解"&gt;&lt;a href="#%e5%87%ba%e6%a0%88%e5%8e%8b%e6%a0%88%e6%b1%87%e7%bc%96%e6%8c%87%e4%bb%a4%e8%af%a6%e8%a7%a3" class="header-anchor"&gt;&lt;/a&gt;出栈/压栈汇编指令详解&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img alt="image-20250804214029244" class="gallery-image" data-flex-basis="596px" data-flex-grow="248" height="478" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250804214029244.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250804214029244_hu_81eb288841a9e55b.png 800w, https://zeseanblog.top/p/freertos/images/image-20250804214029244.png 1188w" width="1188"&gt;&lt;/p&gt;&#10;&lt;h2 id="3任务切换"&gt;&lt;a href="#3%e4%bb%bb%e5%8a%a1%e5%88%87%e6%8d%a2" class="header-anchor"&gt;&lt;/a&gt;3.任务切换&#13;&#10;&lt;/h2&gt;&lt;p&gt;任务切换本质：CPU寄存器的切换&lt;/p&gt;&#10;&lt;p&gt;就是把不同任务加载到CPU寄存器里&lt;/p&gt;&#10;&lt;p&gt;假设要把任务A切换到B：&lt;/p&gt;&#10;&lt;p&gt;第一步：暂停任务A，将此时任务A的寄存器保存（压栈）到任务堆栈，即保存现场&lt;/p&gt;&#10;&lt;p&gt;第二步：将任务B的寄存器值（存在任务堆栈中）恢复到CPU寄存器，即恢复现场&lt;/p&gt;&#10;&lt;p&gt;切换过程：保存A现场，恢复B现场，即上下文切换&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;需要手动的部分：R4-R11&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;切换：任务切换在PendSV中断服务函数里完成&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250804215919484" class="gallery-image" data-flex-basis="483px" data-flex-grow="201" height="554" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250804215919484.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250804215919484_hu_3b34f54a595d72e2.png 800w, https://zeseanblog.top/p/freertos/images/image-20250804215919484.png 1115w" width="1115"&gt;&lt;/p&gt;&#10;&lt;h3 id="如何触发pendsv中断"&gt;&lt;a href="#%e5%a6%82%e4%bd%95%e8%a7%a6%e5%8f%91pendsv%e4%b8%ad%e6%96%ad" class="header-anchor"&gt;&lt;/a&gt;如何触发PendSV中断&#13;&#10;&lt;/h3&gt;&lt;p&gt;1.滴答定时器中断调用&lt;/p&gt;&#10;&lt;p&gt;2.FreeRTOS相关API：portYIELD()；//底层函数&lt;/p&gt;&#10;&lt;p&gt;本质：向中断控制和状态寄存器ICSR的bit28写1挂起PendSV来启动PendSV中断&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;流程&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;1：滴答定时器中断处理函数SysTick_Handler()&lt;/p&gt;&#10;&lt;p&gt;启动了任务调度器，则进入xPortSysTickHandler()&lt;/p&gt;&#10;&lt;p&gt;判断xTaskIncrementTick()&lt;/p&gt;&#10;&lt;p&gt;则执行&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define portNVIC_PENDSVSET_BIT ( 1UL &amp;lt;&amp;lt; 28UL )&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//即向地址0xe000ed04 第28位写入1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;portNVIC_INT_CTRL_REG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;portNVIC_PENDSVSET_BIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;&lt;img alt="image-20250805141250773" class="gallery-image" data-flex-basis="923px" data-flex-grow="384" height="239" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250805141250773.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250805141250773_hu_8090224c4c5f9963.png 800w, https://zeseanblog.top/p/freertos/images/image-20250805141250773.png 920w" width="920"&gt;&lt;/p&gt;&#10;&lt;p&gt;2:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;#define portYIELD() &#10;{ &#10; portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; &#10; __dsb( portSY_FULL_READ_WRITE ); &#10; __isb( portSY_FULL_READ_WRITE ); &#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="pendsv中断服务函数"&gt;&lt;a href="#pendsv%e4%b8%ad%e6%96%ad%e6%9c%8d%e5%8a%a1%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;PendSV中断服务函数&#13;&#10;&lt;/h3&gt;&lt;p&gt;FreeRTOSConfig.h中&lt;/p&gt;&#10;&lt;p&gt;#define xPortPendSVHandler PendSV_Handler&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;span class="lnt"&gt;29&#10;&lt;/span&gt;&lt;span class="lnt"&gt;30&#10;&lt;/span&gt;&lt;span class="lnt"&gt;31&#10;&lt;/span&gt;&lt;span class="lnt"&gt;32&#10;&lt;/span&gt;&lt;span class="lnt"&gt;33&#10;&lt;/span&gt;&lt;span class="lnt"&gt;34&#10;&lt;/span&gt;&lt;span class="lnt"&gt;35&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;__asm&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;xPortPendSVHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;uxCriticalNesting&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;pxCurrentTCB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#9;&#9;&lt;span class="c1"&gt;//任务控制块地址&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;vTaskSwitchContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="c1"&gt;//八字节对齐&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;PRESERVE8&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mrs&lt;/span&gt; &lt;span class="n"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;psp&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;isb&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ldr&lt;/span&gt; &lt;span class="n"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;pxCurrentTCB&lt;/span&gt; &#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ldr&lt;/span&gt; &lt;span class="n"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;r3&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;&#9;&#9;&#9;&#9;&lt;span class="c1"&gt;//r2存放任务控制块地址&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stmdb&lt;/span&gt; &lt;span class="n"&gt;r0&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;r4&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;r11&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &#9;&lt;span class="c1"&gt;//r4到r11压入cpu任务栈&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="n"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;r2&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stmdb&lt;/span&gt; &lt;span class="n"&gt;sp&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r14&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mov&lt;/span&gt; &lt;span class="n"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;configMAX_SYSCALL_INTERRUPT_PRIORITY&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;msr&lt;/span&gt; &lt;span class="n"&gt;basepri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dsb&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;isb&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;bl&lt;/span&gt; &lt;span class="n"&gt;vTaskSwitchContext&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mov&lt;/span&gt; &lt;span class="n"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;msr&lt;/span&gt; &lt;span class="n"&gt;basepri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ldmia&lt;/span&gt; &lt;span class="n"&gt;sp&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r14&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ldr&lt;/span&gt; &lt;span class="n"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;r3&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ldr&lt;/span&gt; &lt;span class="n"&gt;r0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;r1&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ldmia&lt;/span&gt; &lt;span class="n"&gt;r0&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;r4&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;r11&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;msr&lt;/span&gt; &lt;span class="n"&gt;psp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;isb&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;bx&lt;/span&gt; &lt;span class="n"&gt;r14&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;nop&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h1 id="十时间片调度"&gt;&lt;a href="#%e5%8d%81%e6%97%b6%e9%97%b4%e7%89%87%e8%b0%83%e5%ba%a6" class="header-anchor"&gt;&lt;/a&gt;十、时间片调度&#13;&#10;&lt;/h1&gt;&lt;p&gt;当多个任务的任务优先级相同时，CPU 会轮流的处理每一个任务，每个任务享有 CPU 处理的时间都是相同的，这个时间被称为时间片。&lt;/p&gt;&#10;&lt;p&gt;一个时间片就等于 SysTick 中断周期（可以由用户自行设置），CPU 给与了一个时间片运行一个任务，不管这个任务是否运行完成，CPU 都会跑到下一个任务。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="img" class="gallery-image" data-flex-basis="471px" data-flex-grow="196" height="206" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/csdn-ec673027b9e7474581d3c3c5d3159ebd.png" width="405"&gt;&lt;/p&gt;&#10;&lt;p&gt;流程：&lt;/p&gt;&#10;&lt;p&gt;1.task1 运行完一个时间片切换到 task2&lt;/p&gt;&#10;&lt;p&gt;2.task2 运行完一个时间片切换至 task3&lt;/p&gt;&#10;&lt;p&gt;3.task3 运行阻塞(系统延时或等待信号量等)切换至下一个任务 task1&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;没有用完的时间片不会再使用&lt;/strong&gt;，下次任务 task3 得到执行还是按照一个时间片的时钟节拍运行&lt;/p&gt;&#10;&lt;p&gt;4.task1 运行完一个时间片之后，切换至 task2 运行&lt;/p&gt;&#10;&lt;h1 id="十一任务相关api"&gt;&lt;a href="#%e5%8d%81%e4%b8%80%e4%bb%bb%e5%8a%a1%e7%9b%b8%e5%85%b3api" class="header-anchor"&gt;&lt;/a&gt;十一、任务相关API&#13;&#10;&lt;/h1&gt;&lt;p&gt;&lt;img alt="image-20250805151211347" class="gallery-image" data-flex-basis="376px" data-flex-grow="156" height="693" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250805151211347.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250805151211347_hu_e2de76a4f0a3fb67.png 800w, https://zeseanblog.top/p/freertos/images/image-20250805151211347.png 1086w" width="1086"&gt;&lt;/p&gt;&#10;&lt;p&gt;不多介绍&lt;/p&gt;&#10;&lt;h1 id="十二时间管理"&gt;&lt;a href="#%e5%8d%81%e4%ba%8c%e6%97%b6%e9%97%b4%e7%ae%a1%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;十二、时间管理&#13;&#10;&lt;/h1&gt;&lt;p&gt;&lt;img alt="image-20250805153017599" class="gallery-image" data-flex-basis="1517px" data-flex-grow="632" height="174" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250805153017599.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250805153017599_hu_159be6fd7bb21bb4.png 800w, https://zeseanblog.top/p/freertos/images/image-20250805153017599.png 1100w" width="1100"&gt;&lt;/p&gt;&#10;&lt;p&gt;· 相对延时：指每次延时都是从任务执行函数vTaskDelay()开始，延时指定的时间结束。&lt;/p&gt;&#10;&lt;p&gt;· 绝对延时：指每隔指定的时间，执行一次调用vTaskDelayUntil()函数的任务。&lt;/p&gt;&#10;&lt;p&gt;即:vTaskDelay()是从调用其本身开始计时，vTaskDelayUntil()是从调用任务开始计时&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;BaseType_t&lt;/span&gt; &lt;span class="nf"&gt;xTaskDelayUntil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;TickType_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pxPreviousWakeTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &#9;&#9;&#9;&#9;&#9;&#9; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;TickType_t&lt;/span&gt; &lt;span class="n"&gt;xTimeIncrement&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Perform an action every 10 ticks.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;vTaskFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pvParameters&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;TickType_t&lt;/span&gt; &lt;span class="n"&gt;xLastWakeTime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;TickType_t&lt;/span&gt; &lt;span class="n"&gt;xFrequency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;xLastWakeTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;xTaskGetTickCount&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Wait for the next cycle.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Perform action here.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;vTaskDelayUntil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;xLastWakeTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xFrequency&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h1 id="十三freertos消息队列"&gt;&lt;a href="#%e5%8d%81%e4%b8%89freertos%e6%b6%88%e6%81%af%e9%98%9f%e5%88%97" class="header-anchor"&gt;&lt;/a&gt;十三、FreeRTOS消息队列&#13;&#10;&lt;/h1&gt;&lt;h2 id="1队列简介"&gt;&lt;a href="#1%e9%98%9f%e5%88%97%e7%ae%80%e4%bb%8b" class="header-anchor"&gt;&lt;/a&gt;1.队列简介&#13;&#10;&lt;/h2&gt;&lt;p&gt;任务到任务，任务到中断，中断到任务数据交流的一种机制&lt;/p&gt;&#10;&lt;p&gt;为什么不用全局变量？&lt;/p&gt;&#10;&lt;p&gt;假设有一个全局变量a=0，现在俩个认为在写变量a&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250805174038545" class="gallery-image" data-flex-basis="1273px" data-flex-grow="530" height="164" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250805174038545.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250805174038545_hu_d02ef7dbbc872c33.png 800w, https://zeseanblog.top/p/freertos/images/image-20250805174038545.png 870w" width="870"&gt;&lt;/p&gt;&#10;&lt;p&gt;任务1执行到第二步，任务2打断，执行a++，此时a才是1，回到任务1的第三步，a为1，但执行两次a++。&lt;/p&gt;&#10;&lt;p&gt;因此全局变量数据无保护，当多任务操作数据时，数据受损&lt;/p&gt;&#10;&lt;h3 id="使用队列"&gt;&lt;a href="#%e4%bd%bf%e7%94%a8%e9%98%9f%e5%88%97" class="header-anchor"&gt;&lt;/a&gt;使用队列&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img alt="image-20250805174331194" class="gallery-image" data-flex-basis="985px" data-flex-grow="410" height="227" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250805174331194.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250805174331194_hu_c27c2352446e24cd.png 800w, https://zeseanblog.top/p/freertos/images/image-20250805174331194.png 932w" width="932"&gt;&lt;/p&gt;&#10;&lt;p&gt;为什么会安全？因为封装了临界区，即关闭中断，读写队列都有保护，防止多任务冲突&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="img" class="gallery-image" data-flex-basis="985px" data-flex-grow="410" height="143" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/csdn-b69d543cfa214f07ac2e3f0009eec667.png" width="587"&gt;&lt;/p&gt;&#10;&lt;p&gt;队列存储数量有限、大小固定的数据。队列的每个数据叫队列项目&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250805174900810" class="gallery-image" data-flex-basis="728px" data-flex-grow="303" height="246" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250805174900810.png" width="747"&gt;&lt;/p&gt;&#10;&lt;h3 id="队列要点"&gt;&lt;a href="#%e9%98%9f%e5%88%97%e8%a6%81%e7%82%b9" class="header-anchor"&gt;&lt;/a&gt;队列要点&#13;&#10;&lt;/h3&gt;&lt;p&gt;1.数据入队出队：通常FIFO（先入先出），也可以LIFO（后入先出）&lt;/p&gt;&#10;&lt;p&gt;2.数据传递方式：freertos采用实际值，将数据拷贝至队列，在传递较大数据时可以传递指针&lt;/p&gt;&#10;&lt;p&gt;3.多任务访问：队列不属于某任务，任何任务、中断都可以读写&lt;/p&gt;&#10;&lt;p&gt;4.出入阻塞：当任务向队列读写时，可以指定阻塞时间，队列已满或空则无法入队、出队&lt;/p&gt;&#10;&lt;p&gt;阻塞时间是：0：直接返回不等待&lt;/p&gt;&#10;&lt;p&gt;​&#9;&#9;&#9;&#9;&#9;&#9;0~max：超时不入队则不等待&lt;/p&gt;&#10;&lt;p&gt;​&#9;&#9;&#9;&#9;&#9;&#9;max：死等&lt;/p&gt;&#10;&lt;h3 id="入出队阻塞"&gt;&lt;a href="#%e5%85%a5%e5%87%ba%e9%98%9f%e9%98%bb%e5%a1%9e" class="header-anchor"&gt;&lt;/a&gt;入/出队阻塞&#13;&#10;&lt;/h3&gt;&lt;p&gt;入队阻塞，队列满了，此时写不进去数据&lt;/p&gt;&#10;&lt;img src="images/image-20250805180519958.png" alt="image-20250805180519958" style="zoom:50%;" /&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;将该任务的状态列表项挂载再 pxDelayedTaskLisk；&lt;/li&gt;&#10;&lt;li&gt;将该任务的事件列表项挂载在 xTasksWaitingToSend；&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;出队阻塞，队列为空，此时读取不了数据：&lt;/p&gt;&#10;&lt;img src="images/image-20250805180611951.png" alt="image-20250805180611951" style="zoom:50%;" /&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;将该任务的状态列表项挂载再 pxDelayedTaskLisk；&lt;/li&gt;&#10;&lt;li&gt;将该任务的事件列表项挂载在 xTasksWaitingToReceive；&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;多任务都在等待同一个队列入队，都在阻塞，那当队列有空间，谁先进入就绪态:&lt;/p&gt;&#10;&lt;p&gt;那优先级最高的入队，若优先级相同，等最久的入队&lt;/p&gt;&#10;&lt;h2 id="2队列结构体"&gt;&lt;a href="#2%e9%98%9f%e5%88%97%e7%bb%93%e6%9e%84%e4%bd%93" class="header-anchor"&gt;&lt;/a&gt;2.队列结构体&#13;&#10;&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;QueueDefinition&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int8_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pcHead&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* 存储区域的起始地址 */&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int8_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pcWriteTo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* 下一个写入的位置 */&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;union&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;QueuePointers_t&lt;/span&gt; &lt;span class="n"&gt;xQueue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &#9;&#9;&lt;span class="c1"&gt;//当用于队列时&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SemaphoreData_t&lt;/span&gt; &lt;span class="n"&gt;xSemaphore&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &#9;&lt;span class="c1"&gt;//当用于信号量时&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;List_t&lt;/span&gt; &lt;span class="n"&gt;xTasksWaitingToSend&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* 写入阻塞任务列表 */&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;List_t&lt;/span&gt; &lt;span class="n"&gt;xTasksWaitingToReceive&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* 读取阻塞任务列表 */&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="n"&gt;UBaseType_t&lt;/span&gt; &lt;span class="n"&gt;uxMessagesWaiting&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* 非空闲项目的数量 */&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;UBaseType_t&lt;/span&gt; &lt;span class="n"&gt;uxLength&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* 队列的长度 */&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;UBaseType_t&lt;/span&gt; &lt;span class="n"&gt;uxItemSize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* 队列项目的大小 */&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/* 锁用于在任务因队列操作被阻塞前，防止中断或其他任务操作队列。 &#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 上锁期间，队列可以写入和读取消息，但不会操作队列阻塞任务列表， &#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 当有消息写入时，cTxLock加1，当有消息被读取时，cRxLock加1， &#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 在解锁时，会统一处理队列的阻塞任务列表 &#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; */&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;int8_t&lt;/span&gt; &lt;span class="n"&gt;cRxLock&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* 读取上锁计数器 */&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;int8_t&lt;/span&gt; &lt;span class="n"&gt;cTxLock&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* 写入上锁计数器 */&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="c1"&gt;//以下省略一些条件编译&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;xQUEUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h2 id="3队列相关api函数"&gt;&lt;a href="#3%e9%98%9f%e5%88%97%e7%9b%b8%e5%85%b3api%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;3.队列相关API函数&#13;&#10;&lt;/h2&gt;&lt;p&gt;主要流程:创建队列-&amp;gt;写队列-&amp;gt;读队列&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250805192810878" class="gallery-image" data-flex-basis="1413px" data-flex-grow="589" height="110" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250805192810878.png" width="648"&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define xQueueCreate( uxQueueLength, uxItemSize ) &#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;xQueueGenericCreate&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt; &lt;span class="n"&gt;uxQueueLength&lt;/span&gt; &lt;span class="p"&gt;),(&lt;/span&gt; &lt;span class="n"&gt;uxItemSize&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queueQUEUE_TYPE_BASE&lt;/span&gt; &lt;span class="p"&gt;))&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;其中queueQUEUE_TYPE_BASE代表不同创建类型的功能，实际都是基于一个函数实现的&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;#define queueQUEUE_TYPE_BASE ( ( uint8_t ) 0U ) &#9;&#9;&#9;&#9;/* 队列 */ &#10;#define queueQUEUE_TYPE_SET ( ( uint8_t ) 0U ) &#9;&#9;&#9;&#9;/* 队列集 */ &#10;#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U ) &#9;&#9;&#9;/* 互斥信号量 */ &#10;#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( uint8_t ) 2U ) &#9;/* 计数型信号量 */ &#10;#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U )&#9;&#9;/* 二值信号量 */ &#10;#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( uint8_t ) 4U ) &#9;&#9;/* 递归互斥信号量 */&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;QueueHandle_t xQueueCreate( uxQueueLength, uxItemSize )&lt;/p&gt;&#10;&lt;p&gt;uxQueueLength:队列长度&lt;/p&gt;&#10;&lt;p&gt;uxItemSize：队列项大小&lt;/p&gt;&#10;&lt;p&gt;返回值QueueHandle_t句柄&lt;/p&gt;&#10;&lt;p&gt;NULL：创建失败，其他值：创建成功，返回句柄&lt;/p&gt;&#10;&lt;h3 id="31写入消息api"&gt;&lt;a href="#31%e5%86%99%e5%85%a5%e6%b6%88%e6%81%afapi" class="header-anchor"&gt;&lt;/a&gt;3.1写入消息API&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img alt="image-20250805193852464" class="gallery-image" data-flex-basis="1026px" data-flex-grow="427" height="174" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250805193852464.png" width="744"&gt;&lt;/p&gt;&#10;&lt;p&gt;这四个函数都是对xQueueGenericSend()的宏定义&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define xQueueSend(xQueue, pvItemToQueue, xTicksToWait) &#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;xQueueGenericSend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;xQueue&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;pvItemToQueue&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;xTicksToWait&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;queueSEND_TO_BACK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait) &#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;xQueueGenericSend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;xQueue&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;pvItemToQueue&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;xTicksToWait&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;queueSEND_TO_BACK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait) &#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;xQueueGenericSend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;xQueue&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;pvItemToQueue&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;xTicksToWait&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;queueSEND_TO_FRONT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define xQueueOverwrite( xQueue, pvItemToQueue) &#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;xQueueGenericSend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;xQueue&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;pvItemToQueue&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;queueOVERWRITE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;xQueueGenericSend为&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;BaseType_t xQueueGenericSend( QueueHandle_t &#9; xQueue, &#10; &#9;&#9;&#9;&#9;&#9; const void * const pvItemToQueue, &#10; &#9;&#9;&#9;&#9;&#9; TickType_t &#9; xTicksToWait, &#10; &#9;&#9;&#9;&#9;&#9; const BaseType_t xCopyPosition); &#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img alt="image-20250805194502113" class="gallery-image" data-flex-basis="477px" data-flex-grow="198" height="437" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250805194502113.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250805194502113_hu_474c7e7a5e2e6293.png 800w, https://zeseanblog.top/p/freertos/images/image-20250805194502113.png 869w" width="869"&gt;&lt;/p&gt;&#10;&lt;h3 id="32读取消息api"&gt;&lt;a href="#32%e8%af%bb%e5%8f%96%e6%b6%88%e6%81%afapi" class="header-anchor"&gt;&lt;/a&gt;3.2读取消息API&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img alt="image-20250805194543783" class="gallery-image" data-flex-basis="1707px" data-flex-grow="711" height="103" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250805194543783.png" width="733"&gt;&lt;/p&gt;&#10;&lt;p&gt;xQueueReceive&lt;/p&gt;&#10;&lt;p&gt;从队列中读取消息，并且消息读取成功后，会将消息从队列中移除&lt;/p&gt;&#10;&lt;img src="images/image-20250805194845838.png" alt="image-20250805194845838" style="zoom:67%;" /&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;BaseType_t xQueueReceive( QueueHandle_t xQueue,&#10; void * const pvBuffer,&#10; TickType_t xTicksToWait );&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;xQueuePeek&lt;/p&gt;&#10;&lt;p&gt;不会删除的函数，参数一致&lt;/p&gt;&#10;&lt;h2 id="4队列相关api函数解析"&gt;&lt;a href="#4%e9%98%9f%e5%88%97%e7%9b%b8%e5%85%b3api%e5%87%bd%e6%95%b0%e8%a7%a3%e6%9e%90" class="header-anchor"&gt;&lt;/a&gt;4.队列相关API函数解析&#13;&#10;&lt;/h2&gt;&lt;h3 id="41xqueuecreate"&gt;&lt;a href="#41xqueuecreate" class="header-anchor"&gt;&lt;/a&gt;4.1xQueueCreate&#13;&#10;&lt;/h3&gt;&lt;p&gt;#define xQueueCreate( uxQueueLength, uxItemSize )&lt;/p&gt;&#10;&lt;p&gt;​&#9;&#9;&#9; xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) )&lt;/p&gt;&#10;&lt;p&gt;对队列而言xQueueGenericCreate前两个入口参数有效&lt;/p&gt;&#10;&lt;p&gt;首先长度判断&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;if( ( uxQueueLength &amp;gt; ( UBaseType_t ) 0 ) &amp;amp;&amp;amp;&#10; ( ( SIZE_MAX / uxQueueLength ) &amp;gt;= uxItemSize ) &amp;amp;&amp;amp;&#10; ( ( SIZE_MAX - sizeof( Queue_t ) ) &amp;gt;= ( uxQueueLength * uxItemSize ) ) )&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;队列项存储区大小&lt;/p&gt;&#10;&lt;p&gt;xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize );&lt;/p&gt;&#10;&lt;p&gt;申请内存是队列项存储区+结构体存储区，并把首地址给到pxNewQueue&lt;/p&gt;&#10;&lt;p&gt;pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );&lt;/p&gt;&#10;&lt;p&gt;再将地址指向队列项存储区&lt;/p&gt;&#10;&lt;p&gt;pucQueueStorage = ( uint8_t * ) pxNewQueue;&#10;pucQueueStorage += sizeof( Queue_t );&lt;/p&gt;&#10;&lt;img src="images/image-20250805203138966.png" alt="image-20250805203138966" style="zoom:50%;" /&gt;&#10;&lt;p&gt;执行&lt;/p&gt;&#10;&lt;p&gt;QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength,&#10;const UBaseType_t uxItemSize,&#10;const uint8_t ucQueueType )&lt;/p&gt;&#10;&lt;p&gt;除一个是存储区首地址，一个是队列结构体首地址pucQueueStorage，pxNewQueue外，由外部传入&lt;/p&gt;&#10;&lt;p&gt;prvInitialiseNewQueue( uxQueueLength, uxItemSize, &lt;strong&gt;pucQueueStorage&lt;/strong&gt;, ucQueueType, &lt;strong&gt;pxNewQueue&lt;/strong&gt; );&lt;/p&gt;&#10;&lt;p&gt;进入prvInitialiseNewQueue后&lt;/p&gt;&#10;&lt;p&gt;if( uxItemSize == ( UBaseType_t ) 0 )是信号量&lt;/p&gt;&#10;&lt;p&gt;否则是队列，执行以下行，将队列项存储区首地址给到队列首地址&lt;/p&gt;&#10;&lt;p&gt;pxNewQueue-&amp;gt;pcHead = ( int8_t * ) pucQueueStorage;&lt;/p&gt;&#10;&lt;p&gt;再进入&lt;/p&gt;&#10;&lt;p&gt;( void ) xQueueGenericReset( pxNewQueue, pdTRUE );&lt;/p&gt;&#10;&lt;h3 id="42xqueuesend"&gt;&lt;a href="#42xqueuesend" class="header-anchor"&gt;&lt;/a&gt;4.2xQueueSend&#13;&#10;&lt;/h3&gt;&lt;p&gt;#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait )&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;&#9; xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), &#9;&#9;queueSEND_TO_BACK )&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;进入&lt;/p&gt;&#10;&lt;p&gt;xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );&lt;/p&gt;&#10;&lt;p&gt;如果尾部插入&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250805210830882" class="gallery-image" data-flex-basis="929px" data-flex-grow="387" height="228" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250805210830882.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250805210830882_hu_8a7b476ed1e95d0c.png 800w, https://zeseanblog.top/p/freertos/images/image-20250805210830882.png 883w" width="883"&gt;&lt;/p&gt;&#10;&lt;h1 id="十四信号量"&gt;&lt;a href="#%e5%8d%81%e5%9b%9b%e4%bf%a1%e5%8f%b7%e9%87%8f" class="header-anchor"&gt;&lt;/a&gt;十四、信号量&#13;&#10;&lt;/h1&gt;&lt;h2 id="1简介"&gt;&lt;a href="#1%e7%ae%80%e4%bb%8b" class="header-anchor"&gt;&lt;/a&gt;1.简介&#13;&#10;&lt;/h2&gt;&lt;p&gt;队列是发送数据，信号是发送状态，信号量是队列的衍生&lt;/p&gt;&#10;&lt;p&gt;信号量结局同步机制（我做完一件事告诉你），任务间的通信以及事件通知，对共享资源的有序访问&lt;/p&gt;&#10;&lt;p&gt;举例：&lt;/p&gt;&#10;&lt;p&gt;1.停车场车位是否还有（判断信号量是否还有资源）&lt;/p&gt;&#10;&lt;p&gt;2.停车场有空位（有资源），就可以将车开入（获取信号量）&lt;/p&gt;&#10;&lt;p&gt;3.停车场无空位（无资源），不可以将车开入（获取信号量失败），可以等待其他人开出（释放）&lt;/p&gt;&#10;&lt;img src="images/image-20250805214538146.png" alt="image-20250805214538146" style="zoom:50%;" /&gt;&#10;&lt;p&gt;如果最大值被限定为 1 ，那么它就是二值信号量；&#10;如果最大值不是 1 ，它就是计数型信号量。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250805215045090" class="gallery-image" data-flex-basis="694px" data-flex-grow="289" height="371" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250805215045090.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250805215045090_hu_47a5d36768308485.png 800w, https://zeseanblog.top/p/freertos/images/image-20250805215045090.png 1073w" width="1073"&gt;&lt;/p&gt;&#10;&lt;h2 id="1二值信号量"&gt;&lt;a href="#1%e4%ba%8c%e5%80%bc%e4%bf%a1%e5%8f%b7%e9%87%8f" class="header-anchor"&gt;&lt;/a&gt;1.二值信号量&#13;&#10;&lt;/h2&gt;&lt;p&gt;本质：长度为1的队列，该队列只有空和满&lt;/p&gt;&#10;&lt;p&gt;通常用于互斥访问（一个任务持有锁，其他任务无法执行）和任务同步（一个任务等另一个任务完成才能执行下去），互斥信号量相似，但二值信号量可能导致优先级反转&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250805215532525" class="gallery-image" data-flex-basis="1065px" data-flex-grow="444" height="272" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250805215532525.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250805215532525_hu_20a7c39521efa82d.png 800w, https://zeseanblog.top/p/freertos/images/image-20250805215532525.png 1208w" width="1208"&gt;&lt;/p&gt;&#10;&lt;h3 id="二值信号量相关api函数"&gt;&lt;a href="#%e4%ba%8c%e5%80%bc%e4%bf%a1%e5%8f%b7%e9%87%8f%e7%9b%b8%e5%85%b3api%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;二值信号量相关API函数&#13;&#10;&lt;/h3&gt;&lt;p&gt;过程：创建-释放-获取&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250805215908052" class="gallery-image" data-flex-basis="645px" data-flex-grow="268" height="340" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250805215908052.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250805215908052_hu_2a407f0e1f474964.png 800w, https://zeseanblog.top/p/freertos/images/image-20250805215908052.png 914w" width="914"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;创建&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;SemaphoreHandle_t xSemaphoreCreateBinary( void )&lt;/p&gt;&#10;&lt;img src="images/image-20250805220323164.png" alt="image-20250805220323164" style="zoom:50%;" /&gt;&#10;&lt;p&gt;&lt;strong&gt;释放&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;传入句柄xSemaphore&lt;/p&gt;&#10;&lt;p&gt;BaseType_t xSemaphoreGive( xSemaphore )&lt;/p&gt;&#10;&lt;p&gt;返回值pdPASS：成功&lt;/p&gt;&#10;&lt;p&gt;errQUEUE_FULL：失败&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;获取&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;传入句柄xSemaphore，阻塞时间xBlockTime ，死等为portMAX_DELAY&lt;/p&gt;&#10;&lt;p&gt;BaseType_t xSemaphoreTake( xSemaphore,xBlockTime )&lt;/p&gt;&#10;&lt;p&gt;返回值：pdTRUE 获取信号量成功&#10;pdFALSE 超时，获取信号量失败&lt;/p&gt;&#10;&lt;h2 id="2计数型信号量"&gt;&lt;a href="#2%e8%ae%a1%e6%95%b0%e5%9e%8b%e4%bf%a1%e5%8f%b7%e9%87%8f" class="header-anchor"&gt;&lt;/a&gt;2.计数型信号量&#13;&#10;&lt;/h2&gt;&lt;p&gt;计数型信号量相当于队列长度大于 1 的队列，因此计数型信号量能够容纳多个资源，这在计数型信号量被创建的时候确定的&lt;/p&gt;&#10;&lt;p&gt;适用场合：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;事件计数：每次事件发生，事件处理函数中释放计数型信号量，计数值+1，其他任务获取计数型信号量，计数值-1，初始计数值一般设为0&lt;/li&gt;&#10;&lt;li&gt;资源管理：信号量表示有效资源数量，任务必须先获取信号量，计数值-1，才能获取资源控制权，当计数值减到0时表示没有资源，当任务使用完资源后，必须释放，计数值+1,。信号量创建时一般等于最大资源数&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h3 id="计数型信号量相关api"&gt;&lt;a href="#%e8%ae%a1%e6%95%b0%e5%9e%8b%e4%bf%a1%e5%8f%b7%e9%87%8f%e7%9b%b8%e5%85%b3api" class="header-anchor"&gt;&lt;/a&gt;计数型信号量相关API&#13;&#10;&lt;/h3&gt;&lt;p&gt;创建-释放-获取&lt;/p&gt;&#10;&lt;p&gt;创建：&lt;/p&gt;&#10;&lt;img src="images/image-20250806145915838.png" alt="image-20250806145915838" style="zoom: 67%;" /&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//uxMaxCount计数值的最大值限定&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//uxInitialCount计数值的初始值&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define xSemaphoreCreateCounting(uxMaxCount, uxInitialCount)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#9;&#9;&lt;span class="nf"&gt;xQueueCreateCountingSemaphore&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;uxMaxCount&lt;/span&gt;&lt;span class="p"&gt;),(&lt;/span&gt;&lt;span class="n"&gt;uxInitialCount&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//返回值NULL创建失败&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//其他值返回句柄 &#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;获取和释放与二值相同&lt;/p&gt;&#10;&lt;h2 id="3优先级翻转"&gt;&lt;a href="#3%e4%bc%98%e5%85%88%e7%ba%a7%e7%bf%bb%e8%bd%ac" class="header-anchor"&gt;&lt;/a&gt;3.优先级翻转&#13;&#10;&lt;/h2&gt;&lt;p&gt;优先级翻转：高优先级任务反而慢执行，低优先级任务反而先执行&lt;/p&gt;&#10;&lt;p&gt;优先级翻转在抢占式内核中是很常见的问题，但是在实时操作系统中是不允许出现优先级翻转的，因为优先级翻转会破环任务的预期顺序，可能会导致未知的严重后果。在使用二值信号量的时候，经常会遇到优先级翻转问题。&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;角色&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;行为&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;优先级&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;H（高）&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;想用共享资源（如 UART、SPI）&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;3（最高）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;L（低）&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;已经拿到资源，正在用&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1（最低）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;M（中）&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;纯计算任务，不碰资源&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;2&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;&lt;img alt="image-20250806154108779" class="gallery-image" data-flex-basis="739px" data-flex-grow="308" height="449" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250806154108779.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250806154108779_hu_1013becb2ccac855.png 800w, https://zeseanblog.top/p/freertos/images/image-20250806154108779.png 1383w" width="1383"&gt;&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;L 先运行，&lt;strong&gt;拿到互斥量&lt;/strong&gt; → 进入临界区。&lt;/li&gt;&#10;&lt;li&gt;H 就绪，优先级最高，&lt;strong&gt;抢占 L&lt;/strong&gt;，但发现互斥量被占 → &lt;strong&gt;阻塞&lt;/strong&gt;。&lt;/li&gt;&#10;&lt;li&gt;M 就绪，优先级介于 H 和 L 之间 → &lt;strong&gt;抢占 L&lt;/strong&gt;，开始跑长计算。&lt;/li&gt;&#10;&lt;li&gt;结果：&#10;• &lt;strong&gt;H 必须等 M 跑完 → M 跑完 L 才能继续 → L 释放后 H 才能拿到&lt;/strong&gt;。&#10;• H 实际被 &lt;strong&gt;优先级远低于它的 L 间接阻塞&lt;/strong&gt;。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="4互斥信号量"&gt;&lt;a href="#4%e4%ba%92%e6%96%a5%e4%bf%a1%e5%8f%b7%e9%87%8f" class="header-anchor"&gt;&lt;/a&gt;4.互斥信号量&#13;&#10;&lt;/h2&gt;&lt;p&gt;互斥信号量是一个拥有优先级继承的二值信号量，在同步的应用中二值信号量最适合，互斥信号量适用与需要互斥访问的应用中。&lt;/p&gt;&#10;&lt;p&gt;优先级继承：当一个互斥信号量正在被一个低优先级的任务持有时， 如果此时有个高优先级的任务也尝试获取这个互斥信号量，那么这个高优先级的任务就会被阻塞。不过这个高优先级的任务会将低优先级任务的优先级提升到与自己相同的优先级。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250806155928222" class="gallery-image" data-flex-basis="751px" data-flex-grow="313" height="442" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250806155928222.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250806155928222_hu_a173b6b95d8daa22.png 800w, https://zeseanblog.top/p/freertos/images/image-20250806155928222.png 1384w" width="1384"&gt;&lt;/p&gt;&#10;&lt;p&gt;依旧L阻塞H，但M就不会浪费时间执行，将优先级翻转危害降低。&lt;/p&gt;&#10;&lt;p&gt;就是不能完全消除影响，但尽可能把影响降到最低。&lt;/p&gt;&#10;&lt;p&gt;注意：互斥信号量不能用于中断服务函数中。原因：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;互斥信号量有任务优先级继承的机制，但中断不是任务，没有任务优先级，所以互斥信号量只能用于任务中，不能用于中断服务函数&lt;/li&gt;&#10;&lt;li&gt;中断服务函数中不能因为要等待互斥信号量而设置阻塞时间进入阻塞态&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="互斥信号量相关api"&gt;&lt;a href="#%e4%ba%92%e6%96%a5%e4%bf%a1%e5%8f%b7%e9%87%8f%e7%9b%b8%e5%85%b3api" class="header-anchor"&gt;&lt;/a&gt;互斥信号量相关API&#13;&#10;&lt;/h3&gt;&lt;p&gt;宏 configUSE_MUTEXES 置一&lt;/p&gt;&#10;&lt;p&gt;创建互斥信号量 -（ task ）获取信号量 -（ give ）释放信号量&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250806160514786" class="gallery-image" data-flex-basis="1492px" data-flex-grow="621" height="147" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250806160514786.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250806160514786_hu_7a03770570c57bc9.png 800w, https://zeseanblog.top/p/freertos/images/image-20250806160514786.png 914w" width="914"&gt;&lt;/p&gt;&#10;&lt;p&gt;无传入参数&lt;/p&gt;&#10;&lt;p&gt;xSemaphoreCreateMutex()&lt;/p&gt;&#10;&lt;p&gt;返回NULL创建失败，其他值返回句柄&lt;/p&gt;&#10;&lt;p&gt;获取与释放与二值信号量相同，只是不支持中断调用&lt;/p&gt;&#10;&lt;h1 id="十五队列集"&gt;&lt;a href="#%e5%8d%81%e4%ba%94%e9%98%9f%e5%88%97%e9%9b%86" class="header-anchor"&gt;&lt;/a&gt;十五、队列集&#13;&#10;&lt;/h1&gt;&lt;h2 id="1简介-1"&gt;&lt;a href="#1%e7%ae%80%e4%bb%8b-1" class="header-anchor"&gt;&lt;/a&gt;1.简介&#13;&#10;&lt;/h2&gt;&lt;p&gt;一个队列只允许任务间传递同一种数据类型，如果要传递不同数据类型，可以使用队列集。&lt;/p&gt;&#10;&lt;p&gt;作用：&lt;/p&gt;&#10;&lt;p&gt;对多个队列或信号量进行监听，不管哪个消息到来，都可以让任务退出阻塞状态&lt;/p&gt;&#10;&lt;p&gt;原始思路：&lt;/p&gt;&#10; &lt;img src="images/image-20250806164333227.png" alt="image-20250806164333227" style="zoom:50%;" /&gt;&#10;&lt;p&gt;队列集思路：&lt;/p&gt;&#10; &lt;img src="images/image-20250806164353656.png" alt="image-20250806164353656" style="zoom:50%;" /&gt;&#10;&lt;h2 id="2队列集相关api"&gt;&lt;a href="#2%e9%98%9f%e5%88%97%e9%9b%86%e7%9b%b8%e5%85%b3api" class="header-anchor"&gt;&lt;/a&gt;2.队列集相关API&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;img alt="image-20250806164541592" class="gallery-image" data-flex-basis="724px" data-flex-grow="301" height="221" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250806164541592.png" width="667"&gt;&lt;/p&gt;&#10;&lt;h3 id="21创建xqueuecreateset"&gt;&lt;a href="#21%e5%88%9b%e5%bb%baxqueuecreateset" class="header-anchor"&gt;&lt;/a&gt;2.1创建xQueueCreateSet&#13;&#10;&lt;/h3&gt;&lt;p&gt;QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength );&lt;/p&gt;&#10;&lt;p&gt;参数：uxEventQueueLength 队列集可容纳的队列数量&lt;/p&gt;&#10;&lt;p&gt;返回值：NULL：队列集创建失败 其他值：创建成功，返回句柄&lt;/p&gt;&#10;&lt;h3 id="22添加xqueueaddtoset"&gt;&lt;a href="#22%e6%b7%bb%e5%8a%a0xqueueaddtoset" class="header-anchor"&gt;&lt;/a&gt;2.2添加xQueueAddToSet&#13;&#10;&lt;/h3&gt;&lt;p&gt;往队列集添加队列时，队列不能有消息&lt;/p&gt;&#10;&lt;p&gt;BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore ,&#10;QueueSetHandle_t xQueueSet );&lt;/p&gt;&#10;&lt;img src="images/image-20250806164917603.png" alt="image-20250806164917603" style="zoom:67%;" /&gt;&#10;&lt;h3 id="23移除"&gt;&lt;a href="#23%e7%a7%bb%e9%99%a4" class="header-anchor"&gt;&lt;/a&gt;2.3移除&#13;&#10;&lt;/h3&gt;&lt;p&gt;移除前不能有有效消息&lt;/p&gt;&#10;&lt;p&gt;BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore ,&#10;QueueSetHandle_t xQueueSet );&lt;/p&gt;&#10;&lt;img src="images/image-20250806165023992.png" alt="image-20250806165023992" style="zoom:67%;" /&gt;&#10;&lt;h3 id="24获取有效消息xqueueselectfromset"&gt;&lt;a href="#24%e8%8e%b7%e5%8f%96%e6%9c%89%e6%95%88%e6%b6%88%e6%81%afxqueueselectfromset" class="header-anchor"&gt;&lt;/a&gt;2.4获取有效消息xQueueSelectFromSet&#13;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;QueueSetMemberHandle_t&lt;/span&gt; &lt;span class="nf"&gt;xQueueSelectFromSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;QueueSetHandle_t&lt;/span&gt; &lt;span class="n"&gt;xQueueSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&lt;span class="n"&gt;TickType_t&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;xTicksToWait&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;img src="images/image-20250806165250506.png" alt="image-20250806165250506" style="zoom:67%;" /&gt;&#10;&lt;h4 id="示例"&gt;&lt;a href="#%e7%a4%ba%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;示例&#13;&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;member_handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;xQueueSelectFromSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queueset_handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;portMAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;member_handle&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;queue_handle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;xQueueReceive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue_handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;portMAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="n"&gt;pdPASS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;队列queue_handle读取数据成功&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;member_handle&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;semphr_handle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;xSemaphoreTake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;semphr_handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;portMAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="n"&gt;pdPASS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;获取信号量成功&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h1 id="十六事件标志组"&gt;&lt;a href="#%e5%8d%81%e5%85%ad%e4%ba%8b%e4%bb%b6%e6%a0%87%e5%bf%97%e7%bb%84" class="header-anchor"&gt;&lt;/a&gt;十六、事件标志组&#13;&#10;&lt;/h1&gt;&lt;h2 id="1简介-2"&gt;&lt;a href="#1%e7%ae%80%e4%bb%8b-2" class="header-anchor"&gt;&lt;/a&gt;1.简介&#13;&#10;&lt;/h2&gt;&lt;p&gt;事件标志组：用一个位表示时间是否发生&lt;/p&gt;&#10;&lt;p&gt;是一组事件标志位的集合，类似多个标志位&lt;/p&gt;&#10;&lt;p&gt;特点：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;每一个位表示一个事件（高八位不算）&lt;/li&gt;&#10;&lt;li&gt;每位事件的含义由用户决定如bit0表示按键，bit1表示消息是否接受&lt;/li&gt;&#10;&lt;li&gt;1：事件发生，0：事件未发生&lt;/li&gt;&#10;&lt;li&gt;任意任务和中断可读写这些位&lt;/li&gt;&#10;&lt;li&gt;可等待某一位，也可等待多位&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;一个事件组包含，EventBits_t是数据类型变量&lt;/p&gt;&#10;&lt;img src="images/image-20250806175133210.png" alt="image-20250806175133210" style="zoom:67%;" /&gt;&#10;&lt;p&gt;一个事件组最多可以存储 24 个事件标志&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250806175201301" class="gallery-image" data-flex-basis="1227px" data-flex-grow="511" height="251" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250806175201301.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250806175201301_hu_41a042c08b78db83.png 800w, https://zeseanblog.top/p/freertos/images/image-20250806175201301.png 1284w" width="1284"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;与队列信号量区别&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250806175250430" class="gallery-image" data-flex-basis="1180px" data-flex-grow="492" height="353" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250806175250430.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250806175250430_hu_a08245ad99b0c6a0.png 800w, https://zeseanblog.top/p/freertos/images/image-20250806175250430_hu_cc667ebbe191020.png 1600w, https://zeseanblog.top/p/freertos/images/image-20250806175250430.png 1737w" width="1737"&gt;&lt;/p&gt;&#10;&lt;h2 id="2事件标志组相关api"&gt;&lt;a href="#2%e4%ba%8b%e4%bb%b6%e6%a0%87%e5%bf%97%e7%bb%84%e7%9b%b8%e5%85%b3api" class="header-anchor"&gt;&lt;/a&gt;2.事件标志组相关API&#13;&#10;&lt;/h2&gt;&lt;img src="images/image-20250806175445375.png" alt="image-20250806175445375" style="zoom: 50%;" /&gt;&#10;&lt;h3 id="21创建xeventgroupcreate"&gt;&lt;a href="#21%e5%88%9b%e5%bb%baxeventgroupcreate" class="header-anchor"&gt;&lt;/a&gt;2.1创建xEventGroupCreate&#13;&#10;&lt;/h3&gt;&lt;p&gt;EventGroupHandle_t xEventGroupCreate ( void) ;&lt;/p&gt;&#10;&lt;p&gt;返回NULL：失败&lt;/p&gt;&#10;&lt;p&gt;​&#9;&#9;其他值：成功返回句柄&lt;/p&gt;&#10;&lt;h3 id="22清零标志位xeventgroupclearbits"&gt;&lt;a href="#22%e6%b8%85%e9%9b%b6%e6%a0%87%e5%bf%97%e4%bd%8dxeventgroupclearbits" class="header-anchor"&gt;&lt;/a&gt;2.2清零标志位xEventGroupClearBits&#13;&#10;&lt;/h3&gt;&lt;p&gt;EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,&#10;const EventBits_t uxBitsToClear )&lt;/p&gt;&#10;&lt;p&gt;参数：&lt;/p&gt;&#10;&lt;p&gt;xEventGroup 待操作的事件标志组句柄&#10;uxBitsToSet 待清零的事件标志位&lt;/p&gt;&#10;&lt;p&gt;返回：整数=清零事件标志位之前事件组中事件标志位的值&lt;/p&gt;&#10;&lt;h3 id="23设置标志位xeventgroupsetbits"&gt;&lt;a href="#23%e8%ae%be%e7%bd%ae%e6%a0%87%e5%bf%97%e4%bd%8dxeventgroupsetbits" class="header-anchor"&gt;&lt;/a&gt;2.3设置标志位xEventGroupSetBits&#13;&#10;&lt;/h3&gt;&lt;p&gt;EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,&#10;const EventBits_t uxBitsToSet )&lt;/p&gt;&#10;&lt;p&gt;参数：&lt;/p&gt;&#10;&lt;p&gt;xEventGroup 待操作的事件标志组句柄&#10;uxBitsToSet 待设置的事件标志位&lt;/p&gt;&#10;&lt;p&gt;返回：整数=函数返回时，事件组中的事件标志位值&lt;/p&gt;&#10;&lt;h3 id="24等待标志位xeventgroupwaitbits"&gt;&lt;a href="#24%e7%ad%89%e5%be%85%e6%a0%87%e5%bf%97%e4%bd%8dxeventgroupwaitbits" class="header-anchor"&gt;&lt;/a&gt;2.4等待标志位xEventGroupWaitBits&#13;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;EventBits_t&lt;/span&gt; &lt;span class="nf"&gt;xEventGroupWaitBits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;EventGroupHandle_t&lt;/span&gt; &lt;span class="n"&gt;xEventGroup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;EventBits_t&lt;/span&gt; &#9;&lt;span class="n"&gt;uxBitsToWaitFor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;BaseType_t&lt;/span&gt; &#9;&lt;span class="n"&gt;xClearOnExit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;BaseType_t&lt;/span&gt; &#9;&lt;span class="n"&gt;xWaitForAllBits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; &lt;span class="n"&gt;TickType_t&lt;/span&gt; &#9;&#9;&lt;span class="n"&gt;xTicksToWait&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;img src="images/image-20250806180148945.png" alt="image-20250806180148945" style="zoom: 67%;" /&gt;&#10;&lt;h3 id="25同步函数"&gt;&lt;a href="#25%e5%90%8c%e6%ad%a5%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;2.5同步函数&#13;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-C" data-lang="C"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;EventBits_t&lt;/span&gt; &lt;span class="nf"&gt;xEventGroupSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EventGroupHandle_t&lt;/span&gt; &lt;span class="n"&gt;xEventGroup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;EventBits_t&lt;/span&gt; &lt;span class="n"&gt;uxBitsToSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;EventBits_t&lt;/span&gt; &lt;span class="n"&gt;uxBitsToWaitFor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&lt;span class="n"&gt;TickType_t&lt;/span&gt; &#9; &lt;span class="n"&gt;xTicksToWait&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;img src="images/image-20250806191201673.png" alt="image-20250806191201673" style="zoom:67%;" /&gt;&#10;&lt;h3 id="示例-1"&gt;&lt;a href="#%e7%a4%ba%e4%be%8b-1" class="header-anchor"&gt;&lt;/a&gt;示例&#13;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;EventGroupHandle_t&lt;/span&gt; &lt;span class="n"&gt;eventgroup_handle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define EVENTBIT_0 1&amp;lt;&amp;lt;0&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define EVENTBIT_1 1&amp;lt;&amp;lt;1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;eventgroup_handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;xEventGroupCreate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="n"&gt;KEY0_PRES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;xEventGroupSetBits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eventgroup_handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;EVENTBIT_0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="n"&gt;KEY1_PRES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;xEventGroupSetBits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eventgroup_handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;EVENTBIT_1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;event_bit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;xEventGroupWaitBits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eventgroup_handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;EVENTBIT_0&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;EVENTBIT_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pdTRUE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;pdFALSE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;portMAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;等待到的事件标志位值:%#x&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;event_bit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h1 id="十七任务通知"&gt;&lt;a href="#%e5%8d%81%e4%b8%83%e4%bb%bb%e5%8a%a1%e9%80%9a%e7%9f%a5" class="header-anchor"&gt;&lt;/a&gt;十七、任务通知&#13;&#10;&lt;/h1&gt;&lt;h2 id="1简介-3"&gt;&lt;a href="#1%e7%ae%80%e4%bb%8b-3" class="header-anchor"&gt;&lt;/a&gt;1.简介&#13;&#10;&lt;/h2&gt;&lt;p&gt;任务通知：用来通知任务，任务控制块中的结构体成员变量 ulNotifiedValue 就是这个通&lt;/p&gt;&#10;&lt;p&gt;知值&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;为什么还要这个？&lt;/strong&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;使用&lt;strong&gt;任务通知&lt;/strong&gt;时，任务结构体就包含了内部对象，可以直接接收别人发过来的&lt;strong&gt;通知&lt;/strong&gt;&#10;&lt;img alt="在这里插入图片描述" class="gallery-image" data-flex-basis="871px" data-flex-grow="363" height="196" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/csdn-826666d0048549709d41c331ad93a2b4.png" width="712"&gt;&lt;/li&gt;&#10;&lt;li&gt;使用&lt;strong&gt;队列、信号量、事件标志组&lt;/strong&gt;时都需另外创建一个结构体，通过中间的结构体进行简介通信&#10;&lt;img alt="在这里插入图片描述" class="gallery-image" data-flex-basis="955px" data-flex-grow="398" height="178" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/csdn-7865c42904614928b03cb5f96b1c92f5.png" width="709"&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;发送端修改接收端任务控制块中结构体变量：ulNotifiedValue&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;任务通知值的更新方式&lt;/strong&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;覆盖或不覆盖接受任务的通知值（队列）&lt;/li&gt;&#10;&lt;li&gt;更新接收任务通知值的一个过多个 bit（事件标志组）&lt;/li&gt;&#10;&lt;li&gt;增加接收任务的通知值（信号量）&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;但只能在一些场合替代&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;优劣势&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;优势：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;效率高：使用任务通知向任务发送事件或数据比使用队列、事件标志组或信号量快&lt;/li&gt;&#10;&lt;li&gt;使用内存更小：使用其他方法时都要先创建对应的结构体，使用任务通知时无需&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;劣势：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;无法发送数据给 ISR（中断服务函数）：ISR 没有任务结构体，因此无法给 ISR 发送数据，但 ISR可以使用任务通知的功能发送数据给任务&lt;/li&gt;&#10;&lt;li&gt;无法广播给多个任务：任务通知只能是被指定的一个任务接收并处理&lt;/li&gt;&#10;&lt;li&gt;无法缓存多个数据：任务通知是通过更新任务通知值来发送数据的，任务结构体中只有一个任务通知值，只能保持一个数据&lt;/li&gt;&#10;&lt;li&gt;发送受阻不支持阻塞：发送方无法进入阻塞状态等待&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="2任务通知值和通知状态"&gt;&lt;a href="#2%e4%bb%bb%e5%8a%a1%e9%80%9a%e7%9f%a5%e5%80%bc%e5%92%8c%e9%80%9a%e7%9f%a5%e7%8a%b6%e6%80%81" class="header-anchor"&gt;&lt;/a&gt;2.任务通知值和通知状态&#13;&#10;&lt;/h2&gt;&lt;p&gt;任务的任务控制块中，有两个结构体成员变量就是任务通知相关的&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;tskTaskControlBlock&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="cp"&gt;#if(configUSE_TASK_NOTIFICATIONS == 1)&#9;&lt;/span&gt;&lt;span class="c1"&gt;//打开这个宏&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;ulNotifiedValue&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;configTASK_NOTIFICATION_ARRAY_ENTRIES&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#9;&lt;span class="c1"&gt;//通知值&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;ucNotifyState&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;configTASK_NOTIFICATION_ARRAY_ENTRIES&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#9;&#9;&lt;span class="c1"&gt;//通知状态&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;endif&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="n"&gt;tskTCB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define configTASK_NOTIFICATION_ARRAY_ENTRIES 1&#9;&lt;/span&gt;&lt;span class="c1"&gt;//定义任务通知数组的大小，默认为1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;任务通知值ulNotifiedValue&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;更新方式：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;计数值（数值累加，类似信号量）&lt;/li&gt;&#10;&lt;li&gt;相应位置1（类似事件标志组）&lt;/li&gt;&#10;&lt;li&gt;任意数（支持覆写不覆写，类似队列）&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;任务通知状态ucNotifyState&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;三种取值：&lt;/p&gt;&#10;&lt;p&gt;#define taskNOT_WAITING_NOTIFICATION ((uint8_t)0)&#9;&#9;//任务未等待通知&#10;#define taskWAITING_NOTIFICATION &#9; ((uint8_t)1)&#9;&#9;//任务在等待通知&#10;#define taskNOTIFICATION_RECEIVED ((uint8_t)2)&#9;&#9;//任务在等待接收&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;未等待通知：任务通知默认的初始化状态（事不关己，高高挂起）&lt;/li&gt;&#10;&lt;li&gt;等待通知：接收方已经准备好了（调用了&lt;strong&gt;接收&lt;/strong&gt;任务通知函数），等待发送方给个通知&lt;/li&gt;&#10;&lt;li&gt;等待接收：发送方已经发送出去（调用了&lt;strong&gt;发送&lt;/strong&gt;任务通知函数），等待接收方接收&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="3任务通知api函数"&gt;&lt;a href="#3%e4%bb%bb%e5%8a%a1%e9%80%9a%e7%9f%a5api%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;3.任务通知API函数&#13;&#10;&lt;/h2&gt;&lt;p&gt;有发送和接收，发送可在任务和中断中，接收只能在任务（因为中断没TCB）&lt;/p&gt;&#10;&lt;h3 id="31发送"&gt;&lt;a href="#31%e5%8f%91%e9%80%81" class="header-anchor"&gt;&lt;/a&gt;3.1发送&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img alt="image-20250806194128769" class="gallery-image" data-flex-basis="496px" data-flex-grow="207" height="342" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250806194128769.png" width="708"&gt;&lt;/p&gt;&#10;&lt;p&gt;函数原型&lt;/p&gt;&#10;&lt;img src="images/image-20250806195030350.png" alt="image-20250806195030350" style="zoom:67%;" /&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;BaseType_t&lt;/span&gt; &lt;span class="nf"&gt;xTaskGenericNotify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TaskHandle_t&lt;/span&gt; &lt;span class="n"&gt;xTaskToNotify&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#9;&#9;&#9;&#9; &lt;span class="n"&gt;UBaseType_t&lt;/span&gt; &lt;span class="n"&gt;uxIndexToNotify&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &#9; &lt;span class="n"&gt;ulValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9; &lt;span class="n"&gt;eNotifyAction&lt;/span&gt; &lt;span class="n"&gt;eAction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pulPreviousNotificationValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define xTaskNotify(xTaskToNotify, ulValue, eAction) &#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;xTaskGenericNotify&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;xTaskToNotify&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tskDEFAULT_INDEX_TO_NOTIFY&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&#9;&#9; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ulValue&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eAction&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &#9;&#9;&#9;&#9; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define xTaskNotifyAndQuery(xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue) &#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#9;&lt;span class="nf"&gt;xTaskGenericNotify&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;xTaskToNotify&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tskDEFAULT_INDEX_TO_NOTIFY&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#9;&#9;&#9;&#9;&#9; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ulValue&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eAction&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pulPreviousNotifyValue&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &#9;&#9;&#9; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define xTaskNotifyGive(xTaskToNotify) &#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#9; &#9;&lt;span class="nf"&gt;xTaskGenericNotify&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;xTaskToNotify&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tskDEFAULT_INDEX_TO_NOTIFY&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#9;&#9;&#9;&#9; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;eIncrement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;其中通知方式（通知值更新方式）eNotifyAction&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;span class="lnt"&gt;7&#10;&lt;/span&gt;&lt;span class="lnt"&gt;8&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;eNoAction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &#9;&#9;&#9;&#9;&lt;span class="cm"&gt;/* 无操作 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;eSetBits&lt;/span&gt; &#9;&#9;&#9;&#9;&#9;&lt;span class="cm"&gt;/* 更新指定 bit */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;eIncrement&lt;/span&gt; &#9;&#9;&#9;&#9;&#9;&lt;span class="cm"&gt;/* 通知值加一 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;eSetValueWithOverwrite&lt;/span&gt; &#9;&#9;&lt;span class="cm"&gt;/* 覆写的方式更新通知值*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;eSetValueWithoutOverwrite&lt;/span&gt; &#9;&lt;span class="cm"&gt;/* 不覆写通知值 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;eNotifyAction&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h3 id="32接收"&gt;&lt;a href="#32%e6%8e%a5%e6%94%b6" class="header-anchor"&gt;&lt;/a&gt;3.2接收&#13;&#10;&lt;/h3&gt;&lt;img src="images/image-20250806195719064.png" alt="image-20250806195719064" style="zoom:67%;" /&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;当任务通知用作与信号量时，使用函数获取信号量：&lt;code&gt;ulTaskNotifyTake( )&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;当任务通知用作与事件标志组或队列时，使用此函数来获取：&lt;code&gt;xTaskNotifyWait( )&lt;/code&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4 id="321ultasknotifytake"&gt;&lt;a href="#321ultasknotifytake" class="header-anchor"&gt;&lt;/a&gt;3.2.1ulTaskNotifyTake&#13;&#10;&lt;/h4&gt;&lt;p&gt;ulTaskNotifyTake( xClearCountOnExit , xTicksToWait )&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;#define ulTaskNotifyTake(xClearCountOnExit, xTicksToWait) &#10;&#9;&#9;ulTaskGenericNotifyTake((tskDEFAULT_INDEX_TO_NOTIFY), &#10;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;(xClearCountOnExit), &#10;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;(xTicksToWait)) &#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;原型&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;uint32_t ulTaskGenericNotifyTake(UBaseType_t uxIndexToWaitOn, &#10;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; BaseType_t xClearCountOnExit, &#10;&#9;&#9;&#9;&#9;&#9;&#9;&#9; &#9; TickType_t xTicksToWait); &#10;&lt;/code&gt;&lt;/pre&gt;&lt;img src="images/image-20250806201907259.png" alt="image-20250806201907259" style="zoom:67%;" /&gt;&#10;&lt;p&gt;通知值清零模拟二值信号量，通知值减一模拟计数型信号量&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;3.2.2xTaskNotifyWait&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;此函数用于等待任务通知通知值中的指定比特位被置 1，此函数可以在等待前和成功等待到任务通知通知值中的指定比特位被置 1 后清零指定比特位，并且还能获取等待超时后任务通知的通知值。&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;#define xTaskNotifyWait(ulBitsToClearOnEntry, &#10;&#9;&#9;&#9; ulBitsToClearOnExit, &#10;&#9;&#9;&#9; pulNotificationValue, &#10;&#9;&#9;&#9; xTicksToWait) &#10; &#9; xTaskGenericNotifyWait(tskDEFAULT_INDEX_TO_NOTIFY, &#10;&#9;&#9;&#9;&#9;&#9; (ulBitsToClearOnEntry), &#10;&#9;&#9;&#9;&#9;&#9; (ulBitsToClearOnExit), &#10;&#9;&#9;&#9;&#9;&#9; (pulNotificationValue), &#10;&#9;&#9;&#9;&#9;&#9; (xTicksToWait)) &#10;&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;形参&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;描述&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;uxIndexToWaitOn&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;等待的任务通知索引（任务通知数组下标）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;ulBitsToClearOnEntry&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;进入等待前，把任务通知值的哪些位清 0（旧值对应位清零）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;ulBitsToClearOnExit&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;等待成功后，把任务通知值的哪些位清 0（新值对应位清零）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;pulNotificationValue&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;用于取出当时的 32 位通知值；若不需要，可设为 NULL&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;xTicksToWait&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;最大阻塞等待时间（以系统节拍为单位）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;返回值&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;描述&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;pdTRUE&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;等待任务通知成功（已满足等待条件）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;pdFALSE&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;等待任务通知失败（超时或被中断）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="4任务通知模拟信号量"&gt;&lt;a href="#4%e4%bb%bb%e5%8a%a1%e9%80%9a%e7%9f%a5%e6%a8%a1%e6%8b%9f%e4%bf%a1%e5%8f%b7%e9%87%8f" class="header-anchor"&gt;&lt;/a&gt;4.任务通知模拟信号量&#13;&#10;&lt;/h2&gt;&lt;p&gt;模拟二值信号量&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;task1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pvParamenters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;key_scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="n"&gt;KEY0_PRES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;任务通知模拟二值信号量释放&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;xTaskNotifyGive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task2_handle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;task2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pvParamenters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;rev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;rev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ulTaskNotifyTake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdTRUE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;portMAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rev&lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;接受任务通知成功,获取模拟二值信号量&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;模拟计数型信号量&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;task1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pvParamenters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;key_scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="n"&gt;KEY0_PRES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;任务通知模拟计数型信号量释放&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;xTaskNotifyGive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task2_handle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;task2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pvParamenters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;rev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;rev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ulTaskNotifyTake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdFALSE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;portMAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rev&lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;接受任务通知成功,模拟获取计数型信号量,rev:%d&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;rev&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;vTaskDelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h2 id="5任务通知模拟消息邮箱类似队列"&gt;&lt;a href="#5%e4%bb%bb%e5%8a%a1%e9%80%9a%e7%9f%a5%e6%a8%a1%e6%8b%9f%e6%b6%88%e6%81%af%e9%82%ae%e7%ae%b1%e7%b1%bb%e4%bc%bc%e9%98%9f%e5%88%97" class="header-anchor"&gt;&lt;/a&gt;5.任务通知模拟消息邮箱（类似队列）&#13;&#10;&lt;/h2&gt;&lt;p&gt;消息邮箱其实就是长度为1的队列&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;task1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pvParamenters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;key_scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task2_handle&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;任务通知模拟消息邮箱发送,发送的键值为:%d&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;xTaskNotify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task2_handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;eSetValueWithOverwrite&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;vTaskDelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;task2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pvParamenters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;notify_val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;xTaskNotifyWait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xFFFFFFFF&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;notify_val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;portMAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;接受到的通知值为:%d&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;notify_val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h2 id="6任务通知模拟事件标志组"&gt;&lt;a href="#6%e4%bb%bb%e5%8a%a1%e9%80%9a%e7%9f%a5%e6%a8%a1%e6%8b%9f%e4%ba%8b%e4%bb%b6%e6%a0%87%e5%bf%97%e7%bb%84" class="header-anchor"&gt;&lt;/a&gt;6.任务通知模拟事件标志组&#13;&#10;&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;span class="lnt"&gt;29&#10;&lt;/span&gt;&lt;span class="lnt"&gt;30&#10;&lt;/span&gt;&lt;span class="lnt"&gt;31&#10;&lt;/span&gt;&lt;span class="lnt"&gt;32&#10;&lt;/span&gt;&lt;span class="lnt"&gt;33&#10;&lt;/span&gt;&lt;span class="lnt"&gt;34&#10;&lt;/span&gt;&lt;span class="lnt"&gt;35&#10;&lt;/span&gt;&lt;span class="lnt"&gt;36&#10;&lt;/span&gt;&lt;span class="lnt"&gt;37&#10;&lt;/span&gt;&lt;span class="lnt"&gt;38&#10;&lt;/span&gt;&lt;span class="lnt"&gt;39&#10;&lt;/span&gt;&lt;span class="lnt"&gt;40&#10;&lt;/span&gt;&lt;span class="lnt"&gt;41&#10;&lt;/span&gt;&lt;span class="lnt"&gt;42&#10;&lt;/span&gt;&lt;span class="lnt"&gt;43&#10;&lt;/span&gt;&lt;span class="lnt"&gt;44&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define EVENTBIT_0 1&amp;lt;&amp;lt;0&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define EVENTBIT_1 1&amp;lt;&amp;lt;1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;task1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pvParamenters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;key_scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="n"&gt;KEY0_PRES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;更新bit0位置1&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;xTaskNotify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task2_handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;EVENTBIT_0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;eSetBits&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="n"&gt;KEY1_PRES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;更新bit1位置1&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;xTaskNotify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task2_handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;EVENTBIT_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;eSetBits&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;vTaskDelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;task2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pvParamenters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;notify_val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;event_bit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;xTaskNotifyWait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0xFFFFFFFF&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;notify_val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;portMAX_DELAY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;notify_val&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;EVENTBIT_0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;event_bit&lt;/span&gt;&lt;span class="o"&gt;|=&lt;/span&gt;&lt;span class="n"&gt;EVENTBIT_0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;notify_val&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;EVENTBIT_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;event_bit&lt;/span&gt;&lt;span class="o"&gt;|=&lt;/span&gt;&lt;span class="n"&gt;EVENTBIT_1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event_bit&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EVENTBIT_0&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;EVENTBIT_1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;任务通知模拟事件标志组接收成功&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;event_bit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h1 id="十八软件定时器"&gt;&lt;a href="#%e5%8d%81%e5%85%ab%e8%bd%af%e4%bb%b6%e5%ae%9a%e6%97%b6%e5%99%a8" class="header-anchor"&gt;&lt;/a&gt;十八、软件定时器&#13;&#10;&lt;/h1&gt;&lt;p&gt;&lt;img alt="image-20250806205006783" class="gallery-image" data-flex-basis="577px" data-flex-grow="240" height="346" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/image-20250806205006783.png" srcset="https://zeseanblog.top/p/freertos/images/image-20250806205006783_hu_62851451dbd3d8fc.png 800w, https://zeseanblog.top/p/freertos/images/image-20250806205006783.png 833w" width="833"&gt;&lt;/p&gt;&#10;&lt;h2 id="1简介-4"&gt;&lt;a href="#1%e7%ae%80%e4%bb%8b-4" class="header-anchor"&gt;&lt;/a&gt;1.简介&#13;&#10;&lt;/h2&gt;&lt;p&gt;定时器：指定时刻开始，经过指定时间，触发超时事件，用户可自定义周期&lt;/p&gt;&#10;&lt;p&gt;硬件定时器：芯片自带定时器，精度高，通过定时器中断，在中断服务函数处理&lt;/p&gt;&#10;&lt;p&gt;软件定时器：定时功能的软件，可设定定时周期，超时调用回调函数，在回调函数处理&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;软件定时器优缺点&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;优点：硬件定时器有限，而软件定时器理论更多；使用简单&lt;/p&gt;&#10;&lt;p&gt;缺点：精度低，对于高精度要求，不使用&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;FreeRTOS软件定时器特点&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;可裁剪：configUSE_TIMERS 配置项配置成 1&lt;/p&gt;&#10;&lt;p&gt;支持单次和周期&lt;/p&gt;&#10;&lt;p&gt;注：软件定时器的超时回调函数是由软件定时器服务任务调用的，软件定时器的超时回调函数本身不是任务，因此不能在该回调函数中使用可能会导致任务阻塞的 API 函数&lt;/p&gt;&#10;&lt;p&gt;软件定时器服务任务：vTaskStartScheduler()中会创建&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;软件定时器命令队列&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;FreeRTOS 提供了许多软件定时器相关的 API 函数，这些 API 函数大多是往定时器的队列中写入消息（发送命令），这个队列叫做软件定时器命令队列。这个队列控制软件定时器&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="在这里插入图片描述" class="gallery-image" data-flex-basis="664px" data-flex-grow="276" height="320" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/csdn-dec1d4afafd944af9c3d72484668e479.png" srcset="https://zeseanblog.top/p/freertos/images/csdn-dec1d4afafd944af9c3d72484668e479_hu_d4a148b3eebc8b5c.png 800w, https://zeseanblog.top/p/freertos/images/csdn-dec1d4afafd944af9c3d72484668e479.png 886w" width="886"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;软件定时器相关配置&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;configUSE_TIMERS配置为1&lt;/p&gt;&#10;&lt;p&gt;启动任务调度器时，会自动创建软件定时器的服务 / 守护任务&lt;code&gt;prvTimerTask( );&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;软件定时器服务任务的优先级为&lt;code&gt;configTIMER_TASK_PRIORITY = 31;&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;定时器的命令队列长度为&lt;code&gt;configTIMER_QUEUE_LENGTH = 5;&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;注：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;服务任务服务于多个定时器，因此定时器的回调函数不能影响其他定时器&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;回调函数要尽快实行，不能进入阻塞状态，既不能调用那些会阻塞任务的 API 函数，如&lt;code&gt;vTaskDelay( );&lt;/code&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;访问队列或者信号量的非零阻塞时间的 API 函数也不能调用&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;软件定时器状态&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;休眠态、运行态&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;单次定时器和周期定时器&lt;/strong&gt;&lt;/p&gt;&#10;&lt;img src="images/csdn-1a24e562ecc04dc6b02c8e997b73fb93.png" alt="在这里插入图片描述" style="zoom:67%;" /&gt;&#10;&lt;img src="images/csdn-4fe5bfabfcf346cea4ccaa38d865be8f.png" alt="在这里插入图片描述" style="zoom:67%;" /&gt;&#10;&lt;h2 id="2软件定时器结构体"&gt;&lt;a href="#2%e8%bd%af%e4%bb%b6%e5%ae%9a%e6%97%b6%e5%99%a8%e7%bb%93%e6%9e%84%e4%bd%93" class="header-anchor"&gt;&lt;/a&gt;2.软件定时器结构体&#13;&#10;&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pcTimerName&lt;/span&gt; &#9;&#9;&#9;&#9;&#9;&lt;span class="cm"&gt;/* 软件定时器名字 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;ListItem_t&lt;/span&gt; &lt;span class="n"&gt;xTimerListItem&lt;/span&gt; &#9;&#9;&#9;&#9;&#9;&lt;span class="cm"&gt;/* 软件定时器列表项 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;TickType_t&lt;/span&gt; &lt;span class="n"&gt;xTimerPeriodInTicks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &#9;&#9;&#9;&lt;span class="cm"&gt;/* 软件定时器的周期*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pvTimerID&lt;/span&gt; &#9;&#9;&#9;&#9;&#9;&#9;&#9;&lt;span class="cm"&gt;/* 软件定时器的 ID */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;TimerCallbackFunction_t&lt;/span&gt; &lt;span class="n"&gt;pxCallbackFunction&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* 软件定时器的回调函数*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="cp"&gt;#if ( configUSE_TRACE_FACILITY == 1 )&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="n"&gt;UBaseType_t&lt;/span&gt; &lt;span class="n"&gt;uxTimerNumber&lt;/span&gt; &#9;&#9;&#9;&#9;&lt;span class="cm"&gt;/* 软件定时器编号调试用*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="cp"&gt;#endif&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;ucStatus&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &#9;&#9;&#9;&#9;&#9;&#9;&#9;&lt;span class="cm"&gt;/* 软件定时器的状态 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;xTIMER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h2 id="3软件定时器相关api"&gt;&lt;a href="#3%e8%bd%af%e4%bb%b6%e5%ae%9a%e6%97%b6%e5%99%a8%e7%9b%b8%e5%85%b3api" class="header-anchor"&gt;&lt;/a&gt;3.软件定时器相关API&#13;&#10;&lt;/h2&gt;&lt;img src="images/image-20250806211339288.png" alt="image-20250806211339288" style="zoom:50%;" /&gt;&#10;&lt;h3 id="31创建xtimercreate"&gt;&lt;a href="#31%e5%88%9b%e5%bb%baxtimercreate" class="header-anchor"&gt;&lt;/a&gt;3.1创建xTimerCreate&#13;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;TimerHandle_t&lt;/span&gt; &lt;span class="nf"&gt;xTimerCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &#9;&lt;span class="n"&gt;pcTimerName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&#9;&#9; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;TickType_t&lt;/span&gt; &#9; &lt;span class="n"&gt;xTimerPeriodInTicks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&#9;&#9; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;UBaseType_t&lt;/span&gt; &#9;&#9;&lt;span class="n"&gt;uxAutoReload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&#9;&#9; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &#9;&#9;&lt;span class="n"&gt;pvTimerID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&#9;&#9; &lt;span class="n"&gt;TimerCallbackFunction_t&lt;/span&gt; &lt;span class="n"&gt;pxCallbackFunction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;形参&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;描述&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;pcTimerName&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;软件定时器名称（字符串）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;xTimerPeriodInTicks&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;定时周期，以系统时钟节拍（ticks）为单位&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;uxAutoReload&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;定时器模式：&lt;br&gt;&lt;strong&gt;pdTRUE&lt;/strong&gt; = 周期定时器（重复触发）&lt;br&gt;&lt;strong&gt;pdFALSE&lt;/strong&gt; = 单次定时器（触发一次后停止）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;pvTimerID&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;用户自定义 ID，可用于多个定时器共用同一回调函数时区分实例&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;pxCallbackFunction&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;定时器超时时的回调函数指针&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;返回值&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;描述&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;NULL&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;软件定时器创建失败&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;非 NULL 句柄&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;软件定时器创建成功，返回该定时器的句柄&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;创建例子&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;timer1_handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;xTimerCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;timer1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;pdFALSE&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;timer1_callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;timer2_handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;xTimerCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;timer2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;pdTRUE&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;timer2_callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h3 id="32开启xtimerstart"&gt;&lt;a href="#32%e5%bc%80%e5%90%afxtimerstart" class="header-anchor"&gt;&lt;/a&gt;3.2开启xTimerStart&#13;&#10;&lt;/h3&gt;&lt;p&gt;BaseType_t xTimerStart( TimerHandle_t xTimer,&#10;const TickType_t xTicksToWait );&lt;/p&gt;&#10;&lt;p&gt;参数：xTimer 待开启的软件定时器的句柄&#10;xTickToWait 发送命令到软件定时器命令队列的最大等待时间&lt;/p&gt;&#10;&lt;p&gt;返回pdPASS，pdFAIL&lt;/p&gt;&#10;&lt;h3 id="33停止xtimerstop"&gt;&lt;a href="#33%e5%81%9c%e6%ad%a2xtimerstop" class="header-anchor"&gt;&lt;/a&gt;3.3停止xTimerStop&#13;&#10;&lt;/h3&gt;&lt;p&gt;BaseType_t xTimerStop( TimerHandle_t xTimer,&#10;const TickType_t xTicksToWait);&lt;/p&gt;&#10;&lt;p&gt;参数：xTimer 待停止的软件定时器的句柄&#10;xTickToWait 发送命令到软件定时器命令队列的最大等待时间&lt;/p&gt;&#10;&lt;p&gt;返回pdPASS，pdFAIL&lt;/p&gt;&#10;&lt;h3 id="34复位xtimerreset"&gt;&lt;a href="#34%e5%a4%8d%e4%bd%8dxtimerreset" class="header-anchor"&gt;&lt;/a&gt;3.4复位xTimerReset&#13;&#10;&lt;/h3&gt;&lt;p&gt;使软件定时器的重新开启定时&lt;/p&gt;&#10;&lt;p&gt;BaseType_t xTimerReset( TimerHandle_t xTimer,&#10;const TickType_t xTicksToWait);&lt;/p&gt;&#10;&lt;p&gt;参数：xTimer 待复位的软件定时器的句柄&#10;xTickToWait 发送命令到软件定时器命令队列的最大等待时间&lt;/p&gt;&#10;&lt;p&gt;返回pdPASS，pdFAIL&lt;/p&gt;&#10;&lt;h3 id="35更改超时时间xtimerchangeperiod"&gt;&lt;a href="#35%e6%9b%b4%e6%94%b9%e8%b6%85%e6%97%b6%e6%97%b6%e9%97%b4xtimerchangeperiod" class="header-anchor"&gt;&lt;/a&gt;3.5更改超时时间xTimerChangePeriod&#13;&#10;&lt;/h3&gt;&lt;p&gt;BaseType_t xTimerChangePeriod( TimerHandle_t xTimer,&#10;const TickType_t xNewPeriod,&#10;const TickType_t xTicksToWait);&lt;/p&gt;&#10;&lt;p&gt;参数：xTimer 待更新的软件定时器的句柄&#10;xNewPeriod 新的定时超时时间，单位：系统时钟节拍&#10;xTickToWait 发送命令到软件定时器命令队列的最大等待时间&lt;/p&gt;&#10;&lt;p&gt;返回pdPASS，pdFAIL&lt;/p&gt;&#10;&lt;h3 id="示例-2"&gt;&lt;a href="#%e7%a4%ba%e4%be%8b-2" class="header-anchor"&gt;&lt;/a&gt;示例&#13;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;TimerHandle_t&lt;/span&gt; &lt;span class="n"&gt;timer1_handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="cm"&gt;/*单次定时器*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;TimerHandle_t&lt;/span&gt; &lt;span class="n"&gt;timer2_handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="cm"&gt;/*周期定时器*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;timer1_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TimerHandle_t&lt;/span&gt; &lt;span class="n"&gt;pxTimer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;timer2_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TimerHandle_t&lt;/span&gt; &lt;span class="n"&gt;pxTimer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;timer1_handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;xTimerCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;timer1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;pdFALSE&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;timer1_callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;timer2_handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;xTimerCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;timer2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;pdTRUE&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;timer2_callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;xTimerStart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timer2_handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;xTimerStart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timer1_handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;timer1_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TimerHandle_t&lt;/span&gt; &lt;span class="n"&gt;pxTimer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;timer1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Timer1的运行次数:%d&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;timer1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;timer2_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TimerHandle_t&lt;/span&gt; &lt;span class="n"&gt;pxTimer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;timer2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Timer2的运行次数:%d&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;timer2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h1 id="十九tickless低功耗模式"&gt;&lt;a href="#%e5%8d%81%e4%b9%9dtickless%e4%bd%8e%e5%8a%9f%e8%80%97%e6%a8%a1%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;十九、Tickless低功耗模式&#13;&#10;&lt;/h1&gt;&lt;h2 id="1低功耗模式"&gt;&lt;a href="#1%e4%bd%8e%e5%8a%9f%e8%80%97%e6%a8%a1%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;1.低功耗模式&#13;&#10;&lt;/h2&gt;&lt;p&gt;STM32提供集中低功耗，睡眠，停止，待机&lt;/p&gt;&#10;&lt;p&gt;FreeRTOS也提供Tickless低功耗模式，通过动态调整SysTick 减少不必要的 CPU 唤醒，从而降低功耗&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="在这里插入图片描述" class="gallery-image" data-flex-basis="890px" data-flex-grow="370" height="165" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/freertos/images/csdn-513b937e09684f76af4d3b4f8a5a0124.png" width="612"&gt;&lt;/p&gt;&#10;&lt;p&gt;为了降低功耗，又不影响系统运行，可以在本该空闲任务执行期间，让 MCU 进入相应的低功耗模式；当其他任务准备运行的时候，唤醒 MCU 退出低功耗模式，但是进入低功耗之后，多久唤醒，下一个要运行的任务如何被准确唤醒？任何中断均可唤醒 MCU，若滴答定时器频繁中断则会影响低功耗的效果。这些问题可以这样解决：&lt;/p&gt;&#10;&lt;p&gt;将滴答定时器的中断周期修改为低功耗运行时间&#10;推出低功耗之后，补上系统时钟节拍数&lt;/p&gt;&#10;&lt;h2 id="2相关配置"&gt;&lt;a href="#2%e7%9b%b8%e5%85%b3%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;2.相关配置&#13;&#10;&lt;/h2&gt;&lt;p&gt;使能低功耗 Tickless 模式：configUSE_TICKLESS_IDLE&#10;定义系统进入相应低功耗模式的最短时长：configEXPECTED_IDLE_TIME_BEFORE_SLEEP&#10;定义需要在系统进入低功耗模式之前执行的事务，例如：进入低功耗之前关闭外设时钟，以降低功耗：configPRE_SLEEP_PROCESSING(x)，需要自己在 FreeRTOSconfig.h 里面自己定义&#10;定义需要在系统退出低功耗模式之后执行的事务，例如：退出低功耗之后开启被关闭的外设时钟，使系统能够正常运行：configPOST_SLEEP_PROCESSING(x)，需要自己在 FreeRTOSconfig.h 里面自己定义&lt;/p&gt;&#10;&lt;h2 id="3实现"&gt;&lt;a href="#3%e5%ae%9e%e7%8e%b0" class="header-anchor"&gt;&lt;/a&gt;3.实现&#13;&#10;&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;span class="lnt"&gt;29&#10;&lt;/span&gt;&lt;span class="lnt"&gt;30&#10;&lt;/span&gt;&lt;span class="lnt"&gt;31&#10;&lt;/span&gt;&lt;span class="lnt"&gt;32&#10;&lt;/span&gt;&lt;span class="lnt"&gt;33&#10;&lt;/span&gt;&lt;span class="lnt"&gt;34&#10;&lt;/span&gt;&lt;span class="lnt"&gt;35&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define configUSE_TICKLESS_IDLE 1 &#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//接着在 FreeRTOSconfig.h 文件中找个位置定义下面函数&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;#34;freertos_demo.h&amp;#34;&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define configPRE_SLEEP_PROCESSING( x )&#9;&#9;PRE_SLEEP_PROCESSING()&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define configPOST_SLEEP_PROCESSING( x )&#9;POSR_SLEEP_PROCESSING()&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//freertos_demo.h 文件里声明这两个函数&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;PRE_SLEEP_PROCESSING&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;POST_SLEEP_PROCESSING&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//freertos_demo.c 文件里，入口函数上面定义&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//进入低功耗模式前要关闭的事情&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;PRE_SLEEP_PROCESSING&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;__HAL_RCC_GPIOA_CLK_DISABLE&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;__HAL_RCC_GPIOB_CLK_DISABLE&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;__HAL_RCC_GPIOC_CLK_DISABLE&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;__HAL_RCC_GPIOD_CLK_DISABLE&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;__HAL_RCC_GPIOE_CLK_DISABLE&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;__HAL_RCC_GPIOF_CLK_DISABLE&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;__HAL_RCC_GPIOG_CLK_DISABLE&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//退出低功耗模式后需要打开的事情&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;POST_SLEEP_PROCESSING&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;__HAL_RCC_GPIOA_CLK_ENABLE&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;__HAL_RCC_GPIOB_CLK_ENABLE&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;__HAL_RCC_GPIOC_CLK_ENABLE&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;__HAL_RCC_GPIOD_CLK_ENABLE&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;__HAL_RCC_GPIOE_CLK_ENABLE&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;__HAL_RCC_GPIOF_CLK_ENABLE&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;__HAL_RCC_GPIOG_CLK_ENABLE&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h1 id="二十freertos内存管理"&gt;&lt;a href="#%e4%ba%8c%e5%8d%81freertos%e5%86%85%e5%ad%98%e7%ae%a1%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;二十、FreeRTOS内存管理&#13;&#10;&lt;/h1&gt;&lt;h2 id="1freertos内存管理简介"&gt;&lt;a href="#1freertos%e5%86%85%e5%ad%98%e7%ae%a1%e7%90%86%e7%ae%80%e4%bb%8b" class="header-anchor"&gt;&lt;/a&gt;1.FreeRTOS内存管理简介&#13;&#10;&lt;/h2&gt;&lt;p&gt;FreeRTOS创建任务、队列、信号量等时，可用动态方法或者静态方法创建&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;动态方法：申请时FreeRTOS从内存堆中自动申请，删除对象时自动释放&lt;/li&gt;&#10;&lt;li&gt;静态方法：用户提供内存空间，但是占用的空间固定下来了，删除依旧占用&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;本节讲的是动态内存管理方式（实际是管理算法的区别heap.c）&lt;/p&gt;&#10;&lt;p&gt;freertosconfig.h中定义的宏管理内存堆的大小：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define configTOTAL_HEAP_SIZE ((size_t)(10 * 1024)) &#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* FreeRTOS堆中可用的RAM总量, 单位: Byte, 无默认需定义 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h2 id="2freertos内存管理算法"&gt;&lt;a href="#2freertos%e5%86%85%e5%ad%98%e7%ae%a1%e7%90%86%e7%ae%97%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;2.FreeRTOS内存管理算法&#13;&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;算法&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;优点&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;缺点&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;heap_1&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;分配简单，时间确定&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;只允许申请内存，不允许释放内存&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;heap_2&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;允许申请和释放内存&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;不能合并相邻空闲块，产生碎片，时间不定&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;heap_3&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;直接调用 C 库 malloc()/free()，实现简单（不使用）&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;速度慢、时间不定&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;heap_4&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;相邻空闲块可合并，减少碎片&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;时间不定&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;heap_5&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;支持管理&lt;strong&gt;多个非连续内存区域&lt;/strong&gt;，功能同 heap_4&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;时间不定&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h3 id="21-heap_1"&gt;&lt;a href="#21-heap_1" class="header-anchor"&gt;&lt;/a&gt;2.1 heap_1&#13;&#10;&lt;/h3&gt;&lt;p&gt;heap_1只能申请内存无法释放内存，若工程中创建好的任务、队列、信号量等不需要删除，那使用heap_1&lt;/p&gt;&#10;&lt;p&gt;heap_1分配图示：&lt;/p&gt;&#10;&lt;img src="images/image-20250806221459608.png" alt="image-20250806221459608" style="zoom:50%;" /&gt;&#10;&lt;h3 id="22-heap_2"&gt;&lt;a href="#22-heap_2" class="header-anchor"&gt;&lt;/a&gt;2.2 heap_2&#13;&#10;&lt;/h3&gt;&lt;p&gt;heap_2采用最适应算法，支持释放内存，但是并不能将相临空闲内存块合并，不可避免产生内存碎片。如果需要频繁的创建和删除任务，且所创建的任务堆栈都相同，可以用heap_2&lt;/p&gt;&#10;&lt;p&gt;最适应算法：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;假设heap 有 3 块空闲内存：5,25,50&lt;/li&gt;&#10;&lt;li&gt;申请一个总共20字节的任务，先找到最小能满足的内存：25&lt;/li&gt;&#10;&lt;li&gt;删除任务内存释放后，得到20、5两块内存碎片&lt;/li&gt;&#10;&lt;li&gt;最后存在：5,5,20,50&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;heap_2分配图示：&lt;/p&gt;&#10;&lt;img src="images/image-20250806222759001.png" alt="image-20250806222759001" style="zoom:50%;" /&gt;&#10;&lt;h3 id="23-heap_4"&gt;&lt;a href="#23-heap_4" class="header-anchor"&gt;&lt;/a&gt;2.3 heap_4&#13;&#10;&lt;/h3&gt;&lt;p&gt;heap_4 使用了首次适应算法，能够将空闲且相邻的内存进行合并。适合频繁分配释放大小不同内存。&lt;/p&gt;&#10;&lt;p&gt;首次适应算法：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;假设heap 有 3 块空闲内存（按内存块地址由低到高排序）：5,50,25&lt;/li&gt;&#10;&lt;li&gt;申请一个总共20字节的任务，先找到第一个能满足的内存：50&lt;/li&gt;&#10;&lt;li&gt;删除任务内存释放后，这块内存依旧为50&lt;/li&gt;&#10;&lt;li&gt;最后存在：5,50,25&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;heap_4分配图示：&lt;/p&gt;&#10;&lt;img src="images/image-20250806223412620.png" alt="image-20250806223412620" style="zoom:50%;" /&gt;&#10;&lt;h3 id="24-heap_5"&gt;&lt;a href="#24-heap_5" class="header-anchor"&gt;&lt;/a&gt;2.4 heap_5&#13;&#10;&lt;/h3&gt;&lt;p&gt;heap_5能管理多块不连续内存，但需要用户指定内存区域&lt;/p&gt;&#10;&lt;p&gt;使用如下结构体：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;HeapRegion&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pucStartAddress&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* 内存区域的起始地址 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;xSizeInBytes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* 内存区域的大小，单位：字节 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;HeapRegion_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;指定多块不连续内存&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;span class="lnt"&gt;7&#10;&lt;/span&gt;&lt;span class="lnt"&gt;8&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Const&lt;/span&gt; &lt;span class="n"&gt;HeapRegion_t&lt;/span&gt; &lt;span class="n"&gt;xHeapRegions&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mh"&gt;0x80000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x10000&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="cm"&gt;/* 内存区域1 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mh"&gt;0x90000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xA0000&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="cm"&gt;/* 内存区域2 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="cm"&gt;/* 数组终止标志 */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;vPortDefineHeapRegions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xHeapRegions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;</description></item><item><title>CAN 通信协议学习笔记</title><link>https://zeseanblog.top/p/can/</link><pubDate>Sat, 24 May 2025 10:00:00 +0800</pubDate><guid>https://zeseanblog.top/p/can/</guid><description>&lt;h2 id="can简介"&gt;&lt;a href="#can%e7%ae%80%e4%bb%8b" class="header-anchor"&gt;&lt;/a&gt;CAN简介&#13;&#10;&lt;/h2&gt;&lt;p&gt;CAN总线特征：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;两根通信线(CAN_H、CAN_L)，无需共地&lt;/li&gt;&#10;&lt;li&gt;差分信号，抗干扰&lt;/li&gt;&#10;&lt;li&gt;高速CAN:125k-1mbps，&amp;lt;40m&lt;/li&gt;&#10;&lt;li&gt;低速CAN:10k~125kbps, &amp;lt;1km&lt;/li&gt;&#10;&lt;li&gt;异步通信(无时钟线)，通信速率由设备各自约定&lt;/li&gt;&#10;&lt;li&gt;半双工，可挂载多设备，多设备同时发送数据时通过仲裁判断先后顺序&lt;/li&gt;&#10;&lt;li&gt;11位/29位报文ID，用于区分消息功能，同时决定优先级&lt;/li&gt;&#10;&lt;li&gt;可配置1~8字节的有效载荷&lt;/li&gt;&#10;&lt;li&gt;可实现广播式和请求式两种传输方式&lt;/li&gt;&#10;&lt;li&gt;应答、CRC校验、位填充、位同步、错误处理等特性&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="主流通信协议"&gt;&lt;a href="#%e4%b8%bb%e6%b5%81%e9%80%9a%e4%bf%a1%e5%8d%8f%e8%ae%ae" class="header-anchor"&gt;&lt;/a&gt;主流通信协议&#13;&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;strong&gt;名称&lt;/strong&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;strong&gt;引脚&lt;/strong&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;strong&gt;双工&lt;/strong&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;strong&gt;时钟&lt;/strong&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;strong&gt;电平&lt;/strong&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;strong&gt;设备&lt;/strong&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;strong&gt;应用场景&lt;/strong&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;UART&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;TX、RX&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;全双工&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;异步&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;单端&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;点对点&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;两个设备互相通信&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;I2C&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;SCL、SDA&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;半双工&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;同步&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;单端&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;多设备&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;一个主控外挂多个模块&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;SPI&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;SCK、MOSI、MISO、SS&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;全双工&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;同步&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;单端&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;多设备&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;一个主控外挂多个模块（高速）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;CAN&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;CAN_H、CAN_L&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;半双工&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;异步&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;差分&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;多设备&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;多个主控互相通信&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;CAN类似UART和IIC的结合&lt;/p&gt;&#10;&lt;h1 id="第一章"&gt;&lt;a href="#%e7%ac%ac%e4%b8%80%e7%ab%a0" class="header-anchor"&gt;&lt;/a&gt;第一章&#13;&#10;&lt;/h1&gt;&lt;h2 id="can硬件电路"&gt;&lt;a href="#can%e7%a1%ac%e4%bb%b6%e7%94%b5%e8%b7%af" class="header-anchor"&gt;&lt;/a&gt;CAN硬件电路&#13;&#10;&lt;/h2&gt;&lt;p&gt;主控会内置CAN控制器，借助CAN收发器挂载在CAN总线网络&lt;/p&gt;&#10;&lt;p&gt;高速CAN采用闭环网络，CAN的差分信号默认状态下(1，CANH=CANL)，由电阻收紧，而电阻因为阻抗不大，因此电压跃变快，但是功耗高&lt;/p&gt;&#10;&lt;img src="images/image-20251023155654683.png" alt="image-20251023155654683" style="zoom:67%;" /&gt;&#10;&lt;p&gt;低速CAN使用开环网络，两端加开路的电阻，降低反射&lt;/p&gt;&#10;&lt;img src="images/image-20251023155742503.png" alt="image-20251023155742503" style="zoom:67%;" /&gt;&#10;&lt;h2 id="电平标准"&gt;&lt;a href="#%e7%94%b5%e5%b9%b3%e6%a0%87%e5%87%86" class="header-anchor"&gt;&lt;/a&gt;电平标准&#13;&#10;&lt;/h2&gt;&lt;p&gt;差分信号，即电压差传输数据&lt;/p&gt;&#10;&lt;p&gt;高速CAN：&lt;/p&gt;&#10;&lt;p&gt;隐性电平是不碰两根线，电阻处为收紧状态（默认状态1，隐性）&lt;/p&gt;&#10;&lt;p&gt;显性电平是拉开两根线，电阻处为非收紧状态（显性可以控制总线，0强于1，所以能叫显性）&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;电压差为0V时表示逻辑1（隐性电平）&lt;/li&gt;&#10;&lt;li&gt;电压差为2V时表示逻辑0（显性电平）&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img src="images/image-20251023160648825.png" alt="image-20251023160648825" style="zoom:67%;" /&gt;&#10;&lt;h2 id="can收发器-tja1050高速can"&gt;&lt;a href="#can%e6%94%b6%e5%8f%91%e5%99%a8-tja1050%e9%ab%98%e9%80%9fcan" class="header-anchor"&gt;&lt;/a&gt;CAN收发器-TJA1050(高速CAN)&#13;&#10;&lt;/h2&gt;&lt;img src="images/image-20251023162057153.png" alt="image-20251023162057153" style="zoom: 67%;" /&gt;&#10;&lt;p&gt;CANH和CANL有电压差，RECEIVER输出1，下管导通，RXD为0(有电压差，逻辑0，显性)&lt;/p&gt;&#10;&lt;p&gt;CANH和CANL无电压差，RECEIVER输出0，上管导通，RXD为1(无电压差，逻辑1，隐性)&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20251023162504583" class="gallery-image" data-flex-basis="283px" data-flex-grow="118" height="161" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251023162504583.png" width="190"&gt;&lt;/p&gt;&#10;&lt;p&gt;TXD为0时，2,3的场效应管导通，CANH和CANL有电压差（逻辑0，显性）&lt;/p&gt;&#10;&lt;p&gt;而TXD悬空时，电流源默认让TXD为1&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20251023163114449" class="gallery-image" data-flex-basis="318px" data-flex-grow="132" height="119" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251023163114449.png" width="158"&gt;&lt;/p&gt;&#10;&lt;h2 id="can物理层特性"&gt;&lt;a href="#can%e7%89%a9%e7%90%86%e5%b1%82%e7%89%b9%e6%80%a7" class="header-anchor"&gt;&lt;/a&gt;CAN物理层特性&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;img alt="image-20251023163332184" class="gallery-image" data-flex-basis="287px" data-flex-grow="119" height="693" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251023163332184.png" srcset="https://zeseanblog.top/p/can/images/image-20251023163332184_hu_e57a866cf5261929.png 800w, https://zeseanblog.top/p/can/images/image-20251023163332184.png 831w" width="831"&gt;&lt;/p&gt;&#10;&lt;h1 id="第二章"&gt;&lt;a href="#%e7%ac%ac%e4%ba%8c%e7%ab%a0" class="header-anchor"&gt;&lt;/a&gt;第二章&#13;&#10;&lt;/h1&gt;&lt;h2 id="can总线帧格式"&gt;&lt;a href="#can%e6%80%bb%e7%ba%bf%e5%b8%a7%e6%a0%bc%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;CAN总线帧格式&#13;&#10;&lt;/h2&gt;&lt;p&gt;主要看数据帧&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;strong&gt;帧类型&lt;/strong&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;strong&gt;用途&lt;/strong&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;数据帧&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;发送设备主动发送数据（广播式）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;遥控帧&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;接收设备主动请求数据（请求式）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;错误帧&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;某个设备检测出错误时向其他设备通知错误&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;过载帧&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;接收设备通知其尚未做好接收准备&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;帧间隔&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;用于将数据帧及遥控帧与前面的帧分离开&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="数据帧"&gt;&lt;a href="#%e6%95%b0%e6%8d%ae%e5%b8%a7" class="header-anchor"&gt;&lt;/a&gt;数据帧&#13;&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;SOF（Start of Frame）：帧起始，表示后面一段波形为传输的数据位&lt;/li&gt;&#10;&lt;li&gt;ID（Identify）：标识符，区分功能，同时决定优先级&lt;/li&gt;&#10;&lt;li&gt;RTR（Remote Transmission Request ）：远程请求位，区分数据帧和遥控帧&lt;/li&gt;&#10;&lt;li&gt;IDE（Identifier Extension）：扩展标志位，区分标准格式和扩展格式&lt;/li&gt;&#10;&lt;li&gt;SRR（Substitute Remote Request）：替代RTR，协议升级时留下的无意义位&lt;/li&gt;&#10;&lt;li&gt;r0/r1（Reserve）：保留位，为后续协议升级留下空间&lt;/li&gt;&#10;&lt;li&gt;DLC（Data Length Code）：数据长度，指示数据段有几个字节&lt;/li&gt;&#10;&lt;li&gt;Data：数据段的1~8个字节有效数据&lt;/li&gt;&#10;&lt;li&gt;CRC（Cyclic Redundancy Check）：循环冗余校验，校验数据是否正确&lt;/li&gt;&#10;&lt;li&gt;ACK（Acknowledgement）：应答位，判断数据有没有被接收方接收&lt;/li&gt;&#10;&lt;li&gt;CRC/ACK界定符：为应答位前后发送方和接收方释放总线留下时间&lt;/li&gt;&#10;&lt;li&gt;EOF（End of Frame ）：帧结束，表示数据位已经传输完毕&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img alt="image-20251023163910230" class="gallery-image" data-flex-basis="502px" data-flex-grow="209" height="430" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251023163910230.png" srcset="https://zeseanblog.top/p/can/images/image-20251023163910230_hu_87202e28ebbad6da.png 800w, https://zeseanblog.top/p/can/images/image-20251023163910230.png 900w" width="900"&gt;&lt;/p&gt;&#10;&lt;h3 id="标准格式"&gt;&lt;a href="#%e6%a0%87%e5%87%86%e6%a0%bc%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;标准格式&#13;&#10;&lt;/h3&gt;&lt;ol&gt;&#10;&lt;li&gt;开始为空闲状态为隐性&lt;/li&gt;&#10;&lt;li&gt;SOF为帧起始，表明开始一帧数据&lt;/li&gt;&#10;&lt;li&gt;起始帧后发送11位标识符报文，区分功能，同时决定优先级&lt;/li&gt;&#10;&lt;li&gt;RTR为0：数据帧。为1：遥控帧&lt;/li&gt;&#10;&lt;li&gt;IDE为0：标准格式。为1：扩展格式&lt;/li&gt;&#10;&lt;li&gt;r0保留位，暂时无功能&lt;/li&gt;&#10;&lt;li&gt;DLC为数据长度，0001发一个字节，1000发8字节&lt;/li&gt;&#10;&lt;li&gt;Data根据DLC给几个字节能给范围0-64字节&lt;/li&gt;&#10;&lt;li&gt;CRC为校验&lt;/li&gt;&#10;&lt;li&gt;ACK应答位，发送方释放总线，如果接收方收到了，就抢占总线，发送方读取总线状态知道被接受&lt;/li&gt;&#10;&lt;li&gt;CRC/ACK界定符是留出时间交出控制权&lt;/li&gt;&#10;&lt;li&gt;EOF作为结束&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="遥控帧"&gt;&lt;a href="#%e9%81%a5%e6%8e%a7%e5%b8%a7" class="header-anchor"&gt;&lt;/a&gt;遥控帧&#13;&#10;&lt;/h2&gt;&lt;p&gt;适合使用频率低的数据&lt;/p&gt;&#10;&lt;p&gt;遥控帧无数据段，RTR为隐性电平1，其他部分与数据帧相同&lt;/p&gt;&#10;&lt;p&gt;如果有数据需要，首先接收方发出一个遥控帧，遥控帧包含报文ID，如果发送方有这个报文ID，就将数据发送出来，接收方可以及时获取数据&lt;/p&gt;&#10;&lt;h2 id="错误帧"&gt;&lt;a href="#%e9%94%99%e8%af%af%e5%b8%a7" class="header-anchor"&gt;&lt;/a&gt;错误帧&#13;&#10;&lt;/h2&gt;&lt;p&gt;总线所有设备监督总线数据，一旦发现错误，这些设备发出错误帧来破坏数据，同时终止当前的发送设备&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20251023185816885" class="gallery-image" data-flex-basis="581px" data-flex-grow="242" height="429" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251023185816885.png" srcset="https://zeseanblog.top/p/can/images/image-20251023185816885_hu_5c5d0970fb8f6aa8.png 800w, https://zeseanblog.top/p/can/images/image-20251023185816885.png 1040w" width="1040"&gt;&lt;/p&gt;&#10;&lt;h2 id="过载帧"&gt;&lt;a href="#%e8%bf%87%e8%bd%bd%e5%b8%a7" class="header-anchor"&gt;&lt;/a&gt;过载帧&#13;&#10;&lt;/h2&gt;&lt;p&gt;接收方收到大量数据无法处理，发送过载帧，延缓发送方的数据发送，以平衡总线负载，避免数据丢失&lt;/p&gt;&#10;&lt;h2 id="帧间隔"&gt;&lt;a href="#%e5%b8%a7%e9%97%b4%e9%9a%94" class="header-anchor"&gt;&lt;/a&gt;帧间隔&#13;&#10;&lt;/h2&gt;&lt;p&gt;将数据帧和遥控帧与前面的帧分离开&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20251023190001992" class="gallery-image" data-flex-basis="635px" data-flex-grow="264" height="393" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251023190001992.png" srcset="https://zeseanblog.top/p/can/images/image-20251023190001992_hu_64188ad5a2c92944.png 800w, https://zeseanblog.top/p/can/images/image-20251023190001992.png 1040w" width="1040"&gt;&lt;/p&gt;&#10;&lt;h2 id="位填充"&gt;&lt;a href="#%e4%bd%8d%e5%a1%ab%e5%85%85" class="header-anchor"&gt;&lt;/a&gt;位填充&#13;&#10;&lt;/h2&gt;&lt;p&gt;规则：发送方每发送5个相同电平，自动追加相反电平的填充位，接收方检测到填充位，自动移除填充位。&lt;/p&gt;&#10;&lt;p&gt;即将发送：&#9; 100000110&#9; 10000011110&#9; 0111111111110&#10;实际发送： &#9;1000001110&#9; 1000001111100&#9;011111011111010&#10;实际接收： &#9;1000001110&#9; 1000001111100&#9;011111011111010&#10;移除填充后： 100000110&#9; 10000011110&#9; 0111111111110&lt;/p&gt;&#10;&lt;p&gt;作用：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;增加定时信息，有利于接收方同步，防止波形长时间无变化（防止连续很多相同电平，接收方可能数错）&lt;/li&gt;&#10;&lt;li&gt;将正常数据流与“错误帧”和“过载帧”区分（防止连续6个相同电平）&lt;/li&gt;&#10;&lt;li&gt;保持CAN发送数据的活跃状态，防止认为总线空闲（防止连续11个隐性电平1）&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="波形实例"&gt;&lt;a href="#%e6%b3%a2%e5%bd%a2%e5%ae%9e%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;波形实例&#13;&#10;&lt;/h2&gt;&lt;h3 id="标准数据帧"&gt;&lt;a href="#%e6%a0%87%e5%87%86%e6%95%b0%e6%8d%ae%e5%b8%a7" class="header-anchor"&gt;&lt;/a&gt;标准数据帧&#13;&#10;&lt;/h3&gt;&lt;p&gt;11位报文ID：0x555，&lt;/p&gt;&#10;&lt;p&gt;RTR = 0 数据帧，IDE = 0，标准格式&lt;/p&gt;&#10;&lt;p&gt;DLC = 0001(注意其中第一个1为位填充) = 1，一个字节数据&lt;/p&gt;&#10;&lt;p&gt;Data = 10101010 = 0xAA&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20251023191033968" class="gallery-image" data-flex-basis="1210px" data-flex-grow="504" height="255" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251023191033968.png" srcset="https://zeseanblog.top/p/can/images/image-20251023191033968_hu_3426e5dcd4177d2e.png 800w, https://zeseanblog.top/p/can/images/image-20251023191033968.png 1286w" width="1286"&gt;&lt;/p&gt;&#10;&lt;h3 id="扩展数据帧"&gt;&lt;a href="#%e6%89%a9%e5%b1%95%e6%95%b0%e6%8d%ae%e5%b8%a7" class="header-anchor"&gt;&lt;/a&gt;扩展数据帧&#13;&#10;&lt;/h3&gt;&lt;p&gt;扩展数据帧，报文ID为0x0789ABCD，数据长度1字节，数据内容为0x56&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20251023192707532" class="gallery-image" data-flex-basis="1602px" data-flex-grow="667" height="220" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251023192707532.png" srcset="https://zeseanblog.top/p/can/images/image-20251023192707532_hu_d3c3d340c1b2429d.png 800w, https://zeseanblog.top/p/can/images/image-20251023192707532.png 1469w" width="1469"&gt;&lt;/p&gt;&#10;&lt;h1 id="第三章"&gt;&lt;a href="#%e7%ac%ac%e4%b8%89%e7%ab%a0" class="header-anchor"&gt;&lt;/a&gt;第三章&#13;&#10;&lt;/h1&gt;&lt;h2 id="接收方数据采样"&gt;&lt;a href="#%e6%8e%a5%e6%94%b6%e6%96%b9%e6%95%b0%e6%8d%ae%e9%87%87%e6%a0%b7" class="header-anchor"&gt;&lt;/a&gt;接收方数据采样&#13;&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;CAN总线无时钟线，总线设备通过一个约定的波特率方式确定每个数据位的时长&lt;/li&gt;&#10;&lt;li&gt;发送方以约定的位时长每个固定时间输出一个数据位&lt;/li&gt;&#10;&lt;li&gt;接收方以约定的位时长每个固定时间采样总线电平，输入一个数据位&lt;/li&gt;&#10;&lt;li&gt;理想采样是数据位中心附近&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="会遇到的问题"&gt;&lt;a href="#%e4%bc%9a%e9%81%87%e5%88%b0%e7%9a%84%e9%97%ae%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;会遇到的问题&#13;&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;接收方采样点没有对齐数据位中心附近&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;解决：第一个跳变沿对齐（硬同步）&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;接收方刚开始采样正确，但是时钟有误差，随着误差积累，采样点逐渐偏离&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;解决：采样点动态调节，弥补时钟误差（再同步）&lt;/p&gt;&#10;&lt;h2 id="位时序"&gt;&lt;a href="#%e4%bd%8d%e6%97%b6%e5%ba%8f" class="header-anchor"&gt;&lt;/a&gt;位时序&#13;&#10;&lt;/h2&gt;&lt;p&gt;因为要调节采样点，所以会对一个数据位时长进行细分&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;同步段（SS）&lt;/li&gt;&#10;&lt;li&gt;传播时间段（PTS）&lt;/li&gt;&#10;&lt;li&gt;相位缓冲段1（PBS1）&lt;/li&gt;&#10;&lt;li&gt;相位缓冲段2（PBS2）&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;每个段又由若干个最小时间单位（Tq）构成&lt;/p&gt;&#10;&lt;p&gt;SS = 1Tq、PTS = 1&lt;del&gt;8Tq、PBS1 = 1&lt;/del&gt;8Tq、PBS2 = 2~8Tq&lt;/p&gt;&#10;&lt;img src="images/image-20251023193938293.png" alt="image-20251023193938293" style="zoom: 80%;" /&gt;&#10;&lt;p&gt;如果跳边沿在SS段，说明当前设备与波形达成同步，否则不同步，则需要调节时序使跳变沿正好在同步段&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20251023194302175" class="gallery-image" data-flex-basis="261px" data-flex-grow="108" height="146" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251023194302175.png" width="159"&gt;&lt;/p&gt;&#10;&lt;h2 id="硬同步"&gt;&lt;a href="#%e7%a1%ac%e5%90%8c%e6%ad%a5" class="header-anchor"&gt;&lt;/a&gt;硬同步&#13;&#10;&lt;/h2&gt;&lt;p&gt;使第一次采样对齐&lt;/p&gt;&#10;&lt;p&gt;每个设备有一个位时序计时周期，当某设备发送报文，其他设备接收到SOF下降沿，会将位时序计时周期拨到SS段，与发送方保持同步（实际就是让第一个边沿段调整为SS段，类似于时区，绝对时刻不一样，但都规定为北京时间）&lt;/p&gt;&#10;&lt;p&gt;而此时接受段直接确定数据位采样点（PBS1和PBS2段中间）&lt;/p&gt;&#10;&lt;p&gt;硬同步解决没有对齐数据位中心附近，只要时钟没误差，就不会有问题&lt;/p&gt;&#10;&lt;img src="images/image-20251023200536351.png" alt="image-20251023200536351" style="zoom:67%;" /&gt;&#10;&lt;h2 id="再同步"&gt;&lt;a href="#%e5%86%8d%e5%90%8c%e6%ad%a5" class="header-anchor"&gt;&lt;/a&gt;再同步&#13;&#10;&lt;/h2&gt;&lt;p&gt;解决时钟误差，若数据位边沿逐渐偏离SS段，此时接收方根据再同步补偿宽度值（sjw，是最大的补偿，如果误差1tq，sjw2，则补偿1tq；若误差3tq，则补偿2tq）加长PBS1段，或缩短PBS2段&lt;/p&gt;&#10;&lt;p&gt;再同步发生在，第一个下降沿之后每个数据位跳变边沿&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20251023201451502" class="gallery-image" data-flex-basis="310px" data-flex-grow="129" height="500" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251023201451502.png" width="647"&gt;&lt;/p&gt;&#10;&lt;h2 id="波特率计算"&gt;&lt;a href="#%e6%b3%a2%e7%89%b9%e7%8e%87%e8%ae%a1%e7%ae%97" class="header-anchor"&gt;&lt;/a&gt;波特率计算&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;波特率 = 1/一个数据位的时长 = 1/（Tss+Tpts+Tpbs1+Tpbs2）&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;SS = 1Tq，PTS = 3Tq，PBS1 = 3Tq，PBS2 = 3Tq，Tq = 0.5us&lt;/p&gt;&#10;&lt;p&gt;则波特率 = 1 / (0.5us + 1.5us + 1.5us + 1.5us) = 200kbps&lt;/p&gt;&#10;&lt;h1 id="第四章"&gt;&lt;a href="#%e7%ac%ac%e5%9b%9b%e7%ab%a0" class="header-anchor"&gt;&lt;/a&gt;第四章&#13;&#10;&lt;/h1&gt;&lt;h2 id="多设备同时发送遇到的问题"&gt;&lt;a href="#%e5%a4%9a%e8%ae%be%e5%a4%87%e5%90%8c%e6%97%b6%e5%8f%91%e9%80%81%e9%81%87%e5%88%b0%e7%9a%84%e9%97%ae%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;多设备同时发送遇到的问题&#13;&#10;&lt;/h2&gt;&lt;p&gt;CAN总线只有一差分信号线，同时只能有一个设备操作总线&lt;/p&gt;&#10;&lt;p&gt;若多设备同时又发送需求，该如何分配总线资源？&lt;/p&gt;&#10;&lt;h2 id="资源分配规则1-先占先得"&gt;&lt;a href="#%e8%b5%84%e6%ba%90%e5%88%86%e9%85%8d%e8%a7%84%e5%88%991-%e5%85%88%e5%8d%a0%e5%85%88%e5%be%97" class="header-anchor"&gt;&lt;/a&gt;资源分配规则1-先占先得&#13;&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;若当前有设备操作总线发送数据帧/遥控帧，则其他设备不可发（可发错误帧/过载帧）&lt;/li&gt;&#10;&lt;li&gt;任何设备检测到11连续隐性电平，认为总线空闲，才能发送&lt;/li&gt;&#10;&lt;li&gt;若有设备有发送需求要等待总线空闲&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;而位填充的适用范围&lt;/strong&gt;是从&lt;strong&gt;帧起始（SOF）到CRC序列结束&lt;/strong&gt;，不包括&lt;strong&gt;CRC界定符、ACK域和EOF段&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;此时有ACK界定符一个隐性，EOF7个隐性，只需再等三个隐性即可继续发送。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;但有可能不止一个信号在等待&lt;/strong&gt;，多个设备同时到来（总线仲裁）&lt;/p&gt;&#10;&lt;h2 id="资源分配规则2-非破坏性仲裁"&gt;&lt;a href="#%e8%b5%84%e6%ba%90%e5%88%86%e9%85%8d%e8%a7%84%e5%88%992-%e9%9d%9e%e7%a0%b4%e5%9d%8f%e6%80%a7%e4%bb%b2%e8%a3%81" class="header-anchor"&gt;&lt;/a&gt;资源分配规则2-非破坏性仲裁&#13;&#10;&lt;/h2&gt;&lt;p&gt;多设备发送需求同时到来，对仲裁段（ID+RTR）进行非破坏性仲裁，ID号小（优先级高）的取得控制权，ID号大（优先级低）仲裁失利，继续等待空闲&lt;/p&gt;&#10;&lt;p&gt;实现非破坏性仲裁两个需要的特性：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;线与特性：0 &amp;amp; X &amp;amp; X = 0，1 &amp;amp; 1 &amp;amp; 1 = 1&lt;/li&gt;&#10;&lt;li&gt;回读机制：设备发出一个数据位后，读回总线电平状态，确认电平被发送。发送0读回0，发送1读回不一定是1&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;仲裁：发出数据1，读回（回读机制）数据0（被其他设备线与了）&lt;/p&gt;&#10;&lt;h2 id="非破坏性仲裁过程"&gt;&lt;a href="#%e9%9d%9e%e7%a0%b4%e5%9d%8f%e6%80%a7%e4%bb%b2%e8%a3%81%e8%bf%87%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;非破坏性仲裁过程&#13;&#10;&lt;/h2&gt;&lt;p&gt;数据位从前到后依次比较，出现差异且数据位为1的设备仲裁失利&lt;/p&gt;&#10;&lt;p&gt;单元1在仲裁段中某一个数据位发送1，回读出0，判断有其他设备在发生，但自己优先级低，放弃发送。但是总线电平依旧是单元2的，并没有被破坏&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20251023204633782" class="gallery-image" data-flex-basis="381px" data-flex-grow="159" height="594" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251023204633782.png" srcset="https://zeseanblog.top/p/can/images/image-20251023204633782_hu_d41f194ff4f8d877.png 800w, https://zeseanblog.top/p/can/images/image-20251023204633782.png 945w" width="945"&gt;&lt;/p&gt;&#10;&lt;h2 id="数据帧和遥控帧优先级"&gt;&lt;a href="#%e6%95%b0%e6%8d%ae%e5%b8%a7%e5%92%8c%e9%81%a5%e6%8e%a7%e5%b8%a7%e4%bc%98%e5%85%88%e7%ba%a7" class="header-anchor"&gt;&lt;/a&gt;数据帧和遥控帧优先级&#13;&#10;&lt;/h2&gt;&lt;p&gt;数据帧和遥控帧ID号一样时，数据帧的优先级高于遥控帧（RTR决断，因为RTR = 0 为数据帧）&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20251023205811312" class="gallery-image" data-flex-basis="493px" data-flex-grow="205" height="460" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251023205811312.png" srcset="https://zeseanblog.top/p/can/images/image-20251023205811312_hu_120149f9928a316e.png 800w, https://zeseanblog.top/p/can/images/image-20251023205811312.png 945w" width="945"&gt;&lt;/p&gt;&#10;&lt;h2 id="标准格式和拓展格式的优先级"&gt;&lt;a href="#%e6%a0%87%e5%87%86%e6%a0%bc%e5%bc%8f%e5%92%8c%e6%8b%93%e5%b1%95%e6%a0%bc%e5%bc%8f%e7%9a%84%e4%bc%98%e5%85%88%e7%ba%a7" class="header-anchor"&gt;&lt;/a&gt;标准格式和拓展格式的优先级&#13;&#10;&lt;/h2&gt;&lt;p&gt;标准格式11位ID号和扩展格式29位ID号的高11位一样时，标准格式的优先级高于扩展格式（SRR必须始终为1，以保证此要求）&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20251023205932744" class="gallery-image" data-flex-basis="432px" data-flex-grow="180" height="525" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251023205932744.png" srcset="https://zeseanblog.top/p/can/images/image-20251023205932744_hu_816885b17494cda9.png 800w, https://zeseanblog.top/p/can/images/image-20251023205932744.png 945w" width="945"&gt;&lt;/p&gt;&#10;&lt;h1 id="第五章"&gt;&lt;a href="#%e7%ac%ac%e4%ba%94%e7%ab%a0" class="header-anchor"&gt;&lt;/a&gt;第五章&#13;&#10;&lt;/h1&gt;&lt;h2 id="错误类型"&gt;&lt;a href="#%e9%94%99%e8%af%af%e7%b1%bb%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;错误类型&#13;&#10;&lt;/h2&gt;&lt;p&gt;位错误、填充错误、CRC错误、格式错误、应答错误&lt;/p&gt;&#10;&lt;img src="images/image-20251023210342121.png" alt="image-20251023210342121" style="zoom:67%;" /&gt;&#10;&lt;h2 id="错误状态"&gt;&lt;a href="#%e9%94%99%e8%af%af%e7%8a%b6%e6%80%81" class="header-anchor"&gt;&lt;/a&gt;错误状态&#13;&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;主动错误状态参与通信并检测到错误时发送主动错误帧（6个0），可以破坏别的设备的数据&lt;/li&gt;&#10;&lt;li&gt;而频繁发送主动错误，说明这个设备不太可靠，就转到被动错误，收回他破坏其他设备通信的权利&lt;/li&gt;&#10;&lt;li&gt;若还是频繁被动错误，则进入总线关闭&lt;/li&gt;&#10;&lt;li&gt;如何判断：每个设备内部管理一个TEC和REC，根据TEC和REC确定自己状态（信誉分）&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img src="images/image-20251023212056785.png" alt="image-20251023212056785" style="zoom:67%;" /&gt;&#10;&lt;h2 id="错误计数器"&gt;&lt;a href="#%e9%94%99%e8%af%af%e8%ae%a1%e6%95%b0%e5%99%a8" class="header-anchor"&gt;&lt;/a&gt;错误计数器&#13;&#10;&lt;/h2&gt;&lt;p&gt;信誉分积分：&lt;/p&gt;&#10;&lt;img src="images/image-20251023212321573.png" alt="image-20251023212321573" style="zoom:80%;" /&gt;&#10;&lt;h1 id="stm32-can外设"&gt;&lt;a href="#stm32-can%e5%a4%96%e8%ae%be" class="header-anchor"&gt;&lt;/a&gt;STM32 CAN外设&#13;&#10;&lt;/h1&gt;&lt;ul&gt;&#10;&lt;li&gt;STM32内置bxCAN支持CAN2.0A和2.0B，可自动发报文，程序只需处理报文数据&lt;/li&gt;&#10;&lt;li&gt;波特率最高1mbps&lt;/li&gt;&#10;&lt;li&gt;3个可配置优先级的发送邮箱&lt;/li&gt;&#10;&lt;li&gt;2个3级深度接收FIFO&lt;/li&gt;&#10;&lt;li&gt;时间触发通信、自动离线恢复、自动唤醒、禁止自动重传、接收FIFO溢出处理方式可配置、发送优先级可配置、双CAN模式&lt;/li&gt;&#10;&lt;li&gt;STM32F103C8T6 CAN资源：CAN1&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="第一节"&gt;&lt;a href="#%e7%ac%ac%e4%b8%80%e8%8a%82" class="header-anchor"&gt;&lt;/a&gt;第一节&#13;&#10;&lt;/h2&gt;&lt;h3 id="can网络拓扑"&gt;&lt;a href="#can%e7%bd%91%e7%bb%9c%e6%8b%93%e6%89%91" class="header-anchor"&gt;&lt;/a&gt;CAN网络拓扑&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img alt="image-20251024152812279" class="gallery-image" data-flex-basis="545px" data-flex-grow="227" height="411" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251024152812279.png" srcset="https://zeseanblog.top/p/can/images/image-20251024152812279_hu_4e654ea6ccdb2f2f.png 800w, https://zeseanblog.top/p/can/images/image-20251024152812279.png 934w" width="934"&gt;&lt;/p&gt;&#10;&lt;p&gt;STM32F103C8T6 CAN引脚默认复用&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20251024153118991" class="gallery-image" data-flex-basis="1295px" data-flex-grow="539" height="173" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251024153118991.png" srcset="https://zeseanblog.top/p/can/images/image-20251024153118991_hu_b0dec2e0190a9337.png 800w, https://zeseanblog.top/p/can/images/image-20251024153118991.png 934w" width="934"&gt;&lt;/p&gt;&#10;&lt;p&gt;重定义&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20251024153129671" class="gallery-image" data-flex-basis="5741px" data-flex-grow="2392" height="52" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251024153129671.png" srcset="https://zeseanblog.top/p/can/images/image-20251024153129671_hu_9efacbf4ca291fc4.png 800w, https://zeseanblog.top/p/can/images/image-20251024153129671.png 1244w" width="1244"&gt;&lt;/p&gt;&#10;&lt;h3 id="can收发器电路"&gt;&lt;a href="#can%e6%94%b6%e5%8f%91%e5%99%a8%e7%94%b5%e8%b7%af" class="header-anchor"&gt;&lt;/a&gt;CAN收发器电路&#13;&#10;&lt;/h3&gt;&lt;p&gt;注意TX，RX接法与串口区分&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20251024153323173" class="gallery-image" data-flex-basis="592px" data-flex-grow="246" height="281" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251024153323173.png" width="694"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20251024153328481" class="gallery-image" data-flex-basis="436px" data-flex-grow="181" height="382" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251024153328481.png" width="694"&gt;&lt;/p&gt;&#10;&lt;h2 id="第二节"&gt;&lt;a href="#%e7%ac%ac%e4%ba%8c%e8%8a%82" class="header-anchor"&gt;&lt;/a&gt;第二节&#13;&#10;&lt;/h2&gt;&lt;h3 id="can框图"&gt;&lt;a href="#can%e6%a1%86%e5%9b%be" class="header-anchor"&gt;&lt;/a&gt;CAN框图&#13;&#10;&lt;/h3&gt;&lt;img src="images/image-20251024154247741.png" alt="image-20251024154247741" style="zoom:67%;" /&gt;&#10;&lt;p&gt;对于STM32F103C8T6，没有CAN2，只有CAN1。&lt;/p&gt;&#10;&lt;p&gt;通过读写以下寄存器对CAN电路进行配置：&lt;/p&gt;&#10; &lt;img src="images/image-20251024154441586.png" alt="image-20251024154441586" style="zoom: 50%;" /&gt;&#10;&lt;p&gt;3个主发送邮箱，每个可以存入一个CAN报文，若想发送一个报文，可以将报文放入空置邮箱，在设置寄存器请求发送&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20251024154756599" class="gallery-image" data-flex-basis="160px" data-flex-grow="66" height="224" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251024154756599.png" width="150"&gt;&lt;/p&gt;&#10;&lt;p&gt;接收部分包括过滤器和2个FIFO，过滤器设置过滤规则，告诉硬件想要的ID的报文，如果硬件收到相应ID的报文，将报文放入FIFO；如果都没用，就抛弃，减轻软件负担。&lt;/p&gt;&#10;&lt;p&gt;FIFO：先入先出，类似于队列，等待CPU读取&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20251024155100846" class="gallery-image" data-flex-basis="405px" data-flex-grow="168" height="176" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251024155100846.png" width="297"&gt;&lt;/p&gt;&#10;&lt;h3 id="can基本结构"&gt;&lt;a href="#can%e5%9f%ba%e6%9c%ac%e7%bb%93%e6%9e%84" class="header-anchor"&gt;&lt;/a&gt;CAN基本结构&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img alt="image-20251024155405878" class="gallery-image" data-flex-basis="432px" data-flex-grow="180" height="544" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251024155405878.png" srcset="https://zeseanblog.top/p/can/images/image-20251024155405878_hu_3d28aa830b712f95.png 800w, https://zeseanblog.top/p/can/images/image-20251024155405878.png 980w" width="980"&gt;&lt;/p&gt;&#10;&lt;h3 id="发送过程"&gt;&lt;a href="#%e5%8f%91%e9%80%81%e8%bf%87%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;发送过程&#13;&#10;&lt;/h3&gt;&lt;p&gt;选择空置邮箱-写入报文-配置寄存器请求发送&lt;/p&gt;&#10;&lt;p&gt;RQCP：请求完成&lt;/p&gt;&#10;&lt;p&gt;TXOK：发送成功&lt;/p&gt;&#10;&lt;p&gt;TME = 1：发送邮箱空&lt;/p&gt;&#10;&lt;img src="images/image-20251024160418572.png" alt="image-20251024160418572" style="zoom: 50%;" /&gt;&#10;&lt;p&gt;发送流程：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;默认TME=1处于空置状态时，TXRQ（请求发送控制位）=1（产生发送请求）&lt;/li&gt;&#10;&lt;li&gt;进入挂号状态TME=0，排队等到该邮箱为最高优先级发送报文&lt;/li&gt;&#10;&lt;li&gt;进入预定状态，若优先级被比下去，则退回挂号状态&lt;/li&gt;&#10;&lt;li&gt;处于预定的报文，探测到CAN总线=IDLE空闲，管理员将报文发送到CAN总线&lt;/li&gt;&#10;&lt;li&gt;发送成功回到空置状态，发送失败时若启用NART=0（禁止自动重发）回到空置，若禁止，NART=1则回到预定等待发送（比如总线仲裁失败）&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="接收过程"&gt;&lt;a href="#%e6%8e%a5%e6%94%b6%e8%bf%87%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;接收过程&#13;&#10;&lt;/h3&gt;&lt;p&gt;接收到一个报文→匹配过滤器后进入FIFO 0或FIFO 1→CPU读取&lt;/p&gt;&#10;&lt;p&gt;FMP：报文数目&lt;/p&gt;&#10;&lt;p&gt;FOVR：FIFO溢出&lt;/p&gt;&#10;&lt;img src="images/image-20251024163116807.png" alt="image-20251024163116807" style="zoom:50%;" /&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;接收到一个报文时，FMP=1,FOVR=0，依次接收后FMP递增&lt;/li&gt;&#10;&lt;li&gt;有效报文存满FULL置1，在收到有效报文进入溢出FOVR=1&lt;/li&gt;&#10;&lt;li&gt;若读取一个报文，RFOM=1，释放一次邮箱&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;注意：溢出状态释放一次是挂号2&lt;/p&gt;&#10;&lt;h3 id="发送和接收配置位"&gt;&lt;a href="#%e5%8f%91%e9%80%81%e5%92%8c%e6%8e%a5%e6%94%b6%e9%85%8d%e7%bd%ae%e4%bd%8d" class="header-anchor"&gt;&lt;/a&gt;发送和接收配置位&#13;&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;NART：NART=1关闭自动重传，CAN报文只发送一次，不管发送结果如何；置0，自动重传，直到发送成功&lt;/li&gt;&#10;&lt;li&gt;TXFP：TXFP=1，优先级按发送请求的顺序；置0，优先级按报文ID，标志符小的先发送（标志符相等，邮箱号小的先发送）&lt;/li&gt;&#10;&lt;li&gt;RFLM：置1，接收FIFO锁定，FIFO溢出，新报文丢弃；置0，FOFO溢出后最后收到报文被覆盖&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="标识符过滤器"&gt;&lt;a href="#%e6%a0%87%e8%af%86%e7%ac%a6%e8%bf%87%e6%bb%a4%e5%99%a8" class="header-anchor"&gt;&lt;/a&gt;标识符过滤器&#13;&#10;&lt;/h3&gt;&lt;p&gt;x可以表示0-13，每个过滤器都有一套电路&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;每个过滤器由2个32位寄存器组成，R1[31:0] R2[31:0]&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;位宽设置，FSCx=0，16位，FSCx=1,32位&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;若只有标准ID，则16位足矣，若有标准，有拓展需要用到32位&lt;/li&gt;&#10;&lt;li&gt;16位的话两个32位寄存器能写4个ID号，32位写两个&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;模式设置，&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;FBMx=0，屏蔽模式&lt;/p&gt;&#10;&lt;p&gt;允许一类，使用了类似掩码功能，屏蔽的是不需要的ID号的位，如只需要用前三位，可以ID段前三位写001xxxxxxxx，屏蔽写11100000000,过滤ID前三位为001&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;FBMx=1，列表模式（允许个别）&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;关联到队列，FFAx=0，关联FIFO0，否则关联FIFO1&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;激活FACTx:FACTx=0，禁用，否则启用&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img alt="image-20251024170732729" class="gallery-image" data-flex-basis="269px" data-flex-grow="112" height="667" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251024170732729.png" width="748"&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;列表模式&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;想要的ID号写入R1或R2寄存器中&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;位宽32位&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;STID高11位为标准ID&lt;/li&gt;&#10;&lt;li&gt;前29位是拓展ID&lt;/li&gt;&#10;&lt;li&gt;过滤拓展ID，IDE=1，过滤标准ID，IDE=0&lt;/li&gt;&#10;&lt;li&gt;RTR=1，过滤遥控帧，RTR=0,过滤数据帧&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;位宽16位&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;只使用标准ID，4个16位&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;屏蔽模式&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;ID号过多时使用&lt;/li&gt;&#10;&lt;li&gt;采用位与屏蔽，类似掩码功能&lt;/li&gt;&#10;&lt;li&gt;ID段有效位写实际，对应屏蔽位写1&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="过滤器配置示例"&gt;&lt;a href="#%e8%bf%87%e6%bb%a4%e5%99%a8%e9%85%8d%e7%bd%ae%e7%a4%ba%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;过滤器配置示例&#13;&#10;&lt;/h3&gt;&lt;p&gt;&lt;img alt="image-20251024190102576" class="gallery-image" data-flex-basis="498px" data-flex-grow="207" height="525" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251024190102576.png" srcset="https://zeseanblog.top/p/can/images/image-20251024190102576_hu_61d1fe99d93cdfb3.png 800w, https://zeseanblog.top/p/can/images/image-20251024190102576.png 1091w" width="1091"&gt;&lt;/p&gt;&#10;&lt;h2 id="第三节"&gt;&lt;a href="#%e7%ac%ac%e4%b8%89%e8%8a%82" class="header-anchor"&gt;&lt;/a&gt;第三节&#13;&#10;&lt;/h2&gt;&lt;h3 id="测试模式"&gt;&lt;a href="#%e6%b5%8b%e8%af%95%e6%a8%a1%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;测试模式&#13;&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;静默模式：用于分析CAN总线的活动，不会对总线造成影响&lt;/li&gt;&#10;&lt;li&gt;环回模式：用于自测试，同时发送的报文可以在CAN_TX引脚上检测到&lt;/li&gt;&#10;&lt;li&gt;环回静默模式：用于热自测试，自测的同时不会影响CAN总线&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img alt="image-20251024192633712" class="gallery-image" data-flex-basis="827px" data-flex-grow="344" height="396" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251024192633712.png" srcset="https://zeseanblog.top/p/can/images/image-20251024192633712_hu_c2b9f0c6820be399.png 800w, https://zeseanblog.top/p/can/images/image-20251024192633712.png 1366w" width="1366"&gt;&lt;/p&gt;&#10;&lt;h3 id="工作模式"&gt;&lt;a href="#%e5%b7%a5%e4%bd%9c%e6%a8%a1%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;工作模式&#13;&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;初始化模式：用于配置CAN时禁止收发&lt;/li&gt;&#10;&lt;li&gt;正常模式&lt;/li&gt;&#10;&lt;li&gt;睡眠模式：低功耗，CAN外设时钟停止，可以软件唤醒或硬件自动唤醒&lt;/li&gt;&#10;&lt;li&gt;AWUM：置1，自动唤醒，一旦检测到CAN总线活动，硬件就自动清零SLEEP，唤醒CAN外设；置0，手动唤醒，软件清零SLEEP，唤醒CAN外设&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img src="images/image-20251024193220836.png" alt="image-20251024193220836" style="zoom:67%;" /&gt;&#10;&lt;h3 id="位时间特性"&gt;&lt;a href="#%e4%bd%8d%e6%97%b6%e9%97%b4%e7%89%b9%e6%80%a7" class="header-anchor"&gt;&lt;/a&gt;位时间特性&#13;&#10;&lt;/h3&gt;&lt;p&gt;STM32中，PDS和PBS1合在一起&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;SS = 1Tq&#10;BS1 = 1&lt;del&gt;16Tq&#10;BS2 = 1&lt;/del&gt;8Tq&lt;/li&gt;&#10;&lt;li&gt;SJW=1~4Tq&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img alt="image-20251024194312171" class="gallery-image" data-flex-basis="392px" data-flex-grow="163" height="546" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/can/images/image-20251024194312171.png" srcset="https://zeseanblog.top/p/can/images/image-20251024194312171_hu_d16765102ffe9b1c.png 800w, https://zeseanblog.top/p/can/images/image-20251024194312171.png 892w" width="892"&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;波特率=APB1时钟频率/分频系数/1位Tq数&lt;/p&gt;&#10;&lt;p&gt;=36Mhz/(BRP[9:0]+1)/(1+(TS1[3:0]+1)+(TS2[2:0]+1))&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="中断"&gt;&lt;a href="#%e4%b8%ad%e6%96%ad" class="header-anchor"&gt;&lt;/a&gt;中断&#13;&#10;&lt;/h3&gt;&lt;p&gt;CAN外设占用4个专用中断向量&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;发送中断：发送邮箱空时产生&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;FIFO 0中断：收到一个报文/FIFO 0满/FIFO 0溢出时产生&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;FIFO 1中断：收到一个报文/FIFO 1满/FIFO 1溢出时产生&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;状态改变错误中断：出错/唤醒/进入睡眠时产生&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;中断发生条件：&lt;/p&gt;&#10;&lt;img src="images/image-20251024195020980.png" alt="image-20251024195020980" style="zoom:67%;" /&gt;&#10;</description></item><item><title>git学习</title><link>https://zeseanblog.top/p/learngit/</link><pubDate>Thu, 15 May 2025 13:30:00 +0800</pubDate><guid>https://zeseanblog.top/p/learngit/</guid><description>&lt;h4 id="配置git"&gt;&lt;a href="#%e9%85%8d%e7%bd%aegit" class="header-anchor"&gt;&lt;/a&gt;配置Git&#13;&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config --global user.name &amp;#34;Your Name&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config --global user.email &amp;#34;email@example.com&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="创建版本库"&gt;&lt;a href="#%e5%88%9b%e5%bb%ba%e7%89%88%e6%9c%ac%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;创建版本库&#13;&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;span class="lnt"&gt;7&#10;&lt;/span&gt;&lt;span class="lnt"&gt;8&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir learngit&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cd learngit&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pwd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/Users/michael/learngit&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git init&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add readme.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &amp;#34;wrote a readme file&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h2 id="版本管理"&gt;&lt;a href="#%e7%89%88%e6%9c%ac%e7%ae%a1%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;版本管理&#13;&#10;&lt;/h2&gt;&lt;h4 id="版本回退"&gt;&lt;a href="#%e7%89%88%e6%9c%ac%e5%9b%9e%e9%80%80" class="header-anchor"&gt;&lt;/a&gt;版本回退&#13;&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git log&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;span class="lnt"&gt;7&#10;&lt;/span&gt;&lt;span class="lnt"&gt;8&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git log --pretty=oneline&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -&amp;gt; master) append GPL&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;e475afc93c209a690c39c13a46716e8fa000c366 add distributed&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0 wrote a readme file&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git reset --hard HEAD^//根据参数回退对应&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git reset --hard 1094a&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git reflog//查看每次&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;&lt;img alt="image-20250408195757150" class="gallery-image" data-flex-basis="432px" data-flex-grow="180" height="335" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/learngit/images/image-20250408195757150.png" width="604"&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git status//查看状态&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;On branch master&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Changes to be committed:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; (use &amp;#34;git reset HEAD &amp;lt;file&amp;gt;...&amp;#34; to unstage)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;new file: LICENSE&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;modified: readme.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="管理修改"&gt;&lt;a href="#%e7%ae%a1%e7%90%86%e4%bf%ae%e6%94%b9" class="header-anchor"&gt;&lt;/a&gt;管理修改&#13;&#10;&lt;/h4&gt;&lt;p&gt;第一次修改 -&amp;gt; &lt;code&gt;git add&lt;/code&gt; -&amp;gt; 第二次修改 -&amp;gt; &lt;code&gt;git add&lt;/code&gt; -&amp;gt; &lt;code&gt;git commit&lt;/code&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git diff HEAD -- readme.txt //查看工作区和版本库最新版本区别&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="撤销修改"&gt;&lt;a href="#%e6%92%a4%e9%94%80%e4%bf%ae%e6%94%b9" class="header-anchor"&gt;&lt;/a&gt;撤销修改&#13;&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git checkout -- readme.txt//丢弃工作区修改&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git reset HEAD readme.txt//把暂存区的修改撤销掉&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="删除文件"&gt;&lt;a href="#%e5%88%a0%e9%99%a4%e6%96%87%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;删除文件&#13;&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git rm test.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git checkout -- test.txx//此时是还原&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h2 id="远程仓库"&gt;&lt;a href="#%e8%bf%9c%e7%a8%8b%e4%bb%93%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;远程仓库&#13;&#10;&lt;/h2&gt;&lt;h4 id="添加远程库"&gt;&lt;a href="#%e6%b7%bb%e5%8a%a0%e8%bf%9c%e7%a8%8b%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;添加远程库&#13;&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git remote add origin https://github.com/Zesaen/learngit.git&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git push -u origin master//第一次推送master分支时，加上了-u参数&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git push origin master//此后本地提交&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="删除远程库"&gt;&lt;a href="#%e5%88%a0%e9%99%a4%e8%bf%9c%e7%a8%8b%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;删除远程库&#13;&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git remote -v//查看远程库&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git remote rm origin//删除origin&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="从远程库克隆"&gt;&lt;a href="#%e4%bb%8e%e8%bf%9c%e7%a8%8b%e5%ba%93%e5%85%8b%e9%9a%86" class="header-anchor"&gt;&lt;/a&gt;从远程库克隆&#13;&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git clone &#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h2 id="分支管理"&gt;&lt;a href="#%e5%88%86%e6%94%af%e7%ae%a1%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;分支管理&#13;&#10;&lt;/h2&gt;&lt;h4 id="创建并合并"&gt;&lt;a href="#%e5%88%9b%e5%bb%ba%e5%b9%b6%e5%90%88%e5%b9%b6" class="header-anchor"&gt;&lt;/a&gt;创建并合并&#13;&#10;&lt;/h4&gt;&lt;p&gt;查看分支：&lt;code&gt;git branch&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;创建分支：&lt;code&gt;git branch &amp;lt;name&amp;gt;&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;切换分支：&lt;code&gt;git switch &amp;lt;name&amp;gt;&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;创建+切换分支：&lt;code&gt;git switch -c &amp;lt;name&amp;gt;&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;合并某分支到当前分支：&lt;code&gt;git merge &amp;lt;name&amp;gt;&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;删除分支：&lt;code&gt;git branch -d &amp;lt;name&amp;gt;&lt;/code&gt;&lt;/p&gt;&#10;&lt;h4 id="解决冲突"&gt;&lt;a href="#%e8%a7%a3%e5%86%b3%e5%86%b2%e7%aa%81" class="header-anchor"&gt;&lt;/a&gt;解决冲突&#13;&#10;&lt;/h4&gt;&lt;p&gt;&lt;code&gt;master&lt;/code&gt;分支和&lt;code&gt;feature1&lt;/code&gt;分支各自都分别有新的提交&lt;/p&gt;&#10;&lt;img src="images/image-20250408204457302.png" alt="image-20250408204457302" style="zoom: 80%;" /&gt;&#13;&#10;&lt;p&gt;Git用&lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/code&gt;，&lt;code&gt;=======&lt;/code&gt;，&lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt;标记出不同分支的内容&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating a new branch is quick &amp;amp; simple.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;=======&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Creating a new branch is quick AND simple.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; feature1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="bug分支"&gt;&lt;a href="#bug%e5%88%86%e6%94%af" class="header-anchor"&gt;&lt;/a&gt;Bug分支&#13;&#10;&lt;/h4&gt;&lt;p&gt;略&lt;/p&gt;&#10;&lt;h4 id="强制删除分支"&gt;&lt;a href="#%e5%bc%ba%e5%88%b6%e5%88%a0%e9%99%a4%e5%88%86%e6%94%af" class="header-anchor"&gt;&lt;/a&gt;强制删除分支&#13;&#10;&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git branch -D &amp;lt;name&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="多人协作"&gt;&lt;a href="#%e5%a4%9a%e4%ba%ba%e5%8d%8f%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;多人协作&#13;&#10;&lt;/h4&gt;&lt;p&gt;略&lt;/p&gt;&#10;&lt;h2 id="标签管理"&gt;&lt;a href="#%e6%a0%87%e7%ad%be%e7%ae%a1%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;标签管理&#13;&#10;&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git tag v1.0//给最新打标签&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git tag v0.9 f52c633//给对应打标签&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git show v0.9//查看标签信息&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git tag -d v0.1//删除标签&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h4 id="操作标签"&gt;&lt;a href="#%e6%93%8d%e4%bd%9c%e6%a0%87%e7%ad%be" class="header-anchor"&gt;&lt;/a&gt;操作标签&#13;&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;命令&lt;code&gt;git push origin &amp;lt;tagname&amp;gt;&lt;/code&gt;可以推送一个本地标签；&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;命令&lt;code&gt;git push origin --tags&lt;/code&gt;可以推送全部未推送过的本地标签；&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;命令&lt;code&gt;git tag -d &amp;lt;tagname&amp;gt;&lt;/code&gt;可以删除一个本地标签；&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;命令&lt;code&gt;git push origin :refs/tags/&amp;lt;tagname&amp;gt;&lt;/code&gt;可以删除一个远程标签。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>Modbus 通信协议学习笔记</title><link>https://zeseanblog.top/p/modbus/</link><pubDate>Sat, 10 May 2025 10:00:00 +0800</pubDate><guid>https://zeseanblog.top/p/modbus/</guid><description>&lt;p&gt;通信：&lt;/p&gt;&#10;&lt;p&gt;硬件层：RS485解决数据传输问题，如何将“0”或“1”传输到另外一个设备&lt;/p&gt;&#10;&lt;p&gt;软件层：MODBUS，在硬件基础上解决数据传输的含义或意义&lt;/p&gt;&#10;&lt;p&gt;对于RS485：作为两线制485由于传输差分信号，因此是半双工的&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250923164142804" class="gallery-image" data-flex-basis="937px" data-flex-grow="390" height="466" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/modbus/images/image-20250923164142804.png" srcset="https://zeseanblog.top/p/modbus/images/image-20250923164142804_hu_1a7d4f7cc5927610.png 800w, https://zeseanblog.top/p/modbus/images/image-20250923164142804_hu_d7420e5c849dd242.png 1600w, https://zeseanblog.top/p/modbus/images/image-20250923164142804.png 1821w" width="1821"&gt;&lt;/p&gt;&#10;&lt;p&gt;对于MAX485芯片： RE和DE连一根线，为高电平时DE使能，单片机TX发送至DI。为低电平时RE使能，485信号发送至单片机RX&lt;/p&gt;&#10;&lt;img src="images/image-20250923164546337.png" alt="image-20250923164546337" style="zoom:50%;" /&gt;&#10;&lt;p&gt;max485电路：&lt;/p&gt;&#10;&lt;img src="images/image-20250923184642251.png" alt="image-20250923184642251" style="zoom:50%;" /&gt;&#10;&lt;p&gt;对于主从机：RS485和modbus支持主从通信，能够一主多从&lt;/p&gt;&#10;&lt;img src="images/image-20250923165437760.png" alt="image-20250923165437760" style="zoom: 33%;" /&gt;&#10;&lt;p&gt;modbus约定：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;一个系统一主多从，只能进行主从通信，从从通信需要借助主机&lt;/li&gt;&#10;&lt;li&gt;系统中从机不可主动向主机发送数据&lt;/li&gt;&#10;&lt;li&gt;系统上电后所有设备都应处于监听总线的状态，也就是接收状态&lt;/li&gt;&#10;&lt;li&gt;如果要进行一次通信，必须由主机主动发起通信&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;一次modbus通信：模式为主机轮询，从机应答的机制&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;主机一开始也是监听总线的状态，要切换成发送模式（实际上是修改MAX485上RE、DE的电平），发送数据包&lt;/li&gt;&#10;&lt;li&gt;发送完成后立马转成接收模式&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;modbus通信报文或数据包格式：&lt;/p&gt;&#10;&lt;p&gt;通信地址0-247，指定地址0是广播指令，所有设备都会运行&lt;/p&gt;&#10;&lt;img src="images/image-20250923185045174.png" alt="image-20250923185045174" style="zoom: 67%;" /&gt;&#10;&lt;p&gt;常用功能码：&lt;/p&gt;&#10;&lt;img src="images/image-20250923184947054.png" alt="image-20250923184947054" style="zoom: 67%;" /&gt;&#10;&lt;p&gt;03功能码报文示例：从机读数据&lt;/p&gt;&#10;&lt;p&gt;主机发送Tx:01 03 00 00 00 02 C4 0B&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;地址码8bit&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;功能码8bit&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;寄存器起始16bit&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;CRC校验16bit&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;主机发送&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;01&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;03&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;00 00&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;C4 0B&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;从机应答Rx:01 03 04 00 01 00 02 2A 32&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;读了2个寄存器，每个寄存器16位&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;地址码&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;功能码&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;字节数&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;数据1&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;数据2&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;CRC校验&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;从机应答&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;01&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;03&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;04&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;00 01&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;00 02&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;2A 32&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;06功能码报文示例：向从机写一个寄存器数据&lt;/p&gt;&#10;&lt;p&gt;主机发送Tx:01 06 00 03 00 C8 78 5C&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;地址码8bit&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;功能码8bit&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;寄存器个数16bit&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;数据16bit&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;CRC校验16bit&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;主机发送&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;01&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;06&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;00 03&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;00 C8&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;78 5C&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;从机应答Rx::01 06 00 03 00 C8 78 5C与主机发送一致&lt;/p&gt;&#10; &lt;img src="images/image-20250923193620361.png" alt="image-20250923193620361" style="zoom:67%;" /&gt;&#10;&lt;p&gt;如何接受报文：&lt;/p&gt;&#10;&lt;p&gt;9600波特率，3字符 1个字符占10bit&lt;/p&gt;&#10;&lt;p&gt;3*10*1/9600=3ms 超时时间10ms就认为一个新的数据包&lt;/p&gt;&#10;</description></item><item><title>IIC 通信协议学习笔记</title><link>https://zeseanblog.top/p/iic/</link><pubDate>Sat, 19 Apr 2025 09:30:00 +0800</pubDate><guid>https://zeseanblog.top/p/iic/</guid><description>&lt;h3 id="111-i2c硬件"&gt;&lt;a href="#111-i2c%e7%a1%ac%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;11.1 I2C硬件&#13;&#10;&lt;/h3&gt;&lt;p&gt;SCL,SDA，一条I2C总线可接很多设备，SCL,SDA放上拉电阻&lt;/p&gt;&#10;&lt;img src="images/image-20250828205720777.png" alt="image-20250828205720777" style="zoom:67%;" /&gt;&#10;&lt;h3 id="112-传输数据类比"&gt;&lt;a href="#112-%e4%bc%a0%e8%be%93%e6%95%b0%e6%8d%ae%e7%b1%bb%e6%af%94" class="header-anchor"&gt;&lt;/a&gt;11.2 传输数据类比&#13;&#10;&lt;/h3&gt;&lt;p&gt;如何通过IIC传数据，&lt;/p&gt;&#10;&lt;p&gt;主设备：一主多从，可把数据从主设备发到从设备，也可从设备发到主设备&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;发送&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;主设备：开始(start)&lt;/p&gt;&#10;&lt;p&gt;主设备：A，我把数据发你(地址/方向)&lt;/p&gt;&#10;&lt;p&gt;A：收到(回应)&lt;/p&gt;&#10;&lt;p&gt;主设备：发送数据(传输)&lt;/p&gt;&#10;&lt;p&gt;A：收到后，告诉主设备(回应)&lt;/p&gt;&#10;&lt;p&gt;主设备：结束(停止)&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;接收&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;主设备：开始(start)&lt;/p&gt;&#10;&lt;p&gt;主设备：B，把数据发我(地址/方向)&lt;/p&gt;&#10;&lt;p&gt;B：收到(回应)&lt;/p&gt;&#10;&lt;p&gt;B：把数据发给主设备(传输)&lt;/p&gt;&#10;&lt;p&gt;主设备：收到数据后，告诉A(回应)&lt;/p&gt;&#10;&lt;p&gt;主设备：结束(停止)&lt;/p&gt;&#10;&lt;h3 id="113-iic传输数据格式"&gt;&lt;a href="#113-iic%e4%bc%a0%e8%be%93%e6%95%b0%e6%8d%ae%e6%a0%bc%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;11.3 IIC传输数据格式&#13;&#10;&lt;/h3&gt;&lt;h4 id="1131写操作"&gt;&lt;a href="#1131%e5%86%99%e6%93%8d%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;11.3.1写操作&#13;&#10;&lt;/h4&gt;&lt;ul&gt;&#10;&lt;li&gt;主设备发出start信号&lt;/li&gt;&#10;&lt;li&gt;发出设备地址，方向(读1/写0)&lt;/li&gt;&#10;&lt;li&gt;从设备发出应答信号&lt;/li&gt;&#10;&lt;li&gt;主设备发送一字节数据，等待回应&lt;/li&gt;&#10;&lt;li&gt;每传输一字节，接收方回应一次，在传输下一个数据&lt;/li&gt;&#10;&lt;li&gt;数据发送完成，主设备发送stop信号&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img alt="image-20250828211121367" class="gallery-image" data-flex-basis="1566px" data-flex-grow="652" height="99" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/iic/images/image-20250828211121367.png" width="646"&gt;&lt;/p&gt;&#10;&lt;h4 id="1132读操作"&gt;&lt;a href="#1132%e8%af%bb%e6%93%8d%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;11.3.2读操作&#13;&#10;&lt;/h4&gt;&lt;p&gt;&lt;img alt="image-20250828212451496" class="gallery-image" data-flex-basis="1475px" data-flex-grow="614" height="108" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/iic/images/image-20250828212451496.png" width="664"&gt;&lt;/p&gt;&#10;&lt;h4 id="1133-iic信号"&gt;&lt;a href="#1133-iic%e4%bf%a1%e5%8f%b7" class="header-anchor"&gt;&lt;/a&gt;11.3.3 IIC信号&#13;&#10;&lt;/h4&gt;&lt;p&gt;IIC协议栈数据传输单位是字节，但是要用到9个时钟，前面8个时钟用来传输8数据，第9个始终用来传输回应信号，先传输最高位&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;开始信号(S)：SCL为高时，SDA由高跳低，开始传输数据&lt;/li&gt;&#10;&lt;li&gt;结束信号(P)：SCL为高时，SDA由低跳高，结束传输数据&lt;/li&gt;&#10;&lt;li&gt;响应信号(ACK)：接收到8位数据，第九个时钟周期，拉低SDA&lt;/li&gt;&#10;&lt;li&gt;SDA数据必须在SCL高时稳定，只能在SCL为低时变化&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img alt="image-20250828213228809" class="gallery-image" data-flex-basis="708px" data-flex-grow="295" height="335" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/iic/images/image-20250828213228809.png" srcset="https://zeseanblog.top/p/iic/images/image-20250828213228809_hu_9c82e3ce5d874844.png 800w, https://zeseanblog.top/p/iic/images/image-20250828213228809.png 989w" width="989"&gt;&lt;/p&gt;&#10;&lt;h4 id="1134-协议细节"&gt;&lt;a href="#1134-%e5%8d%8f%e8%ae%ae%e7%bb%86%e8%8a%82" class="header-anchor"&gt;&lt;/a&gt;11.3.4 协议细节&#13;&#10;&lt;/h4&gt;&lt;p&gt;1.SDA引脚必须双向IO，因为有发有收&lt;/p&gt;&#10;&lt;ol start="2"&gt;&#10;&lt;li&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;img src="images/image-20250828214833582.png" alt="image-20250828214833582" style="zoom:67%;" /&gt;&#10;&lt;img src="images/image-20250828214855838.png" alt="image-20250828214855838" style="zoom:67%;" /&gt;&#10;&lt;img src="images/image-20250828215155892.png" alt="image-20250828215155892" style="zoom:67%;" /&gt;&#10;</description></item><item><title>SPI 通信协议学习笔记</title><link>https://zeseanblog.top/p/spi/</link><pubDate>Sat, 12 Apr 2025 09:30:00 +0800</pubDate><guid>https://zeseanblog.top/p/spi/</guid><description>&lt;h1 id="spi通信"&gt;&lt;a href="#spi%e9%80%9a%e4%bf%a1" class="header-anchor"&gt;&lt;/a&gt;SPI通信&#13;&#10;&lt;/h1&gt;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;SPI：通用数据总线&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;四根通信线：轻松Mhz&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;SCK(Serial Clock)&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;MOSI(Master Output Slave Input)&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;MISO(Master Input Slave Output)&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;SS(Slave Select)&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;同步，全双工&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;支持总线挂载多设备（一主多从）&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;常用模块：W25Q64 FLASH存储器、SPI OLED屏、NRF24L01 2.4G无线通讯模块、SD卡 支持SPI&lt;/p&gt;&#10;&lt;h2 id="硬件电路"&gt;&lt;a href="#%e7%a1%ac%e4%bb%b6%e7%94%b5%e8%b7%af" class="header-anchor"&gt;&lt;/a&gt;硬件电路&#13;&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;所有SPI设备SCK、MOSI、MISO分别连接在一起&lt;/li&gt;&#10;&lt;li&gt;主机引出多条SS控制线，分别连接各从机SS引脚&lt;/li&gt;&#10;&lt;li&gt;输出引脚配置推挽输出（驱动能力强，驱动上下降沿强），输入引脚配置浮空或上拉&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img src="images/image-20250925170440759.png" alt="image-20250925170440759" style="zoom:67%;" /&gt;&#10;&lt;p&gt;主机指定从机：将对应SS线输出低电平，其余高电平&lt;/p&gt;&#10;&lt;h2 id="移位示意图"&gt;&lt;a href="#%e7%a7%bb%e4%bd%8d%e7%a4%ba%e6%84%8f%e5%9b%be" class="header-anchor"&gt;&lt;/a&gt;移位示意图&#13;&#10;&lt;/h2&gt;&lt;img src="images/image-20250925171058081.png" alt="image-20250925171058081" style="zoom:80%;" /&gt;&#10;&lt;p&gt;波特率发生器作为时钟，每一个上升沿，移位寄存器移出一位，进行数据发送；每一个下降沿，最低位采样&lt;/p&gt;&#10;&lt;img src="images/image-20250925171304695.png" alt="image-20250925171304695" style="zoom:80%;" /&gt;&#10;&lt;p&gt;一般主机发0x00或0xff跟从机交换数据&lt;/p&gt;&#10;&lt;h2 id="spi时序基本单元"&gt;&lt;a href="#spi%e6%97%b6%e5%ba%8f%e5%9f%ba%e6%9c%ac%e5%8d%95%e5%85%83" class="header-anchor"&gt;&lt;/a&gt;SPI时序基本单元&#13;&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;起始条件：SS高电平到低电平&lt;/li&gt;&#10;&lt;li&gt;终止条件：SS低电平切换高电平&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;img alt="image-20250925171622639" class="gallery-image" data-flex-basis="1494px" data-flex-grow="622" height="137" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/spi/images/image-20250925171622639.png" srcset="https://zeseanblog.top/p/spi/images/image-20250925171622639_hu_bf9253fce5076353.png 800w, https://zeseanblog.top/p/spi/images/image-20250925171622639.png 853w" width="853"&gt;&lt;/p&gt;&#10;&lt;p&gt;SPI由不同的移位模型，能根据SCK的不同边沿变化进行移位。&lt;/p&gt;&#10;&lt;h3 id="模式1"&gt;&lt;a href="#%e6%a8%a1%e5%bc%8f1" class="header-anchor"&gt;&lt;/a&gt;模式1&#13;&#10;&lt;/h3&gt;&lt;p&gt;CPOL=0：空闲状态时，SCK低电平&lt;/p&gt;&#10;&lt;p&gt;CPHA=1：SCK第一个边沿移出数据，第二个边沿移入数据（数据采样）&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250925171826936" class="gallery-image" data-flex-basis="732px" data-flex-grow="305" height="326" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/spi/images/image-20250925171826936.png" srcset="https://zeseanblog.top/p/spi/images/image-20250925171826936_hu_911829cf886d67fc.png 800w, https://zeseanblog.top/p/spi/images/image-20250925171826936.png 995w" width="995"&gt;&lt;/p&gt;&#10;&lt;h3 id="模式0"&gt;&lt;a href="#%e6%a8%a1%e5%bc%8f0" class="header-anchor"&gt;&lt;/a&gt;模式0&#13;&#10;&lt;/h3&gt;&lt;p&gt;CPOL=0:空闲状态时，SCK为低电平&#10;CPHA=0: SCK第一个边沿移入数据,第二个边沿移出数据&lt;/p&gt;&#10;&lt;p&gt;将第一个数据变化的时机提前&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="image-20250925172507991" class="gallery-image" data-flex-basis="720px" data-flex-grow="300" height="335" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://zeseanblog.top/p/spi/images/image-20250925172507991.png" srcset="https://zeseanblog.top/p/spi/images/image-20250925172507991_hu_3ab423fd4e852e0f.png 800w, https://zeseanblog.top/p/spi/images/image-20250925172507991.png 1006w" width="1006"&gt;&lt;/p&gt;&#10;&lt;h2 id="spi时序"&gt;&lt;a href="#spi%e6%97%b6%e5%ba%8f" class="header-anchor"&gt;&lt;/a&gt;SPI时序&#13;&#10;&lt;/h2&gt;&lt;p&gt;W25Q64为例，芯片厂商规定&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;发送指令&lt;/li&gt;&#10;&lt;li&gt;向SS指定设备，发送指令（0x06），00000110&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img src="images/image-20250925173135029.png" alt="image-20250925173135029" style="zoom:67%;" /&gt;&#10;</description></item><item><title>如何更新这个博客</title><link>https://zeseanblog.top/p/how-to-publish/</link><pubDate>Sat, 15 Mar 2025 11:30:00 +0800</pubDate><guid>https://zeseanblog.top/p/how-to-publish/</guid><description>&lt;p&gt;这是一篇备忘录，记录本博客的日常更新流程。现在有两种方式：**本地笔记工作台（推荐）**和手工流程。&lt;/p&gt;&#10;&lt;h2 id="1-notes-ui-本地工作台推荐"&gt;&lt;a href="#1-notes-ui-%e6%9c%ac%e5%9c%b0%e5%b7%a5%e4%bd%9c%e5%8f%b0%e6%8e%a8%e8%8d%90" class="header-anchor"&gt;&lt;/a&gt;1. notes-ui 本地工作台（推荐）&#13;&#10;&lt;/h2&gt;&lt;p&gt;仓库里的 &lt;code&gt;tools/notes-ui/&lt;/code&gt; 是一个只监听本机的 Web 工具，双击 &lt;code&gt;start.bat&lt;/code&gt; 启动后浏览器自动打开 http://127.0.0.1:8091 ：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;导入笔记&lt;/strong&gt;：拖拽 &lt;code&gt;.md&lt;/code&gt; 文件或整个笔记文件夹（图片会自动带上），也可以直接粘贴文本&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;检查元数据&lt;/strong&gt;：标题、描述、分类、标签、发布时间都会自动预填，slug 实时查重；右侧图片清单能看到正文引用的图片是否齐全，缺的可补传&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;生成页面包&lt;/strong&gt;：图片自动拷入 &lt;code&gt;images/&lt;/code&gt;、正文路径自动改写、front matter 按站内规范生成&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;本地预览&lt;/strong&gt;：弹窗内嵌真实主题渲染（含公式和 Mermaid）&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;分步发布&lt;/strong&gt;：构建验证 → 部署上线（二次确认）→ 线上抽查 → git 提交，每步独立日志，出问题可停在中途&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;「文章管理」页还能改历史文章的元数据、切换草稿、改 slug、删除（进本地回收站）。&lt;/p&gt;&#10;&lt;h2 id="2-手工流程备用"&gt;&lt;a href="#2-%e6%89%8b%e5%b7%a5%e6%b5%81%e7%a8%8b%e5%a4%87%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;2. 手工流程（备用）&#13;&#10;&lt;/h2&gt;&lt;p&gt;不用工具时，流程如下。&lt;/p&gt;&#10;&lt;h3 id="写新文章"&gt;&lt;a href="#%e5%86%99%e6%96%b0%e6%96%87%e7%ab%a0" class="header-anchor"&gt;&lt;/a&gt;写新文章&#13;&#10;&lt;/h3&gt;&lt;p&gt;在 &lt;code&gt;content/post/&lt;/code&gt; 目录下新建页面包 &lt;code&gt;my-new-post/index.md&lt;/code&gt;（图片放同目录 &lt;code&gt;images/&lt;/code&gt;），或单文件 &lt;code&gt;my-new-post.md&lt;/code&gt;：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;文章标题&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ld"&gt;2025-03-15T11:30:00&lt;/span&gt;&lt;span class="m"&gt;+08&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;my-new-post&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;draft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;文章摘要，会显示在首页卡片上。&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;分类名&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;标签&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;正文从这里开始，支持标准 Markdown。&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#13;&#10; &lt;blockquote&gt;&#13;&#10; &lt;p&gt;把 &lt;code&gt;draft&lt;/code&gt; 设为 &lt;code&gt;true&lt;/code&gt; 可以存草稿，构建时不会发布。注意 front matter 的 &lt;code&gt;date&lt;/code&gt; 不要写成未来时间，否则 Hugo 默认不构建该文章。&lt;/p&gt;&#10;&#13;&#10; &lt;/blockquote&gt;&#13;&#10;&lt;h3 id="本地预览可选"&gt;&lt;a href="#%e6%9c%ac%e5%9c%b0%e9%a2%84%e8%a7%88%e5%8f%af%e9%80%89" class="header-anchor"&gt;&lt;/a&gt;本地预览（可选）&#13;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;hugo&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="n"&gt;-D&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;浏览器打开 http://localhost:1313 实时预览，&lt;code&gt;Ctrl+C&lt;/code&gt; 退出。&lt;/p&gt;&#10;&lt;h3 id="构建并部署"&gt;&lt;a href="#%e6%9e%84%e5%bb%ba%e5%b9%b6%e9%83%a8%e7%bd%b2" class="header-anchor"&gt;&lt;/a&gt;构建并部署&#13;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 在博客根目录执行一键部署脚本（构建 + 上传 + 原子替换）&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bash deploy/deploy.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;部署完成，访问 &lt;a class="link" href="https://zeseanblog.top" target="_blank" rel="noopener"&#13;&#10; &gt;https://zeseanblog.top&lt;/a&gt; 即可看到新文章。&lt;/p&gt;&#10;&lt;h2 id="3-让-ai-助手代劳"&gt;&lt;a href="#3-%e8%ae%a9-ai-%e5%8a%a9%e6%89%8b%e4%bb%a3%e5%8a%b3" class="header-anchor"&gt;&lt;/a&gt;3. 让 AI 助手代劳&#13;&#10;&lt;/h2&gt;&lt;p&gt;直接说一句「帮我发布新文章」即可——本文件夹的 AGENTS.md 里记录了完整的环境信息和部署流程。&lt;/p&gt;&#10;&lt;h2 id="4-提交代码备份"&gt;&lt;a href="#4-%e6%8f%90%e4%ba%a4%e4%bb%a3%e7%a0%81%e5%a4%87%e4%bb%bd" class="header-anchor"&gt;&lt;/a&gt;4. 提交代码（备份）&#13;&#10;&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 只提交这篇 文章 的路径，避免带上工作区其他未完成的改动&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git add content/post/my-new-post&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit -m &lt;span class="s2"&gt;&amp;#34;post: 新文章标题&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;文章源码就是备份，随时可以回滚或迁移。&lt;/p&gt;&#10;</description></item><item><title>你好，世界</title><link>https://zeseanblog.top/p/hello-world/</link><pubDate>Sat, 15 Mar 2025 10:00:00 +0800</pubDate><guid>https://zeseanblog.top/p/hello-world/</guid><description>&lt;p&gt;折腾了一阵子，个人博客终于上线了 🎉 这是本站的第一篇文章，简单记录一下搭建过程。&lt;/p&gt;&#10;&lt;h2 id="技术栈"&gt;&lt;a href="#%e6%8a%80%e6%9c%af%e6%a0%88" class="header-anchor"&gt;&lt;/a&gt;技术栈&#13;&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;组件&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;选择&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;说明&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;静态站点生成器&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Hugo&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;单二进制，构建速度极快&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;主题&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Stack&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;卡片式设计，简洁美观&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Web 服务器&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Nginx&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;托管静态文件，性能足够&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;HTTPS&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Let&amp;rsquo;s Encrypt&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;免费证书，自动续期&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;服务器&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;腾讯云&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Ubuntu 22.04&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="为什么选择静态博客"&gt;&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e9%80%89%e6%8b%a9%e9%9d%99%e6%80%81%e5%8d%9a%e5%ae%a2" class="header-anchor"&gt;&lt;/a&gt;为什么选择静态博客？&#13;&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;快&lt;/strong&gt;：纯静态 HTML，没有数据库查询，加载飞快&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;稳&lt;/strong&gt;：没有后端服务，几乎不会被黑，维护成本极低&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;省&lt;/strong&gt;：一台最小配置的服务器就能流畅运行&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="接下来"&gt;&lt;a href="#%e6%8e%a5%e4%b8%8b%e6%9d%a5" class="header-anchor"&gt;&lt;/a&gt;接下来&#13;&#10;&lt;/h2&gt;&lt;p&gt;以后这里会不定期更新：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;📝 技术学习笔记&lt;/li&gt;&#10;&lt;li&gt;🔨 项目开发记录&lt;/li&gt;&#10;&lt;li&gt;💭 生活随想&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;欢迎常来逛逛～&lt;/p&gt;&#10;</description></item></channel></rss>