首页 > 编程笔记 > 嵌入式笔记

单片机和嵌入式入门教程

嵌入式开发是一个比较大的概念,单片机开发是一个比较小的概念。单片机开发是嵌入式开发的一个部分,或者说一个分支,或者说一个子集;反过来说,嵌入式开发又完全包含了单片机开发。


图1:单片机开发 VS 嵌入式开发

所谓嵌入式,就是把计算机放到其它设备里面,让计算机来控制设备的运行和使用。

这种计算机非常小非常简陋,只有一个低配的板子,或者一个 MCU(单片机),没有屏幕、键盘、鼠标这些外设,在外观/外形方面和常用的电脑等存在巨大的差异;并且,它还被放到设备内部了,所以我们通常感受不到它的存在。

如果需要显式温度、湿度、风量等信息,也会有一个小屏幕露在外面。

由于技术进步和政策推动,这几年硬件设备开始朝着智能化方向发展,需要越来越多的芯片和软件为它赋能,这让传统的嵌入式开发又掀起了一股热潮,不但工作岗位增加了,而且薪资待遇也提高了。

当然,嵌入式的薪资肯定还赶不上互联网。比如,应届生入职互联网大厂的年包在 40w 左右,而入职硬件公司的年包在 30w 左右,从这个角度看,嵌入式的年包比互联网低 20%~30%。

至于单片机,那就更拉胯了,比较顶流的也就拿到 25w 左右。算算比例的话,比嵌入式低 20%。这个很正常,因为单片机的技术栈简单,需要学习的知识少;同时,单片机产品的功能也不复杂,有时候一个人就可以搞定一款产品。

传统的嵌入式开发既要精通软件,也要了解硬件,工作经验越丰富就越能开发出稳定与合规的产品,所以会有一种「小火慢炖、越老越香」的感觉。和互联网相比,传统嵌入式确实不那么容易中年危机。

然而,这几年嵌入式领域发生了一些变化,涌现出了一堆新技术,比如嵌入式+物联网+云端、嵌入式+大数据、嵌入式+AI,嵌入式+无人驾驶等。很多大公司都参与其中,并提供了可以落地的软硬件解决方案。

因为硬件、驱动、操作系统、各种组件/库/算法,都是别人给你提供好的,你更多的是在面向业务逻辑写应用,所以和互联网开发没有什么太大的区别了。

这意味着,刚毕业的年轻人也能胜任工作了,35 岁以上的老人优势不明显了,被裁员以后很有可能找不到满意的工作,从而产生中年危机。不仅仅是互联网和嵌入式,所有不能靠经验维持自己优势的行业,所有不能靠时间竖立起壁垒的行业,都会有中年危机。

很多自媒体都说嵌入式越老越香,学到的技术不容易落伍,这种观点在以前是对的,但是在当下就没有那么乐观了。技术是在进步的,我们要向前看,不要把目光停留在过去。

不过根据目前的就业形式来看,嵌入式还是比较好找工作的,这算是它的一点优势吧。

什么是单片机?

很多人都有自己组装电脑的经历,精心挑选 CPU、内存条、硬盘、显卡、电源,然后选一款合适的主板,把这些硬件装插在主板上,再弄个机箱装进去便大功告成。

这其中,CPU、存储、输入输出接口是比较核心的部件,如果我们用集成电路的方式把它们都放到一起,并通过总线相连,这样就构成了一个微型的、简陋的计算机。这种计算机有一个专业的名字,叫做 MCU(Microcontroller Unit),翻译成中文就是“微控制单元”。

另外,因为采用了集成电路技术,所以它的外观是一块芯片/硅片,而不是一块板子,所以又叫做单片机(Single-Chip Microcomputer)。

单片机实物照片
图2:单片机实物照片

单片机不是用来完成某一种种特定功能的芯片/电路,而是多种芯片/电路的集合体。

说白了,单片机是一个经过简化和缩小的计算机,它把一些比较核心的、不可或缺的硬件以「集成电路」的方式封装到一块芯片上。

和普通电脑相比,单片机部件少、配置低、体积小、功耗低、价钱便宜;当然,它的性能也非常弱鸡,和普通电脑存在数量级的差距。单片机通常用于工业生产中,所以它的稳定性很高。

下面这是一张比较典型的 51 单片机的内部结构图:

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 位之分,位数越多,算力就越强,就越能支持复杂程序。当然,功耗和成本也会更高。

就目前来说:
单片机应用举例:
现在的物联网设备(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
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。

单片机开发和嵌入式开发

从学术和定义上来讲,这两种开发是没有什么区别的,都是一码事,因为嵌入式系统使用的都是单片机。

但是在现实生活中,或者在程序员的交流中,我们通常又会区分两者:
不过两者之间也没有明显的分界线,因为你没法定量的说哪种操作系统简单,或者哪种操作系统复杂。此时你再回到文章开头看看那张图片(图1),是不是就豁然开朗了。

至此,我们总算吧单片机和嵌入式的概念讲明白了。

嵌入式板子

上面提到了,嵌入式是一种专用的计算机,它把「单片机 + 支撑电路 + 功能部件」都封装到一块电路板上(俗称板子),然后再放进设备内部。

这里的板子,你可以自己从零制作,也可以使用第三方公司提供的现成产品,或者基于第三方公司的板子进行二次开发。这个没法一概而论,要根据自己的需求和成本来规划。

但是,自己制作板子是一个繁杂的系统工程,你除了要选择硬件,然后设计电路板,还要适配软件,包括驱动、操作系统、标准库、IDE(包括编译器、调试器、仿真工具等)。如果现有的软件没法满足需求,那你就要进行修改,或者从零开发。

这需要硬件工程师、驱动工程师、底层开发工程师、应用开发工程师、系统工程师、测试工程师等多个岗位进行配合与协调,研发周期可能长达半年、一年甚至数年,时间成本和资金成本都是巨大的。

当然,如果设备能够大规模量产,自己定制板子会节省成本,提高利润,这是很多公司选择自己定制板子的一个重要原因。

另外,如果你的产品比较特殊(比如工作环境非常严苛、产品体积非常小),现有的板子可能就满足不了你的需求,那你只能自己制作板子了。比如,手环和蓝牙耳机上使用的嵌入式板子就很小,第三方公司往往没有这样的板子。

核心板和开发板

第三方公司提供的嵌入式板子通常有两种,一种是核心板,一种是开发板。
从开发板上选取一部分必要的硬件,让它们满足特定领域的需求,然后重新制作成板子,这就是核心板。可以认为,核心板是开发板的一个子集。

开发板可能包含的组件:
核心板可能包含的组件:
开发板示意图
图6:开发板示意图

核心板示意图
图7:核心板示意图

嵌入式开发使用的编程语言

嵌入式是一个很大的话题,不同的场景会使用不同的编程语言。

传统的嵌入式领域,硬件性能比较差,同时又对稳定性和及时性有着严苛的要求,所以通常会使用一些高效的语言,比如C语言、C++、汇编:
其它嵌入式场景:
声明:《嵌入式系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。