本文由 AI 辅助生成并经自动审查;尚未完成真实硬件验证。涉及具体芯片、时序和电气行为时,请以文末第一方资料和实际测试为准。
第 1 课:从源文件到可观察结果 #
本课只建立两个心智模型:嵌入式系统与主机的运行环境不同,以及源文件到可观察结果的最小闭环。代码是主机示例,待主机验证;没有开发板或运行记录,因此不表示已经上板。
1. 本节目标 #
完成本课后,你应该能:
- 说明为什么不能把主机程序拥有的条件直接当成嵌入式程序也拥有的条件。
- 说出并亲手走通
源文件 -> 构建产物 -> 运行 -> 可观察结果。
预计用时 30 分钟。本课不要求任何 C 语言、构建系统或单片机前置知识。
2. 它解决什么问题 #
在 Windows 上运行程序时,我们习惯了屏幕、终端和操作系统已经存在。嵌入式系统(embedded system,嵌入到设备中完成特定任务的计算系统)的目标环境可能没有这些条件。具体目标到底提供什么,必须由开发板资料和工程配置确认,不能从主机经验猜测。
另一方面,初学者常把“写完代码”当成“程序已经工作”。源文件只是输入;只有得到可运行文件、实际运行,并观察到结果,才形成最小验证闭环。
3. 必要前置知识 #
无。本课只需要:
- 一台普通 Windows 主机;
- PowerShell 终端;
- 一个可在终端调用的 GCC C 编译器。
先在 PowerShell 输入 gcc --version。若提示找不到命令,说明实验依赖尚未满足,应先安装或配置编译器;这不代表示例代码有错。
4. 核心原理 #
模型一:主机环境不等于嵌入式环境 #
- 解决的问题:阻止程序依赖目标设备并不存在的条件。
- 条件在哪里定义:主机条件由 Windows 和终端提供;目标条件应在具体硬件资料与工程配置中确认。
- 谁持有条件:当前实验由主机持有终端和可执行文件;未来目标设备持有处理器、存储器及实际可用的输入输出资源。
- 谁提供条件:本课由 Windows、GCC 和学习者输入的命令共同提供;迁移时由目标硬件、工具链和工程配置提供。
- 调用如何流动:学习者输入命令,主机启动程序,程序把结果交回终端;迁移后,结果必须改由目标设备实际具备的观察通道交出。
因此,不要先问“这段主机代码能否原样放进单片机”,而要先问“它依赖了哪些运行条件,目标是否提供”。ST 的 STM32CubeIDE 官方手册把构建、运行和调试 STM32 工程列为开发工具职责,也表明主机开发工具与目标程序是工作流中的不同位置。[1]
模型二:源文件到可观察结果的最小闭环 #
- 解决的问题:把“我写了代码”变成可检查的事实。
- 对象在哪里定义:程序规则写在
main.c;输出文件名写在构建命令中;预期结果写在实验步骤中。 - 谁持有对象:学习者持有源文件,文件系统持有构建产物,运行中的程序持有本次计算结果。
- 谁提供输入:学习者把
main.c和选项交给编译器;主机在运行时提供执行环境。 - 调用如何流动:
main.c -> GCC -> lesson.exe -> Windows 运行 -> 终端文本与退出状态。
GCC 官方文档说明,一次普通调用会完成得到最终程序所需的处理阶段;本课只使用这个整体能力,不展开内部阶段。[2]
5. 关键术语与直观模型 #
| 术语 | 本课中的意思 |
|---|---|
main |
主机程序开始执行本课代码时使用的入口名称;启动细节以后再学。 |
| 编译器(compiler) | 接收源文件并产生可运行构建产物的工具。 |
| 构建产物(build artifact) | 本实验生成的 lesson.exe 程序文件。 |
| 退出状态(exit status) | 程序结束时交给主机的整数;本实验约定 0 表示检查通过,1 表示失败。 |
| Host Fake(主机替身) | 在主机上提供可控的替代对象,用来代替暂时不可用的硬件依赖。 |
把源文件想成“可执行规则的文字记录”。编译器把它变成主机能运行的文件,但是否正确仍要靠运行后的可观察结果判断。
6. 从输入到结果的完整流程 #
- 在
main.c中写下规则:把40加2。 - 用 GCC 读取源文件,生成
lesson.exe。 - Windows 启动
lesson.exe,执行从main开始的代码。 - 程序在终端显示
result=42。 - 程序退出;PowerShell 用
$LASTEXITCODE显示退出状态。 - 同时看到文本
result=42和状态0,才满足本实验的预期。
7. 嵌入式系统中的对应位置 #
本实验的 main.c 对应未来固件中的程序规则;GCC 对应工具链中的构建工具;lesson.exe 对应面向目标平台的构建产物;终端输出和退出状态对应“可观察结果”。
差别在最后两步:目标程序不能默认拥有 Windows 终端或 .exe 运行方式。以后选定开发板后,才能依据官方资料决定如何构建、下载和观察。本课不指定芯片、引脚、时钟或外设。
8. 主机实验与硬件迁移边界 #
本课使用两个写在源文件中的确定数值完成主机逻辑验证。这里还没有需要替代的硬件依赖,因此没有实现 Host Fake;以后代码开始读取硬件输入时,才需要用可控的主机对象代替该依赖。当前实验只验证“输入经过规则得到结果”,不验证任何硬件。
迁移到硬件时,可以把固定输入替换为真实输入,并把观察方式替换为调试器中的变量观察或板上已有的输出通道。但具体做法依赖开发板、工具版本和连接方式,当前均为待核对。本课 hardware_verified=false。
9. 最小代码示例 #
将以下内容保存为 main.c:
#include <stdint.h>
#include <stdio.h>
int main(void)
{
uint32_t input = 40U;
uint32_t result = input + 2U;
printf("result=%lu\n", (unsigned long)result);
if (result != 42U) {
return 1;
}
return 0;
}这是 C11 子集示例,不使用动态内存。uint32_t 表示宽度固定为 32 位的无符号整数;input 保存输入,result 保存计算结果;printf 把文本交给主机终端;if 在结果不等于 42 时返回失败状态。这里不展开这些语法的通用规则。
代码属于本课的主机验证层,只依赖 C 标准库和主机运行环境。
10. 常见错误 #
- 只保存源文件就宣布完成:还缺少构建、运行和观察。
- 只看见
result=42:还应检查退出状态是否为0。 - 命令找不到
gcc:先处理工具可用性,不要随意改代码。 - 把主机输出当成上板结果:本实验没有硬件证据。
- 把
.exe当成单片机产物:它是为当前 Windows 主机生成的文件。
11. 调试观察点 #
按顺序检查:
main.c是否位于终端当前目录。- 构建命令是否生成
lesson.exe。 - 运行时终端是否出现准确文本
result=42。 - 运行后
$LASTEXITCODE是否为0。 - 若结果不符,先核对源文件中的
40U、2U和42U,一次只改一个位置再重试。
12. 实战实验 #
在含有 main.c 的目录打开 PowerShell,逐条执行:
gcc -std=c11 -Wall -Wextra -pedantic main.c -o lesson.exe
./lesson.exe
$LASTEXITCODE预期观察:
result=42
0然后把代码中的 input = 40U 改为 input = 41U,重新构建并运行。预期文本变为 result=43,退出状态变为 1。这一步证明退出状态来自实际规则,而不是固定展示。
没有本机运行记录前,上述内容均是“示例,待主机验证”。完成实验也只证明主机闭环成立,不证明硬件可用。
13. 自检题 #
- 为什么
main.c保存成功不等于程序已经工作? - 本实验的两个可观察结果分别是什么?
- 为什么不能默认嵌入式目标也拥有 PowerShell?
lesson.exe由谁产生,在哪里运行?- 把输入改为
41U后,哪两个观察结果应变化?
14. 面试题 #
问:怎样最小化地证明一段新写的 C 逻辑确实被执行?
答题要点:明确源文件、构建产物和运行环境;实际运行;选择至少一个可观察值;同时检查成功或失败状态;区分主机验证与硬件验证。
15. 延伸思考 #
- 如果目标设备没有终端,哪些结果仍可能被观察?先列方法,不假定具体硬件。
- 如果只保留退出状态、不打印文本,闭环是否仍成立?它会损失什么信息?
- 为什么每次修改源文件后都必须重新生成构建产物?
16. 本节总结 #
嵌入式程序和主机程序可能面对不同的运行条件,因此依赖必须逐项确认。可靠的第一步不是堆叠功能,而是跑通 源文件 -> 构建产物 -> 运行 -> 可观察结果。本课用确定输入完成主机逻辑验证;以后 Host Fake 可以替代硬件依赖,但仍不能代替硬件验证。
17. 下一步 #
下一课可在课程规划确认后继续学习第一个 C 程序的基本组成。本课的生成不代表已经掌握;只有你的自检答案、实验记录或后续复习结果才能改变掌握度。
18. 参考资料 #
- STMicroelectronics, STM32CubeIDE user guide, UM2609 Rev 18, June 2026,访问日期:2026-09-21。用于核对 STM32 主机开发工具的构建、运行与调试定位。
- GNU Project, Using the GNU Compiler Collection (GCC): Invoking GCC, GCC 14.2.0,访问日期:2026-09-21。用于核对 GCC 调用及本课构建命令的官方说明。