单片机和嵌入式入门教程

图1:单片机开发 VS 嵌入式开发
所谓嵌入式,就是把计算机放到其它设备里面,让计算机来控制设备的运行和使用。
这种计算机非常小非常简陋,只有一个低配的板子,或者一个 MCU(单片机),没有屏幕、键盘、鼠标这些外设,在外观/外形方面和常用的电脑等存在巨大的差异;并且,它还被放到设备内部了,所以我们通常感受不到它的存在。
如果需要显式温度、湿度、风量等信息,也会有一个小屏幕露在外面。
由于技术进步和政策推动,这几年硬件设备开始朝着智能化方向发展,需要越来越多的芯片和软件为它赋能,这让传统的嵌入式开发又掀起了一股热潮,不但工作岗位增加了,而且薪资待遇也提高了。当然,嵌入式的薪资肯定还赶不上互联网。比如,应届生入职互联网大厂的年包在 40w 左右,而入职硬件公司的年包在 30w 左右,从这个角度看,嵌入式的年包比互联网低 20%~30%。
至于单片机,那就更拉胯了,比较顶流的也就拿到 25w 左右。算算比例的话,比嵌入式低 20%。这个很正常,因为单片机的技术栈简单,需要学习的知识少;同时,单片机产品的功能也不复杂,有时候一个人就可以搞定一款产品。
传统的嵌入式开发既要精通软件,也要了解硬件,工作经验越丰富就越能开发出稳定与合规的产品,所以会有一种「小火慢炖、越老越香」的感觉。和互联网相比,传统嵌入式确实不那么容易中年危机。
然而,这几年嵌入式领域发生了一些变化,涌现出了一堆新技术,比如嵌入式+物联网+云端、嵌入式+大数据、嵌入式+AI,嵌入式+无人驾驶等。很多大公司都参与其中,并提供了可以落地的软硬件解决方案。
因为硬件、驱动、操作系统、各种组件/库/算法,都是别人给你提供好的,你更多的是在面向业务逻辑写应用,所以和互联网开发没有什么太大的区别了。
这意味着,刚毕业的年轻人也能胜任工作了,35 岁以上的老人优势不明显了,被裁员以后很有可能找不到满意的工作,从而产生中年危机。不仅仅是互联网和嵌入式,所有不能靠经验维持自己优势的行业,所有不能靠时间竖立起壁垒的行业,都会有中年危机。
很多自媒体都说嵌入式越老越香,学到的技术不容易落伍,这种观点在以前是对的,但是在当下就没有那么乐观了。技术是在进步的,我们要向前看,不要把目光停留在过去。
不过根据目前的就业形式来看,嵌入式还是比较好找工作的,这算是它的一点优势吧。
什么是单片机?
很多人都有自己组装电脑的经历,精心挑选 CPU、内存条、硬盘、显卡、电源,然后选一款合适的主板,把这些硬件装插在主板上,再弄个机箱装进去便大功告成。这其中,CPU、存储、输入输出接口是比较核心的部件,如果我们用集成电路的方式把它们都放到一起,并通过总线相连,这样就构成了一个微型的、简陋的计算机。这种计算机有一个专业的名字,叫做 MCU(Microcontroller Unit),翻译成中文就是“微控制单元”。
另外,因为采用了集成电路技术,所以它的外观是一块芯片/硅片,而不是一块板子,所以又叫做单片机(Single-Chip Microcomputer)。

图2:单片机实物照片
单片机不是用来完成某一种种特定功能的芯片/电路,而是多种芯片/电路的集合体。
说白了,单片机是一个经过简化和缩小的计算机,它把一些比较核心的、不可或缺的硬件以「集成电路」的方式封装到一块芯片上。和普通电脑相比,单片机部件少、配置低、体积小、功耗低、价钱便宜;当然,它的性能也非常弱鸡,和普通电脑存在数量级的差距。单片机通常用于工业生产中,所以它的稳定性很高。
下面这是一张比较典型的 51 单片机的内部结构图:

图3:51单片机内部结构图
初学者可能看不懂这张图,没关系,有个大致的印象就可以,以后如果想从事单片机开发,自然就明白了。
结合这张图,我们再具体说一下单片机内部组成:
1) CPU内核
由一些 CPU 开发厂商开发设计,常见的几种 CPU 内核如 51 内核、AVR 内核、ARM 内核、RISC-V 内核。单片机厂家都是在已有 CPU 内核基础上设计单片机,比如 ST 公司就是在 ARM 授权 Cortex-M 内核的基础上设计出来 Stm32 单片机。
2) RAM(随机存储器)
相当于计算机的运行内存。主要用来存储单片机运行时一些中间数据、临时数据,所以也称数据存储器。RAM 的特点就是读写快、容量小、断电后数据会丢失,这些特点和计算机的内存是一样的。
3) ROM(只读存储器)
主要用来存储单片机的程序。我们写的代码,经过编译产生的二进制文件就是存储在这里,CPU 只能读取它,而不能修改它。它的特点是速度较慢、容量通常比 RAM 要大、断电后不会丢失。单片机中的 ROM 有多种类型,其中以 Flash 最为常见,单片机的数据手册里基本都是说 Flash 容量有多大,如 64KB、128KB,而不会说 ROM 容量有多大。
4) GPIO(通用输入/输出端口)
单片机有很多引脚(pin),比如 32pin、48pin、64pin 等,这些引脚中的大部分既可以被设置成输入模式,又可以被设置成输出模式,从而完成与外部设备的通讯、或者控制,这些引脚都属于 GPIO。输入就是接收外部信号,输出就是向外输出信号。
不过,有些引脚只能做特定功能使用,比如:- 电源引脚只能接外部电源;
- 复位引脚只能做复位使用;
- 下载引脚只能下载程序用;
- 时钟引脚只能接外部晶振。
类似这样的引脚就不属于 GPIO。
5) 其它外设
所谓外设,是指除 CPU 以外的外围功能模块;它们并不是真的在单片机外面,而是依旧封装在单片机内部,通过总线与 CPU 相连。上面提到的 RAM、ROM 都可以称为单片机的外设,但是单片机的外设不局限于这些,还有中断系统、定时器/计数器、串行通讯接口、模数转换器、显示驱动电路、脉宽调制电路等等。
不同厂家、不同型号、不同用途的单片机,它的外设也是不一样的。
单片机的运行方式
单片机集成了 CPU、存储、输入输出,那我们自然而然会想到,单片机上是不是可以跑程序?是的,单片机是一种可编程的芯片,可以将写好的程序编译之后下载到单片机里运行。但是只有单片机自己肯定是运行不了程序的,它连最起码的电都没有,所以它还需要一些外部电路的支撑才行,比如下面几种基本的电路:
1) 供电电路
单片机的工作电压通常是直流 5V 或者 3.3V,属于弱电。5V 的电源还比较常见,比如原来手机充电器都是 5V 的,只不过近几年快充的出现使不少充电器的充电电压提升到了 9V、12V。能直接输出 3.3V 的电源就没有了,3.3V 的电压需要通过 5V 或者更高的电压转换得到。
2) 时钟电路
正如计算机里的 CPU 一样,单片机执行程序指令时是有时钟周期的,没有时钟脉冲信号,它里面的那些门电路就不知道什么时候该做出什么动作,程序也就没法执行。时钟就像心脏一样,打着节拍,驱动着单片机的运行。
单片机内部一般都有振荡电路可以产生时钟信号,但是精度不高,所以通常都是通过外接晶振的方式来产生时钟。
3) 复位电路
复位就是回到初始状态,本质上是让单片机内的寄存器复位,否则状态未知,程序就会跑飞,运行出现错误。就像电脑死机需要重启一样,单片机出现错误时需要复位。刚上电的时候,单片机会自动复位,所以复位电路必不可少,否则单片机上电后无法复位,也就无法正常运行。4) 程序下载电路
这个就不用多说了,如果没有下载程序的接口,那怎么把程序放进单片机里呢。人们通常所说的烧程序,就是通过下载电路,把已经编译好的程序从电脑复制到单片机里面。
5) 串口通讯电路
这是调试程序、输出信息、写入配置信息最常用的电路了。如果说单片机是一个黑箱,那么串口通讯就是在这个黑箱上打开了一扇窗,让我们能看到里面发生着什么。通过串口发出来的信息,可以通过一些转换工具,最后发到电脑上、人机交互的显示屏上等等。
串口通信是人们一种通俗的叫法,更标准的叫法是串行通信。串行通信是对照并行通信来说的,串行通信的意思是数据逐位传输,每次只传输一个bit(0或1),比如一个字节有8位,就要传输8次。
串口通信最低只需要一根信号线,成本低、传输距离远但是传输速度慢。
并行通信则是增加了信号线的数量,所以一次可以传输多位,比如有8根信号线,一个字节一次就可以传输完成。并行通信传输速度快,但是传输距离近、成本高、抗干扰能力差,应用远不如串口通信广泛。
不像个人电脑这种通用型的计算机设备,用单片机开发的电路板通常都是有特定用途的,在消费电子、工业、汽车电子、各种仪器仪表当中随处可见其身影。
下面看两个电路板实物照:

图4:继电器模块

图5:信号采集模块
图4是一个工业级继电器控制模块,主要功能就是单片机控制继电器开/关,继而控制更多的大功率的设备。图5是一个信号采集模块,单片机采集光信号,处理后输出到上位机(比如个人计算机)。
再谈嵌入式
所谓嵌入式,就是把单片机,以及它周边的支撑电路和功能部件(也就是制作好的电路板),一起放到其它设备/装置的内部,控制设备/装置的运行和使用。因为镶嵌到设备内部了,而不是裸露在外边,所以才叫嵌入式。再粗暴的理解一下,嵌入式就是把单片机放到设备内部。前面我们提到的嵌入式开发,就是在单片机上进行开发。
单片机 + 支撑电路 + 功能部件,这些已经构成了一台计算机。但是,这种计算机和我们通常使用的电脑又有很大区别:
- 第一,这种计算机是专用的,只为某种特定功能/用途服务,干不了其它事情。
- 第二,这种计算机是设备/装置的一部分,和设备/装置的连接非常紧密,拆下来以后将没有用武之地。
- 第三,这种计算机因为使用的功能部件不一样,所以外形也不一样,甚至有很大差距。
总起来说,单片机是一种硬件,是一块包含了计算机核心部件的芯片。而嵌入式既不是硬件也不是软件,它是一种计算机的应用形式/落地形式/使用方式。
当然,如果你愿意,我们也可以不咬文嚼字,将嵌入式简单地理解为一块制作好的电路板,或者一种专用的计算机,它包含了单片机 + 支撑电路 + 功能部件。此时,嵌入式就是一种硬件,并且它包含了单片机。
单片机的位数
单片机有 8 位、16 位、32 位和 64 位之分,位数越多,算力就越强,就越能支持复杂程序。当然,功耗和成本也会更高。就目前来说:
- 16 位单片机非常冷门,极少使用;
- 8 位和 32 位单片机是主流,并且 32 位使用得越来越多,只有那些控制逻辑极其简单的设备,或者对价格敏感,对性能不敏感的设备,才会使用 8 位单片机。
- 64 位单片机和常见的平板/手机没有什么区别了,它们可以安装多种软件,可以支持复杂的交互逻辑,可以播放高清视频,还可以访问各种网站。64 位单片机在传统意义上的嵌入式领域非常少见。
单片机应用举例:
- 8 位单片机用于简单的逻辑控制或者数据处理,包括计数器、计算器、遥控器、电子玩具等,比如老式微波炉的控制面板、卡西欧(Casio)的基本款口袋计算器。
-
32 位单片有更高的计算能力和内存容量,堪比一个低配的手机,控制任务可以非常复杂,甚至可以处理多媒体,可以用于:
- 智能家居设备(如智能灯泡、智能插座)
- 汽车电子系统(如发动机控制单元使用单片机来控制燃油喷射和点火时间)
- 工业自动化设备(如 PLC 控制器)
- 医疗设备(血糖检测仪、体重秤)
- 高级的机器人控制系统
- 64 位单片机其实应用得很少,但是却离我们生活很近,我们可以看得见,比如汽车娱乐系统、MRI 和 CT 扫描仪。
现在的物联网设备(IoT)和智能家居设备一般都需要联网(WiFi、蓝牙等),这个时候通常会采用 32 位单片机,因为 32 位单片机可以安装操作系统,而操作系统可以内置网络协议栈。这一点下面会提到。
嵌入式操作系统
一个应用程序可以直接跑在硬件上,也就是不需要操作系统的支持,这种叫做裸机程序。应用程序也可以跑在操作系统上面,这样就不用直接操作硬件了,不但写代码简单了很多,而且还可以进行多任务开发。所谓多任务,就是让计算机同时干多件事情。多任务程序需要操作系统的支持,否则自己实现起来非常麻烦,没有必要。
8 位单片机由于硬件资源有限,控制逻辑也比较简单,所以通常不安装操作系统,而是直接跑裸机程序;32 位单片机可以根据实际情况来选择,可以跑裸机程序,也可以安装操作系统;64 位单片机就是平板/手机了,不安装操作系统就没法玩了。单片机上的操作系统有的非常简单,主要以多线程的方式来实现多任务,而不是传统意义的进程;为了方便理解,你可以简单的理解为只能运行一个应用程序,只是这个应用程序包含了多个线程。有的操作系统则比较复杂,和我们平时使用的 Windows、Linux 没有多大区别,可以同时运行多个应用程序,并且同时支持多进程和多线程(当然是经过了一些裁剪,阉割了不必要的功能和组件)。
RTOS
32 位单片机上使用的这种简单的、只支持多线程的操作系统,通常都是 RTOS(Real Time Operating System),也就是实时操作系统。和我们平常使用的 Windows、Linux、Android、iOS 相比,RTOS 有很多不一样的地方。第一,嵌入式系统用来控制其它设备的运行,它的操作系统必须要能够做到快速和及时的响应,不能卡顿或者拖延,否则就会导致故障甚至灾难。因为响应速度非常快,并且通常都是有保证的,所以这类操作系统被称为“实时”操作系统。
注意,RTOS 只能尽量做到“实时”,并不能 100% 保证实时;但是和我们平常使用的操作系统相比,RTOS 还是要靠谱很多的。
第二,RTOS 主要支持多线程,而不是传统意义上的多进程。比如在 FreeRTOS 中,一个线程就是一个函数;如果你想编写多线程的程序,那么写多个函数就行了。注意,RTOS 中其实通常使用“任务(Task)”这个术语,而不是线程;站长只是为了方便大家理解,所以才说线程。
第三,RTOS 设计非常精简,功能有限,资源占用很少,运行效率极高。当 RTOS 被编译成二进制映像以后,它最小只有几 KB;如果你添加更多的库和组件(TCP/IP协议栈、文件系统等),它可能增加到几十 KB,或者几百 KB。第四,RTOS 没有提供用户界面,重点在于后台服务和硬件交互。
第五,RTOS 采用模块化设计,支持高度的定制和裁剪,以适应不同的嵌入式需求。比如,如果你不需要联网,那就用不上 TCP/IP 协议栈;再如,文件系统也可以被裁减掉。
第六,RTOS 不是单独安装在单片机上的,而是以源代码的形式提供给程序员,然后和应用程序代码(我们写的代码)、底层库、功能组件等一起被编译/链接成一个单独的二进制映像文件,最后再烧录进单片机。
从这个角度看,RTOS 更像是应用程序的一个运行底座,或者一个支撑库。
其实在 RTOS 中,没有像 .exe 这种应用程序的概念,因为我们写的代码只是最终二进制文件的一部分,它不能单独生成一个二进制文件。
RTOS | 优点 | 缺点 | 适用场景 |
---|---|---|---|
FreeRTOS | 开源,轻量,占用资源少,文档丰富,支持多种微处理器架构,适合资源受限的嵌入式系统 | 相比于更复杂的 RTOS,功能较为基本 | 广泛应用于中小型嵌入式设备,如家电、工业控制器等。 |
µC/OS | 可预测性强,稳定可靠,源代码可读性高,功能丰富 | 需要商业授权 | 适用于对实时性和可靠性要求较高的系统,如医疗设备、汽车电子等。 |
VxWorks | 性能强大,支持广泛的硬件平台;提供丰富的网络和安全功能 | 成本较高,相对复杂,学习曲线较陡。 | 适用于高端和复杂的嵌入式系统,广泛用于航空航天、国防和工业自动化等领域。 |
Zephyr RTOS | 高度模块化,支持多种微处理器架构,社区活跃,持续更新,强调安全性和扩展性 | 相对较新,可能缺少某些特定硬件或者功能的支持 | 特别适合物联网和可穿戴设备。 |
RT-Thread | 国产,模块化和可配置性强,支持丰富的中间件,拥有活跃的社区 | 在国际上的知名度不高 | 提供了丰富的中间件和组件,适合复杂的应用,比如物联网、智能家居、工业控制等 |
更复杂的操作系统
RTOS 是一种非常简单的操作系统,除了这些,还有一些更加强大和高级的操作系统,用来应对那些比较复杂嵌入式开发任务。它们在概念上和我们常用的 Windows/Linux 就没有什么区别了,或者说非常接近了,比如它们支持多进程,支持用户界面和交互,支持使用互联网,甚至还可以安装应用程序。当然,他们肯定进行了轻量化裁剪,删除了那些不必要的组件和功能,并针对嵌入式环境进行了深度优化。
常见的复杂嵌入式系统有 Linux Embedded(嵌入式 Linux)、Android Things/Embedded Android(嵌入式 Android)、Windows Embedded/Windows IoT(嵌入式 Windows)、QNX、VxWorks 等。
QNX 和 VxWorks 是一个集 RTOS 的实时性和高级操作系统功能(可以支持多进程)于一身的嵌入式操作系统,它比许多传统的 RTOS 更复杂和功能丰富,同时又保持了 RTOS 所需的实时性和高效性。QNX 和 VxWorks 都以高可靠性和安全性而闻名,其中,QNX 在汽车、医疗、工业控制等关键应用领域非常受欢迎,VxWorks 广泛应用于航空航天、国防、汽车电子、工业自动化等行业。。
比如,BBA 的一些车型就使用 QNX 作为车载娱乐系统,一些工业机器人、自动化生产线也使用 QNX;波音空客的飞机、国际空间站、导弹和雷达系统、汽车的电子稳定程序(ESP)和防抱死制动系统(ABS)都使用了 VxWorks。
单片机开发和嵌入式开发
从学术和定义上来讲,这两种开发是没有什么区别的,都是一码事,因为嵌入式系统使用的都是单片机。但是在现实生活中,或者在程序员的交流中,我们通常又会区分两者:
- 针对裸机的开发,或者针对简单 RTOS 的开发,一般被冠以“单片机开发”的称呼;
- 而基于复杂操作系统(尤其是嵌入式 Linux)的开发,一般被冠以“嵌入式开发”的称呼。
不过两者之间也没有明显的分界线,因为你没法定量的说哪种操作系统简单,或者哪种操作系统复杂。此时你再回到文章开头看看那张图片(图1),是不是就豁然开朗了。
至此,我们总算吧单片机和嵌入式的概念讲明白了。
嵌入式板子
上面提到了,嵌入式是一种专用的计算机,它把「单片机 + 支撑电路 + 功能部件」都封装到一块电路板上(俗称板子),然后再放进设备内部。这里的板子,你可以自己从零制作,也可以使用第三方公司提供的现成产品,或者基于第三方公司的板子进行二次开发。这个没法一概而论,要根据自己的需求和成本来规划。
但是,自己制作板子是一个繁杂的系统工程,你除了要选择硬件,然后设计电路板,还要适配软件,包括驱动、操作系统、标准库、IDE(包括编译器、调试器、仿真工具等)。如果现有的软件没法满足需求,那你就要进行修改,或者从零开发。
这需要硬件工程师、驱动工程师、底层开发工程师、应用开发工程师、系统工程师、测试工程师等多个岗位进行配合与协调,研发周期可能长达半年、一年甚至数年,时间成本和资金成本都是巨大的。
当然,如果设备能够大规模量产,自己定制板子会节省成本,提高利润,这是很多公司选择自己定制板子的一个重要原因。
另外,如果你的产品比较特殊(比如工作环境非常严苛、产品体积非常小),现有的板子可能就满足不了你的需求,那你只能自己制作板子了。比如,手环和蓝牙耳机上使用的嵌入式板子就很小,第三方公司往往没有这样的板子。
核心板和开发板
第三方公司提供的嵌入式板子通常有两种,一种是核心板,一种是开发板。- 核心板用于量产设备,所以它更加紧凑和小巧,更加皮实和稳定。一种核心板只针对某些特定的开发场景,它的外设/部件/插槽/接口不会太多,基本够用就行。
- 开发板用于学习、开发或者测试,它是一个大而全的完整环境,包含各种各样的接口和传感器,甚至还有 LED 灯组和 LCD 显示器。
从开发板上选取一部分必要的硬件,让它们满足特定领域的需求,然后重新制作成板子,这就是核心板。可以认为,核心板是开发板的一个子集。
开发板可能包含的组件:
- 核心处理器:处理器是开发板的核心,执行程序和控制其他部件。
- 内存:包括 RAM 和存储设备(如 SD 卡或内置闪存)。
- 输入/输出端口:包括 GPIO(通用输入输出)、串行端口、USB 端口等。
- 网络接口:如以太网端口和/或无线模块(Wi-Fi、蓝牙等)。
- 显示接口:如 HDMI、VGA 或 LCD 连接器,用于连接显示器。
- 音频接口:包括音频输入和输出,用于连接麦克风和扬声器。
- 传感器:一些开发板可能包括温度传感器、运动传感器等。
- 扩展槽/接口:如 PCIe、HATs 或 Arduino 兼容的扩展槽。
- 电源管理:负责为板上各组件提供稳定电源。
- 调试接口:如 JTAG、串行控制台等,用于调试和编程。
- 用户界面组件:如按钮、LED 灯等。
核心板可能包含的组件:
- 处理器(CPU/GPU):是核心板的核心,负责执行指令和处理数据。
- 内存:包括 RAM(随机存取存储器)和闪存,用于存储运行时数据和系统软件。
- 电源管理电路:负责为板上的各种组件提供稳定的电源。
- 通信接口:如以太网、USB、SPI、I2C 等,用于与其他设备或模块通信。
- 无线通信模块(如果需要):如 Wi-Fi、蓝牙、Zigbee、LTE 等。
- 音视频处理单元(如适用):用于处理图像和声音数据。
- 存储接口:如 SD 卡插槽、eMMC、NAND/NOR 闪存等。
- 扩展端口:用于连接外部设备或主板。

图6:开发板示意图

图7:核心板示意图
嵌入式开发使用的编程语言
嵌入式是一个很大的话题,不同的场景会使用不同的编程语言。传统的嵌入式领域,硬件性能比较差,同时又对稳定性和及时性有着严苛的要求,所以通常会使用一些高效的语言,比如C语言、C++、汇编:
- 如果没有安装操作系统(裸机程序),那么基本都使用C语言。
-
如果安装了简单的 RTOS,那么通常会使用C语言;不过,很多较新的 RTOS(FreeRTOS、RT-Thread、µC/OS 等)也能支持阉割版的 C++了。
具体支持多少,还得看编译器的实现。不过考虑到资源开销和实时性的要求,通常不会支持那些高级特性,比如,异常处理、动态内存分配(new和delete)、运行时类类型信息(RTTI)、标准模板库(STL)一般都无法使用。
- 如果安装了比较复杂的操作系统,比如 Linux、VxWorks、QNX 等,那么就能支持完整的 C++ 了;当然,如果你在意资源消耗,也可以使用C语言。
- 如果需要编写驱动程序,或者启动代码(Bootloader),那么也会使用汇编语言(ASM)。
其它嵌入式场景:
- 如果你使用 VxWorks 和 QNX,并且对安全性和可靠性有着极高的要求,比如航空航天和军事领域,那么也可以使用 Ada 语言。
- 嵌入式 Android 应用开发通常使用 Java 和 Kotlin。
- 嵌入式 Windows 应用开发可以使用 C#,如果你对性能有要求,也可以使用 C++。
- 树莓派(Raspberry Pi)是一款强大且灵活的单板计算机,支持安装 Raspberry Pi OS(Debian 衍生版)、Ubuntu、Windows 10 IoT Core 等操作系统,可以使用各种编程语言,比如 Python、C/C++、Java、Java/Node.js、Scratch、Ruby、PHP 等。
声明:《嵌入式系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。