嵌入式系统 - 快速指南
嵌入式系统 - 概述
系统
系统是一种所有单元组件根据一组规则协同工作的安排。它也可以定义为一种工作、组织或执行一项或多项任务的方式,根据固定的计划进行。例如,手表是一个显示时间的系统。它的组件遵循一组规则来显示时间。如果其中一个部件发生故障,手表将停止工作。因此,我们可以说,在一个系统中,所有其子组件都相互依赖。
嵌入式系统
顾名思义,嵌入式意味着某物附着在另一物上。嵌入式系统可以被认为是具有嵌入软件的计算机硬件系统。嵌入式系统可以是独立的系统,也可以是大型系统的一部分。嵌入式系统是一个基于微控制器或微处理器的系统,旨在执行特定任务。例如,火警报警器就是一个嵌入式系统;它只会感应烟雾。
嵌入式系统具有三个组成部分 -
它具有硬件。
它具有应用软件。
它具有实时操作系统 (RTOS),它监督应用软件并提供机制,让处理器根据调度运行进程,遵循计划以控制延迟。RTOS 定义了系统的工作方式。它在应用程序执行期间设置规则。小型嵌入式系统可能没有 RTOS。
因此,我们可以将嵌入式系统定义为基于微控制器的、软件驱动的、可靠的、实时控制系统。
嵌入式系统的特点
单功能 - 嵌入式系统通常执行专门的操作并重复执行相同的操作。例如:寻呼机始终充当寻呼机。
严格约束 - 所有计算系统对设计指标都有约束,但嵌入式系统的约束尤其严格。设计指标是衡量实现功能的指标,例如其成本、尺寸、功耗和性能。它必须能够安装在单个芯片上,必须能够快速地实时处理数据,并且必须消耗最少的功率以延长电池寿命。
反应式和实时 - 许多嵌入式系统必须持续对系统环境的变化做出反应,并且必须实时计算某些结果,而没有任何延迟。以汽车巡航控制为例;它持续监控和响应速度和制动传感器。它必须在有限的时间内反复计算加速或减速;计算延迟会导致无法控制汽车。
基于微处理器 - 它必须基于微处理器或微控制器。
内存 - 它必须具有内存,因为其软件通常嵌入在 ROM 中。它不需要计算机中的任何辅助存储器。
连接 - 它必须具有连接的外设以连接输入和输出设备。
软硬件系统 - 软件用于更多功能和灵活性。硬件用于性能和安全性。
优点
- 易于定制
- 低功耗
- 低成本
- 性能增强
缺点
- 开发工作量大
- 上市时间长
嵌入式系统的基本结构
下图显示了嵌入式系统的基本结构 -
传感器 - 它测量物理量并将其转换为电信号,观察者或任何电子仪器(如 A2D 转换器)都可以读取该信号。传感器将测得的量存储到内存中。
A-D 转换器 - 模数转换器将传感器发送的模拟信号转换为数字信号。
处理器和 ASIC - 处理器处理数据以测量输出并将其存储到内存中。
D-A 转换器 - 数模转换器将处理器提供的数字数据转换为模拟数据
执行器 - 执行器将 D-A 转换器给出的输出与存储在其中的实际(预期)输出进行比较,并存储批准的输出。
嵌入式系统 - 处理器
处理器是嵌入式系统的核心。它是获取输入并在处理数据后产生输出的基本单元。对于嵌入式系统设计人员来说,必须了解微处理器和微控制器。
系统中的处理器
处理器有两个基本单元 -
- 程序流程控制单元 (CU)
- 执行单元 (EU)
CU 包括用于从内存中获取指令的获取单元。EU 具有实现与数据传输操作相关的指令以及将数据从一种形式转换为另一种形式的电路。
EU 包括算术逻辑单元 (ALU),以及执行程序控制任务(例如中断或跳转到另一组指令)的指令的电路。
处理器运行获取和执行指令的循环,其顺序与从内存中获取指令的顺序相同。
处理器类型
处理器可以属于以下类别 -
通用处理器 (GPP)
- 微处理器
- 微控制器
- 嵌入式处理器
- 数字信号处理器
- 媒体处理器
专用系统处理器 (ASSP)
专用指令处理器 (ASIP)
应用专用集成电路 (ASIC) 或超大规模集成电路 (VLSI) 上的 GPP 核心或 ASIP 核心。
微处理器
微处理器是一个具有 CPU 的单个 VLSI 芯片。此外,它还可以具有其他单元,例如教练、浮点处理算术单元和流水线单元,这些单元有助于更快地处理指令。
早期版本的微处理器的获取和执行周期由大约 1 MHz 数量级的时钟频率引导。现在的处理器以 2GHz 的时钟频率运行
微控制器
微控制器是一个单芯片 VLSI 单元(也称为微型计算机),尽管计算能力有限,但具有增强的输入/输出能力和许多片上功能单元。
CPU | RAM | ROM |
I/O 端口 | 定时器 | 串行通信端口 |
微控制器特别用于具有片上程序存储器和设备的实时控制应用中的嵌入式系统。
微处理器与微控制器的区别
现在让我们看一下微处理器和微控制器之间最显著的区别。
微处理器 | 微控制器 |
---|---|
微处理器本质上是多任务的。可以同时执行多个任务。例如,在计算机上,我们可以在文本编辑器中编写文本的同时播放音乐。 | 面向单一任务。例如,洗衣机仅设计用于洗衣服。 |
RAM、ROM、I/O 端口和定时器可以外部添加,数量也可以变化。 | RAM、ROM、I/O 端口和定时器不能外部添加。这些组件必须一起嵌入到芯片上,数量是固定的。 |
设计人员可以决定所需的内存或 I/O 端口数量。 | 内存或 I/O 的固定数量使微控制器非常适合有限但特定的任务。 |
外部存储器和 I/O 端口的外部支持使基于微处理器的系统更重且成本更高。 | 微控制器比微处理器轻巧且价格更低。 |
外部设备需要更多空间,功耗也更高。 | 基于微控制器的系统功耗更低,占用空间更小。 |
嵌入式系统 - 架构类型
8051 微控制器使用 8 位数据总线。因此,它们最多可以支持 64K 的外部数据内存和 64k 的外部程序内存。总的来说,8051 微控制器可以寻址 128k 的外部内存。
当数据和代码位于不同的内存块中时,该架构称为哈佛架构。如果数据和代码位于同一个内存块中,则该架构称为冯·诺伊曼架构。
冯·诺伊曼架构
冯·诺伊曼架构最初由计算机科学家约翰·冯·诺伊曼提出。在这种架构中,存在一条用于指令和数据的公共数据路径或总线。因此,CPU 每次执行一项操作。它要么从内存中获取指令,要么对数据执行读/写操作。因此,指令获取和数据操作不能同时发生,它们共享一个公共总线。
冯·诺伊曼架构支持简单的硬件。它允许使用单个顺序内存。如今的处理速度远远超过内存访问时间,我们使用少量但速度极快的内存(缓存)作为处理器的本地内存。
哈佛架构
哈佛架构为指令和数据提供单独的存储和信号总线。这种架构的数据存储完全包含在 CPU 内部,并且无法将指令存储作为数据访问。计算机使用内部数据总线为程序指令和数据设置单独的内存区域,允许同时访问指令和数据。
程序需要由操作员加载;处理器无法自行启动。在哈佛架构中,无需使两个内存共享属性。
冯·诺伊曼架构与哈佛架构的比较
以下几点将冯·诺伊曼架构与哈佛架构区分开来。
冯·诺伊曼架构 | 哈佛架构 |
---|---|
代码和数据共享单个内存。 | 代码和数据使用单独的内存。 |
处理器需要在单独的时钟周期中获取代码,在另一个时钟周期中获取数据。因此,它需要两个时钟周期。 | 由于使用单独的总线访问代码和数据,因此单个时钟周期就足够了。 |
速度更快,因此耗时更少。 | 速度较慢,因此耗时更多。 |
设计简单。 | 设计复杂。 |
CISC 和 RISC
CISC 是复杂指令集计算机。它是一种可以处理大量指令的计算机。
在 20 世纪 80 年代初期,计算机设计师建议计算机应该使用更少的指令和简单的结构,以便它们可以在 CPU 内更快地执行,而无需使用内存。此类计算机分类为精简指令集计算机或 RISC。
CISC 与 RISC 的比较
以下几点区分了 CISC 和 RISC -
CISC | RISC |
---|---|
更大的指令集。易于编程 | 更小的指令集。难以编程。 |
考虑到更大的指令集,编译器的设计更简单。 | 编译器的设计复杂。 |
许多寻址模式导致复杂的指令格式。 | 寻址方式较少,需要修正指令格式。 |
指令长度可变。 | 指令长度变化。 |
每秒更高的时钟周期。 | 每秒较低的时钟周期。 |
重点在于硬件。 | 重点在于软件。 |
控制单元使用微程序单元实现大型指令集。 | 每个指令都由硬件执行。 |
执行速度较慢,因为指令需要从内存读取并由解码单元解码。 | 执行速度较快,因为每个指令都由硬件执行。 |
流水线技术不可行。 | 考虑到单个时钟周期,指令流水线是可能的。 |
嵌入式系统 - 工具与外设
编译器和汇编器
编译器
编译器是一个计算机程序(或一组程序),它将用编程语言(源语言)编写的源代码转换为另一种计算机语言(通常为二进制格式)。转换的最常见原因是创建可执行程序。术语“编译器”主要用于将源代码从高级编程语言转换为低级语言(例如,汇编语言或机器码)的程序。
交叉编译器
如果编译后的程序可以在与编译器编译该程序的计算机不同的 CPU 或操作系统上运行,则该编译器称为交叉编译器。
反编译器
可以将程序从低级语言翻译成高级语言的程序称为反编译器。
语言转换器
翻译用不同高级语言编写的程序的程序通常称为语言转换器、源到源转换器或语言转换器。
编译器可能会执行以下操作:
- 预处理
- 语法分析
- 语义分析(语法制导翻译)
- 代码生成
- 代码优化
汇编器
汇编器是一个程序,它接收基本的计算机指令(称为汇编语言)并将其转换为计算机处理器可用于执行其基本操作的比特模式。汇编器通过将汇编指令助记符转换为操作码并解析符号名称到内存位置来创建目标代码。汇编语言使用助记符来表示每个低级机器操作(操作码)。
嵌入式系统中的调试工具
调试是一个系统化的过程,用于查找并减少计算机程序或电子硬件中的错误数量,使其按预期工作。当子系统紧密耦合时,调试很困难,因为一个子系统中的微小变化可能会在另一个子系统中产生错误。嵌入式系统中使用的调试工具在开发时间和调试功能方面差异很大。这里我们将讨论以下调试工具:
- 模拟器
- 微控制器入门套件
- 仿真器
模拟器
通过在用于代码开发的主机计算机上模拟 MCU/系统来测试代码。模拟器尝试在软件中模拟整个微控制器的行为。
模拟器的功能
模拟器执行以下功能:
定义目标系统的处理器或处理设备系列及其各种版本。
在每次单步执行过程中,监视带标签和符号参数的源代码部分的详细信息。
提供每次单步执行的目标系统的 RAM 和模拟端口的状态。
监视系统响应并确定吞吐量。
提供程序计数器内容与处理器寄存器输出的跟踪。
提供当前命令的详细含义。
监视从键盘输入或从菜单中选择的模拟器命令的详细信息。
支持条件(最多 8 或 16 或 32 个条件)和无条件断点。
提供断点和跟踪,它们共同构成了重要的测试和调试工具。
促进内部外设和延迟的同步。
微控制器入门套件
微控制器入门套件包括:
- 硬件板(评估板)
- 在线编程器
- 一些软件工具,如编译器、汇编器、链接器等。
- 有时,IDE 和编译器的代码大小受限的评估版本。
与模拟器相比,这些套件的一大优势在于它们可以实时工作,从而可以轻松验证输入/输出功能。但是,入门套件完全足够,并且是开发简单微控制器项目的最便宜选择。
仿真器
仿真器是一个硬件套件或软件程序,或者两者兼而有之,它在一个计算机系统(主机)中模拟另一个计算机系统(客户机)的功能,与第一个系统不同,因此模拟的行为与真实系统的行为非常相似(客户机)。
仿真指的是电子设备中的计算机程序模拟(模仿)另一个程序或设备的能力。仿真侧重于重建原始计算机环境。仿真器能够与数字对象的真实性保持更紧密的联系。仿真器帮助用户以类似于软件在其原始环境中运行的方式,在平台上运行任何类型的应用程序或操作系统。
嵌入式系统中的外设
嵌入式系统通过其外设与外部世界通信,例如:
- 串行通信接口 (SCI),如 RS-232、RS-422、RS-485 等。
- 同步串行通信接口,如 I2C、SPI、SSC 和 ESSI。
- 通用串行总线 (USB)
- 多媒体卡(SD 卡、Compact Flash 等)。
- 网络,如以太网、LonWorks 等。
- 现场总线,如 CAN 总线、LIN 总线、PROFIBUS 等。
- 定时器,如 PLL、捕获/比较和时间处理单元。
- 离散 I/O 又名通用输入/输出 (GPIO)
- 模数/数模转换器 (ADC/DAC)
- 调试,如 JTAG、ISP、ICSP、BDM 端口、BITP 和 DP9 端口。
选择微控制器的标准
在选择微控制器时,确保它满足手头的任务并且具有成本效益。我们必须查看 8 位、16 位或 32 位微控制器哪一个最适合处理任务的计算需求。此外,在选择微控制器时应牢记以下几点:
速度 - 微控制器可以支持的最高速度是多少?
封装 - 是 40 引脚 DIP(双列直插封装)还是 QFP(四侧扁平封装)?这在最终产品的空间、组装和原型设计方面很重要。
功耗 - 对于电池供电的产品,这是一个重要的标准。
芯片上的RAM 和 ROM 容量。
芯片上的I/O 引脚和定时器数量。
单位成本 - 这对于使用微控制器的产品的最终成本至关重要。
此外,确保您拥有微控制器提供的工具,例如编译器、调试器和汇编器。最重要的是,您应该从可靠的来源购买微控制器。
嵌入式系统 - 8051 微控制器
8051 的简史
第一个微处理器4004是由英特尔公司发明的。8085 和8086 微处理器也是由英特尔发明的。1981 年,英特尔推出了一款名为8051 的 8 位微控制器。它被称为片上系统,因为它在一个芯片上集成了 128 字节的 RAM、4K 字节的片上 ROM、两个定时器、一个串行端口和 4 个端口(8 位宽)。当它变得非常流行时,英特尔允许其他制造商制造和销售 8051 的不同版本,并且其代码与 8051 兼容。这意味着如果您为 8051 的一个版本编写程序,它也将在其他版本上运行,无论制造商是谁。这导致了几个具有不同速度和片上 RAM 容量的版本。
8051 版本/成员
8052 微控制器 - 8052 具有 8051 微控制器的所有标准功能,以及额外的 128 字节 RAM 和一个额外的定时器。它还具有 8K 字节的片上程序 ROM,而不是 4K 字节。
8031 微控制器 - 它是 8051 系列的另一个成员。该芯片通常被称为无 ROM 8051,因为它具有 0K 字节的片上 ROM。您必须向其添加外部 ROM 才能使用它,其中包含要获取和执行的程序。该程序可以大到 64K 字节。但在向 8031 添加外部 ROM 的过程中,它丢失了 4 个端口中的 2 个端口。为了解决这个问题,我们可以向 8031 添加外部 I/O。
8051 系列成员之间的比较
下表比较了 8051、8052 和 8031 中可用的功能。
功能 | 8051 | 8052 | 8031 |
---|---|---|---|
ROM(字节) | 4K | 8K | 0K |
RAM(字节) | 128 | 256 | 128 |
定时器 | 2 | 3 | 2 |
I/O 引脚 | 32 | 32 | 32 |
串行端口 | 1 | 1 | 1 |
中断源 | 6 | 8 | 6 |
8051 微控制器的特性
8051 微控制器捆绑了以下特性:
- 4KB 字节片上程序存储器 (ROM)
- 128 字节片上数据存储器 (RAM)
- 四个寄存器组
- 128 个用户定义的软件标志
- 8 位双向数据总线
- 16 位单向地址总线
- 32 个通用寄存器,每个寄存器 8 位
- 16 位定时器(通常为 2 个,但可能更多或更少)
- 三个内部中断和两个外部中断
- 四个 8 位端口(短型号有两个 8 位端口)
- 16 位程序计数器和数据指针
- 8051 还可能具有一些特殊功能,例如 UART、ADC、运算放大器等。
8051 微控制器的框图
下图显示了 8051 微控制器的框图:
嵌入式系统 - I/O 编程
在 8051 中,I/O 操作是使用四个端口和 40 个引脚完成的。以下引脚图显示了 40 个引脚的详细信息。I/O 操作端口保留了 32 个引脚,每个端口有 8 个引脚。其他 8 个引脚被指定为 Vcc、GND、XTAL1、XTAL2、RST、EA(反相)、ALE/PROG(反相)和 PSEN(反相)。
它是一个 40 引脚 PDIP(塑料双列直插封装)
注意 - 在 DIP 封装中,您可以通过 IC 中间的切口识别第一个引脚和最后一个引脚。第一个引脚位于此切口标记的左侧,最后一个引脚(在本例中为第 40 个引脚)位于切口标记的右侧。
I/O 端口及其功能
四个端口 P0、P1、P2 和 P3 各使用 8 个引脚,使其成为 8 位端口。在复位后,所有端口都配置为输入,准备用作输入端口。当第一个 0 写入端口时,它将变为输出。要将其重新配置为输入,必须向端口发送 1。
端口 0(引脚号 32 – 引脚号 39)
它有 8 个引脚(32 到 39)。它可以用于输入或输出。与 P1、P2 和 P3 端口不同,我们通常将 P0 连接到 10K 欧姆上拉电阻,以将其用作输入或输出端口,因为它是一个开漏输出。
端口0(引脚32-39)也被指定为AD0-AD7,这意味着它既可以作为地址总线,也可以作为数据总线使用。对于8031(即无ROM芯片),当我们需要访问外部ROM时,P0将同时用作地址总线和数据总线。ALE(引脚31)指示P0是地址还是数据。当ALE=0时,它提供数据D0-D7,但当ALE=1时,它具有地址A0-A7。如果没有外部存储器连接,则必须将P0外部连接到一个10K欧姆的上拉电阻。
MOV A,#0FFH ;(comments: A=FFH(Hexadecimal i.e. A=1111 1111) MOV P0,A ;(Port0 have 1's on every pin so that it works as Input)
端口1(引脚1至8)
它是一个8位端口(引脚1至8),可以用作输入或输出。它不需要上拉电阻,因为它们已经在内部连接。复位后,端口1配置为输入端口。以下代码可用于向端口1发送55H和AAH的交替值。
;Toggle all bits of continuously MOV A,#55 BACK: MOV P2,A ACALL DELAY CPL A ;complement(invert) reg. A SJMP BACK
如果将端口1配置为输出端口,则要再次将其用作输入端口,请通过向其所有位写入1来对其进行编程,如下面的代码所示。
;Toggle all bits of continuously MOV A ,#0FFH ;A = FF hex MOV P1,A ;Make P1 an input port MOV A,P1 ;get data from P1 MOV R7,A ;save it in Reg R7 ACALL DELAY ;wait MOV A,P1 ;get another data from P1 MOV R6,A ;save it in R6 ACALL DELAY ;wait MOV A,P1 ;get another data from P1 MOV R5,A ;save it in R5
端口2(引脚21至28)
端口2占用总共8个引脚(引脚21至28),可用于输入和输出操作。与P1(端口1)一样,P2也不需要外部上拉电阻,因为它们已经在内部连接。它必须与P0一起使用,以提供外部存储器的16位地址。因此,它也被指定为(A0-A7),如引脚图所示。当8051连接到外部存储器时,它为16位地址的高8位提供路径,并且不能用作I/O。复位后,端口2配置为输入端口。以下代码可用于向端口2发送55H和AAH的交替值。
;Toggle all bits of continuously MOV A,#55 BACK: MOV P2,A ACALL DELAY CPL A ; complement(invert) reg. A SJMP BACK
如果将端口2配置为输出端口,则要再次将其用作输入端口,请通过向其所有位写入1来对其进行编程,如下面的代码所示。
;Get a byte from P2 and send it to P1 MOV A,#0FFH ;A = FF hex MOV P2,A ;make P2 an input port BACK: MOV A,P2 ;get data from P2 MOV P1,A ;send it to Port 1 SJMP BACK ;keep doing that
端口3(引脚10至17)
它也是8位的,可以用作输入/输出。此端口提供一些非常重要的信号。P3.0和P3.1分别是RxD(接收器)和TxD(发送器),它们共同用于串行通信。P3.2和P3.3引脚用于外部中断。P3.4和P3.5分别用于定时器T0和T1。P3.6和P3.7是写(WR)和读(RD)引脚。这些是低电平有效的引脚,这意味着当向它们提供0时它们将处于活动状态,并且它们用于在基于8031的系统中向外部ROM提供读写操作。
P3位 | 功能 | 引脚 |
---|---|---|
P3.0 | RxD | 10 |
P3.1 < | TxD | 11 |
P3.2 < | INT0的反码 | 12 |
P3.3 < | INT1 | 13 |
P3.4 < | T0 | 14 |
P3.5 < | T1 | 15 |
P3.6 < | WR | 16 |
P3.7 < | RD的反码 | 17 |
端口0和端口2的双重角色
端口0的双重角色 - 端口0也被指定为AD0-AD7,因为它可以同时用于数据和地址处理。在将8051连接到外部存储器时,端口0可以提供地址和数据。8051微控制器然后将输入多路复用为地址或数据,以节省引脚。
端口2的双重角色 - 除了用作I/O外,端口P2还与端口0一起用于为外部存储器提供16位地址总线。端口P2也被指定为(A8-A15),而端口0通过A0-A7提供低8位。换句话说,我们可以说,当8051连接到外部存储器(ROM)时,该存储器最多可以达到64KB,这是通过16位地址总线实现的,因为我们知道216 = 64KB。端口2用于16位地址的高8位,并且不能用作I/O,这是访问外部ROM程序代码的方式。
引脚的硬件连接
Vcc - 引脚40为芯片供电,为+5V。
Gnd - 引脚20为参考提供接地。
XTAL1,XTAL2(引脚18和引脚19) - 8051具有片上振荡器,但需要外部时钟来运行它。石英晶体连接在芯片的XTAL1和XTAL2引脚之间。该晶体还需要两个30pF的电容来产生所需频率的信号。每个电容的一端连接到地。8051 IC有各种速度,这都取决于这个石英晶体,例如,一个20MHz的微控制器需要一个频率不超过20MHz的晶体。
RST(引脚9) - 它是一个输入引脚,并且是高电平有效的引脚。在该引脚上施加高脉冲,即1,微控制器将复位并终止所有活动。此过程称为上电复位。激活上电复位将导致寄存器中的所有值丢失。它会将程序计数器设置为全0。为了确保复位的有效输入,高脉冲必须在允许其变为低电平之前保持高电平至少两个机器周期,这取决于电容值和其充电速率。(机器周期是执行单个指令所需的最小频率。)
EA或外部访问(引脚31) - 它是一个输入引脚。此引脚是低电平有效的引脚;在施加低脉冲后,它会被激活。对于具有片上ROM的微控制器(8051/52),EA(反码)引脚连接到Vcc。但在没有片上ROM的8031微控制器中,代码存储在外部ROM中,然后由微控制器获取。在这种情况下,我们必须将(引脚31)EA连接到Gnd,以指示程序代码存储在外部。
PSEN或程序存储器使能(引脚29) - 这也是一个低电平有效的引脚,即在施加低脉冲后它会被激活。它是一个输出引脚,与EA引脚一起在基于8031的(即无ROM)系统中使用,以允许将程序代码存储在外部ROM中。
ALE或(地址锁存使能) - 这是一个输出引脚,并且是高电平有效的。它专门用于8031 IC将其连接到外部存储器。在确定P0引脚将用作地址总线还是数据总线时可以使用它。当ALE=1时,P0引脚用作数据总线,当ALE=0时,P0引脚用作地址总线。
I/O端口和位寻址
在为8051编写代码时,这是8051最广泛使用的功能之一。有时我们需要访问端口的1或2位,而不是整个8位。8051提供了访问端口各个位的功能。
以单比特方式访问端口时,我们使用语法“SETB X.Y”,其中X是端口号(0到3),Y是数据位(0到7)的位号,其中D0是最低有效位,D7是最高有效位。例如,“SETB P1.5”将端口1的第5位设置为高电平。
以下代码显示了我们如何连续切换P1.2位。
AGAIN: SETB P1.2 ACALL DELAY CLR P1.2 ACALL DELAY SJMP AGAIN
单比特指令
指令 | 功能 |
---|---|
SETB bit | 设置位(bit = 1) |
CLR bit | 清除位(bit = 0) |
CPL bit | 反转位(bit = NOT bit) |
JB bit, target | 如果bit = 1,则跳转到target(如果bit,则跳转) |
JNB bit, target | 如果bit = 0,则跳转到target(如果无bit,则跳转) |
JBC bit, target | 如果bit = 1,则跳转到target,并清除bit(如果bit,则跳转,然后清除) |
嵌入式系统 - 术语
程序计数器
程序计数器是一个16位或32位寄存器,其中包含要执行的下一条指令的地址。每次获取指令时,PC都会自动递增到下一个连续的内存位置。分支、跳转和中断操作会将程序计数器加载到除下一个连续位置之外的其他地址。
激活上电复位将导致寄存器中的所有值丢失。这意味着复位后PC(程序计数器)的值为0,迫使CPU从ROM内存位置0000获取第一个操作码。这意味着我们必须将操作码的第一字节放在ROM位置0000,因为这是CPU期望找到第一条指令的位置。
复位向量
复位向量的意义在于它将处理器指向包含固件第一条指令的内存地址。如果没有复位向量,处理器将不知道从哪里开始执行。复位后,处理器从预定义的内存位置加载程序计数器(PC)的复位向量值。在CPU08架构上,此位置位于$FFFE:$FFFF。
当不需要复位向量时,开发人员通常认为它是理所当然的,并且不会将其编程到最终映像中。结果,处理器不会在最终产品上启动。这是调试阶段发生的常见错误。
堆栈指针
堆栈在RAM中实现,并且使用一个称为SP(堆栈指针)寄存器的CPU寄存器来访问它。SP寄存器是一个8位寄存器,可以寻址范围为00h到FFh的内存地址。最初,SP寄存器包含值07,以将位置08指向为8051使用的第一个堆栈位置。
当CPU寄存器的内容存储在堆栈中时,称为PUSH操作。当堆栈的内容存储在CPU寄存器中时,称为POP操作。换句话说,将寄存器压入堆栈以保存它,并从堆栈中弹出以检索它。
无限循环
无限循环或无休止循环可以识别为计算机程序中的一系列指令,由于以下原因,这些指令在循环中无限执行:
- 没有终止条件的循环。
- 终止条件永远无法满足的循环。
- 终止条件导致循环重新开始的循环。
此类无限循环通常会导致旧的操作系统变得无响应,因为无限循环会消耗所有可用的处理器时间。等待用户输入的I/O操作也称为“无限循环”。计算机“冻结”的一个可能原因是无限循环;其他原因包括死锁和访问冲突。
与PC不同,嵌入式系统永远不会“退出”应用程序。它们通过一个无限循环空闲,等待以中断或预先安排的任务的形式发生的事件。为了节省电力,一些处理器进入特殊的睡眠或等待模式,而不是通过无限循环空闲,但它们将在定时器或外部中断后退出此模式。
中断
中断大多是硬件机制,用于指示程序已发生事件。它们可能随时发生,因此与程序流异步。它们需要处理器进行特殊处理,并最终由相应的中断服务程序(ISR)处理。中断需要快速处理。如果您花费太多时间处理中断,那么您可能会错过另一个中断。
小端序与大端序
尽管数字始终以相同的方式显示,但它们在内存中的存储方式并不相同。大端序机器将数据的最高有效字节存储在最低内存地址中。大端序机器将0x12345678存储为 -
ADD+0: 0x12 ADD+1: 0x34 ADD+2: 0x56 ADD+3: 0x78
另一方面,小端序机器将数据的最低有效字节存储在最低内存地址中。小端序机器将0x12345678存储为 -
ADD+0: 0x78 ADD+1: 0x56 ADD+2: 0x34 ADD+3: 0x12
嵌入式系统 - 汇编语言
汇编语言是为了提供机器级代码指令的助记符或符号而开发的。汇编语言程序由助记符组成,因此应将其转换为机器代码。负责此转换的程序称为汇编器。汇编语言通常被称为低级语言,因为它直接与CPU的内部结构交互。要使用汇编语言编程,程序员必须了解CPU的所有寄存器。
诸如 C、C++、Java 等不同的编程语言被称为高级语言,因为它们不涉及 CPU 的内部细节。相比之下,汇编器用于将汇编语言程序转换为机器码(有时也称为目标代码或操作码)。类似地,编译器将高级语言转换为机器码。例如,要编写 C 语言程序,必须使用 C 编译器将程序转换为机器语言。
汇编语言的结构
汇编语言程序是一系列语句,这些语句要么是汇编语言指令(例如 ADD 和 MOV),要么是称为指令的语句。
指令告诉 CPU 要做什么,而指令(也称为伪指令)则向汇编器发出指令。例如,ADD 和 MOV 指令是 CPU 运行的命令,而 ORG 和 END 是汇编器指令。当使用 ORG 指令时,汇编器将操作码放置到内存位置 0,而 END 指示源代码的结尾。程序语言指令包含以下四个字段:
[ label: ] mnemonics [ operands ] [;comment ]
方括号([ ])表示该字段是可选的。
标号字段允许程序通过名称引用代码行。标号字段不能超过一定数量的字符。
助记符和操作数字段共同执行程序的实际工作并完成任务。例如语句 ADD A , C & MOV C, #68,其中 ADD 和 MOV 是助记符,生成操作码;“A, C” 和 “C, #68” 是操作数。这两个字段可以包含指令。指令不会生成机器码,仅供汇编器使用,而指令则被转换为机器码供 CPU 执行。
1.0000 ORG 0H ;start (origin) at location 0 2 0000 7D25 MOV R5,#25H ;load 25H into R5 3.0002 7F34 MOV R7,#34H ;load 34H into R7 4.0004 7400 MOV A,#0 ;load 0 into A 5.0006 2D ADD A,R5 ;add contents of R5 to A 6.0007 2F ADD A,R7 ;add contents of R7 to A 7.0008 2412 ADD A,#12H ;add to A value 12 H 8.000A 80FE HERE: SJMP HERE ;stay in this loop 9.000C END ;end of asm source file
注释字段以分号开头,分号是注释指示符。
请注意程序中的标号“HERE”。任何引用指令的标号都应后跟冒号。
汇编和运行 8051 程序
在这里,我们将讨论汇编语言的基本形式。创建、汇编和运行汇编语言程序的步骤如下:
首先,我们使用编辑器键入类似于上述程序的程序。所有 Microsoft 操作系统附带的类似 MS-DOS EDIT 程序的编辑器可用于创建或编辑程序。编辑器必须能够生成 ASCII 文件。源文件的“asm”扩展名在下一步中由汇编器使用。
“asm”源文件包含在步骤 1 中创建的程序代码。它被馈送到 8051 汇编器。然后,汇编器将汇编语言指令转换为机器码指令,并生成.obj 文件(目标文件)和.lst 文件(列表文件)。它也被称为源文件,因此一些汇编器要求此文件具有“src”扩展名。“lst”文件是可选的。它对程序非常有用,因为它列出了所有操作码和地址以及汇编器检测到的错误。
汇编器需要一个称为链接的第三步。链接程序获取一个或多个目标文件,并生成一个扩展名为“abs”的绝对目标文件。
接下来,“abs”文件被馈送到一个名为“OH”(目标到十六进制转换器)的程序,该程序创建一个扩展名为“hex”的文件,该文件已准备好刻录到 ROM 中。
数据类型
8051 微控制器包含一种 8 位的单一数据类型,每个寄存器也是 8 位大小。程序员必须将大于 8 位(00 到 FFH,或十进制的 255)的数据分解,以便 CPU 可以处理它。
DB(定义字节)
DB 指令是汇编器中最广泛使用的数据指令。它用于定义 8 位数据。它还可以用于定义十进制、二进制、十六进制或 ASCII 格式的数据。对于十进制,十进制数后的“D”是可选的,但“B”(二进制)和“Hl”(十六进制)是必需的。
要指示 ASCII,只需将字符放在引号中('像这样')。汇编器会自动为数字/字符生成 ASCII 代码。DB 指令是唯一可以用于定义大于两个字符的 ASCII 字符串的指令;因此,它应该用于所有 ASCII 数据定义。下面给出了一些 DB 的示例:
ORG 500H DATA1: DB 28 ;DECIMAL (1C in hex) DATA2: DB 00110101B ;BINARY (35 in hex) DATA3: DB 39H ;HEX ORG 510H DATA4: DB "2591" ;ASCII NUMBERS ORG 520H DATA6: DA "MY NAME IS Michael" ;ASCII CHARACTERS
ASCII 字符串周围可以使用单引号或双引号。DB 也用于以字节大小的块分配内存。
汇编器指令
8051 的一些指令如下:
ORG(原点) - 原点指令用于指示地址的开头。它采用十六进制或十进制格式的数字。如果数字后提供 H,则该数字被视为十六进制,否则为十进制。汇编器将十进制数转换为十六进制。
EQU(等价) - 它用于定义常量而不占用内存位置。EQU 将常量值与数据标号关联,以便标号出现在程序中,其常量值将替换为标号。在执行指令“MOV R3, #COUNT”时,寄存器 R3 将加载值为 25(注意 # 符号)。使用 EQU 的优点是程序员可以更改一次,汇编器将更改其所有出现;程序员不必搜索整个程序。
END 指令 - 它指示源(asm)文件的结尾。END 指令是程序的最后一行;END 指令之后的任何内容都会被汇编器忽略。
汇编语言中的标号
汇编语言中的所有标号都必须遵循以下规则:
每个标号名称必须唯一。汇编语言编程中用于标号的名称由大小写字母、数字 0 到 9 以及特殊字符(如问号(?)、句点(.)、@ 符号、下划线(_)和美元符号($))组成。
第一个字符应为字母字符;它不能是数字。
保留字不能用作程序中的标号。例如,ADD 和 MOV 词是保留字,因为它们是指令助记符。
嵌入式系统 - 寄存器
寄存器用于 CPU 中临时存储信息,这些信息可能是要处理的数据,或者指向要获取的数据的地址。在 8051 中,有一种数据类型为 8 位,从 MSB(最高有效位)D7 到 LSB(最低有效位)D0。对于 8 位数据类型,任何大于 8 位的数据类型都必须在处理之前分解成 8 位块。
8051 最常用的寄存器是 A(累加器)、B、R0-R7、DPTR(数据指针)和 PC(程序计数器)。所有这些寄存器都是 8 位的,除了 DPTR 和 PC。
8051 中的存储寄存器
我们将在这里讨论以下类型的存储寄存器:
- 累加器
- R 寄存器
- B 寄存器
- 数据指针 (DPTR)
- 程序计数器 (PC)
- 堆栈指针 (SP)
累加器
累加器,寄存器 A,用于所有算术和逻辑运算。如果没有累加器,则每次计算(加法、乘法、移位等)的结果都必须存储到主内存中。访问主内存比访问像累加器这样的寄存器慢,因为用于大型主内存的技术比用于寄存器的技术慢(但更便宜)。
“R”寄存器
“R”寄存器是一组八个寄存器,即 R0、R1 到 R7。这些寄存器在许多操作中充当辅助或临时存储寄存器。考虑 10 和 20 之和的示例。将变量 10 存储在累加器中,将另一个变量 20 存储在,例如,寄存器 R4 中。要处理加法运算,请执行以下命令:
ADD A,R4
执行此指令后,累加器将包含值 30。因此,“R”寄存器是非常重要的辅助或辅助寄存器。如果没有这些“R”寄存器,累加器本身将不是很有用。“R”寄存器用于临时存储值。
让我们再举一个例子。我们将 R1 和 R2 中的值加在一起,然后从结果中减去 R3 和 R4 的值。
MOV A,R3 ;Move the value of R3 into the accumulator ADD A,R4 ;Add the value of R4 MOV R5,A ;Store the resulting value temporarily in R5 MOV A,R1 ;Move the value of R1 into the accumulator ADD A,R2 ;Add the value of R2 SUBB A,R5 ;Subtract the value of R5 (which now contains R3 + R4)
如您所见,我们使用 R5 临时保存 R3 和 R4 的和。当然,这不是计算 (R1 + R2) – (R3 + R4) 的最有效方法,但它确实说明了“R”寄存器作为临时存储值的方式。
“B”寄存器
“B”寄存器与累加器非常相似,因为它可以保存 8 位(1 字节)的值。“B”寄存器仅由两个 8051 指令使用:MUL AB 和DIV AB。要快速轻松地将 A 乘以或除以另一个数字,您可以将另一个数字存储在“B”中并使用这两个指令。除了使用 MUL 和 DIV 指令外,“B”寄存器通常用作另一个临时存储寄存器,就像第九个 R 寄存器一样。
数据指针
数据指针 (DPTR) 是 8051 唯一用户可访问的 16 位(2 字节)寄存器。累加器、R0-R7 寄存器和 B 寄存器是 1 字节值寄存器。DPTR 用于指向数据。它由 8051 用于使用 DPTR 指示的地址访问外部存储器。DPTR 是唯一可用的 16 位寄存器,通常用于存储 2 字节值。
程序计数器
程序计数器 (PC) 是一个 2 字节地址,它告诉 8051 在哪里可以找到内存中要执行的下一条指令。当 8051 初始化时,PC 从 0000h 开始,并在每次执行指令后递增。PC 并不总是递增 1。某些指令可能需要 2 或 3 个字节;在这种情况下,PC 将递增 2 或 3。
分支、跳转和中断操作将程序计数器加载到下一个顺序位置以外的地址。激活上电复位将导致寄存器中的所有值丢失。这意味着 PC 的值为复位后的 0,迫使 CPU 从 ROM 位置 0000 获取第一个操作码。这意味着我们必须将第一个操作码字节放在 ROM 位置 0000,因为那是 CPU 期望找到第一条指令的地方。
堆栈指针 (SP)
堆栈指针与除 DPTR 和 PC 之外的所有寄存器一样,可以保存 8 位(1 字节)的值。堆栈指针指示从何处从堆栈中删除下一个值的地址。当将值压入堆栈时,SP 的值会递增,然后将该值存储到结果内存位置。当从堆栈中弹出值时,将从 SP 指示的内存位置返回该值,然后 SP 的值会递减。
操作顺序很重要。当 8051 初始化时,SP 将被初始化为 07h。如果同时将一个值压入堆栈,则该值将存储在内部 RAM 地址 08h 中,因为 8051 将首先增加 SP 的值(从 07h 到 08h),然后将压入的值存储到该内存地址(08h)。SP 由 8051 通过六条指令直接修改:PUSH、POP、ACALL、LCALL、RET 和 RETI。
8051 中的 ROM 空间
一些 8051 家族成员只有 4K 字节的片上 ROM(例如 8751、AT8951);有些有 8K ROM,如 AT89C52,还有一些家族成员有 32K 字节和 64K 字节的片上 ROM,例如达拉斯半导体。需要记住的是,8051 家族的任何成员都不能访问超过 64K 字节的操作码,因为 8051 中的程序计数器是一个 16 位寄存器(0000 到 FFFF 地址)。
8051 内部的程序 ROM 的第一个位置的地址为 0000H,而最后一个位置可能因芯片上 ROM 的大小而异。在 8051 家族成员中,AT8951 有 $k 字节的片上 ROM,其内存地址从 0000(第一个位置)到 0FFFH(最后一个位置)。
8051 标志位和 PSW 寄存器
程序状态字 (PSW) 寄存器是一个 8 位寄存器,也称为标志寄存器。它是 8 位宽的,但只有 6 位被使用。两个未使用的位是用户定义标志。其中四个标志称为条件标志,这意味着它们指示指令执行后产生的条件。这四个是CY(进位)、AC(辅助进位)、P(奇偶校验)和OV(溢出)。RS0 和 RS1 位用于更改寄存器组。下图显示了程序状态字寄存器。
PSW 寄存器包含反映 CPU 当前状态的状态位。
CY | CA | F0 | RS1 | RS0 | OV | - | P |
---|
CY | PSW.7 | 进位标志 |
AC | PSW.6 | 辅助进位标志 |
F0 | PSW.5 | 用户可用于通用目的的标志 0。 |
RS1 | PSW.4 | 寄存器组选择位 1 |
RS0 | PSW.3 | 寄存器组选择位 0 |
OV | PSW.2 | 溢出标志 |
- | PSW.1 | 用户可定义标志 |
P | PSW.0 | 奇偶校验标志。在指令周期期间由硬件设置/清除,以指示累加器中 1 位的奇偶数。 |
我们可以使用 RS0 和 RS1 位选择相应的寄存器组位。
RS1 | RS2 | 寄存器组 | 地址 |
---|---|---|---|
0 | 0 | 0 | 00H-07H |
0 | 1 | 1 | 08H-0FH |
1 | 0 | 2 | 10H-17H |
1 | 1 | 3 | 18H-1FH |
CY,进位标志 - 每当从 D7 位进位时,此进位标志就被置位 (1)。它在 8 位加法或减法运算后受到影响。它也可以通过指令(例如“SETB C”和“CLR C”)直接重置为 1 或 0,其中“SETB”代表设置进位位,“CLR”代表清除进位。
AC,辅助进位标志 - 如果在 ADD 或 SUB 操作期间 D3 和 D4 之间有进位,则 AC 位被置位;否则,它被清除。它用于指令执行二进制编码十进制算术。
P,奇偶校验标志 - 奇偶校验标志仅表示累加器寄存器中 1 的数量。如果 A 寄存器包含奇数个 1,则 P = 1;对于偶数个 1,P = 0。
OV,溢出标志 - 每当带符号数运算的结果过大导致高位溢出到符号位时,此标志就被置位。它仅用于检测带符号算术运算中的错误。
示例
在以下指令中,显示 9CH 和 64H 相加后 CY、AC 和 P 标志的状态。
MOV A, #9CH
ADD A, # 64H
Solution: 9C 10011100 +64 01100100 100 00000000 CY = 1 since there is a carry beyond D7 bit AC = 0 since there is a carry from D3 to D4 P = 0 because the accumulator has even number of 1's
嵌入式系统 - 寄存器组/堆栈
8051 微控制器共有 128 字节的 RAM。我们将讨论这 128 字节 RAM 的分配,并检查它们作为堆栈和寄存器的用法。
8051 中的 RAM 内存空间分配
8051 内部的 128 字节 RAM 被分配了地址 00 到 7FH。它们可以直接作为内存位置访问,并分为以下三组 -
从 00H 到 1FH 位置的 32 字节留给寄存器组和堆栈。
从 20H 到 2FH 位置的 16 字节留给按位寻址的读/写内存。
从 30H 到 7FH 位置的 80 字节用于读写存储;它被称为暂存器。这 80 个位置的 RAM 被 8051 程序员广泛用于存储数据和参数。
8051 中的寄存器组
总共 32 字节的 RAM 留给寄存器组和堆栈。这 32 字节被分为四个寄存器组,每个寄存器组有 8 个寄存器,R0–R7。RAM 位置 0 到 7 留给 R0–R7 的组 0,其中 R0 是 RAM 位置 0,R1 是 RAM 位置 1,R2 是位置 2,依此类推,直到内存位置 7,它属于组 0 的 R7。
寄存器 R0–R7 的第二个组从 RAM 位置 08 开始,到位置 OFH。R0–R7 的第三个组从内存位置 10H 开始,到位置 17H。最后,RAM 位置 18H 到 1FH 留给 R0–R7 的第四个组。
默认寄存器组
如果 RAM 位置 00–1F 留给四个寄存器组,那么当 8051 加电时,我们能够访问哪个寄存器组 R0–R7?答案是寄存器组 0;也就是说,在对 8051 进行编程时,RAM 位置 0 到 7 使用名称 R0 到 R7 进行访问。因为用 R0 到 R7 等名称引用这些 RAM 位置比用它们的内存位置引用更容易。
如何切换寄存器组
8051 加电时,寄存器组 0 为默认组。我们可以使用 PSW 寄存器切换到其他组。PSW 的 D4 和 D3 位用于选择所需的寄存器组,因为它们可以通过按位寻址指令 SETB 和 CLR 进行访问。例如,“SETB PSW.3”将设置 PSW.3 = 1 并选择寄存器组 1。
RS1 | RS2 | 选择的组 |
---|---|---|
0 | 0 | 组 0 |
0 | 1 | 组 1 |
1 | 0 | 组 2 |
1 | 1 | 组 3 |
堆栈及其操作
8051 中的堆栈
堆栈是 CPU 用于临时存储信息(如数据或内存地址)的 RAM 的一部分。考虑到寄存器的数量有限,CPU 需要此存储区域。
如何访问堆栈
由于堆栈是 RAM 的一部分,因此 CPU 内部有寄存器指向它。用于访问堆栈的寄存器称为堆栈指针寄存器。8051 中的堆栈指针为 8 位宽,其值可以为 00 到 FFH。当 8051 初始化时,SP 寄存器包含值 07H。这意味着 RAM 位置 08 是堆栈使用的第一个位置。将 CPU 寄存器存储到堆栈中的操作称为PUSH,将堆栈中的内容取回 CPU 寄存器称为POP。
压入堆栈
在 8051 中,堆栈指针 (SP) 指向堆栈的最后一个使用位置。当数据被压入堆栈时,堆栈指针 (SP) 会递增 1。当执行 PUSH 时,寄存器的内容被保存到堆栈中,并且 SP 递增 1。要将寄存器压入堆栈,我们必须使用它们的 RAM 地址。例如,指令“PUSH 1”将寄存器 R1 压入堆栈。
从堆栈弹出
将堆栈的内容弹出到给定的寄存器中与压入过程相反。在每次弹出操作中,堆栈的顶部字节都会被复制到指令指定的寄存器中,并且堆栈指针会递减一次。
嵌入式系统 - 指令
程序流以顺序方式进行,从一条指令到下一条指令,除非执行了控制转移指令。汇编语言中的各种类型的控制转移指令包括条件或无条件跳转和调用指令。
循环和跳转指令
8051 中的循环
重复执行一系列指令一定次数称为循环。指令DJNZ reg, label用于执行循环操作。在此指令中,寄存器递减 1;如果它不为零,则 8051 跳转到标签引用的目标地址。
在循环开始之前,寄存器加载循环次数的计数器。在此指令中,寄存器递减和跳转决策被组合到单个指令中。寄存器可以是 R0–R7 中的任何一个。计数器也可以是 RAM 位置。
示例
使用重复加法技术将 25 乘以 10。
解决方案 - 乘法可以通过重复添加被乘数来实现,次数与乘数相同。例如,
25 * 10 = 250(FAH)
25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 = 250
MOV A,#0 ;A = 0,clean ACC MOV R2,#10 ; the multiplier is replaced in R2 Add A,#25 ;add the multiplicand to the ACC AGAIN:DJNZ R2, AGAIN:repeat until R2 = 0 (10 times) MOV R5 , A ;save A in R5 ;R5 (FAH)
8051 中的缺点 - 使用指令DJNZ Reg label进行循环操作仅限于 256 次迭代。如果没有进行条件跳转,则执行跳转后的指令。
循环内的循环
当我们在另一个循环内使用循环时,这称为嵌套循环。当最大计数限制为 256 时,使用两个寄存器来保存计数。因此,我们使用此方法使操作重复的次数超过 256 次。
示例
编写一个程序 -
- 将累加器加载为值 55H。
- 对 ACC 取反 700 次。
解决方案 - 由于 700 大于 255(任何寄存器的最大容量),因此使用两个寄存器来保存计数。以下代码显示了如何使用两个寄存器 R2 和 R3 进行计数。
MOV A,#55H ;A = 55H NEXT: MOV R3,#10 ;R3 the outer loop counter AGAIN:MOV R2,#70 ;R2 the inner loop counter CPL A ;complement
其他条件跳转
下表列出了 8051 中使用的条件跳转 -
指令 | 操作 |
---|---|
JZ | 如果 A = 0 则跳转 |
JNZ | 如果 A ≠ 0 则跳转 |
DJNZ | 递减并如果寄存器 ≠ 0 则跳转 |
CJNE A, data | 如果 A ≠ 数据,则跳转 |
CJNE 寄存器, #数据 | 如果字节 ≠ 数据,则跳转 |
JC | 如果 CY = 1,则跳转 |
JNC | 如果 CY ≠ 1,则跳转 |
JB | 如果位 = 1,则跳转 |
JNB | 如果位 = 0,则跳转 |
JBC | 如果位 = 1 且清零该位,则跳转 |
JZ(如果 A = 0,则跳转) - 在此指令中,检查累加器的内容。如果为零,则 8051 跳转到目标地址。JZ 指令仅适用于累加器,不适用于任何其他寄存器。
JNZ(如果 A 不等于 0,则跳转) - 在此指令中,检查累加器的内容是否非零。如果非零,则 8051 跳转到目标地址。
JNC(如果无进位,则跳转,如果 CY = 0,则跳转) - 标志(或 PSW)寄存器中的进位标志位用于决定是否跳转“JNC 标签”。CPU 查看进位标志以查看它是否被置位(CY = 1)。如果未置位,则 CPU 开始从标签地址获取并执行指令。如果 CY = 1,它将不会跳转,而是执行 JNC 下面的下一条指令。
JC(如果进位,则跳转,如果 CY = 1,则跳转) - 如果 CY = 1,则跳转到目标地址。
JB(如果位为高,则跳转)
JNB(如果位为低,则跳转)
注意 - 必须注意,所有条件跳转都是短跳转,即目标地址必须在程序计数器内容的 -128 到 +127 字节内。
无条件跳转指令
8051 中有两个无条件跳转 -
LJMP(长跳转) - LJMP 是 3 字节指令,其中第一个字节表示操作码,第二个和第三个字节表示目标位置的 16 位地址。2 字节目标地址允许从 0000 到 FFFFH 的任何内存位置跳转。
SJMP(短跳转) - 它是一个 2 字节指令,其中第一个字节是操作码,第二个字节是目标位置的相对地址。相对地址范围从 00H 到 FFH,分为向前跳转和向后跳转;也就是说,相对于当前 PC(程序计数器)地址的内存中 -128 到 +127 字节内。对于向前跳转,目标地址可以位于当前 PC 的 127 字节空间内。对于向后跳转,目标地址可以位于当前 PC 的 -128 字节内。
计算短跳转地址
所有条件跳转(JNC、JZ 和 DJNZ)都是短跳转,因为它们是 2 字节指令。在这些指令中,第一个字节表示操作码,第二个字节表示相对地址。目标地址始终相对于程序计数器的值。要计算目标地址,将第二个字节添加到跳转指令正下方的指令的 PC 中。请查看下面给出的程序 -
Line PC Op-code Mnemonic Operand 1 0000 ORG 0000 2 0000 7800 MOV R0,#003 3 0002 7455 MOV A,#55H0 4 0004 6003 JZ NEXT 5 0006 08 INC R0 6 0007 04 AGAIN: INC A 7 0008 04 INC A 8 0009 2477 NEXT: ADD A, #77h 9 000B 5005 JNC OVER 10 000D E4 CLR A 11 000E F8 MOV R0, A 12 000F F9 MOV R1, A 13 0010 FA MOV R2, A 14 0011 FB MOV R3, A 15 0012 2B OVER: ADD A, R3 16 0013 50F2 JNC AGAIN 17 0015 80FE HERE: SJMP HERE 18 0017 END
向后跳转目标地址计算
对于向前跳转,位移值是 0 到 127(十六进制为 00 到 7F)之间的正数。但是,对于向后跳转,位移值是 0 到 -128 的负数。
CALL 指令
CALL 用于调用子程序或方法。子程序用于执行需要频繁执行的操作或任务。这使程序更具结构化并节省内存空间。有两个指令 - LCALL 和 ACALL。
LCALL(长调用)
LCALL 是一个 3 字节指令,其中第一个字节表示操作码,第二个和第三个字节用于提供目标子程序的地址。LCALL 可用于调用 8051 的 64K 字节地址空间内的子程序。
为了成功返回到调用子程序执行后的点,CPU 将 LCALL 正下方的指令地址保存在堆栈中。因此,当调用子程序时,控制权将转移到该子程序,处理器将 PC(程序计数器)保存在堆栈中,并开始从新位置获取指令。RET(返回)指令在完成子程序执行后将控制权转移回调用方。每个子程序都使用 RET 作为最后一条指令。
ACALL(绝对调用)
ACALL 是一个 2 字节指令,与 3 字节的 LCALL 相比。子程序的目标地址必须在 2K 字节内,因为只有 2 字节中的 11 位用于地址。ACALL 和 LCALL 之间的区别在于 LCALL 的目标地址可以在 8051 的 64K 字节地址空间中的任何位置,而 CALL 的目标地址在 2K 字节范围内。
嵌入式系统 - 编址模式
编址模式是指如何寻址给定的内存位置。执行此指令有五种不同的方式或五种编址模式,如下所示 -
- 立即寻址模式
- 直接寻址模式
- 寄存器直接寻址模式
- 寄存器间接寻址模式
- 索引寻址模式
立即寻址模式
让我们从一个例子开始。
MOV A, #6AH
一般来说,我们可以写,
MOV A, #data
它被称为立即,因为 8 位数据立即传输到累加器(目标操作数)。
下图描述了上述指令及其执行过程。操作码 74H 保存到 0202 地址。数据 6AH 保存到程序内存的 0203 地址。读取操作码 74H 后,下一个程序内存地址处的数据被传输到累加器 A(E0H 是累加器的地址)。由于指令为 2 字节并在一个周期内执行,因此程序计数器将递增 2 并指向程序内存的 0204。
注意 - 6AH 前面的“#”符号表示操作数是数据(8 位)。在没有“#”的情况下,十六进制数将被视为地址。
直接寻址模式
这是另一种寻址操作数的方式。在这里,数据的地址(源数据)作为操作数给出。让我们举个例子。
MOV A, 04H
寄存器组 #0(第 4 个寄存器)的地址为 04H。执行 MOV 指令时,寄存器 04H 中存储的数据将移动到累加器。由于寄存器 04H 存储数据 1FH,因此 1FH 将移动到累加器。
注意 - 与立即寻址模式不同,我们在直接寻址模式中未使用“#”。如果我们使用了“#”,则数据值 04H 将被传输到累加器而不是 1FH。
现在,请查看下图。它显示了指令如何执行。
如上图所示,这是一个 2 字节指令,需要 1 个周期才能完成。PC 将递增 2 并指向 0204。MOV A,address 指令的操作码为 E5H。当执行 0202 处的指令(E5H)时,累加器被激活并准备好接收数据。然后 PC 转到下一个地址 0203 并查找 04H 位置的地址,其中源数据(要传输到累加器)位于。在 04H 处,控制找到数据 1F 并将其传输到累加器,因此执行完成。
寄存器直接寻址模式
在此寻址模式下,我们直接使用寄存器名称(作为源操作数)。让我们尝试通过一个例子来理解。
MOV A, R4
一次,寄存器可以取值 R0 到 R7。有 32 个这样的寄存器。为了仅使用 8 个变量来寻址寄存器而使用 32 个寄存器,使用了寄存器组。有 4 个寄存器组,命名为 0 到 3。每个组包含 8 个寄存器,命名为 R0 到 R7。
一次,可以选择一个寄存器组。寄存器组的选择可以通过名为处理器状态字(PSW)的特殊功能寄存器(SFR)实现。PSW 是一个 8 位 SFR,其中每个位都可以根据需要进行编程。位从 PSW.0 到 PSW.7 指定。PSW.3 和 PSW.4 用于选择寄存器组。
现在,请查看下图以清楚地了解其工作原理。
操作码 EC 用于 MOV A,R4。操作码存储在地址 0202 处,当它被执行时,控制权直接转到相应寄存器组的 R4(在 PSW 中选择)。如果选择了寄存器组 #0,则寄存器组 #0 的 R4 中的数据将移动到累加器。这里 2F 存储在 04H 处。04H 表示寄存器组 #0 的 R4 的地址。
数据(2F)移动以粗体突出显示。2F 从数据内存位置 0C H 传输到累加器,并显示为虚线。0CH 是寄存器组 #1 的寄存器 4(R4)的地址位置。上述指令为 1 字节,需要 1 个周期才能完成执行。这意味着,您可以通过使用寄存器直接寻址模式来节省程序内存。
寄存器间接寻址模式
在此寻址模式下,数据的地址存储在寄存器中作为操作数。
MOV A, @R0
这里 R0 内的值被视为地址,其中包含要传输到累加器的数据。示例:如果 R0 的值为 20H,并且数据 2FH 存储在地址 20H 处,则执行此指令后,值 2FH 将被传输到累加器。请参阅下图。
因此,MOV A,@R0 的操作码为 E6H。假设选择了寄存器组 #0,则寄存器组 #0 的 R0 存储数据 20H。程序控制移动到 20H,在那里它找到数据 2FH 并将其传输到累加器。这是一个 1 字节指令,程序计数器递增 1 并移动到程序内存的 0203。
注意 - 只有 R0 和 R1 才能构成寄存器间接寻址指令。换句话说,程序员可以使用 @R0 或 @R1 创建指令。所有寄存器组都允许。
索引寻址模式
我们将举两个例子来理解索引寻址模式的概念。请查看以下指令 -
MOVC A,@A+DPTR
和
MOVC A,@A+PC
其中 DPTR 是数据指针,PC 是程序计数器(两者都是 16 位寄存器)。考虑第一个示例。
MOVC A, @A+DPTR
源操作数为@A+DPTR。它包含来自此位置的源数据。这里我们将DPTR的内容与累加器的当前内容相加。此加法将得到一个新地址,即源数据的地址。然后将此地址指向的数据传输到累加器。
操作码为93H。DPTR的值为01FE,其中01位于DPH(高8位),FE位于DPL(低8位)。累加器的值为02H。然后执行16位加法,01FE H+02H的结果为0200 H。位置0200H处的数据将被传输到累加器。累加器中的先前值(02H)将被来自0200H的新数据替换。累加器中的新数据在插图中突出显示。
这是一个1字节指令,需要2个周期才能执行,并且此指令所需的执行时间与之前的指令(所有指令都是1个周期)相比较高。
另一个示例MOVC A, @A+PC的工作方式与上述示例相同。这里不是将DPTR与累加器相加,而是将程序计数器(PC)内部的数据与累加器相加以获得目标地址。
嵌入式系统 - SFR寄存器
特殊功能寄存器(或特殊用途寄存器,或简称特殊寄存器)是微处理器中控制或监控微处理器各种功能的寄存器。由于特殊寄存器与处理器的某些特殊功能或状态密切相关,因此它们可能无法通过普通指令(如加法、移动等)直接写入。相反,某些处理器架构中的一些特殊寄存器需要特殊指令来修改它们。
在8051中,寄存器A、B、DPTR和PSW是通常称为SFR(特殊功能寄存器)的寄存器组的一部分。可以通过其名称或地址访问SFR。
下表显示了SFR及其地址的列表。
字节地址 | 位地址 | ||||||||
---|---|---|---|---|---|---|---|---|---|
FF | |||||||||
F0 | F7 | F6 | F5 | F4 | F3 | F2 | F1 | F0 | B |
E0 | E7 | E6 | E5 | E4 | E3 | E2 | E1 | E0 | ACC |
D0 | D7 | D6 | D5 | D4 | D3 | D2 | - | D0 | PSW |
B8 | - | - | - | BC | BB | BA | B9 | B8 | IP |
B0 | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | P3 |
A2 | AF | - | - | AC | AB | AA | A9 | A8 | IE |
A0 | A7 | A6 | A5 | A4 | A3 | A2 | A1 | A0 | P2 |
99 | 不可位寻址 | SBUF | |||||||
98 | 9F | 9E | 9D | 9C | 9B | 9A | 99 | 98 | SCON |
90 | 97 | 96 | 95 | 94 | 93 | 92 | 91 | 90 | P1 |
8D | 不可位寻址 | TH1 | |||||||
8C | 不可位寻址 | TH0 | |||||||
8B | 不可位寻址 | TL1 | |||||||
8A | 不可位寻址 | TL0 | |||||||
89 | 不可位寻址 | TMOD | |||||||
88 | 8F | 8E | 8D | 8C | 8B | 8A | 89 | 88 | TCON |
87 | 不可位寻址 | PCON | |||||||
83 | 不可位寻址 | DPH | |||||||
82 | 不可位寻址 | DPL | |||||||
81 | 不可位寻址 | SP | |||||||
80 | 87 | 87 | 85 | 84 | 83 | 82 | 81 | 80 | P0 |
关于SFR地址,请考虑以下两点。
特殊功能寄存器可以具有80H到FFH之间的地址。这些地址高于80H,因为从00到7FH的地址是8051内部RAM存储器的地址。
并非所有80到FF的地址空间都由SFR使用。未使用的80H到FFH位置是保留的,8051程序员不得使用。
CY | PSW.7 | 进位标志 |
AC | PSW.6 | 辅助进位标志 |
F0 | PSW.5 | 用户可用于通用目的的标志 0。 |
RS1 | PSW.4 | 寄存器组选择位 1 |
RS0 | PSW.3 | 寄存器组选择位 0 |
OV | PSW.2 | 溢出标志 |
- | PSW.1 | 用户可定义标志 |
P | PSW.0 | 奇偶校验标志。在指令周期期间由硬件设置/清除,以指示累加器中 1 位的奇偶数。 |
在以下示例中,SFR寄存器的名称被替换为它们的地址。
CY | AC | F0 | RS1 | RS0 | OV | - | P |
---|
我们可以使用 RS0 和 RS1 位选择相应的寄存器组位。
RS1 | RS2 | 寄存器组 | 地址 |
---|---|---|---|
0 | 0 | 0 | 00H-07H |
0 | 1 | 1 | 08H-0FH |
1 | 0 | 2 | 10H-17H |
1 | 1 | 3 | 18H-1FH |
程序状态字 (PSW) 包含状态位以反映CPU的当前状态。8051 变体提供了一个特殊功能寄存器 PSW,其中包含此状态信息。8251 提供了两个额外的状态标志 Z 和 N,它们在称为 PSW1 的第二个特殊功能寄存器中可用。
嵌入式系统 - 定时器/计数器
定时器是一种专门的时钟类型,用于测量时间间隔。通常将从零开始向上计数以测量经过时间的定时器称为秒表。它是一种从指定时间间隔倒数的设备,用于生成时间延迟,例如,沙漏就是一个定时器。
计数器是一种存储(有时还显示)特定事件或过程发生的次数的设备,相对于时钟信号而言。它用于计数微控制器外部发生的事件。在电子学中,可以使用寄存器类型电路(如触发器)非常轻松地实现计数器。
定时器和计数器的区别
区分定时器和计数器的要点如下:
定时器 | 计数器 |
---|---|
每个机器周期都会递增寄存器。 | 考虑到其对应的外部输入引脚(T0、T1)的1到0转换,寄存器会递增。 |
最大计数速率为振荡器频率的1/12。 | 最大计数速率为振荡器频率的1/24。 |
定时器使用内部时钟的频率并生成延迟。 | 计数器使用外部信号来计数脉冲。 |
8051的定时器及其相关寄存器
8051有两个定时器,定时器0和定时器1。它们可以用作定时器或事件计数器。定时器0和定时器1均为16位宽。由于8051遵循8位架构,因此每个16位被访问为两个独立的低字节和高字节寄存器。
定时器0寄存器
定时器0的16位寄存器被访问为低字节和高字节。低字节寄存器称为TL0(定时器0低字节),高字节寄存器称为TH0(定时器0高字节)。可以像访问任何其他寄存器一样访问这些寄存器。例如,指令MOV TL0, #4H将值移入定时器#0的低字节。
定时器1寄存器
定时器1的16位寄存器被访问为低字节和高字节。低字节寄存器称为TL1(定时器1低字节),高字节寄存器称为TH1(定时器1高字节)。可以像访问任何其他寄存器一样访问这些寄存器。例如,指令MOV TL1, #4H将值移入定时器1的低字节。
TMOD(定时器模式)寄存器
定时器0和定时器1都使用同一个寄存器来设置各种定时器操作模式。它是一个8位寄存器,其中低4位留给定时器0,高四位留给定时器。在每种情况下,低2位用于预先设置定时器模式,高2位用于指定位置。
门控 - 设置后,定时器仅在INT(0,1)为高电平时运行。
C/T - 计数器/定时器选择位。
M1 - 模式位1。
M0 - 模式位0。
GATE
每个定时器都有启动和停止的方法。有些定时器通过软件执行此操作,有些通过硬件执行,有些同时具有软件和硬件控制。8051定时器同时具有软件和硬件控制。定时器的启动和停止由软件使用指令SETB TR1和CLR TR1(对于定时器1)以及SETB TR0和CLR TR0(对于定时器0)来控制。
SETB指令用于启动它,并由CLR指令停止它。只要TMOD寄存器中的GATE = 0,这些指令就会启动和停止定时器。可以通过使TMOD寄存器中的GATE = 1来通过外部源启动和停止定时器。
C/T(时钟/定时器)
TMOD寄存器中的此位用于确定定时器是作为延迟生成器还是事件管理器使用。如果C/T = 0,则将其用作定时器以生成定时器延迟。创建时间延迟的时钟源是8051的晶体频率。如果C/T = 0,则连接到8051的晶体频率也决定了8051定时器以规则间隔滴答的频率。
定时器频率始终为连接到8051的晶体频率的1/12。尽管各种基于8051的系统具有10 MHz到40 MHz的XTAL频率,但我们通常使用11.0592 MHz的XTAL频率。这是因为8051的串行通信波特率。XTAL = 11.0592允许8051系统与PC通信而不会出现错误。
M1 / M2
M1 | M2 | 模式 |
---|---|---|
0 | 0 | 13位定时器模式。 |
0 | 1 | 16位定时器模式。 |
1 | 0 | 8位自动重载模式。 |
1 | 1 | 分时模式。 |
定时器的不同模式
模式0(13位定时器模式)
模式0下的定时器1和定时器0都作为8位计数器运行(带32分频预分频器)。定时器寄存器配置为一个13位寄存器,由TH1的所有8位和TL1的低5位组成。TL1的高3位是不确定的,应忽略。设置运行标志(TR1)不会清除寄存器。当计数从全1翻转到全0时,会设置定时器中断标志TF1。模式0操作对于定时器0与定时器1相同。
模式1(16位定时器模式)
定时器模式“1”是一个16位定时器,是一种常用的模式。它的功能与13位模式相同,只是使用了所有16位。TLx从0开始递增到最大255。一旦达到值255,TLx重置为0,然后THx递增1。作为完整的16位定时器,定时器最多可以包含65536个不同的值,并且在65,536个机器周期后将溢出回0。
模式2(8位自动重载)
两个定时器寄存器都配置为带自动重载的8位计数器(TL1和TL0)。TL1(TL0)的溢出设置TF1(TF0),并将TL1(TL0)重新加载为Th1(TH0)的内容,后者由软件预设。重载不会更改TH1(TH0)。
自动重载模式的好处是您可以使定时器始终包含从200到255的值。如果您使用模式0或1,则必须在代码中检查溢出,在这种情况下,将定时器重置为200。在这种情况下,宝贵的指令检查值和/或被重新加载。在模式2中,微控制器负责此操作。一旦您将定时器配置为模式2,就不必担心检查定时器是否溢出,也不必担心重置值,因为微控制器硬件将为您完成所有操作。自动重载模式用于建立常见的波特率。
模式3(分时模式)
定时器模式“3”称为分时模式。当定时器0置于模式3时,它会变成两个独立的8位定时器。定时器0是TL0,定时器1是TH0。两个定时器都从0计数到255,并在溢出时重置回0。定时器1的所有位现在都将与TH0绑定。
当定时器0处于分时模式时,真正的定时器1(即TH1和TL1)可以设置为模式0、1或2,但不能启动/停止,因为执行此操作的位现在已链接到TH0。真正的定时器1将在每个机器周期递增。
初始化定时器
确定定时器模式。考虑一个连续运行且独立于任何外部引脚的16位定时器。
初始化 TMOD 特殊功能寄存器。使用 TMOD 的最低 4 位并考虑定时器 0。保持两位 GATE 0 和 C/T 0 为 0,因为我们希望定时器独立于外部引脚。由于 16 位模式是定时器模式 1,因此清除 T0M1 并设置 T0M0。实际上,唯一需要打开的位是 TMOD 的第 0 位。现在执行以下指令:
MOV TMOD,#01h
现在,定时器 0 处于 16 位定时器模式,但定时器未运行。要启动定时器使其运行,请通过执行以下指令设置 TR0 位:
SETB TR0
现在,定时器 0 将立即开始计数,每个机器周期递增一次。
读取定时器
16 位定时器可以通过两种方式读取。要么读取定时器的实际值作为 16 位数字,要么检测定时器何时溢出。
检测定时器溢出
当定时器从其最高值溢出到 0 时,微控制器会自动设置 TCON 寄存器中的 TFx 位。因此,无需检查定时器的精确值,而是可以检查 TFx 位。如果 TF0 设置,则定时器 0 已溢出;如果 TF1 设置,则定时器 1 已溢出。
嵌入式系统 - 中断
中断是硬件或软件发出的发送到处理器的信号,指示需要立即注意的事件。每当发生中断时,控制器都会完成当前指令的执行并开始执行中断服务程序 (ISR) 或中断处理程序。ISR 告诉处理器或控制器中断发生时该做什么。中断可以是硬件中断或软件中断。
硬件中断
硬件中断是由外部设备(如磁盘控制器或外部外设)发送到处理器的电子警报信号。例如,当我们在键盘上按下按键或移动鼠标时,它们会触发硬件中断,导致处理器读取按键或鼠标位置。
软件中断
软件中断是由异常情况或指令集中导致中断的特殊指令引起的,当处理器执行该指令时会导致中断。例如,如果处理器的算术逻辑单元运行一条将数字除以零的命令,则会导致除以零异常,从而导致计算机放弃计算或显示错误消息。软件中断指令的工作方式类似于子程序调用。
什么是轮询?
持续监控的状态称为轮询。微控制器不断检查其他设备的状态;在执行此操作时,它不执行其他操作,并消耗所有处理时间进行监控。这个问题可以通过使用中断来解决。
在中断方法中,控制器仅在发生中断时响应。因此,控制器不需要定期监控接口和内置设备的状态(标志、信号等)。
中断与轮询
以下是一个区分中断和轮询的类比:
中断 | 轮询 |
---|---|
中断就像一个店员。如果需要服务或产品,他会去找他并告知他自己的需求。在中断的情况下,当接收到标志或信号时,它们会通知控制器需要对其进行服务。 | 轮询方法就像一个销售人员。销售人员挨家挨户地推销产品或服务。类似地,控制器逐个监控所有设备的标志或信号,并为需要其服务的任何组件提供服务。 |
中断服务程序
对于每个中断,都必须有一个中断服务程序 (ISR) 或中断处理程序。当发生中断时,微控制器会运行中断服务程序。对于每个中断,内存中都有一个固定位置保存其中断服务程序 ISR 的地址。为保存 ISR 地址而预留的内存位置表称为中断向量表。
中断向量表
8051 中有六个中断,包括复位。
中断 | ROM 位置(十六进制) | 引脚 |
---|---|---|
中断 | ROM 位置(十六进制) | |
串行通信 (RI 和 TI) | 0023 | |
定时器 1 中断 (TF1) | 001B | |
外部硬件中断 1 (INT1) | 0013 | P3.3 (13) |
外部硬件中断 0 (INT0) | 0003 | P3.2 (12) |
定时器 0 (TF0) | 000B | |
复位 | 0000 | 9 |
当复位引脚被激活时,8051 会跳转到地址位置 0000。这是上电复位。
为定时器预留了两个中断:一个用于定时器 0,一个用于定时器 1。内存位置分别为中断向量表中的 000BH 和 001BH。
为硬件外部中断预留了两个中断。端口 3 中的引脚 12 和引脚 13 分别用于外部硬件中断 INT0 和 INT1。内存位置分别为中断向量表中的 0003H 和 0013H。
串行通信有一个属于接收和发送的单个中断。内存位置 0023H 属于此中断。
执行中断的步骤
当中断变为活动状态时,微控制器会执行以下步骤:
微控制器关闭当前正在执行的指令并将下一条指令的地址 (PC) 保存到堆栈中。
它还内部保存所有中断的当前状态(即,不在堆栈中)。
它跳转到保存中断服务程序地址的中断向量表的内存位置。
微控制器从中断向量表获取 ISR 的地址并跳转到该地址。它开始执行中断服务子程序,即 RETI(从中断返回)。
执行 RETI 指令后,微控制器返回到中断处的位置。首先,它通过将堆栈的顶部字节弹出到 PC 中来从堆栈获取程序计数器 (PC) 地址。然后,它开始从该地址执行。
边沿触发与电平触发
中断模块有两种类型:电平触发或边沿触发。
电平触发 | 边沿触发 |
---|---|
电平触发中断模块只要中断源的电平被置位就会始终生成中断。 | 边沿触发中断模块仅在检测到中断源的置位边沿时才生成中断。当中断源电平实际发生变化时,边沿会被检测到。它也可以通过周期性采样并在先前样本被取消置位时检测到置位电平来检测到。 |
如果中断源在固件中断处理程序处理中断时仍处于置位状态,则中断模块将重新生成中断,导致中断处理程序再次被调用。 | 边沿触发中断模块可以立即执行,无论中断源的行为如何。 |
电平触发中断对固件来说很麻烦。 | 边沿触发中断使固件的代码复杂度保持较低,减少了固件的条件数量,并在处理中断时提供了更大的灵活性。 |
启用和禁用中断
复位后,即使中断被激活,所有中断也会被禁用。必须使用软件启用中断,以便微控制器响应这些中断。
IE(中断启用)寄存器负责启用和禁用中断。IE 是一个按位寻址的寄存器。
中断启用寄存器
EA | - | ET2 | ES | ET1 | EX1 | ET0 | EX0 |
---|
EA - 全局启用/禁用。
- - 未定义。
ET2 - 启用定时器 2 中断。
ES - 启用串口中断。
ET1 - 启用定时器 1 中断。
EX1 - 启用外部中断 1。
ET0 - 启用定时器 0 中断。
EX0 - 启用外部中断 0。
要启用中断,我们执行以下步骤:
IE 寄存器 (EA) 的位 D7 必须为高电平才能使寄存器的其余部分生效。
如果 EA = 1,则中断将被启用并将得到响应,如果它们在 IE 中的相应位为高电平。如果 EA = 0,则任何中断都不会响应,即使它们在 IE 寄存器中的关联引脚为高电平。
8051 中的中断优先级
我们可以通过将较高优先级分配给任何一个中断来更改中断优先级。这是通过编程一个名为IP(中断优先级)的寄存器来实现的。
下图显示了 IP 寄存器的位。复位后,IP 寄存器包含全 0。要为任何中断赋予较高优先级,我们将 IP 寄存器中相应的位设置为高电平。
- | - | - | - | PT1 | PX1 | PT0 | PX0 |
---|
- | IP.7 | 未实现。 |
- | IP.6 | 未实现。 |
- | IP.5 | 未实现。 |
- | IP.4 | 未实现。 |
PT1 | IP.3 | 定义定时器 1 中断优先级。 |
PX1 | IP.2 | 定义外部中断 1 优先级。 |
PT0 | IP.1 | 定义定时器 0 中断优先级。 |
PX0 | IP.0 | 定义外部中断 0 优先级。 |
中断内部中断
如果 8051 正在执行属于一个中断的 ISR 并且另一个中断变为活动状态会发生什么?在这种情况下,高优先级中断可以中断低优先级中断。这称为中断内部中断。在 8051 中,低优先级中断可以被高优先级中断中断,但不能被任何其他低优先级中断中断。
通过软件触发中断
有时我们需要通过模拟的方式测试 ISR。这可以通过简单的指令来完成,这些指令将中断置位,从而导致 8051 跳转到中断向量表。例如,将 IE 位设置为定时器 1 的 1。指令SETB TF1 将中断 8051 当前正在执行的操作并强制其跳转到中断向量表。