单片机技术概述
在现代生产和生活中,计算机的应用越来越广泛,人们不仅可以使用计算机来处理文档、上网等,而且在我们的CD播放机、日常家电、汽车等里面也有着更多的计算机,当然,这些不再是传统意义上的计算机,而是所谓的嵌入式计算机。在嵌入式计算机家族里面,单片机占有重要的地位,是嵌入式计算机领域的主力军。本章主要介绍单片机的概念、单片机和计算机的区别、单片机的应用场合、主流单片机的特点和单片机的发展方向。
计算机系统基本上分为两类:第一类是常见的台式计算机,当你跟别人说“计算机”的时候,别人所理解的通常就是这样一台机器;第二类是嵌入式计算机,这种计算机往往为控制/监控目的而集成到另外的系统中。嵌入式计算机在数量上远远超过桌面系统,而这看起来很不明显。实际上,在人们的家中可能有几十台的嵌入式计算机,这些计算机可能藏在电视机、录像机、遥控器、移动电话等设备里面。本节将着眼于通常的计算机体系结构,这种体系结构对嵌入式计算机和台式机都是适用的。台式计算机和嵌入式计算机的基本架构都是一样的。粗略地看,两者都有处理器、存储器以及一些输入/输出形式。两者的主要差别在于用途的不同,而这点体现在它们所使用的软件上,在操作系统对系统资源的协调下,台式计算机可以使用各种应用程序,通过运行这些不同的应用程序,可以让台式机实现各种不同的功能。而与此相反,嵌入式计算机通常用于执行某些特殊任务,在专用电子设备上使用一个嵌入式微处理器,其优势在于系统的功能是由软件而非硬件决定的。一般情况下,嵌入式计算机系统仅拥有一种特定的应用,并且该应用一直不停地运行。嵌入式计算机可能有,也可能没有操作系统,并且它通常不能随意安装新的软件,因为所使用的软件通常已经固化在系统的存储器里面。本节先介绍与计算机体系结构有关的一些重要概念,重点介绍与嵌入式计算机系统有关的。在此基础上,下一节介绍单片机的基本概念与应用。
1.1.1 基本概念
计算机所做的事情,从网页的浏览到打印,都包括对数字的转移和处理,计算机只不过是用来保存、转移和改变这些数字的一个系统而已。计算机是由软件和硬件的诸多部件组成的。其核心部件是用来执行计算机程序的硬件设备———处理器。另外,存储器对处理器正在执行的程序进行保存,也对这些程序所操纵的数据进行保存。计算机还有存储数据或与外界交换数据的设备。
计算机软件控制着计算机的操作和功能。计算机中的软件可以分为许多的层,如图2 1所示。
图2 1
计算机软件的分层结构
处在上述结构最底层的是在计算机刚启动时由处理器运行的程序。这些程序将其他硬件子系统初始化到一个已知的状态,并为计算机的正常运行进行配置。这种软件由于永久地存储在计算机的内存中而被称作为固件。引导程序位于固件中。引导程序是由处理器运行的一个特殊程序,它把操作系统从磁盘(或者非易失性存储器、网络等)中读取到内存中,以便处理器随后正常运行。在台式计算机和工作站中都有这种引导程序,在一些嵌入式计算机中也可能存在。在固件之上,由操作系统控制着计算机的操作。操作系统对存储器的使用进行组织,对键盘、鼠标、显示器和磁盘驱动器之类的设备进行读、写以及控制。操作系统为用户提供接口,以便用户运行应用程序,存取磁盘里的文件系统软件,操作系统也为应用程序提供了一套软件工具。通过这种机制,这些应用程序也可以对显示器、磁盘驱动器等设备进行访问。并不是所有的嵌入式计算机都需要使用操作系统,嵌入式计算机常常运行面向特定任务的简单代码,在这种情况下往往无需使用操作系统,否则反而会带来不必要的麻烦。但是在有些场合,如网络路由器,具有复杂人机界面的手持设备等,操作系统提供了必要的软件集成,大大简化了开发过程。在嵌入式计算机中,是否需要操作系统,以及操作系统是否有用,实际取决于这一嵌入式计算机的预定用途。
在上述结构的最高层是应用软件,应用软件由为计算机提供功能模块的应用程序组成,应用软件层之下的所有软件都被看作系统软件。对于嵌入式计算机而言,应用软件和系统软件的概念比较模糊。在嵌入式设计中的一个基本原则就是:系统应尽可能地以简单、直接的方式达到其目标。
1.处理器
处理器是计算机中最为重要的部件,所有的其他部件都以此为中心。其实,处理器就是计算机的运算部分,是一个能够以指令序列指定的方式对数据进行操作的电子器件,这里的指令也就是操作码或机器码,指令的序列可以随应用程序而改变,指令的执行序列就是所谓的程序。一个给定的处理器可以执行的程序很可能看起来像这样:B04FF7010007…早期的计算机编程就是使用这种方式来进行程序设计的。人们发现,对于这样的程序难于编写,更难于理解。为了使其便于使用,采用了叫做汇编语言的符号,以助记符来代替操作码,汇编语言指令直接等同于机器码指令。采用汇编语言编写程序提高了可读性,但是又存在一些问题,因为不同的处理器系列使用不同的汇编语言,虽然看起来有很多地方是一样的,但实际上没有任何两类是相同的。不同的汇编语言由于建立在不同的处理器硬件之上,因此具有不同的汇编语法。实际上计算机并不能直接理解汇编语言。在汇编语言出现的早期,每个指令助记符都是由程序员查找并转换成适当的操作码,虽然代码也是由字符构成的,但是这种转换非常麻烦,并且非常容易出错,为了使编程变得容易,人们使用编译器承担从助记符到操作码转换的功能。即使这样,用汇编语言进行编程,直接为处理器编写代码,仍然是相当困难的,特别是编写较大的软件。如果要编写较大的软件,就要选择C语言这样的高级语言。高级语言使得软件开发更加容易,并且所编写的代码在不同的目标机器之间具有某种程度的可移植性。这些高级语言编译器将源代码直接转换成机器的操作码。因此,通过使用高级语言编译器,程序员便从必须了解处理器的细节以及直接以机器码编写程序中解脱出来。
由于高级语言在编写程序方面的优势,越来越多的人使用高级语言来编写程序,但有些时候程序员还是直接用汇编语言来写程序,为什么呢?因为汇编语言直接对应处理器操作,程序员能够根据实际需要精确地控制处理器的执行,从而发挥计算机硬件的最高性能,这对于嵌入式计算机系统这种资源稀缺,执行时间要求严格的系统来说更为重要。更进一步地讲,直接用汇编语言写的代码有时候所需要的代码空间更小,运算速度更快。当需要在有限的存储器里装入复杂的软件,并要求软件运行得迅速高效,那汇编语言可能是唯一的选择。当然,这需要软件设计师具有相当的经验,否则效果有可能不如汇编器产生的汇编代码。使用汇编语言的缺点就是软件难以维护,并且所编写的代码不能移植到其他的处理器。现在更多的做法是,在C语言代码中内嵌汇编语言,从而达到两全其美的效果。
2.系统体系结构
单个处理器是不能完成任何任务的,还需要存储器、支撑逻辑以及至少一个I/O设备,用来实现计算机系统与外界之间的数据传输。微处理器(microprocessor)通常是在一个单独的集成电路上实现的处理器。除了在一些大型超级计算机中存在差异之外,几乎所有的现代处理器都是微处理器,因此,这两个术语经常交替使用,现在普遍使用的微处理器有IntelPentium系列、Motorola/IBMPowerPC以及SunSPARC等。微处理器有时也指CPU(CentralProcessingUnit,中央处理器)。
微控制器在单一集成电路中包含了一个处理器、存储器以及一些I/O部件,可用于嵌入式系统,连接处理器及其I/O部件的总线也存在于同一集成电路中。现有的微控制器种类繁多,从51系列到AVR、MSP430系列(本书重点讨论)都内置了I/O,主要面向一些嵌入式应用。微控制器通常将它们的存储器集成到芯片上,并且只为外部存储设备提供有限的支持。计算机系统的存储器包含了处理器,将要执行的指令及其将要操作的数据。计算机系统的存储器从来不会是空的,里面总是有指令,有用数据或者系统启动时所产生的随机无用数据。指令由计算机系统从存储器里读取,而数据则可以读出和写入存储器。上述形式的计算机结构就是所谓的冯·诺依曼结构,这种体系结构是以其创始人之一约翰·冯·诺依曼的名字命名的。几乎现代所有的计算机都是遵循冯·诺依曼体系结构的,很少有例外。冯·诺依曼计算机可以归类为控制流计算机,在这种体系结构中,计算机的执行步骤由程序的顺序控制所管理。
冯·诺依曼计算机的主要特点如下:
① 数据和指令没有本质区别。处理器能够从存储器中给定点处直接开始执行,而它本身却无法得知自该点开始执行的数字序列是指令还是数据。如果一个数字由处理器执行,那么它就是指令;如果一个数字由处理器操作,那么它就是数据。
② 数据没有固定含义。数据的具体含义取决于在程序控制下如何由微处理器对这些数字进行处理。例如,数据0x24可能代表图像中颜 {MOD}的一个像素的数字,也可能代表文本文档中的一个字符,这对处理器而言没有任何差别。
③ 数据和指令共享同一内存,这意味着一个程序的指令序列可以被另外一个程序当作数据来处理。计算机的编译器通过在存储器中生成数字序列来建立一个二进制程序。对于编译器而言,所编译的程序不过是数据而已,因此,它也就按照数据对其进行处理。只有当处理器开始执行这个二进制程序时,它才是一个程序。同样,操作系统通过把应用程序指令序列看作是数据,而从磁盘中加载到内存,进而实现上述数据/指令处理。程序如图像和文本文件那样被加载到内存,这归功于共享内存空间。现有的大多数微处理器都是标准的冯·诺依曼机。与这种体系结构相背的主要是哈佛体系结构,其指令和数据具有不同的内存空间。这样,每一内存空间里都有各自的地址、数据和控制总线。这种哈佛体系结构具有很多优点,比如说可以同时取指令和数据,指令字长并不由标准数据单元所决定。
3.总 线
所谓总线,就是具有相关功能的信号线的物理集合。总线允许在计算机系统的不同部件之间传输电子信号,因此可把信息从一个设备传输到另外一个设备上。例如,数据总线是在处理器和组成计算机系统的不同子系统之间传输数据的信号线集合。总线的宽度是指用于传输信息的信号线的数目,如一个8位宽总线一次并行传输8位数据。
当今的多数微处理器采用了三总线体系结构,分别是地址总线、数据总线和控制总线。如图2
2所示。
图2 2
计算机的三总线结构数据总线是双向的,具体的传输方向由处理器决定。地址总线传输的是地址信息,这一地址指向微处理器想要访问的内存单元。由外部线路来决定指定的内存单元位于哪个外部设备上,并由外部线路来激活该设备,这就是地址解码。控制总线携带来自处理器的当前访问状态信息,如它是写操作还是读操作。控制总线也将当前访问状态信息返回给处理器,例如地址错误等。不同的处理器具有不同的控制线,但有一些控制线是通用的。控制总线可能含有一些输出信号,如读、写、有效地址等。一个处理器有几条输入控制线,如复位(RESET),一个或多个中断线以及时钟线等。
4.处理器操作
处理器能够实现6个基本功能:向系统的内存写入数据或向I/O设备写入数据;从系统的内存读出数据或从I/O设备读出数据;从系统的内存读取指令;执行处理器里数据的内部操作。在很多系统中,向内存写入数据在功能上等同于向一个I/O设备中写入数据。同样,从系统的内存中读取数据也就等同于从I/O设备中读取数据或者从内存中读取指令这样的外部操作。也就是说,处理器对内存和I/O做相同对待。处理器的内部数据存储由它的寄存器来完成。一个处理器拥有一定数量的寄存器,由这些寄存器来保存处理器正在操作的当前数据。处理器从寄存器中存取数据的速度要远远快于外部存储器。
5.ALU
ALU(ArithmeticLogicUnit,算术逻辑单元)完成处理器里数据的内部算术操作。由处理器读取并执行的指令控制着寄存器和ALU之间的数据流向,进而经由ALU完成操作,通过ALU控制数据的输入。一旦收到处理器的指示,ALU就对一个或多个值执行一个操作。ALU所操作的值就是操作数,主要是从两个寄存器里或一个寄存器和一个内存单元中取得。ALU的运算结果可以暂时存储到给定的目标寄存器或者内存单元中。ALU的状态输出表明有关一个ALU操作的任何特殊属性,如结果是否为零或为负,是否溢出或产生进位等。有一些处理器还有专门的单元用来进行乘法、除法以及移位操作,这样能够提供更快的运算速度。
6.寄存器
寄存器是处理器内部的存储器件。不同的处理器体系结构之间寄存器的数量差距极大。典型的情况是,处理器含有一个或多个累加器。所谓的累加器就是可以在其上进行算术操作的寄存器。在一些处理器体系结构中,所有的寄存器都具有累加器功能,而在另外一些体系结构中,有些寄存器只用于存储,而具有有限的功能。一些处理器具有索引寄存器,能够通过它指向内存空间。在一些处理器体系结构中,所有的通用寄存器都可以作为索引寄存器;而在另外一些体系结构中,具有专门的索引寄存器。所有的处理器都有一个程序计数器,它跟踪将要被读取并执行的下一条指令在内存中的单元地址。所有的处理器都有一个状态寄存器,里面含有反映当前操作状态的各种状态位。这些标记可以表明最近一步操作的结果是否为零或为负,是否产生了进位,是否接受一个中断等。有些处理器里还有一个或多个控制寄存器,里面包含了影响处理器操作的配置位,以及各种内部子系统的操作模式。许多外部设备也有一些寄存器,这些寄存器控制着外部设备的操作或者包含外部设备的操作结果。这些外部设备的寄存器通常被映射到处理器的地址空间之内。处理器通常所说的8位、16位、32位或者64位,是指它们的寄存器的位宽。用得最多的是8位处理器,它们被广泛应用于大量简单的控制和监控应用中。当然现在16位、32位的嵌入式处理器也越来越广泛地被应用。
7.堆 栈
堆栈通常作为外部存储器的临时存放地,处理器能够把一个来自寄存器的数据压入堆栈保存起来以备后用。通过出栈,处理器可以把该值从堆栈中取出来返回给寄存器。大多数处理器都有一个堆栈指针,指向堆栈中的下一个空闲单元。有些处理器实现了不止一个堆栈,因此也就有多个堆栈指针。大多数堆栈沿着内存由高地址区向低地址区方向增长。当处理器在堆栈中对一个值进行压入/弹出操作时,堆栈指针就自动地递减以指向下一个空闲单元。
8.中 断
中断是处理器暂停执行当前程序,以便能够处理已发生的某些事件的技术。这些事件可能是来自外部设备的一个错误,或者仅仅是I/O设备已经完成上一个任务而等待下一个新任务。中断技术大大减轻了处理器不断检查I/O设备是否需要服务的负荷,使得处理器可以持续进行其他任务。当I/O设备需要处理器介入时,它就会发出一个中断输入来通知处理器。
在一些处理器中,中断可被赋予不同的优先级,因此能够对中断处理器的不同事件指派不同的重要性。正服务于低优先级中断的处理器可以暂停当前任务而为高优先级中断服务。当然,如果此时有更低优先级的中断产生,处理器将忽略此中断直至它完成当前相对较高优先级的中断服务。当一个中断产生时,处理器就通过把寄存器和程序计数器等压入堆栈,来保存当前执行状态。接着,处理器就把响应的中断向量加载到程序计数器。中断向量就是中断服务程序(InterruptServiceRoutine,ISR)所在的地址。这样,加载中断向量到程序计数器也就导致处理器开始执行ISR,完成产生中断的设备的任何服务请求。中断服务程序的最后一条指令通常是中断返回指令。通过这一中断返回指令,微处理器能够从堆栈中重装它所保存的前一程序状态,从而恢复原有的程序执行。中断在很大程度上对原来的程序是透明的,这就是说,原来的程序根本没有察觉处理器已经接受中断了,除了损失一些中断时间外。
9.CISC和RISC处理器
处理器体系结构主要有两大分支:其一是CISC(ComplexInstructionSetComputer,复杂指令集计算机);其二是RISC(ReducedInstructionSetComputer,精简指令集计算机)。标准的CISC处理器有Intel的X86系列、Motorola的68xxx系列以及NS的32xxx系列。普通的RISC体系结构处理器有Motorola/IBM的PowerPC、MIPS体系结构,Sun的SPARC、ARM和ATMEL的AVR以及Microchip的PIC等。
CISC处理器有一个单一处理单元、外部存储器、一个相对较小的寄存器集以及几百条不同的指令。这类处理器的优势在于它使汇编语言程序员编程更为容易———程序员只需要编写很少的代码就可以完成任务。由于在早期存储器非常昂贵,所以这种方式对于让每一条指令完成更多功能来讲具有一定的意义,因为它减少了完成给定功能所需要的指令数,进而降低了存储空间,以及读取所需指令的访问次数。随着内存价格的不断降低及速度的不断提高,加上编译器的效率越来越高,CISC方式的处理器的相对优势也就逐渐消失了。CISC处理器的主要缺点之一就是这种处理器的本身变得越来越复杂了。这是由于处理器要支持这样一个庞大而且多样的指令集,使得控制和指令解码单元变得复杂且迟缓起来,硅片越来越大且难以生产,并且这些功能部件不但耗电,而且导致了大量的热量产生。随着处理器越来越先进,CISC在硅片上的开销严重制约了处理器的应用。人们发现,通过将指令集简化为最为普遍使用的指令,处理器就变得简单快速起来,通过这种方式,译码并执行每一条指令只需要很少的指令周期,这样执行一个程序总的指令周期就大大缩短了。其缺点就是完成一个任务需要更多的指令,但这个缺点在处理器性能的提升上得到了弥补。这种思路就导致了对处理器设计的再思考。其结果就是RISC体系结构,它导致更高性能处理器的发展。RISC的基本原则是:把硅片的复杂性转移到语言编译器里,硬件部分尽可能地保持简单和快速。
在RISC处理器中,一个给定的复杂指令可以通过一系列更简单的指令来实现。举例来说,许多处理器都有一个针对位操作的“与”(AND)指令,也有一个清空(clear)指令来给一个指定的寄存器置零。然而,给一个寄存器清零也可以通过使用AND指(AND0x00,R6)来实现,这样就不需要单独的寄存器清零指令了。
RISC处理器具有许多显著的特性。它具有规模较大的寄存器组,从而减少了处理器访问主存储器的次数。经常使用的变量就可以保留在处理器内部,这就减少了处理器访问外部存储器的次数,高级语言编译器就利用这点来优化处理器的性能。通过采用更小和更简单的指令解码单元,RISC处理器具有很高的指令执行速度,同时也降低了处理单元的尺寸和功耗。
2.1.2 存储器
存储器用来为处理器存放数据和软件。其类型多样,经常在单个系统内混合了各种各样的存储器类型。有些存储器能够在断电情况下保持它里面的内容,但访问起来比较慢;有些存储器容量很大,但需要额外的支持电路,访问起来更慢;还有一些存储器拿容量来换取速度,这种存储器相对较小,但能够跟得上最高速的处理器。
存储器可以由两种方式来组织,字组织和位组织。在字组织方案中,全部的半字节、字节、或字都存储在一个元件里;而在位组织方式的存储器里,一个字节或者字的每一个位各占一个单独的元件。存储器芯片具有不同的大小,位宽是描述存储器大小的一个重要指标。例如,一个DRAM芯片可以描述成4MB×1(位组织),而一个SRAM可以描述为512KB×8(字组织)。在上述两种存储器里,每个芯片拥有完全相同的容量,但组织方式却不相同。在DRAM里,为了匹配一个8位数据总线,需要8个芯片来组成一个存储器块,而SRAM只需一个芯片就够了。由于DRAM是以并行方式组织的,因而可以被同时访问。DRAM存储块的最终大小就是(4MB×1)×8
个设备,即32MB。通常在一个存储器模块上放置多块DRAM。
1.RAM
RAM 代表随机访问存储器(RandomAccessMemory)。这个叫法其实有点不恰当,因为大多数存储器都可以被看作是随机访问的。RAM是计算机系统中