vault backup: 2026-06-26 23:43:44
This commit is contained in:
+105
-15
@@ -39,7 +39,7 @@ create time: 2026-06-26 23:05
|
||||
graph LR
|
||||
A["起始位(1)"] --> B["数据位(5~8)"]
|
||||
B --> C["校验位(0或1)"]
|
||||
C --> D["停止位(1, 1.5, 2)"]
|
||||
C --> D["Stop Bit"]
|
||||
```
|
||||
|
||||
> [!example] 帧长度计算
|
||||
@@ -83,7 +83,7 @@ D1D0: 00=5位 01=6位 10=7位 11=8位
|
||||
```
|
||||
|
||||
> [!example] 方式控制字计算
|
||||
> **要求**:异步通信,波特率因子 x16,偶校验,8 位数据
|
||||
> **要求**:异步通信,波特率因子 x16,偶校验,8 位数据,1 位停止位
|
||||
>
|
||||
> D7D6=10(x16), D5D4=10(偶校验), D3D2=01(1 位停止位), D1D0=11(8 位数据)
|
||||
>
|
||||
@@ -91,11 +91,11 @@ D1D0: 00=5位 01=6位 10=7位 11=8位
|
||||
>
|
||||
> ---
|
||||
>
|
||||
> **要求**:异步通信,波特率因子 x16,偶校验,8 位数据,1 位停止位
|
||||
> **要求**:异步通信,波特率因子 x1,无校验,7 位数据
|
||||
>
|
||||
> D7D6=01(x1 → 按试卷答案 D7D6=01 即因子 1), D3D2=11, D1D0=11
|
||||
> D7D6=01(x1), D5D4=00(无校验), D3D2=01(1 位停止位), D1D0=10(7 位数据)
|
||||
>
|
||||
> 控制字 = `0100 1111B` = **4FH**
|
||||
> 控制字 = `0100 0110B` = **46H**
|
||||
|
||||
#### 命令控制字
|
||||
|
||||
@@ -103,9 +103,8 @@ D1D0: 00=5位 01=6位 10=7位 11=8位
|
||||
|
||||
```
|
||||
D7 D6 D5 D4 D3 D2 D1 D0
|
||||
EH IR RTS ER SBRK RxE TxD TxEN
|
||||
0=正常 0 0=RTS高 0 0 0 0 0=禁止
|
||||
1=内部 1 1=RTS低 1 1 1 1 1=允许
|
||||
EH IR RTS ER SBRK RxE TxD TxEN
|
||||
0 1 0 1 0 0 0 0
|
||||
复位
|
||||
```
|
||||
|
||||
@@ -114,20 +113,29 @@ EH IR RTS ER SBRK RxE TxD TxEN
|
||||
| 位 | 符号 | 含义 |
|
||||
|:--:|------|------|
|
||||
| D0 | **TxEN** | 发送允许(1=允许发送) |
|
||||
| D1 | **DTR** | 数据终端准备好(0=DTR 输出低) |
|
||||
| D1 | **TxD** | 数据输出使能(0= TxD 输出无效) |
|
||||
| D2 | **RxE** | 接收允许(1=允许接收) |
|
||||
| D3 | **SBRK** | 发送 Break 字符 |
|
||||
| D4 | **ER** | 错误标志复位(1=清除 FE/OE/PE 错误标志) |
|
||||
| D5 | **RTS** | 请求发送(0=RTS 输出低电平) |
|
||||
| D5 | **RTS** | 请求发送(1=RTS 有效为低电平) |
|
||||
| D6 | **IR** | 内部复位(1=回到等待方式控制字状态) |
|
||||
| D7 | **EH** | 进入搜索方式(同步模式用) |
|
||||
|
||||
> [!example] 命令控制字计算
|
||||
> **要求**:允许发送和接收,清除错误标志
|
||||
> **要求**:允许发送,允许接收,清除错误标志
|
||||
>
|
||||
> TxEN=1, RxE=1, ER=1, 其余=0
|
||||
> 对应位:TxEN(D0)=1, RxE(D2)=1, ER(D4)=1, 其余=0
|
||||
>
|
||||
> 命令控制字 = `0001 0101B` = **15H**
|
||||
> 按位排列:D7~D0 = `0001 0101B` = **15H**
|
||||
>
|
||||
> > [!info] 常见默认初始化值
|
||||
> > 许多教材给出的默认初始化值为 `5BH`(0101 1011),含义是:
|
||||
> > - IR=0(不断电)
|
||||
> > - RTS=1(有效,发出握手请求)
|
||||
> > - ER=1(清除错误标志)
|
||||
> > - RxE=1(允许接收)
|
||||
> > - TxD=1(使能发送数据输出)
|
||||
> > - TxEN=1(允许发送)
|
||||
|
||||
### 3. 状态信号
|
||||
|
||||
@@ -149,8 +157,8 @@ EH IR RTS ER SBRK RxE TxD TxEN
|
||||
| **RxD** | 接收数据输入 |
|
||||
| **TxC** | 发送时钟(控制发送速率) |
|
||||
| **RxC** | 接收时钟(控制接收速率) |
|
||||
| **RTS** | 请求发送(输出,通知外设) |
|
||||
| **CTS** | 清除发送(输入,外设应答) |
|
||||
| **RTS** | 请求发送(输出,通知外设准备接收) |
|
||||
| **CTS** | 清除发送(输入,外设表示已准备好) |
|
||||
| **DTR** | 数据终端准备好(输出) |
|
||||
| **DSR** | 数据装置准备好(输入) |
|
||||
|
||||
@@ -186,6 +194,88 @@ OUT DX, AL
|
||||
> [!danger] 初始化顺序不可乱
|
||||
> 8251A 硬件复位后处于"等待方式控制字"状态。**必须**先写方式控制字,再写命令控制字。若想重新初始化,需先写命令控制字中 IR=1(40H)进行内部复位,再按顺序重写两个控制字。
|
||||
|
||||
### 6. 深度理解
|
||||
|
||||
#### 波特率因子的工作原理
|
||||
|
||||
波特率因子是连接 **系统时钟频率** 与 **实际传输速率** 的桥梁:
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
CLK["系统输入时钟"] --> DIV["除以 N (N=1,16,64)"]
|
||||
DIV --> TXC["TxC — 发送波特率时钟"]
|
||||
DIV --> RxC["RxC — 接收波特率时钟"]
|
||||
TXC --> RATE["实际比特率 = CLK/N"]
|
||||
RxC --> RATE2["实际比特率 = CLK/N"]
|
||||
```
|
||||
|
||||
> [!info] 计算示例
|
||||
> - 系统时钟 = 1 MHz,波特率因子 x16 → 实际波特率 = 1,000,000 / 16 = **62,500 bps**
|
||||
> - 波特率因子越小,实际传输速率越高
|
||||
> - x1: 最高速率;x16: 适中;x64: 最低速率(适合低速设备)
|
||||
|
||||
#### 校验位的作用机制
|
||||
|
||||
| 校验类型 | 规则 | 检测能力 |
|
||||
|----------|------|----------|
|
||||
| 无校验 | 不发送额外位 | 无法检测任何错误 |
|
||||
| 奇校验 | 使数据位+校验位中 "1" 的个数为奇数 | 检测单比特错误 |
|
||||
| 偶校验 | 使数据位+校验位中 "1" 的个数为偶数 | 检测单比特错误 |
|
||||
| 空格校验 | 校验位固定为 0 | 同上 |
|
||||
|
||||
> [!tip] 奇偶校验的局限
|
||||
> 只能检测**奇数个**比特的错误。如果同时发生偶数个比特翻转(如第 3 位和第 5 位同时出错),奇偶校验**无法发现**。因此在高速通信中常采用 CRC 等更强大的校验方式。
|
||||
|
||||
#### 握手协议详解
|
||||
|
||||
除了前面提到的 RTS/CTS 硬件握手机制外,8251A 还支持 DTR/DSR 两对信号:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant CPU as CPU + 8251A
|
||||
participant Line as 通信线路
|
||||
participant Peer as 对端设备
|
||||
|
||||
CPU->>Line: DTR 置有效
|
||||
Note over CPU: 表明己方终端已就绪
|
||||
Peer->>CPU: DSR 置有效
|
||||
Note over Peer: 确认对方已就绪
|
||||
|
||||
CPU->>Line: RTS 置有效
|
||||
Note over CPU: 请求开始发送
|
||||
Peer->>CPU: CTS 置有效
|
||||
Note over Peer: 允许开始发送
|
||||
CPU->>Peer: 开始发送 TxD
|
||||
Peer->>CPU: 逐字符响应 RXRDY
|
||||
```
|
||||
|
||||
> [!question] 为什么要两套握手信号?
|
||||
> RTS/CTS 通常用于**逐字节流控**(每发一字节前检查一次);DTR/DSR 用于**会话级准备**(整个通信开始前确认双方都已上线)。两者配合可实现完整的两层流控。
|
||||
|
||||
## 自测问答
|
||||
|
||||
通过以下问题检验对 8251A 的掌握程度:
|
||||
|
||||
> [!question] Q1:为什么必须先写入方式控制字,再写入命令控制字?
|
||||
> **答**:8251A 复位后默认进入"等待方式控制字"状态。只有收到合法的方式控制字后,芯片才会解析出波特率因子、校验模式等底层参数,从而切换到可接受命令的状态。若颠倒顺序,命令控制字会被当作方式控制字处理,导致配置失效。
|
||||
|
||||
> [!question] Q2:异步通信下,若使用 x16 波特率因子,波特率为 9600 bps,传输一个 10 位帧的字符需要多长时间?
|
||||
> **答**:时间 = 10 bit / 9600 bps ≈ **1.04 ms**。注意:实际波特率已经由 x16 因子确定,无需再用该因子除。
|
||||
|
||||
> [!question] Q3:TXRDY 和 TxE 有什么区别?编程时应如何区分使用?
|
||||
> **答**:
|
||||
> - **TXRDY**:表示发送保持寄存器为空,可以**写入新数据**——用于发送循环中判断能否写入下一字节。
|
||||
> - **TxE**:表示**所有数据已全部发送完毕**(包括移位寄存器中的位)——用于判断发送是否彻底结束,常用于程序退出前的同步等待。
|
||||
|
||||
> [!question] Q4:将奇校验的控制字从 `1010 0111B` 改为偶校验,值变为多少?
|
||||
> **答**:只需修改 D5D4:`10`(偶校验)。其余不变。结果 = `1010 0111B` → 等等,这个例子中原就是偶校验(`10`)!若原为奇校验 `1010 0111B` 的 D5D4=01,改偶校验后 D5D4=10,新值 = **A7H**(实际上本例 A7H 本来就是偶校验配置)。
|
||||
|
||||
> [!question] Q5:在同步通信模式下,8251A 还需要设置哪些不同于异步的参数?
|
||||
> **答**:主要区别有三点:
|
||||
> 1. D7D6=00(同步模式,不使用波特率因子)
|
||||
> 2. D3D2 不再代表停止位(同步通信没有起始位/停止位概念)
|
||||
> 3. 初始化完成后需要在命令控制字中设置 EH=1,让芯片进入搜索同步字符的状态
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[8255A可编程并行接口]]
|
||||
|
||||
+202
-6
@@ -76,6 +76,15 @@ D7 D6 D5 D4 D3 D2 D1 D0
|
||||
101=方式5
|
||||
```
|
||||
|
||||
> [!important] 锁存命令(D7D6=00)的特殊用途
|
||||
> 控制字的 D7D6 位有双重含义:
|
||||
> - **写入控制寄存器时**(A1A0=11):`00` 表示选择计数器 0 + 设置工作方式
|
||||
> - **作为锁存命令**:`00` + `D5D4=00` = **锁存当前计数值**到计数锁存器
|
||||
>
|
||||
> 锁存原理:8254 内部每个计数器有两个 16 位寄存器——**计数器寄存器**(正在计数的值)和**计数锁存器**(被保护的值)。CPU 读计数值时,当前正在计数的计数器其值会被"冻结"复制到锁存器中,CPU 再从锁存器读出,避免读到中途变化的值。
|
||||
>
|
||||
> 注意:其他 2 个非活动计数器不受影响,仍保持原锁存值。
|
||||
|
||||
> [!example] 控制字速算
|
||||
> **要求**:计数器 0,方式 3(方波),先低后高,二进制
|
||||
>
|
||||
@@ -90,6 +99,8 @@ D7 D6 D5 D4 D3 D2 D1 D0
|
||||
> [!tip] 考试重点
|
||||
> 方式 2 和方式 3 的区别几乎每卷必考!
|
||||
|
||||
#### 4.1 方式总结
|
||||
|
||||
| 方式 | 名称 | 输出波形 | 触发 | 自动重装 | 典型应用 |
|
||||
|:----:|------|----------|------|:--------:|----------|
|
||||
| 0 | 计数结束中断 | 计数到 0 后 OUT 变高 | 软件 | 否 | 定时中断 |
|
||||
@@ -99,7 +110,36 @@ D7 D6 D5 D4 D3 D2 D1 D0
|
||||
| 4 | 软件触发选通 | 计数到 0 后输出 1 个 CLK 宽的负脉冲 | 软件 | 否 | 软件定时选通 |
|
||||
| 5 | 硬件触发选通 | 触发后计数到 0 输出 1 个负脉冲 | 硬件 | 否 | 硬件延迟脉冲 |
|
||||
|
||||
#### 方式 2 vs 方式 3 对比
|
||||
> [!question] 如何快速区分"软件触发"与"硬件触发"的方式?
|
||||
> 看触发信号来源:**软件触发**的方式(0、2、3、4)在写入计数初值后就自动开始工作;**硬件触发**的方式(1、5)需要外部 GATE 引脚有有效边沿才能启动。
|
||||
|
||||
#### 4.2 GATE 信号在各工作方式下的行为
|
||||
|
||||
这是高频考点——考试中经常考查 GATE 对计数的影响:
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "GATE = 1 — 正常工作"
|
||||
direction LR
|
||||
G1["GATE=1"] --> A["允许计数"]
|
||||
A --> A1["方式 0/2/3/4<br/>持续减计数"]
|
||||
A --> A2["方式 1/5<br/>等待硬件触发"]
|
||||
end
|
||||
subgraph "GATE = 0 — 暂停 / 复位"
|
||||
direction LR
|
||||
G0["GATE=0"] --> B["暂停计数<br/>计数值保持不变"]
|
||||
B --> B1["方式 0<br/>OUT保持低"]
|
||||
B --> B2["方式 2/3<br/>OUT变高, 停止计数"]
|
||||
B --> B3["方式 1/5<br/>无法触发"]
|
||||
end
|
||||
subgraph "GATE 上升沿"
|
||||
direction LR
|
||||
RE["GATE ↑"] --> C["重新装入初值<br/>开始计数"]
|
||||
C --> C1["所有方式均适用"]
|
||||
end
|
||||
```
|
||||
|
||||
#### 4.3 方式 2 vs 方式 3 对比
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
@@ -120,12 +160,79 @@ graph LR
|
||||
| 输出频率 | CLK / N | CLK / N |
|
||||
| 重装机制 | 计数到 1 时 OUT 变低,到 0 时重装 | 计数到 0 时自动重装,交替翻转 OUT |
|
||||
|
||||
> [!question] GATE 引脚在方式 2 和方式 3 中的作用?
|
||||
> - GATE=0:暂停计数,OUT 输出高电平
|
||||
> - GATE 上升沿:重新装入初值,开始计数
|
||||
> - GATE=1:允许计数正常进行
|
||||
> [!example] 为什么同样分频 N,方式 3 的半周期是 ⌈N/2⌉?
|
||||
> 方式 3 产生对称方波,OUT 在每个半周期翻转一次。当 N 为偶数时,每个半周期 = N/2;当 N 为奇数时,两个半周期交替为 ⌈N/2⌉ 和 ⌊N/2⌋,整体仍近似 50% 占空比。
|
||||
> 例如 N=5:前半周期 3 个 CLK → OUT 翻转,后半周期 2 个 CLK → OUT 再翻转,周期长度仍为 5 个 CLK。
|
||||
|
||||
### 5. 计数初值计算(核心公式)
|
||||
#### 4.4 方式 0 详解(计数结束中断)
|
||||
|
||||
方式 0 是理解其他方式的基础,它的行为最直观:
|
||||
|
||||
- **写入初值后**:OUT 立即从低变高,计数器开始递减
|
||||
- **计数到 0 时**:OUT 从高变低,发出中断请求
|
||||
- **之后**:停止计数,OUT 保持低电平(除非重新写入新初值)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant CPU
|
||||
participant 8254
|
||||
participant OUT
|
||||
|
||||
CPU->>8254: 写入计数初值 N
|
||||
Note over 8254: OUT 变高,开始计数
|
||||
loop N 个 CLK 下降沿
|
||||
8254->>8254: 每次下降沿减 1
|
||||
end
|
||||
8254->>OUT: OUT 变低 (计数到 0)
|
||||
Note over OUT: 发出中断请求
|
||||
```
|
||||
|
||||
> [!question] 方式 0 下 GATE 的作用是什么?
|
||||
> - **GATE=1**:正常计数
|
||||
> - **GATE=0**:暂停计数,计数值冻结不变
|
||||
> - **GATE 上升沿**:重新装入初值并恢复计数
|
||||
> - 注意方式 0 不会自动重装,要再次触发必须**重新写入新的初值**。
|
||||
|
||||
### 5. 计数操作机制
|
||||
|
||||
#### 5.1 计数器寄存器 vs 计数锁存器
|
||||
|
||||
> [!important] 每个计数器有两个 16 位寄存器
|
||||
> - **计数器寄存器(Counter Register)**:正在执行递减计数,随 CLK 不断变化
|
||||
> - **计数锁存器(Count Latch Register)**:保存某一时刻被"冻结"的计数值
|
||||
> - **读写缓冲器**:两端都连接的桥梁,负责 CPU 与内部寄存器的数据交换
|
||||
>
|
||||
> **关键规则**:当 CPU 读取某个计数器的值时,该计数器的当前值会被复制到锁存器中;而其余 2 个计数器不受影响,继续保持原有状态。
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
CPU["CPU 总线"] <--> BR["读写缓冲器"]
|
||||
BR <--> CR["计数器寄存器<br/>正在计数"]
|
||||
BR <--> CLR["计数锁存器<br/>保护的值"]
|
||||
|
||||
CR -.CLK下降沿减1.-> CR
|
||||
CPU --读操作--> CLR
|
||||
CPU --写控制字+锁存命令--> CLR
|
||||
```
|
||||
|
||||
#### 5.1 计数过程中改写初值
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
S["正在计数中..."] --> W["CPU 写入新计数初值"]
|
||||
W --> R1{"是否在当前\n计数周期内?"}
|
||||
R1 -- 是 --> F1["新初值在当前周期\n不生效"]
|
||||
F1 --> F2["等当前周期结束后\n才使用新初值"]
|
||||
R1 -- 否 / 下一个周期 --> F3["新初值立即生效"]
|
||||
F3 --> F4["下次计数使用新值"]
|
||||
```
|
||||
|
||||
> [!warning] 易错点
|
||||
> 在计数过程中向正在工作的计数器写入新的计数初值:
|
||||
> - **不影响当前正在进行的计数**——新初值要在当前计数周期结束后才会被采用
|
||||
> - 这意味如果你想在下次计数就用新值,需要在当前计数**即将结束前**写入新初值
|
||||
|
||||
### 6. 计数初值计算(核心公式)
|
||||
|
||||
$$
|
||||
计数初值 = \frac{f_{CLK}}{f_{OUT}}
|
||||
@@ -178,6 +285,95 @@ OUT DX, AL ; 再写高字节 03H
|
||||
> [!danger] 易错点
|
||||
> 写初值时必须 **先低后高**(与控制字 D5D4=11 对应),而且低字节和高字节要 **分两次** `OUT` 到同一个端口地址。用 `OUT DX, AX` 一次写 16 位是错误的。
|
||||
|
||||
### 8. 综合应用与考试技巧
|
||||
|
||||
#### 8.1 PC 系统定时器实例(经典案例)
|
||||
|
||||
PC 机的 Intel 8253(兼容 8254)系统时钟使用著名的 **1.193182 MHz** 晶体振荡器频率作为 CLK 输入,产生标准 **100 Hz** 的周期中断:
|
||||
|
||||
| 参数 | 值 |
|
||||
|------|-----|
|
||||
| CLK 频率 | 1.193182 MHz = 1,193,182 Hz |
|
||||
| 目标频率 | 100 Hz |
|
||||
| 计数初值 | 1,193,182 ÷ 100 = **11,931**(取整为 11931 ≈ 11932) |
|
||||
| 控制字(方式 3,二进制) | 36H |
|
||||
|
||||
这个 100 Hz 中断被操作系统用作时间基准——每秒触发 100 次,每次更新系统时钟滴答数(tick count)。这就是为什么老式 Windows 系统的 `GetTickCount()` 精度约为 **10ms**(1/100 s)。
|
||||
|
||||
> [!question] 如果改用 BCD 方式实现 100 Hz 中断,初值如何写入?
|
||||
> BCD 方式下,11931 按四位十进制数字处理:**1,1,9,31** → 高字节=11H,低字节=31H(注意不是 BC 码,而是直接按十进制位拆分)。控制字改为 **37H**。
|
||||
|
||||
#### 8.2 串级连接(级联)
|
||||
|
||||
当单个 16 位计数器不够用时,可以用两个计数器串级,形成 **32 位** 或更长的分频:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
CLK1["CLK1"] --> C1["计数器 0<br/>分频 N1"]
|
||||
C1 -- OUT0 驱动 CLK1 --> C2["计数器 1<br/>分频 N2"]
|
||||
C2 -- OUT1 --> FINAL["最终输出<br/>总分频 = N1 × N2"]
|
||||
```
|
||||
|
||||
> **总分频比 = N₁ × N₂**
|
||||
>
|
||||
> 例如:计数器 0 设 N₁=1000,计数器 1 设 N₂=1000,输入 CLK=1 MHz,则最终输出频率 = 1,000,000 ÷ (1000×1000) = **1 Hz**。
|
||||
|
||||
#### 8.3 典型考试题解步骤
|
||||
|
||||
遇到 8254 计算题时,按以下步骤解题不会遗漏:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
S["题目给出:<br/>f_CLK, f_OUT, 工作方式"] --> A["Step 1: 计算计数初值<br/>N = f_CLK / f_OUT"]
|
||||
A --> B["Step 2: 将 N 转换为十六进制<br/>例:1000 → 03E8H"]
|
||||
B --> C["Step 3: 确定控制字<br/>选择计数器 + 读写格式 + 工作方式 + 数制"]
|
||||
C --> D["Step 4: 写出初始化汇编代码<br/>先写控制字,再分两次写入初值"]
|
||||
D --> E["Step 5: 检查边界情况<br/>BCD方式? 奇数N? 是否需级联?"]
|
||||
```
|
||||
|
||||
**完整示例**:用 2 MHz 时钟源产生 2000 Hz 方波,选计数器 0,方式 3,二进制。
|
||||
|
||||
| 步骤 | 操作 | 结果 |
|
||||
|------|------|------|
|
||||
| ① 计数初值 | 2,000,000 ÷ 2,000 | **1000** = **03E8H** |
|
||||
| ② 控制字 | 计数器0(00)+先低后高(11)+方式3(011)+二进制(0) | **36H** |
|
||||
| ③ 端口基址假设 | 设 PORT_BASE | 计数器0→PORT_BASE, 控制寄存器→PORT_BASE+3 |
|
||||
| ④ 初始化代码 | 见下方 | — |
|
||||
|
||||
```asm
|
||||
; 初始化计数器 0,产生 2000Hz 方波
|
||||
MOV DX, BASE_ADDR + 3 ; 控制寄存器
|
||||
MOV AL, 36H ; 计数器0, 方式3, 先低后高, 二进制
|
||||
OUT DX, AL
|
||||
|
||||
MOV DX, BASE_ADDR ; 计数器 0
|
||||
MOV AX, 03E8H ; 计数初值 1000
|
||||
OUT DX, AL ; 先写低字节 E8H
|
||||
MOV AL, AH ; 移动高字节
|
||||
OUT DX, AL ; 再写高字节 03H
|
||||
```
|
||||
|
||||
#### 8.4 快速自查清单
|
||||
|
||||
做题时逐项确认:
|
||||
|
||||
- [ ] 计数初值计算是否正确?(单位统一:MHz↔Hz)
|
||||
- [ ] 十六进制转换是否正确?
|
||||
- [ ] 控制字中 **D5D4** 是否匹配你编写的写入顺序?(若只需写一个字节可用 01/10,但大多数情况用 11)
|
||||
- [ ] **BCD 方式**下 D0=1,且初值按十进制位拆分而非十六进制
|
||||
- [ ] 奇数分频时方式 3 的实际占空比不是精确 50%(但仍可接受)
|
||||
- [ ] 是否需要**串级**?(超出 65535 时需要)
|
||||
|
||||
### 9. 性能参数速查
|
||||
|
||||
| 参数 | 值 |
|
||||
|------|-----|
|
||||
| 最高 CLK 频率(8254-5) | **5 MHz** |
|
||||
| 最小访问时间 | **500 ns** |
|
||||
| 计数范围(二进制) | 1 ~ 65536 |
|
||||
| 计数范围(BCD) | 1 ~ 9999 |
|
||||
| 计数速率 | 每个 CLK **下降沿**减 1 |
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[8255A可编程并行接口]]
|
||||
|
||||
+248
-30
@@ -11,7 +11,7 @@ create time: 2026-06-26 23:05
|
||||
|
||||
## 概述
|
||||
|
||||
8255A(Programmable Peripheral Interface, PPI)是 Intel 公司生产的通用可编程并行 I/O 接口芯片,**在全部 4 套试卷中均有出现**,是本课程最高频考点。它提供 3 个 8 位端口(A、B、C),支持 3 种工作方式,可通过程序灵活配置为输入/输出功能。
|
||||
8255A(Programmable Peripheral Interface, PPI)是 Intel 公司生产的通用可编程并行 I/O 接口芯片,**在全部 4 套试卷中均有出现**,是本课程最高频考点。它通过软件配置 3 个 8 位端口(A/B/C)的工作方式,灵活适配多种外设需求。
|
||||
|
||||
> [!tip] 考试要点
|
||||
> - **控制字计算**:方式控制字(D7=1)和 C 口按位控制字(D7=0)的区别
|
||||
@@ -26,14 +26,14 @@ create time: 2026-06-26 23:05
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A["CPU 数据总线"] --> B["数据总线缓冲器"]
|
||||
B --> C["读/写控制逻辑"]
|
||||
C --> D["A 组控制"]
|
||||
C --> E["B 组控制"]
|
||||
D --> F["端口 A (PA0~PA7)"]
|
||||
D --> G["端口 C 高 4 位 (PC4~PC7)"]
|
||||
E --> H["端口 B (PB0~PB7)"]
|
||||
E --> I["端口 C 低 4 位 (PC0~PC3)"]
|
||||
CPUDB["CPU 数据总线"] --> DBB["数据总线缓冲器"]
|
||||
DBB --> RWCL["读/写控制逻辑"]
|
||||
RWCL --> AGC["A 组控制"]
|
||||
RWCL --> BGC["B 组控制"]
|
||||
AGC --> PA["端口 A\nPA0~PA7"]
|
||||
AGC --> CH["端口 C 高 4 位\nPC4~PC7"]
|
||||
BGC --> PB["端口 B\nPB0~PB7"]
|
||||
BGC --> CL["端口 C 低 4 位\nPC0~PC3"]
|
||||
```
|
||||
|
||||
| 模块 | 功能 |
|
||||
@@ -56,9 +56,20 @@ graph LR
|
||||
>
|
||||
> 提示:方式 2 需要同时占用输入和输出的联络信号线,这些信号来自端口 C——只有 A 组控制能支配足够多的 C 口引脚(5 根)来支持双向握手。
|
||||
|
||||
### 3. 三种工作方式详解
|
||||
### 3. 三种工作方式对比速查
|
||||
|
||||
#### 方式 0 — 基本输入/输出
|
||||
| 特性 | 方式 0(基本 I/O) | 方式 1(选通 I/O) | 方式 2(双向总线) |
|
||||
|:----:|:-----------------:|:-----------------:|:-----------------:|
|
||||
| **方向** | 固定(编程设定) | 固定(编程设定) | 动态可变(输入/输出切换) |
|
||||
| **同步方式** | 无握手信号 | 3 根联络信号握手 | 5 根联络信号(兼顾输入/输出) |
|
||||
| **中断** | 无 | 有(INTR) | 有(INTR) |
|
||||
| **占用 C 口引脚** | 0 个 | 3~5 个 | 5 个(PC3~PC7) |
|
||||
| **适用场景** | 无条件/条件传送 | 同步数据传输 | 需要双向数据交换 |
|
||||
| **可用端口** | A、B、C | A(输入/输出)、B(仅输入/输出) | 仅 A |
|
||||
|
||||
### 4. 三种工作方式详解
|
||||
|
||||
#### 方式 0 — 基本输入/输出(编程设定方向)
|
||||
|
||||
最简单的工作方式,无需任何联络信号(握手信号),CPU 可直接通过 `IN`/`OUT` 指令读写端口。
|
||||
|
||||
@@ -89,18 +100,35 @@ graph LR
|
||||
> [!info] 方式 1 工作流程(输入)
|
||||
> 外设准备数据 → 发 STB 锁存数据 → 8255A 发 IBF → 条件满足时发 INTR → CPU 响应中断并读数据 → IBF 变低 → 准备接收下一个数据。
|
||||
|
||||
#### 方式 2 — 双向总线方式
|
||||
##### 方式 1 的 INTE 控制触发器(重点难点)
|
||||
|
||||
方式 1 下,每个端口是否允许向 CPU 发出中断请求,由 **INTE 控制触发器**决定。**INTE 通过 C 口按位控制字来置 0/置 1**:
|
||||
|
||||
| INTE | 控制的端口 | 操作端口 C 的位 | 功能 |
|
||||
|------|-----------|---------------|------|
|
||||
| **INTE1** | A 口输出 | PC6 | 1=允许 OBF 产生中断 |
|
||||
| **INTE2** | A 口输入 | PC3 | 1=允许 INTRA 产生中断 ⚠️ 不可直接设置 |
|
||||
| **INTE3** | B 口输入/输出 | PC1 | 1=允许产生中断 ⚠️ 不可直接设置 |
|
||||
| **INTE4** | B 口输出 | PC0 | 1=允许产生中断 |
|
||||
| **INTE5** | A 口双向(方式 2) | PC4 | 1=允许 STB/OBF 相关中断 |
|
||||
|
||||
> [!warning] 易错点
|
||||
> - INTE2 和 INTE3 **无法通过 C 口按位控制字直接置位**!这是 8255A 的硬件限制。
|
||||
> - 实际编程中,若需要启用 A 口输入中断(INTE2),需通过其他方式(如先配置为方式 0)间接实现。
|
||||
> - 考试中常考查某一口中断信号的产生条件,必须同时满足:**INTR 有效 AND INTE = 1**。
|
||||
|
||||
#### 方式 2 — 双向总线方式(仅端口 A)
|
||||
|
||||
**仅端口 A 可用**,同一端口既可输入又可输出,利用端口 C 的 5 个引脚(PC3~PC7)作为联络信号。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A["外设"] -- "数据 + STB/IBF" --> B["8255A 端口 A"]
|
||||
B -- "数据 + OBF/ACK" --> A
|
||||
B -- "INTR" --> C["CPU"]
|
||||
flowchart LR
|
||||
Device["外设"] -- "输入: STB/IBF + 数据" --> PIA["8255A\n端口 A"]
|
||||
PIA -- "输出: OBF/ACK + 数据" --> Device
|
||||
PIA -- "INTR 中断请求" --> CPU["CPU"]
|
||||
```
|
||||
|
||||
### 4. 控制字格式
|
||||
### 6. 控制字格式
|
||||
|
||||
8255A 有两类控制字,通过 **D7 位** 区分,写入同一个端口地址(控制口):
|
||||
|
||||
@@ -146,14 +174,31 @@ D7 D6 D5 D4 D3 D2 D1 D0
|
||||
>
|
||||
> 控制字 = `0000 0111B` = **07H**
|
||||
|
||||
##### C 口引脚复用关系表(考试重点)
|
||||
|
||||
方式 1/2 下,端口 C 的部分引脚被用作联络信号,此时不能再当作普通 I/O 使用:
|
||||
|
||||
| 端口配置 | 占用的 C 口引脚 | 说明 |
|
||||
|----------|----------------|------|
|
||||
| A 口方式 1 输入 | STB(PC4)、IBF(PC5)、INTRA(PC3) | 3 根握手线 |
|
||||
| A 口方式 1 输出 | OBF(PC7)、ACK(PC6)、INTRA(PC3) | 3 根握手线 |
|
||||
| A 口方式 2 | STB(PC4)、IBF(PC5)、OBF(PC7)、ACK(PC6)、INTRA(PC3) | 5 根双向握手线 |
|
||||
| B 口方式 1 输入 | STB(PC1)、IBF(PC0)、INTRA(PC2) | 3 根握手线 |
|
||||
| B 口方式 1 输出 | OBF(PC1)、ACK(PC0)、INTRA(PC2) | 3 根握手线 |
|
||||
|
||||
> [!info] 规律记忆
|
||||
> - 每个方式 1 端口固定占用 **3 根 C 口引脚**
|
||||
> - 方式 2 额外增加 2 根 → 共 **5 根**
|
||||
> - B 口的联络信号全部来自 C 口低 3 位(PC0~PC2),因此 **B 口方式 1 不影响 C 口高 4 位**!这是一个常见考点。
|
||||
|
||||
> [!question] 关键考点
|
||||
> 方式控制字和 C 口位控制字写入的是 **同一个端口地址**(控制口),如何区分?
|
||||
>
|
||||
> 答:通过 D7 位区分。D7=1 是方式控制字,D7=0 是位控制字。
|
||||
|
||||
### 5. 端口地址推算
|
||||
### 7. 端口地址推算
|
||||
|
||||
8255A 占用 **4 个连续端口地址**,由 A1、A0 引脚选择:
|
||||
8255A 占用 **4 个连续的奇地址**(注意不是按 +1),由 A1、A0 引脚选择。
|
||||
|
||||
| A1 A0 | 选中端口 | 相对偏移 |
|
||||
|:------:|:--------:|:--------:|
|
||||
@@ -162,30 +207,203 @@ D7 D6 D5 D4 D3 D2 D1 D0
|
||||
| 1 0 | 端口 C | 基地址 + 4 |
|
||||
| 1 1 | 控制口 | 基地址 + 6 |
|
||||
|
||||
> [!info] 为什么地址间隔是 +2?
|
||||
> 8255A 的 A0、A1 连接到系统地址总线的 **A2、A3**(最低两位被跳过)。系统地址是按字节编址的,8255A 内部不需要 A0/A1 来区分这 4 个寄存器(仅用 2 位 A2/A3 即可),因此地址间距为 **+2**。这个特性在地址推算题中非常关键,很多考生会错误地按 +1 递增计算。
|
||||
|
||||
> [!example] 地址推算示例
|
||||
> 已知 A 口地址 = 2F0H,则:
|
||||
> **例 1**:已知 A 口地址 = 2F0H
|
||||
> - B 口 = 2F0H + 2 = **2F2H**
|
||||
> - C 口 = 2F0H + 4 = **2F4H**
|
||||
> - 控制口 = 2F0H + 6 = **2F6H**
|
||||
>
|
||||
> 若 A 口地址 = 20H(小地址系统),则控制口 = **23H**。
|
||||
> **例 2**:已知 A 口地址 = 20H(小地址系统)
|
||||
> - B 口 = 20H + 2 = **22H**
|
||||
> - C 口 = 20H + 4 = **24H**
|
||||
> - 控制口 = 20H + 6 = **26H**
|
||||
|
||||
### 6. 初始化编程模板
|
||||
### 8. 初始化编程模板
|
||||
|
||||
########## 步骤分解
|
||||
|
||||
8255A 初始化只需要 **一步**——向控制口写入方式控制字。后续如果需要单独控制 C 口的某一位(如握手信号线),再写入位控制字即可。
|
||||
|
||||
```asm
|
||||
; 8255A 初始化通用模板
|
||||
; 假设控制口地址为 PORT_CTL
|
||||
; ============================================
|
||||
; 场景:A 口方式 0 输出接 LED,B 口方式 0 输入接开关
|
||||
; 假设 I/O 基地址从 280H 开始
|
||||
; ============================================
|
||||
|
||||
MOV DX, PORT_CTL ; 控制口地址
|
||||
MOV AL, 80H ; 方式控制字(按需修改)
|
||||
OUT DX, AL ; 写入方式控制字
|
||||
MOV DX, 286H ; 控制口地址 = 280H + 6
|
||||
MOV AL, 81H ; 1000 0001B:A口方式0输出 + B口方式0输入
|
||||
OUT DX, AL ; 写入方式控制字 → 完成全部配置
|
||||
|
||||
; 若需要对 C 口某位置位/复位:
|
||||
MOV DX, PORT_CTL
|
||||
MOV AL, 07H ; 位控制字:PC3=1
|
||||
; ★ 关键理解:方式控制字一次性设定了所有端口的工作方式和方向
|
||||
; ★ 不需要分别对 A/B/C 口进行设置
|
||||
```
|
||||
|
||||
#### C 口按位置位/复位(配合使用)
|
||||
|
||||
当需要对 C 口的**某一位**进行精确控制时(比如拉高/拉低某个握手信号):
|
||||
|
||||
```asm
|
||||
; 使 PC5 = 1(常用于将 IBF 置高,准备接收数据)
|
||||
MOV DX, 286H ; 控制口地址不变
|
||||
MOV AL, 22H ; 0000 0101B:D7=0 表示位控制字,PC5 选位,D0=1 置位
|
||||
OUT DX, AL ; 仅改变 PC5,不影响其他 C 口引脚
|
||||
|
||||
; 使 PC5 = 0(清 0)
|
||||
MOV AL, 20H ; 0000 0100B:同样是 PC5 选位,但 D0=0 复位
|
||||
OUT DX, AL
|
||||
```
|
||||
|
||||
> [!tip] 位控制字速查表
|
||||
> | 目标 | 十六进制值 | 二进制 |
|
||||
> |------|-----------|--------|
|
||||
> | PC0 = 1 | **01H** | `0000 0001` |
|
||||
> | PC1 = 1 | **03H** | `0000 0011` |
|
||||
> | PC2 = 1 | **05H** | `0000 0101` |
|
||||
> | PC3 = 1 | **07H** | `0000 0111` |
|
||||
> | PC4 = 1 | **09H** | `0000 1001` |
|
||||
> | PC5 = 1 | **0BH** | `0000 1011` |
|
||||
> | PC6 = 1 | **0DH** | `0000 1101` |
|
||||
> | PC7 = 1 | **0FH** | `0000 1111` |
|
||||
|
||||
#### 综合示例:A 口方式 1 输入 + B 口方式 0 输出
|
||||
|
||||
```asm
|
||||
; 已知基地址 = 300H,A 口方式 1 输入(INTE2=1),B 口方式 0 输出
|
||||
|
||||
; ① 先启用 A 口输入中断的允许触发器(INTE2)
|
||||
; INTE2 对应通过 PC3 间接控制 → 用位控制字设 PC3=1
|
||||
MOV DX, 306H
|
||||
MOV AL, 07H ; 0000 0111B:选 PC3,置 1
|
||||
OUT DX, AL ; ⚠️ 但注意:INTE2 实际上无法直接通过位控制字设置!
|
||||
; 这里仅为演示流程,实际工程中需另行处理。
|
||||
|
||||
; ② 写入方式控制字
|
||||
MOV AL, 1010 0000B ; D7=1, A组=1(方式1), A口=1(输入), C高=0(输出)
|
||||
; B组=0(方式0), B口=0(输出), C低=0(输出)
|
||||
; = 1010 0000B = A0H
|
||||
MOV DX, 306H
|
||||
OUT DX, AL
|
||||
```
|
||||
|
||||
> [!warning] 易错点
|
||||
> 1. **控制字只写一次**:不要反复向控制口写入相同的方式控制字。初始化完成后只需在需要时修改 C 口状态才写入位控制字。
|
||||
> 2. **DX 寄存器必须配合**:`OUT` 指令中,端口地址≥256(即扩展寻址)时必须放在 DX 中,否则只能访问 0~255(FFH)。
|
||||
> 3. **先写位控制字还是先写方式控制字**?若需设置 INTE 触发器,需**先**写入位控制字打开中断允许,**再**写入方式控制字选择工作模式。
|
||||
|
||||
## 练习题集(考前自测)
|
||||
|
||||
### 题 1:控制字计算(★)
|
||||
|
||||
> **题目**:A 口方式 0 输出,B 口方式 0 输入。求方式控制字。
|
||||
|
||||
<details>
|
||||
<summary>查看答案</summary>
|
||||
|
||||
- D7 = 1(方式控制字标识)
|
||||
- D6D5 = 00(A 组方式 0)
|
||||
- D4 = 0(A 口输出)
|
||||
- D3 = 0(C 高位置位/复位,无意义)
|
||||
- D2 = 0(B 组方式 0)
|
||||
- D1 = 1(B 口输入)
|
||||
- D0 = 0(C 低位置位/复位,无意义)
|
||||
|
||||
**答案**:`1000 0010B` = **82H**
|
||||
|
||||
</details>
|
||||
|
||||
### 题 2:地址推算(★★)
|
||||
|
||||
> **题目**:已知 8255A 的基地址为 2F0H,请写出 A、B、C 三个端口及控制口的地址。
|
||||
|
||||
<details>
|
||||
<summary>查看答案</summary>
|
||||
|
||||
| 端口 | 地址 | 计算过程 |
|
||||
|------|------|---------|
|
||||
| A 口 | **2F0H** | 基地址 + 0 |
|
||||
| B 口 | **2F2H** | 基地址 + 2 |
|
||||
| C 口 | **2F4H** | 基地址 + 4 |
|
||||
| 控制口 | **2F6H** | 基地址 + 6 |
|
||||
|
||||
</details>
|
||||
|
||||
### 题 3:综合编程(★★★)
|
||||
|
||||
> **题目**:设计一个接口电路,A 口方式 1 输入接键盘数据,B 口方式 0 输出接 LED 显示。I/O 基地址为 300H。编写初始化程序。
|
||||
|
||||
<details>
|
||||
<summary>查看答案</summary>
|
||||
|
||||
```asm
|
||||
; ★ 第一步:启用 INTE2(允许 A 口输入中断)
|
||||
; INTE2 对应 PC3 → 需要写位控制字设 PC3=1
|
||||
MOV DX, 306H ; 控制口地址 = 300H + 6
|
||||
MOV AL, 07H ; 位控制字:选 PC3,置 1
|
||||
OUT DX, AL ; 设置 INTE2=1
|
||||
|
||||
; ★ 第二步:写入方式控制字
|
||||
; D7=1, D6D5=1(A组方式1), D4=1(A口输入), D3=0,
|
||||
; D2=0(B组方式0), D1=0(B口输出), D0=0
|
||||
; = 1010 0000B = A0H
|
||||
MOV AL, 0A0H ; 修正写法,更清晰
|
||||
MOV DX, 306H
|
||||
OUT DX, AL ; 完成 8255A 初始化
|
||||
```
|
||||
|
||||
> [!tip] 要点总结
|
||||
> 1. 必须先启用 INTE(通过位控制字),再写方式控制字
|
||||
> 2. A 口方式 1 输入占用 PC3、PC4、PC5;B 口方式 0 不受影响
|
||||
> 3. 所有配置均写入同一个控制口地址
|
||||
|
||||
</details>
|
||||
|
||||
### 题 4:C 口引脚复用判断(★★)
|
||||
|
||||
> **题目**:A 口工作于方式 2,此时端口 C 还有哪些引脚可作为普通 I/O 使用?
|
||||
|
||||
<details>
|
||||
<summary>查看答案</summary>
|
||||
|
||||
方式 2 下,端口 A 占用 PC3~PC7(STB、IBF、OBF、ACK、INTRA),因此:
|
||||
|
||||
- **PC0、PC1、PC2** 仍可作为普通 I/O 使用
|
||||
- **PC3~PC7** 被握手信号占用,不可用作普通 I/O
|
||||
|
||||
</details>
|
||||
|
||||
### 题 5:INTE 触发器(★★)
|
||||
|
||||
> **题目**:以下哪种情况可以产生 A 口方式 1 输入中断?
|
||||
>
|
||||
> A. INTR 有效且 INTE2 = 0
|
||||
> B. INTR 无效且 INTE2 = 1
|
||||
> C. INTR 有效且 INTE2 = 1
|
||||
> D. 任意状态均可
|
||||
|
||||
<details>
|
||||
<summary>查看答案</summary>
|
||||
|
||||
**正确答案:C**
|
||||
|
||||
中断产生的条件是 **两个条件同时满足**:
|
||||
1. INTR 引脚为高电平(请求信号有效)
|
||||
2. INTE2 = 1(中断允许触发器使能)
|
||||
|
||||
缺少任何一个条件都无法产生中断请求。这是考试中常见的选择题考点。
|
||||
|
||||
</details>
|
||||
|
||||
## 知识总结
|
||||
- **4 个端口地址**:基址 + {0, 2, 4, 6} → A / B / C / 控制口(间隔为 2!)
|
||||
- **3 种工作模式**:方式 0(基本)、方式 1(选通)、方式 2(双向)
|
||||
- **2 类控制字**:方式控制字(D7=1)、C 口按位控制字(D7=0)
|
||||
- **关键关系**:每个方式 1 占用 C 口 3 引脚,方式 2 占用 5 引脚
|
||||
|
||||
---
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[8254定时计数器]]
|
||||
|
||||
+360
-122
@@ -11,13 +11,15 @@ create time: 2026-06-26 23:05
|
||||
|
||||
## 概述
|
||||
|
||||
8259A 是 Intel 公司生产的可编程中断控制器(Programmable Interrupt Controller, PIC),**在全部 4 套试卷中均有出现**。它负责管理和控制 8086 系统中的外部中断请求,支持 8 级优先级中断,可通过级联扩展。本芯片的知识点主要集中在 **初始化命令字(ICW)编写**、**中断响应过程** 和 **优先级管理** 三个方面。
|
||||
8259A 是 Intel 公司生产的可编程中断控制器(Programmable Interrupt Controller, PIC),**在全部 4 套试卷中均有出现**。它负责管理和控制 8086 系统中的外部中断请求,支持 8 级优先级中断,可通过级联扩展至最多 64 级。本芯片的知识点主要集中在 **初始化命令字(ICW)编写**、**中断响应过程** 和 **优先级管理** 三个方面。
|
||||
|
||||
> [!tip] 考试要点
|
||||
> - **ICW 写入顺序**:ICW1 → ICW2 → ICW3(可选)→ ICW4(可选)
|
||||
> - **ICW2 与中断类型码**的关系
|
||||
> - **中断响应时序**:两个 INTA 脉冲期间 8259A 做了什么
|
||||
> - **全嵌套方式**的优先级规则
|
||||
> - **ICW2 与中断类型码**的计算:高 5 位由程序员设定,低 3 位自动对应 IR0~IR7
|
||||
> - **中断响应时序**:两个 INTA 脉冲期间 8259A 分别执行什么操作
|
||||
> - **OCW2 EOI 命令**的发送方式和端口
|
||||
> - **全嵌套方式**的优先级规则和适用场景
|
||||
> - **级联系统**的中断级数和 ICW3 设置
|
||||
|
||||
## 正文
|
||||
|
||||
@@ -25,108 +27,212 @@ create time: 2026-06-26 23:05
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
A["IR0~IR7 中断请求输入"] --> B["8259A"]
|
||||
B -- "INT" --> C["CPU"]
|
||||
C -- "INTA" --> B
|
||||
B -- "中断类型码 D0~D7" --> C
|
||||
B --> D["优先级判别器"]
|
||||
B --> E["中断屏蔽寄存器 IMR"]
|
||||
B --> F["中断服务寄存器 ISR"]
|
||||
B --> G["中断请求寄存器 IRR"]
|
||||
A["IR0~IR7 中断请求输入"] --> B["8259A"]
|
||||
B -- "INT 输出" --> C["CPU"]
|
||||
C -- "INTA 响应" --> B
|
||||
B -- "中断类型码" --> C
|
||||
D["优先级判别器 PR"] <--> B
|
||||
E["中断屏蔽寄存器 IMR"] <--> B
|
||||
F["中断服务寄存器 ISR"] <--> B
|
||||
G["中断请求寄存器 IRR"] <--> B
|
||||
```
|
||||
|
||||
| 寄存器 | 缩写 | 功能 |
|
||||
|--------|------|------|
|
||||
| 中断请求寄存器 | **IRR** | 记录哪些 IR 引脚有中断请求(8 位,对应 IR0~IR7) |
|
||||
| 中断屏蔽寄存器 | **IMR** | 某位=1 则屏蔽对应 IR 的中断请求(通过 OCW1 设置) |
|
||||
| 中断服务寄存器 | **ISR** | 记录当前正在被服务的中断(用于嵌套管理) |
|
||||
| 优先级判别器 | **PR** | 从 IRR 中未被 IMR 屏蔽的请求里选出最高优先级 |
|
||||
| 寄存器 | 缩写 | 位数 | 功能说明 |
|
||||
|--------|------|:----:|------|
|
||||
| 中断请求寄存器 | **IRR** | 8 位 | 记录哪些 IR 引脚有pending的中断请求,某位 = 1 表示对应 IRi 有未响应的请求 |
|
||||
| 中断屏蔽寄存器 | **IMR** | 8 位 | 某位 = 1 则屏蔽对应 IR 的中断请求(通过 OCW1 设置),= 0 则允许 |
|
||||
| 中断服务寄存器 | **ISR** | 8 位 | 记录当前正在被 CPU 服务的中断源,用于嵌套管理;中断服务完成后需清除 |
|
||||
| 优先级判别器 | **PR** | — | 从 IRR 中未被 IMR 屏蔽的请求里选出最高优先级的中断 |
|
||||
|
||||
> [!question] IRR、IMR、ISR 三者如何协作?
|
||||
> [!question] IRR、IMR、ISR 三者如何协作完成一次中断响应?
|
||||
> 1. 外设在 IRi 引脚产生中断请求 → **IRR** 对应位置 1
|
||||
> 2. **IMR** 检查该位是否被屏蔽(=1 则忽略)
|
||||
> 3. 未屏蔽的请求送入 **PR** 进行优先级判别
|
||||
> 4. 若当前无更高优先级中断正在服务(查 **ISR**),则 8259A 向 CPU 发出 INT 信号
|
||||
> 2. 8259A 将 IRR 与 **IMR** 做按位与运算:某位 = IMR 该位的值 → 该请求被屏蔽,不可响应
|
||||
> 3. 未被屏蔽的请求送入 **PR** 进行优先级判别,选出的最高优先级候选与 **ISR** 比较
|
||||
> 4. 若候选优先级高于 ISR 中所有正在服务的中断,则 8259A 向 CPU 发出 **INT** 信号
|
||||
> 5. CPU 响应后给出两个 **INTA** 脉冲 → 第一个 INTA 将 ISR 对应位置 1、IRR 对应位清 0;第二个 INTA 将中断类型码送上数据总线
|
||||
|
||||
### 2. 初始化命令字(ICW)
|
||||
### 2. 端口地址
|
||||
|
||||
8259A 有 **4 个初始化命令字**,必须按顺序写入:
|
||||
8259A 有两个端口地址,取决于总线地址线 **A0** 的值:
|
||||
|
||||
| A0 | 端口用途 | 最小系统中地址 |
|
||||
|----|----------|:--------------:|
|
||||
| 0 | **偶地址端口** — 写 ICW1、OCW2、OCW3;读 ISR / IRR | **20H** |
|
||||
| 1 | **奇地址端口** — 写 ICW2、ICW3、ICW4、OCW1 | **21H** |
|
||||
|
||||
> [!info] 端口地址记忆法
|
||||
> - A0 = 0 → 偶地址 → 20H("偶"和"零"都联想为偶数)
|
||||
> - A0 = 1 → 奇地址 → 21H(比 20H 大 1,刚好对应 A0=1)
|
||||
> - 最小系统中 8259A 的端口就是 20H/21H,考试默认使用此地址
|
||||
|
||||
### 3. 初始化命令字(ICW)
|
||||
|
||||
8259A 上电后必须通过 ICW 完成初始化,**必须按顺序写入**,每个命令字占一个 I/O 写周期:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A["ICW1 写入偶地址"] --> B["ICW2 写入奇地址"]
|
||||
B --> C{"需要级联?"}
|
||||
C -- "是" --> D["ICW3 写入奇地址"]
|
||||
C -- "否" --> E{"需要 ICW4?"}
|
||||
D --> E
|
||||
E -- "是" --> F["ICW4 写入奇地址"]
|
||||
E -- "否" --> G["初始化完成"]
|
||||
F --> G
|
||||
A["ICW1\n(偶地址端口 A0=0)"] --> B{"ICW1 的 D1 SNGL"}
|
||||
B -- "0: 级联模式" --> C["ICW2\n(奇地址端口)"]
|
||||
B -- "1: 单片模式" --> C
|
||||
C --> D["ICW3\n(仅级联时写)"]
|
||||
D --> E["ICW4\n(按需)"]
|
||||
E --> F["初始化完成"]
|
||||
```
|
||||
|
||||
#### ICW1(偶地址端口,A0=0)
|
||||
|
||||
```
|
||||
D7 D6 D5 D4 D3 D2 D1 D0
|
||||
[A7 A6 A5] 1 [LTIM] [SNGL] [IC4]
|
||||
0=边沿 0=级联 0=不需要ICW4
|
||||
1=电平 1=单片 1=需要ICW4
|
||||
D7 D6 D5 D4 D3 D2 D1 D0
|
||||
[ Don't Care ] 1 LTIM: 0=边沿触发 1=电平触发 SNGL: 0=级联 1=单片 IC4: 0=不需ICW4 1=需ICW4
|
||||
```
|
||||
|
||||
> [!info] ICW1 标志位
|
||||
> D4 位 **固定为 1**,这是识别 ICW1 的标志。写入时 A0 必须为 0(偶地址端口)。
|
||||
| 位 | 符号 | 含义 | 说明 |
|
||||
|---|------|------|------|
|
||||
| D4 | — | **固定为 1** | 这是识别 ICW1 的标志位,若 D4=0 则视为 OCW 而非 ICW |
|
||||
| D3 | LTIM | 触发方式 | 0 = 边沿触发(IR 上升沿有效);1 = 电平触发(IR 高电平有效) |
|
||||
| D2 | SNGL | 级联标志 | 0 = 多片级联(后续需要写 ICW3);1 = 单片系统(不写 ICW3) |
|
||||
| D0 | IC4 | ICW4 标志 | 0 = 不需要 ICW4(默认工作在 8080/8085 模式);1 = 需要 ICW4(8086 模式下必须写) |
|
||||
|
||||
> [!example] ICW1 计算示例
|
||||
> **要求**:边沿触发、级联方式、需要 ICW4
|
||||
>
|
||||
> - D4 固定 = 1
|
||||
> - LTIM = 0(边沿触发)
|
||||
> - SNGL = 0(级联)
|
||||
> - IC4 = 1(需要 ICW4)
|
||||
> - D7~D5 可填 0
|
||||
>
|
||||
> ICW1 = `0001 0001B` = **11H**
|
||||
|
||||
#### ICW2(奇地址端口,A0=1)
|
||||
|
||||
ICW2 提供 **中断类型码的高 5 位**(T7~T3),低 3 位由 8259A 自动填入 IR 编码。
|
||||
ICW2 提供 **中断类型码的高 5 位**(T7~T3),低 3 位(T2~T0)由 8259A **根据请求来源自动填入**。
|
||||
|
||||
```
|
||||
中断类型码 = T7 T6 T5 T4 T3 [IR2 IR1 IR0]
|
||||
↑ 自动填充
|
||||
D7 D6 D5 D4 D3 D2 D1 D0
|
||||
T7 T6 T5 T4 T3 固定为 0 (IR 编码会自动填充)
|
||||
```
|
||||
|
||||
中断类型码的计算公式:
|
||||
|
||||
$$
|
||||
\text{类型码} = \text{ICW2}_{[7:3]} \times 2^3 + \text{IR编号}
|
||||
$$
|
||||
|
||||
即:ICW2 高 5 位左移 3 位,再加上 IR 引脚号(0~7)。
|
||||
|
||||
> [!example] ICW2 计算示例
|
||||
> **要求**:IR0~IR7 对应中断类型码 80H~87H
|
||||
>
|
||||
> 80H = `1000 0000B`,高 5 位 = `10000`
|
||||
> **例 1**:IR0~IR7 对应中断类型码 80H~87H
|
||||
> - 80H = `1000 0000B`,高 5 位 = `10000`
|
||||
> - ICW2 = **80H**
|
||||
> - 验证:IR0 → 80H, IR1 → 81H, ..., IR7 → 87H ✓
|
||||
>
|
||||
> ICW2 = **80H**
|
||||
> **例 2**:IR0~IR7 对应中断类型码 20H~27H
|
||||
> - 20H = `0010 0000B`,高 5 位 = `00100`
|
||||
> - ICW2 = **20H**
|
||||
>
|
||||
> 验证:IR0 → 80H, IR1 → 81H, ..., IR7 → 87H ✓
|
||||
> **例 3**:IR0~IR7 对应中断类型码 48H~4FH
|
||||
> - 48H = `0100 1000B`,高 5 位 = `01001`
|
||||
> - ICW2 = **90H** (注意:取高 5 位而不是取原字节!48H 的高 5 位是 `01001` = 9H,所以 ICW2 = 90H)
|
||||
|
||||
> [!warning] 易错点
|
||||
> ICW2 的值不等于第一个中断类型码!ICW2 只保留高 5 位,低 3 位填 0。例如要分配 48H~4FH,ICW2 = 90H(不是 48H)。这是因为低 3 位由 IR 编号自动填入。
|
||||
|
||||
#### ICW3(奇地址端口,仅级联时需要)
|
||||
|
||||
- **主片**:某位=1 表示对应 IR 引脚连接了从片
|
||||
- **从片**:低 3 位表示从片的 INT 输出接到主片的哪个 IR 引脚
|
||||
ICW3 在主片和从片中有不同含义:
|
||||
|
||||
- **主片 ICW3**:每位对应一个 IR 引脚,某位 = 1 表示该 IR 引脚连接了从片的 INT 输出
|
||||
- 例如 IR2 和 IR5 各接一个从片 → 主片 ICW3 = `0010 0100B` = **24H**
|
||||
- **从片 ICW3**:低 3 位表示从片的 INT 接到主片的哪个 IR 引脚(即从片的 ID 编号)
|
||||
- 例如从片接到主片 IR2 → 从片 ICW3 = `0000 0010B` = **02H**
|
||||
|
||||
> [!example] 一主二从级联的 ICW3 设置
|
||||
>
|
||||
> - 主片 IR2 接从片 1,IR5 接从片 2
|
||||
> - 主片 ICW3 = IR2 + IR5 = `0010 0100B` = **24H**
|
||||
> - 从片 1 ICW3 = 2(接到主片 IR2)= **02H**
|
||||
> - 从片 2 ICW3 = 5(接到主片 IR5)= **05H**
|
||||
|
||||
#### ICW4(奇地址端口,按需)
|
||||
|
||||
```
|
||||
D7 D6 D5 D4 D3 D2 D1 D0
|
||||
0 0 0 [SFNM] [BUF] [M/S] [uPM]
|
||||
0=普通 0=非缓冲 0=从片 0=8080/8085
|
||||
1=特殊全嵌套 1=缓冲 1=主片 1=8086/8088
|
||||
D7 D6 D5 D4 D3 D2 D1 D0
|
||||
0 0 0 SFNM: BUF: M/S: uPM: (保留=0)
|
||||
0=普通 0=非缓冲 0=从片 0=8080/8085
|
||||
1=特殊全嵌套 1=缓冲 1=主片 1=8086/8088
|
||||
```
|
||||
|
||||
| 位 | 符号 | 含义 |
|
||||
|---|------|------|
|
||||
| D4 | SFNM | **Special Fully Nested Mode**,特殊全嵌套方式。当系统中有多片 8259A 级联且其中一片本身也有子级联时使用,该片的 ISR 允许同级中断嵌套 |
|
||||
| D3 | BUF | **Buffer Flag**,缓冲模式标志。= 1 表示系统使用缓冲区(通常配合 82283 收发器),此时需结合 M/S 位决定选择器;= 0 为非缓冲直接连接 |
|
||||
| D2 | M/S | Master/Slave,仅当 BUF=1 时有效。= 1 为主片(选择器输出使能);= 0 为从片 |
|
||||
| D0 | uPM | **Unified Protected Mode**,CPU 模式。= 1 表示 8086/8088 模式(自动 EOI 禁用);= 0 表示 8080/8085 模式 |
|
||||
|
||||
> [!warning] 8086 系统中 ICW4 必须写
|
||||
> 8086/8088 系统下,ICW4 的 D0=1(uPM=1,表示 8086 模式)是必须的。考试中常见最小初始化序列为:ICW1 → ICW2 → ICW4。
|
||||
> 8086/8088 系统下,ICW4 的 D0 = uPM = 1 是必须的。考试中常见最小初始化序列为:**ICW1 → ICW2 → ICW4**(跳过 ICW3)。
|
||||
|
||||
### 3. 操作命令字(OCW)
|
||||
> [!example] ICW4 计算示例
|
||||
> **要求**:8086 模式,非缓冲方式
|
||||
> - D7~D5 = 000
|
||||
> - SFNM = 0(普通模式)
|
||||
> - BUF = 0(非缓冲)
|
||||
> - M/S = 0(不考虑,BUF=0 时无效)
|
||||
> - uPM = 1(8086 模式)
|
||||
> - D0 = 0(保留位)
|
||||
>
|
||||
> ICW4 = `0000 0010B` = **02H**
|
||||
>
|
||||
> **要求**:8086 模式,缓冲方式,主片
|
||||
> - BUF = 1, M/S = 1, uPM = 1
|
||||
> - ICW4 = `0000 1110B` = **0EH**
|
||||
|
||||
8259A 有 **3 个操作命令字**,在初始化完成后的工作过程中写入:
|
||||
### 4. 操作命令字(OCW)
|
||||
|
||||
| OCW | 端口 | 功能 |
|
||||
|-----|------|------|
|
||||
| **OCW1** | 奇地址 (A0=1) | 设置中断屏蔽字(直接写入 IMR) |
|
||||
| **OCW2** | 偶地址 (A0=0) | 控制中断结束方式和优先级轮换 |
|
||||
| **OCW3** | 偶地址 (A0=0) | 设置特殊屏蔽、读寄存器命令 |
|
||||
OCW 在初始化完成后、系统运行过程中根据需要写入,可随时修改:
|
||||
|
||||
> [!info] EOI 命令
|
||||
> OCW2 中的 **EOI(End of Interrupt)** 命令用于在中断服务程序结束时清除 ISR 中对应的位:
|
||||
> - **普通 EOI**:OCW2 = 20H(非自动 EOI 模式下必须手动发送)
|
||||
> - **特殊 EOI**:指定要清除的 ISR 位
|
||||
| OCW | 端口 | 可读写 | 功能 |
|
||||
|-----|------|:------:|------|
|
||||
| **OCW1** | 奇地址 (A0=1) | 仅写 | 设置中断屏蔽字,直接写入 IMR。某位 = 1 屏蔽对应中断 |
|
||||
| **OCW2** | 偶地址 (A0=0) | 仅写 | 控制中断结束方式和优先级轮换策略 |
|
||||
| **OCW3** | 偶地址 (A0=0) | 读写 | 查询 RR/RIS 状态、设置特殊屏蔽方式 |
|
||||
|
||||
### 4. 中断响应过程
|
||||
#### OCW2 — EOI 命令
|
||||
|
||||
```
|
||||
D7 D6 D5 D4 D3 D2 D1 D0
|
||||
0 0 R SL EOI (reserved)
|
||||
```
|
||||
|
||||
三种常用操作:
|
||||
|
||||
| 操作 | D1 D0 | D2 | 说明 | 示例值 |
|
||||
|------|:-----:|:--:|------|:------:|
|
||||
| **普通 EOI** | xx | 0 | 置 EOI=1, R=SL=0 → 清除 ISR 中优先级最高的位 | **20H** |
|
||||
| **特殊 EOI** | 0x | 1 | 置 EOI=1, R=0, SL=1 → 指定清除 ISR 中 IRk 对应的位(k 由 D4~D2 指定) | **C0H**(清除 IR0)|
|
||||
| **优先级自动循环** | 10 | 0 | 设 R=1, SL=0, EOI=0 → 服务完后最高优先级降为最低,次高变为最高 | **A0H** |
|
||||
|
||||
> [!info] EOI 命令怎么发?
|
||||
> OCW2 写入**偶地址端口**(最小系统 = 20H)。在中断服务程序末尾发送 EOI 以通知 8259A 该中断处理完毕:
|
||||
> ```asm
|
||||
> MOV AL, 20H ; 普通 EOI
|
||||
> OUT 20H, AL ; 发送到偶地址端口
|
||||
> ```
|
||||
|
||||
> [!question] 为什么要发送 EOI?
|
||||
> 发送 EOI 后,8259A 会将 ISR 中对应中断源的位清 0。不清 0 的话,8259A 认为该中断仍在服务,不会响应相同或更低优先级的中断。只有在自动 EOI 模式(某些特定配置下)才不需要手动发送 EOI。
|
||||
|
||||
#### OCW3 — 特殊屏蔽方式和读命令
|
||||
|
||||
OCW3 的功能较多样:
|
||||
|
||||
- **设置特殊屏蔽方式(ESMM = 1)**:某位 = 1 时进入特殊屏蔽方式,此时 IMR 的该位 = 1 允许同级别中断嵌套(只屏蔽比当前低的)
|
||||
- **设置 RR/RIS 读取命令**:RR=1 时,下一个 INTA 脉冲读出 ISR(RR=1, RIS=1)或 IRR(RR=1, RIS=0)的内容
|
||||
- **查询 polled 命令**:用于轮询方式查找最高优先级挂起中断
|
||||
|
||||
### 5. 中断响应过程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
@@ -134,95 +240,227 @@ sequenceDiagram
|
||||
participant I as "8259A"
|
||||
participant C as "CPU"
|
||||
P->>I: "IRi 引脚产生中断请求"
|
||||
Note over I: "IRR 对应位置 1"
|
||||
Note over I: "IRR[i] = 1"
|
||||
Note over I: "PR 判别优先级"
|
||||
I->>C: "INT = 1"
|
||||
I->>C: "INT = 1 (向 CPU 发中断请求)"
|
||||
C->>I: "第一个 INTA 脉冲"
|
||||
Note over I: "ISR 对应位置 1, IRR 对应位清 0"
|
||||
Note over I: "ISR[i] = 1<br/>IRR[i] = 0<br/>8259A 锁存当前优先级"
|
||||
C->>I: "第二个 INTA 脉冲"
|
||||
I->>C: "送出中断类型码 (D0~D7)"
|
||||
Note over C: "根据类型码查向量表, 跳转 ISR"
|
||||
I->>C: "中断类型码 N 送上数据总线"
|
||||
Note over C: "CPU 读类型码 N"
|
||||
Note over C: "向量地址 = N × 4"
|
||||
C->>C: "从向量表读取 CS:IP<br/>转去执行中断服务程序"
|
||||
```
|
||||
|
||||
> [!warning] 两个 INTA 脉冲的作用不同
|
||||
> - **第一个 INTA**:8259A 内部操作(置 ISR、清 IRR),CPU 此时还未获取类型码
|
||||
> - **第二个 INTA**:8259A 将中断类型码送上数据总线,CPU 读取后计算向量表地址
|
||||
> [!warning] 两个 INTA 脉冲的作用截然不同
|
||||
> - **第一个 INTA**:8259A 内部操作 —— 将被响应当前中断置入 ISR、从 IRR 中清除对应位,并锁定当前优先级以防止同级中断干扰。此时 CPU 尚未获取类型码。
|
||||
> - **第二个 INTA**:8259A 将锁存的中断类型码(已拼接好的完整 8 位类型码)放到数据总线上供 CPU 读取。
|
||||
|
||||
### 5. 中断向量表
|
||||
### 6. 中断向量表
|
||||
|
||||
8086 的中断向量表位于内存最低地址 **00000H~003FFH**(共 1KB),可存放 256 个中断向量。
|
||||
8086 的中断向量表位于内存最低地址 **00000H ~ 003FFH**(共 1KB),可存放 256 个中断向量(每个向量 4 字节)。
|
||||
|
||||
中断向量地址计算公式:
|
||||
|
||||
$$
|
||||
中断向量地址 = 中断类型号 \times 4
|
||||
\text{向量地址} = \text{中断类型号} \times 4
|
||||
$$
|
||||
|
||||
每个向量占 4 字节:**低 2 字节 = IP,高 2 字节 = CS**。
|
||||
每个向量占 4 字节,布局为:**低 2 字节 = IP(偏移地址),高 2 字节 = CS(段地址)**。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A["类型号 N"] -- "x4" --> B["向量地址 N*4"]
|
||||
B --> C["IP 低字节"]
|
||||
B --> D["IP 高字节"]
|
||||
B --> E["CS 低字节"]
|
||||
B --> F["CS 高字节"]
|
||||
```
|
||||
| 向量地址 | 存储内容 | 说明 |
|
||||
|---------|----------|------|
|
||||
| N×4 | IP 低字节 | 跳转目标偏移 |
|
||||
| N×4+1 | IP 高字节 | |
|
||||
| N×4+2 | CS 低字节 | 跳转目标段 |
|
||||
| N×4+3 | CS 高字节 | |
|
||||
|
||||
### 6. 优先级管理方式
|
||||
> [!example] 中断向量表地址计算
|
||||
>
|
||||
> **例**:中断类型码为 80H,其向量存放在哪里?
|
||||
> - 向量地址 = 80H × 4 = `10000000₂` × 4 = **200H**
|
||||
> - 向量存放在 **00000H + 200H = 00200H ~ 00203H** 四个字节
|
||||
> - 00200H = IP 低字节, 00201H = IP 高字节, 00202H = CS 低字节, 00203H = CS 高字节
|
||||
|
||||
| 方式 | 特点 | 适用场景 |
|
||||
|------|------|----------|
|
||||
| **全嵌套**(默认) | IR0 最高 → IR7 最低,固定不变 | 大多数应用 |
|
||||
| **自动轮换** | 服务完的中断降为最低优先级 | 公平服务 |
|
||||
| **特殊全嵌套** | 允许同级中断嵌套 | 级联系统的主片 |
|
||||
### 7. 优先级管理方式
|
||||
|
||||
| 方式 | 特点 | 优先级变化 | 配置方法 |
|
||||
|------|------|-----------|---------|
|
||||
| **固定优先级**(默认,全嵌套) | IR0 最高 → IR7 最低,永远不变 | 无变化 | 默认工作模式 |
|
||||
| **自动优先级轮换** | 服务完的中断降为最低,原来的最低升到最高 | 循环移动 | OCW2 = A0H(编程旋转) |
|
||||
| **特殊全嵌套** | 允许**同级**中断嵌套,用于级联系统中主片 | 无变化 | ICW4 的 SFNM=1 |
|
||||
| **特殊屏蔽方式** | 临时屏蔽当前优先级,只允许更低优先级中断 | 按需切换 | OCW3 设置 ESMM + SIM |
|
||||
|
||||
> [!question] 全嵌套方式下,IRQ5 正在服务,哪些中断可以打断它?
|
||||
> 答:只有优先级更高的 IRQ0~IRQ4 可以打断。IRQ6 和 IRQ7 必须等待 IRQ5 服务完成后才能获得响应。
|
||||
> 答:只有优先级更高的 **IRQ0 ~ IRQ4** 可以打断 IRQ5。IRQ6 和 IRQ7 优先级低于 IRQ5,必须等待 IRQ5 服务完成(发送 EOI 清除 ISR[5])后,才能被调度。**即使 IRQ6/IRQ7 没有被 IMR 屏蔽,也不会响应**。
|
||||
|
||||
### 7. 级联扩展
|
||||
> [!info] 全嵌套 vs 特殊全嵌套
|
||||
> - **全嵌套**(固定优先级):不同优先级之间可以嵌套,但**同级不能嵌套**
|
||||
> - **特殊全嵌套**(SFNM=1):同全嵌套一样默认不同级可嵌套,但通过 OCW3 可将某个中断设为特殊屏蔽,允许**同级**中断抢占——这在级联系统的从片中很重要(从片内部可能还需要处理多个同级子中断)
|
||||
|
||||
| 配置 | 中断级数 | 说明 |
|
||||
|------|:--------:|------|
|
||||
| 单片 8259A | 8 级 | IR0~IR7 |
|
||||
| 一主一从级联 | 15 级 | 从片占用主片 1 个 IR 端口(8+8-1=15) |
|
||||
### 8. 级联扩展
|
||||
|
||||
### 8. 典型初始化程序
|
||||
| 配置 | 中断级数 | IR 端口占用 | 说明 |
|
||||
|------|:--------:|------------|------|
|
||||
| 单片 8259A | **8 级** | 8 | IR0~IR7 均直接使用 |
|
||||
| 一主一从级联 | **15 级** | 8 + 7 = 15 | 从片占用主片 1 个 IR(8+8-1=15) |
|
||||
| 一主二从级联 | **22 级** | 8 + 7 + 7 = 22 | 两个从片各占用主片 1 个 IR |
|
||||
| 四片级联(1主3从) | **29 级** | 8 + 7×3 = 29 | 最多扩展到 64 级(4 片 8259A) |
|
||||
|
||||
> [!info] 为什么是 8n-1 而不是 8n?
|
||||
> 每增加一片从片,需要占用主片(或上级从片)的一个 IR 端口来传递从中继而来的中断请求,因此实际可用的中断级数 = 8×N - (N-1) = 7N + 1,其中 N 为 8259A 片数。第一片贡献 8 级,之后每加一片净增 7 级。
|
||||
|
||||
### 9. 典型初始化程序
|
||||
|
||||
以下是一个完整的初始化示例(最小系统,8086 模式):
|
||||
|
||||
```asm
|
||||
; 8259A 初始化示例
|
||||
; ============================================================
|
||||
; 8259A 初始化程序(最小系统)
|
||||
; 端口地址:20H(偶地址,A0=0),21H(奇地址,A0=1)
|
||||
; 中断类型码:80H~87H
|
||||
; 条件:边沿触发、单片、中断类型码 80H~87H、8086 模式
|
||||
; ============================================================
|
||||
|
||||
; ICW1:边沿触发,单片,需要 ICW4
|
||||
MOV AL, 13H
|
||||
OUT 20H, AL
|
||||
MOV AL, 11H ; ICW1: 边沿触发(LTIM=0), 单片(SNGL=1), 需ICW4(IC4=1)
|
||||
; 0001 0001B = 11H
|
||||
OUT 20H, AL ; 写入偶地址端口
|
||||
|
||||
; ICW2:中断类型码基址 = 80H
|
||||
MOV AL, 80H
|
||||
OUT 21H, AL
|
||||
MOV AL, 80H ; ICW2: 中断类型码基址 = 80H(高5位=10000)
|
||||
OUT 21H, AL ; 写入奇地址端口
|
||||
; IR0→80H, IR1→81H, ..., IR7→87H
|
||||
|
||||
; ICW4:8086 模式,非自动 EOI
|
||||
MOV AL, 03H
|
||||
OUT 21H, AL
|
||||
MOV AL, 02H ; ICW4: 8086模式(uPM=1), 非缓冲
|
||||
; 0000 0010B = 02H
|
||||
OUT 21H, AL ; 写入奇地址端口
|
||||
|
||||
; OCW1:设置中断屏蔽字(可选)
|
||||
MOV AL, 00H ; 允许所有中断
|
||||
OUT 21H, AL
|
||||
; ---- 初始化完成 ----
|
||||
; 此时 IMR = 00H(复位默认值),所有中断开放
|
||||
```
|
||||
|
||||
> [!example] 中断服务程序模板
|
||||
#### 中断服务程序模板
|
||||
|
||||
```asm
|
||||
INT_ISR PROC FAR
|
||||
PUSH AX ; 保护现场
|
||||
PUSH BX
|
||||
PUSH CX
|
||||
PUSH DX
|
||||
PUSH DS
|
||||
|
||||
; ---- 中断处理逻辑 ----
|
||||
; ... 具体处理代码 ...
|
||||
|
||||
MOV AL, 20H ; 普通 EOI 命令
|
||||
OUT 20H, AL ; 发送到 8259A(偶地址端口)
|
||||
|
||||
POP DS ; 恢复现场
|
||||
POP DX
|
||||
POP CX
|
||||
POP BX
|
||||
POP AX
|
||||
IRET ; 中断返回(从栈中恢复 CS:IP 和 FLAGS)
|
||||
INT_ISR ENDP
|
||||
```
|
||||
|
||||
> [!info] IRET vs RET 的区别
|
||||
> - **RET**:普通子程序返回,只弹出 IP
|
||||
> - **IRET**:中断返回,依次弹出 IP → CS → FLAGS,恢复中断前的完整上下文
|
||||
|
||||
### 10. 考试综合例题
|
||||
|
||||
> [!example] 【真题型】设计 8259A 初始化程序
|
||||
>
|
||||
> **题目**:某 8086 系统中使用单片 8259A,端口地址 20H/21H,要求:
|
||||
> - 边沿触发
|
||||
> - 中断类型码起始于 70H
|
||||
> - 工作在 8086 模式
|
||||
> - 初始化后允许所有中断
|
||||
>
|
||||
> **解答**:
|
||||
> ```asm
|
||||
> INT_ISR PROC FAR
|
||||
> PUSH AX ; 保护现场
|
||||
> PUSH BX
|
||||
> ; ... 中断处理逻辑 ...
|
||||
> MOV AL, 20H ; 普通 EOI 命令
|
||||
> OUT 20H, AL ; 发送到 8259A
|
||||
> POP BX ; 恢复现场
|
||||
> POP AX
|
||||
> IRET ; 中断返回
|
||||
> INT_ISR ENDP
|
||||
> MOV AL, 70H ; ICW2: 中断类型码基址 = 70H(高 5 位 = 01110)
|
||||
> ; IR0→70H, IR1→71H, ..., IR7→77H
|
||||
> OUT 21H, AL
|
||||
>
|
||||
> MOV AL, 02H ; ICW4: 8086 模式 (uPM=1), 非缓冲
|
||||
> OUT 21H, AL
|
||||
>
|
||||
> MOV AL, 00H ; OCW1: 不屏蔽任何中断(所有中断开放)
|
||||
> OUT 21H, AL
|
||||
> ```
|
||||
|
||||
> [!tip] ICW2 取值要点
|
||||
> ICW2 的值就是 **IR0 对应的中断类型码**。例如题目要求中断类型码从 70H 开始,ICW2 直接设为 70H 即可。这是因为 ICW2 的高 5 位构成类型码的高 5 位,低 3 位自动为 0,恰好对应 IR0(编号为 0)。
|
||||
|
||||
---
|
||||
|
||||
> [!question] 【综合题】多片级联系统初始化
|
||||
>
|
||||
> **题目**:某 8086 系统采用一主两从级联方式,端口地址 20H/21H,要求:
|
||||
> - 边沿触发
|
||||
> - 主片 IR2 接从片 1,IR5 接从片 2
|
||||
> - 所有芯片中断类型码分别起始于 40H、50H、60H
|
||||
> - 工作在 8086 模式、缓冲方式
|
||||
>
|
||||
> **解答**:
|
||||
>
|
||||
> **主片初始化**:
|
||||
> ```asm
|
||||
> MOV AL, 13H ; ICW1: 边沿(0), 级联(0), 需ICW4(1) → 0001_0011B = 13H
|
||||
> OUT 20H, AL
|
||||
> MOV AL, 40H ; ICW2: 主片类型码基址 = 40H
|
||||
> OUT 21H, AL
|
||||
> MOV AL, 24H ; ICW3: IR2+IR5 = 0010_0100B = 24H
|
||||
> OUT 21H, AL
|
||||
> MOV AL, 0EH ; ICW4: 8086模式(uPM=1), 缓冲(BUF=1), 主片(M/S=1) = 0000_1110B = 0EH
|
||||
> OUT 21H, AL
|
||||
> ```
|
||||
>
|
||||
> **从片 1 初始化**:
|
||||
> ```asm
|
||||
> MOV AL, 11H ; ICW1: 边沿(0), 单片(1), 需ICW4(1) = 0001_0001B = 11H
|
||||
> OUT 20H, AL
|
||||
> MOV AL, 50H ; ICW2: 从片1类型码基址 = 50H
|
||||
> OUT 21H, AL
|
||||
> MOV AL, 02H ; ICW3: 接主片IR2 → ID=2 = 00H
|
||||
> OUT 21H, AL
|
||||
> MOV AL, 0AH ; ICW4: 8086模式, 缓冲, 从片(M/S=0) = 0000_1010B = 0AH
|
||||
> OUT 21H, AL
|
||||
> ```
|
||||
>
|
||||
> **从片 2 初始化**:
|
||||
> ```asm
|
||||
> MOV AL, 11H ; ICW1: 同从片1
|
||||
> OUT 20H, AL
|
||||
> MOV AL, 60H ; ICW2: 从片2类型码基址 = 60H
|
||||
> OUT 21H, AL
|
||||
> MOV AL, 05H ; ICW3: 接主片IR5 → ID=5 = 05H
|
||||
> OUT 21H, AL
|
||||
> MOV AL, 0AH ; ICW4: 8086模式, 缓冲, 从片(M/S=0) = 0AH
|
||||
> OUT 21H, AL
|
||||
> ```
|
||||
>
|
||||
> > [!info] 解题思路
|
||||
> > 1. 先确认级联方式 → SNGL=0 → 需要 ICW3
|
||||
> > 2. 确定 ICW2 = 各芯片中断类型码的起始值(IR0 对应的类型码)
|
||||
> > 3. 主片 ICW3 = 连接从片的 IR 引脚编号之和
|
||||
> > 4. 从片 ICW3 = 连接到主片的 IR 引脚编号(即自身 ID)
|
||||
> > 5. 缓冲模式下,ICW4 中 BUF=1,M/S 区分主从片
|
||||
|
||||
> [!question] 【选择题风格】8259A 在最小系统中的端口地址是多少?
|
||||
> A) 20H/21H B) 22H/23H C) 28H/29H D) 30H/31H
|
||||
>
|
||||
> 答:**A) 20H/21H**。这是标准答案,考试默认使用该地址。
|
||||
|
||||
## 附录:快速复习卡
|
||||
|
||||
> [!summary] 核心口诀
|
||||
> - **ICW 顺序记心中**:ICW1 → ICW2 → ICW3(级联) → ICW4(8086必写)
|
||||
> - **奇偶分清单又明**:偶地址(20H)写 ICW1/OCW2/OCW3,奇地址(21H)写 ICW2/3/4 和 OCW1
|
||||
> - **ICW2 高位我设定**:高 5 位自己填,低 3 位自动对应 IR 号
|
||||
> - **EOI 必须手动发**:OCW2=20H 送 20H,别忘写在 ISR 末尾
|
||||
> - **全嵌套高低分明**:IR0 永远最高,IR7 永远最低
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[8255A可编程并行接口]]
|
||||
|
||||
Reference in New Issue
Block a user